diff --git a/apps/bitwarden_event_logs/VERSION b/apps/bitwarden_event_logs/VERSION deleted file mode 100755 index dd36387e..00000000 --- a/apps/bitwarden_event_logs/VERSION +++ /dev/null @@ -1,2 +0,0 @@ -2.1.0 -2.1.0 \ No newline at end of file diff --git a/apps/bitwarden_event_logs/app.manifest b/apps/bitwarden_event_logs/app.manifest deleted file mode 100755 index a9d6a137..00000000 --- a/apps/bitwarden_event_logs/app.manifest +++ /dev/null @@ -1,54 +0,0 @@ -{ - "dependencies": null, - "incompatibleApps": null, - "info": { - "author": [ - { - "company": "Bitwarden Inc.", - "email": "support@bitwarden.com", - "name": "Bitwarden Inc." - } - ], - "classification": { - "categories": [], - "developmentStatus": null, - "intendedAudience": null - }, - "commonInformationModels": null, - "description": "Bitwarden event logs integration into Splunk.", - "id": { - "group": null, - "name": "bitwarden_event_logs", - "version": "2.1.0" - }, - "license": { - "name": null, - "text": null, - "uri": null - }, - "privacyPolicy": { - "name": null, - "text": null, - "uri": null - }, - "releaseDate": null, - "releaseNotes": { - "name": "README", - "text": "README.txt", - "uri": "" - }, - "title": "Bitwarden Event Logs" - }, - "inputGroups": null, - "platformRequirements": null, - "schemaVersion": "2.0.0", - "supportedDeployments": [ - "_standalone", - "_distributed" - ], - "targetWorkloads": [ - "_search_heads", - "_indexers" - ], - "tasks": null -} \ No newline at end of file diff --git a/apps/bitwarden_event_logs/default/collections.conf b/apps/bitwarden_event_logs/default/collections.conf deleted file mode 100755 index 14acf53b..00000000 --- a/apps/bitwarden_event_logs/default/collections.conf +++ /dev/null @@ -1,6 +0,0 @@ -[eventsapi] -enforceTypes = true -field.next_request.start = string -field.next_request.end = string -field.next_request.continuation_token = string -field.last_log_date = string diff --git a/apps/bitwarden_event_logs/default/data/ui/views/authentication_events_dashboard.xml b/apps/bitwarden_event_logs/default/data/ui/views/authentication_events_dashboard.xml deleted file mode 100755 index 86879de7..00000000 --- a/apps/bitwarden_event_logs/default/data/ui/views/authentication_events_dashboard.xml +++ /dev/null @@ -1,147 +0,0 @@ -
- -
- - - - -14h@h - now - - - - - User Email - User ID - User Email - User Name - -
- - - - Successful Log In Attempts - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" type=1000 | iplocation ipAddress | lookup geo_countries longitude as lon, latitude as lat | stats count by Country | geom geo_countries featureIdField=Country - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - - - - - - - Authentication Events by Device - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" (type=1000 OR type=1001 OR type=1002 OR type=1003 OR type=1004 OR type=1005 OR type=1006 OR type=1008 OR type=1009) | timechart count by deviceName - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - Authentication Events by Type - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" (type=1000 OR type=1001 OR type=1002 OR type=1003 OR type=1004 OR type=1005 OR type=1006 OR type=1008 OR type=1009) | timechart count by typeName - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - - Authentication Events by Device - - Device - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" (type=1000 OR type=1001 OR type=1002 OR type=1003 OR type=1004 OR type=1005 OR type=1006 OR type=1008 OR type=1009) | stats count by deviceName - -24h@h - now - - - - - - - - Authentication Events by Type - - Type - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" (type=1000 OR type=1001 OR type=1002 OR type=1003 OR type=1004 OR type=1005 OR type=1006 OR type=1008 OR type=1009) | stats count by typeName - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - - - Top Failed Log In Attempts - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" (type=1005 OR type=1006) | stats count by $top_users_by$ | sort - count - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - - - - - - - Top Successful Log In Attempts - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" type=1000 | stats count by $top_users_by$ | sort - count - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - - - - - - Latest Authentication Events - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" (type=1000 OR type=1001 OR type=1002 OR type=1003 OR type=1004 OR type=1005 OR type=1006 OR type=1008 OR type=1009) - - $timeframe.earliest$ - $timeframe.latest$ - - - - - -
\ No newline at end of file diff --git a/apps/bitwarden_event_logs/default/data/ui/views/configuration.xml b/apps/bitwarden_event_logs/default/data/ui/views/configuration.xml index 627e945f..32def83d 100755 --- a/apps/bitwarden_event_logs/default/data/ui/views/configuration.xml +++ b/apps/bitwarden_event_logs/default/data/ui/views/configuration.xml @@ -1,5 +1,4 @@ - -#test \ No newline at end of file + \ No newline at end of file diff --git a/apps/bitwarden_event_logs/default/data/ui/views/organization_events_dashboard.xml b/apps/bitwarden_event_logs/default/data/ui/views/organization_events_dashboard.xml deleted file mode 100755 index 220bb918..00000000 --- a/apps/bitwarden_event_logs/default/data/ui/views/organization_events_dashboard.xml +++ /dev/null @@ -1,126 +0,0 @@ -
- -
- - - - -24h@h - now - - - - - User Email - User ID - User Email - User Name - -
- - - - Organization Events - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1300 AND type<1800)]]> | iplocation ipAddress | lookup geo_countries longitude as lon, latitude as lat | stats count by Country | geom geo_countries featureIdField=Country - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - - - - - - - - Organization Events by Device - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1300 AND type<1800)]]> | timechart count by deviceName - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - Organization Events by Type - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1300 AND type<1800)]]> | timechart count by typeName - $timeframe.earliest$ - $timeframe.latest$> - - - - - - - - - Organization Events by Device - - Device - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1300 AND type<1800)]]> | stats count by deviceName - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - Organization Events by Type - - Type - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1300 AND type<1800)]]> | stats count by typeName - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - - - Top Organization Event Users - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1300 AND type<1800)]]> | stats count by $top_users_by$ | sort - count - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - - - - - Latest Organization Events - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1300 AND type<1800)]]> - $timeframe.earliest$ - $timeframe.latest$ - - - - - -
\ No newline at end of file diff --git a/apps/bitwarden_event_logs/default/data/ui/views/setup_page_dashboard.xml b/apps/bitwarden_event_logs/default/data/ui/views/setup_page_dashboard.xml deleted file mode 100755 index 891a4104..00000000 --- a/apps/bitwarden_event_logs/default/data/ui/views/setup_page_dashboard.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - -
- -
-
-
diff --git a/apps/bitwarden_event_logs/default/data/ui/views/vault_item_events_dashboard.xml b/apps/bitwarden_event_logs/default/data/ui/views/vault_item_events_dashboard.xml deleted file mode 100755 index aa71eaae..00000000 --- a/apps/bitwarden_event_logs/default/data/ui/views/vault_item_events_dashboard.xml +++ /dev/null @@ -1,127 +0,0 @@ -
- -
- - - - -24h@h - now - - - - - User Email - User ID - User Email - User Name - -
- - - - Vault Item Events - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1100 AND type<1200)]]> | iplocation ipAddress | lookup geo_countries longitude as lon, latitude as lat | stats count by Country | geom geo_countries featureIdField=Country - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - - - - - - - - Vault Item Events by Device - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1100 AND type<1200)]]> | timechart count by deviceName - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - Vault Item Events by Type - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1100 AND type<1200)]]> | timechart count by typeName - $timeframe.earliest$ - $timeframe.latest$> - - - - - - - - - Vault Item Events by Device - - Device - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1100 AND type<1200)]]> | stats count by deviceName - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - Vault Item Events by Type - - Type - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1100 AND type<1200)]]> | stats count by typeName - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - - - Top Vault Item Event Users - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1100 AND type<1200)]]> | stats count by $top_users_by$ | sort - count - $timeframe.earliest$ - $timeframe.latest$ - - - - - - - - - - - - - Latest Vault Item Events - - `bitwarden_event_logs_index` sourcetype="bitwarden:events" =1100 AND type<1200)]]> - - $timeframe.earliest$ - $timeframe.latest$ - - - - - -
\ No newline at end of file diff --git a/apps/bitwarden_event_logs/default/inputs.conf b/apps/bitwarden_event_logs/default/inputs.conf deleted file mode 100755 index 4c92bb09..00000000 --- a/apps/bitwarden_event_logs/default/inputs.conf +++ /dev/null @@ -1,6 +0,0 @@ -[script://$SPLUNK_HOME/etc/apps/bitwarden_event_logs/bin/bitwarden_event_logs.py] -interval = 60 -sourcetype = bitwarden:events -index = main -passAuth = splunk-system-user -python.version = python3 diff --git a/apps/bitwarden_event_logs/default/macros.conf b/apps/bitwarden_event_logs/default/macros.conf deleted file mode 100755 index d46034ba..00000000 --- a/apps/bitwarden_event_logs/default/macros.conf +++ /dev/null @@ -1,2 +0,0 @@ -[bitwarden_event_logs_index] -definition=index=* \ No newline at end of file diff --git a/apps/bitwarden_event_logs/default/props.conf b/apps/bitwarden_event_logs/default/props.conf deleted file mode 100755 index c492648e..00000000 --- a/apps/bitwarden_event_logs/default/props.conf +++ /dev/null @@ -1,138 +0,0 @@ -[bitwarden:events] -LINE_BREAKER = ([\r\n]) -SHOULD_LINEMERGE = false -TRUNCATE = 5000 -KV_MODE = json -FIELDALIAS-alias_1 = ipAddress AS src -FIELDALIAS-alias_2 = date AS timestamp -EVAL-typeName = coalesce(case(\ - type==1000,"User_LoggedIn",\ - type==1001,"User_ChangedPassword",\ - type==1002,"User_Updated2fa",\ - type==1003,"User_Disabled2fa",\ - type==1004,"User_Recovered2fa",\ - type==1005,"User_FailedLogIn",\ - type==1006,"User_FailedLogIn2fa",\ - type==1007,"User_ClientExportedVault",\ - type==1008,"User_UpdatedTempPassword",\ - type==1009,"User_MigratedKeyToKeyConnector",\ - type==1010,"User_RequestedDeviceApproval",\ - type==1011,"User_TdeOffboardingPasswordSet",\ - type==1100,"Cipher_Created",\ - type==1101,"Cipher_Updated",\ - type==1102,"Cipher_Deleted",\ - type==1103,"Cipher_AttachmentCreated",\ - type==1104,"Cipher_AttachmentDeleted",\ - type==1105,"Cipher_Shared",\ - type==1106,"Cipher_UpdatedCollections",\ - type==1107,"Cipher_ClientViewed",\ - type==1108,"Cipher_ClientToggledPasswordVisible",\ - type==1109,"Cipher_ClientToggledHiddenFieldVisible",\ - type==1110,"Cipher_ClientToggledCardCodeVisible",\ - type==1111,"Cipher_ClientCopiedPassword",\ - type==1112,"Cipher_ClientCopiedHiddenField",\ - type==1113,"Cipher_ClientCopiedCardCode",\ - type==1114,"Cipher_ClientAutofilled",\ - type==1115,"Cipher_SoftDeleted",\ - type==1116,"Cipher_Restored",\ - type==1117,"Cipher_ClientToggledCardNumberVisible",\ - type==1300,"Collection_Created",\ - type==1301,"Collection_Updated",\ - type==1302,"Collection_Deleted",\ - type==1400,"Group_Created",\ - type==1401,"Group_Updated",\ - type==1402,"Group_Deleted",\ - type==1500,"OrganizationUser_Invited",\ - type==1501,"OrganizationUser_Confirmed",\ - type==1502,"OrganizationUser_Updated",\ - type==1503,"OrganizationUser_Removed",\ - type==1504,"OrganizationUser_UpdatedGroups",\ - type==1505,"OrganizationUser_UnlinkedSso",\ - type==1506,"OrganizationUser_ResetPassword_Enroll",\ - type==1507,"OrganizationUser_ResetPassword_Withdraw",\ - type==1508,"OrganizationUser_AdminResetPassword",\ - type==1509,"OrganizationUser_ResetSsoLink",\ - type==1510,"OrganizationUser_FirstSsoLogin",\ - type==1511,"OrganizationUser_Revoked",\ - type==1512,"OrganizationUser_Restored",\ - type==1513,"OrganizationUser_ApprovedAuthRequest",\ - type==1514,"OrganizationUser_RejectedAuthRequest",\ - type==1515,"OrganizationUser_Deleted",\ - type==1516,"OrganizationUser_Left",\ - type==1517,"OrganizationUser_AutomaticallyConfirmed",\ - type==1600,"Organization_Updated",\ - type==1601,"Organization_PurgedVault",\ - type==1602,"Organization_ClientExportedVault",\ - type==1603,"Organization_VaultAccessed",\ - type==1604,"Organization_EnabledSso",\ - type==1605,"Organization_DisabledSso",\ - type==1606,"Organization_EnabledKeyConnector",\ - type==1607,"Organization_DisabledKeyConnector",\ - type==1608,"Organization_SponsorshipsSynced",\ - type==1609,"Organization_CollectionManagement_Updated",\ - type==1610,"Organization_CollectionManagement_LimitCollectionCreationEnabled",\ - type==1611,"Organization_CollectionManagement_LimitCollectionCreationDisabled",\ - type==1612,"Organization_CollectionManagement_LimitCollectionDeletionEnabled",\ - type==1613,"Organization_CollectionManagement_LimitCollectionDeletionDisabled",\ - type==1614,"Organization_CollectionManagement_LimitItemDeletionEnabled",\ - type==1615,"Organization_CollectionManagement_LimitItemDeletionDisabled",\ - type==1616,"Organization_CollectionManagement_AllowAdminAccessToAllCollectionItemsEnabled",\ - type==1617,"Organization_CollectionManagement_AllowAdminAccessToAllCollectionItemsDisabled",\ - type==1620,"Organization_AutoConfirmEnabled_Admin",\ - type==1621,"Organization_AutoConfirmDisabled_Admin",\ - type==1622,"Organization_AutoConfirmEnabled_Portal",\ - type==1623,"Organization_AutoConfirmDisabled_Portal",\ - type==1700,"Policy_Updated",\ - type==1800,"ProviderUser_Invited",\ - type==1801,"ProviderUser_Confirmed",\ - type==1802,"ProviderUser_Updated",\ - type==1803,"ProviderUser_Removed",\ - type==1900,"ProviderOrganization_Created",\ - type==1901,"ProviderOrganization_Added",\ - type==1902,"ProviderOrganization_Removed",\ - type==1903,"ProviderOrganization_VaultAccessed",\ - type==2000,"OrganizationDomain_Added",\ - type==2001,"OrganizationDomain_Removed",\ - type==2002,"OrganizationDomain_Verified",\ - type==2003,"OrganizationDomain_NotVerified",\ - type==2100,"Secret_Retrieved",\ - type==2101,"Secret_Created",\ - type==2102,"Secret_Edited",\ - type==2103,"Secret_Deleted",\ - type==2104,"Secret_Permanently_Deleted",\ - type==2105,"Secret_Restored",\ - type==2200,"Project_Retrieved",\ - type==2201,"Project_Created",\ - type==2202,"Project_Edited",\ - type==2203,"Project_Deleted"\ - ), type) -EVAL-deviceName = coalesce(case(device==0,"Android",\ - device==1,"iOS",\ - device==2,"Chrome Extension",\ - device==3,"Firefox Extension",\ - device==4,"Opera Extension",\ - device==5,"Edge Extension",\ - device==6,"Windows Desktop",\ - device==7,"macOS Desktop",\ - device==8,"Linux Desktop",\ - device==9,"Chrome Browser",\ - device==10,"Firefox Browser",\ - device==11,"Opera Browser",\ - device==12,"Edge Browser",\ - device==13,"IEBrowser",\ - device==14,"Unknown Browser",\ - device==15,"Android Amazon",\ - device==16,"UWP",\ - device==17,"Safari Browser",\ - device==18,"Vivaldi Browser",\ - device==19,"Vivaldi Extension",\ - device==20,"Safari Extension",\ - device==21,"SDK",\ - device==22,"Server",\ - device==23,"Windows CLI",\ - device==24,"MacOs CLI",\ - device==25,"Linux CLI",\ - device==26,"DuckDuckGo"\ - ), device) -TIME_PREFIX = "date":" -TIME_FORMAT = %Y-%m-%dT%H:%M:%S.%6N%Z diff --git a/apps/bitwarden_event_logs/default/script.conf b/apps/bitwarden_event_logs/default/script.conf deleted file mode 100755 index 53e6133d..00000000 --- a/apps/bitwarden_event_logs/default/script.conf +++ /dev/null @@ -1,4 +0,0 @@ -[config] -apiUrl=https://api.bitwarden.com -identityUrl=https://identity.bitwarden.com -loggingLevel=INFO diff --git a/apps/bitwarden_event_logs/default/server.conf b/apps/bitwarden_event_logs/default/server.conf deleted file mode 100755 index d1193e0e..00000000 --- a/apps/bitwarden_event_logs/default/server.conf +++ /dev/null @@ -1,3 +0,0 @@ -[shclustering] -conf_replication_include.script = true - diff --git a/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/INSTALLER deleted file mode 100755 index a1b589e3..00000000 --- a/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/LICENSE b/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/LICENSE deleted file mode 100755 index 04b6b1f3..00000000 --- a/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright 2006 Dan-Haim. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -3. Neither the name of Dan Haim nor the names of his contributors may be used - to endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE. diff --git a/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/METADATA b/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/METADATA deleted file mode 100755 index ae2ae341..00000000 --- a/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/METADATA +++ /dev/null @@ -1,321 +0,0 @@ -Metadata-Version: 2.1 -Name: PySocks -Version: 1.7.1 -Summary: A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information. -Home-page: https://github.com/Anorov/PySocks -Author: Anorov -Author-email: anorov.vorona@gmail.com -License: BSD -Keywords: socks,proxy -Platform: UNKNOWN -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* -Description-Content-Type: text/markdown - -PySocks -======= - -PySocks lets you send traffic through SOCKS and HTTP proxy servers. It is a modern fork of [SocksiPy](http://socksipy.sourceforge.net/) with bug fixes and extra features. - -Acts as a drop-in replacement to the socket module. Seamlessly configure SOCKS proxies for any socket object by calling `socket_object.set_proxy()`. - ----------------- - -Features -======== - -* SOCKS proxy client for Python 2.7 and 3.4+ -* TCP supported -* UDP mostly supported (issues may occur in some edge cases) -* HTTP proxy client included but not supported or recommended (you should use urllib2's or requests' own HTTP proxy interface) -* urllib2 handler included. `pip install` / `setup.py install` will automatically install the `sockshandler` module. - -Installation -============ - - pip install PySocks - -Or download the tarball / `git clone` and... - - python setup.py install - -These will install both the `socks` and `sockshandler` modules. - -Alternatively, include just `socks.py` in your project. - --------------------------------------------- - -*Warning:* PySocks/SocksiPy only supports HTTP proxies that use CONNECT tunneling. Certain HTTP proxies may not work with this library. If you wish to use HTTP (not SOCKS) proxies, it is recommended that you rely on your HTTP client's native proxy support (`proxies` dict for `requests`, or `urllib2.ProxyHandler` for `urllib2`) instead. - --------------------------------------------- - -Usage -===== - -## socks.socksocket ## - - import socks - - s = socks.socksocket() # Same API as socket.socket in the standard lib - - s.set_proxy(socks.SOCKS5, "localhost") # SOCKS4 and SOCKS5 use port 1080 by default - # Or - s.set_proxy(socks.SOCKS4, "localhost", 4444) - # Or - s.set_proxy(socks.HTTP, "5.5.5.5", 8888) - - # Can be treated identical to a regular socket object - s.connect(("www.somesite.com", 80)) - s.sendall("GET / HTTP/1.1 ...") - print s.recv(4096) - -## Monkeypatching ## - -To monkeypatch the entire standard library with a single default proxy: - - import urllib2 - import socket - import socks - - socks.set_default_proxy(socks.SOCKS5, "localhost") - socket.socket = socks.socksocket - - urllib2.urlopen("http://www.somesite.com/") # All requests will pass through the SOCKS proxy - -Note that monkeypatching may not work for all standard modules or for all third party modules, and generally isn't recommended. Monkeypatching is usually an anti-pattern in Python. - -## urllib2 Handler ## - -Example use case with the `sockshandler` urllib2 handler. Note that you must import both `socks` and `sockshandler`, as the handler is its own module separate from PySocks. The module is included in the PyPI package. - - import urllib2 - import socks - from sockshandler import SocksiPyHandler - - opener = urllib2.build_opener(SocksiPyHandler(socks.SOCKS5, "127.0.0.1", 9050)) - print opener.open("http://www.somesite.com/") # All requests made by the opener will pass through the SOCKS proxy - --------------------------------------------- - -Original SocksiPy README attached below, amended to reflect API changes. - --------------------------------------------- - -SocksiPy - -A Python SOCKS module. - -(C) 2006 Dan-Haim. All rights reserved. - -See LICENSE file for details. - - -*WHAT IS A SOCKS PROXY?* - -A SOCKS proxy is a proxy server at the TCP level. In other words, it acts as -a tunnel, relaying all traffic going through it without modifying it. -SOCKS proxies can be used to relay traffic using any network protocol that -uses TCP. - -*WHAT IS SOCKSIPY?* - -This Python module allows you to create TCP connections through a SOCKS -proxy without any special effort. -It also supports relaying UDP packets with a SOCKS5 proxy. - -*PROXY COMPATIBILITY* - -SocksiPy is compatible with three different types of proxies: - -1. SOCKS Version 4 (SOCKS4), including the SOCKS4a extension. -2. SOCKS Version 5 (SOCKS5). -3. HTTP Proxies which support tunneling using the CONNECT method. - -*SYSTEM REQUIREMENTS* - -Being written in Python, SocksiPy can run on any platform that has a Python -interpreter and TCP/IP support. -This module has been tested with Python 2.3 and should work with greater versions -just as well. - - -INSTALLATION -------------- - -Simply copy the file "socks.py" to your Python's `lib/site-packages` directory, -and you're ready to go. [Editor's note: it is better to use `python setup.py install` for PySocks] - - -USAGE ------- - -First load the socks module with the command: - - >>> import socks - >>> - -The socks module provides a class called `socksocket`, which is the base to all of the module's functionality. - -The `socksocket` object has the same initialization parameters as the normal socket -object to ensure maximal compatibility, however it should be noted that `socksocket` will only function with family being `AF_INET` and -type being either `SOCK_STREAM` or `SOCK_DGRAM`. -Generally, it is best to initialize the `socksocket` object with no parameters - - >>> s = socks.socksocket() - >>> - -The `socksocket` object has an interface which is very similiar to socket's (in fact -the `socksocket` class is derived from socket) with a few extra methods. -To select the proxy server you would like to use, use the `set_proxy` method, whose -syntax is: - - set_proxy(proxy_type, addr[, port[, rdns[, username[, password]]]]) - -Explanation of the parameters: - -`proxy_type` - The type of the proxy server. This can be one of three possible -choices: `PROXY_TYPE_SOCKS4`, `PROXY_TYPE_SOCKS5` and `PROXY_TYPE_HTTP` for SOCKS4, -SOCKS5 and HTTP servers respectively. `SOCKS4`, `SOCKS5`, and `HTTP` are all aliases, respectively. - -`addr` - The IP address or DNS name of the proxy server. - -`port` - The port of the proxy server. Defaults to 1080 for socks and 8080 for http. - -`rdns` - This is a boolean flag than modifies the behavior regarding DNS resolving. -If it is set to True, DNS resolving will be preformed remotely, on the server. -If it is set to False, DNS resolving will be preformed locally. Please note that -setting this to True with SOCKS4 servers actually use an extension to the protocol, -called SOCKS4a, which may not be supported on all servers (SOCKS5 and http servers -always support DNS). The default is True. - -`username` - For SOCKS5 servers, this allows simple username / password authentication -with the server. For SOCKS4 servers, this parameter will be sent as the userid. -This parameter is ignored if an HTTP server is being used. If it is not provided, -authentication will not be used (servers may accept unauthenticated requests). - -`password` - This parameter is valid only for SOCKS5 servers and specifies the -respective password for the username provided. - -Example of usage: - - >>> s.set_proxy(socks.SOCKS5, "socks.example.com") # uses default port 1080 - >>> s.set_proxy(socks.SOCKS4, "socks.test.com", 1081) - -After the set_proxy method has been called, simply call the connect method with the -traditional parameters to establish a connection through the proxy: - - >>> s.connect(("www.sourceforge.net", 80)) - >>> - -Connection will take a bit longer to allow negotiation with the proxy server. -Please note that calling connect without calling `set_proxy` earlier will connect -without a proxy (just like a regular socket). - -Errors: Any errors in the connection process will trigger exceptions. The exception -may either be generated by the underlying socket layer or may be custom module -exceptions, whose details follow: - -class `ProxyError` - This is a base exception class. It is not raised directly but -rather all other exception classes raised by this module are derived from it. -This allows an easy way to catch all proxy-related errors. It descends from `IOError`. - -All `ProxyError` exceptions have an attribute `socket_err`, which will contain either a -caught `socket.error` exception, or `None` if there wasn't any. - -class `GeneralProxyError` - When thrown, it indicates a problem which does not fall -into another category. - -* `Sent invalid data` - This error means that unexpected data has been received from -the server. The most common reason is that the server specified as the proxy is -not really a SOCKS4/SOCKS5/HTTP proxy, or maybe the proxy type specified is wrong. - -* `Connection closed unexpectedly` - The proxy server unexpectedly closed the connection. -This may indicate that the proxy server is experiencing network or software problems. - -* `Bad proxy type` - This will be raised if the type of the proxy supplied to the -set_proxy function was not one of `SOCKS4`/`SOCKS5`/`HTTP`. - -* `Bad input` - This will be raised if the `connect()` method is called with bad input -parameters. - -class `SOCKS5AuthError` - This indicates that the connection through a SOCKS5 server -failed due to an authentication problem. - -* `Authentication is required` - This will happen if you use a SOCKS5 server which -requires authentication without providing a username / password at all. - -* `All offered authentication methods were rejected` - This will happen if the proxy -requires a special authentication method which is not supported by this module. - -* `Unknown username or invalid password` - Self descriptive. - -class `SOCKS5Error` - This will be raised for SOCKS5 errors which are not related to -authentication. -The parameter is a tuple containing a code, as given by the server, -and a description of the -error. The possible errors, according to the RFC, are: - -* `0x01` - General SOCKS server failure - If for any reason the proxy server is unable to -fulfill your request (internal server error). -* `0x02` - connection not allowed by ruleset - If the address you're trying to connect to -is blacklisted on the server or requires authentication. -* `0x03` - Network unreachable - The target could not be contacted. A router on the network -had replied with a destination net unreachable error. -* `0x04` - Host unreachable - The target could not be contacted. A router on the network -had replied with a destination host unreachable error. -* `0x05` - Connection refused - The target server has actively refused the connection -(the requested port is closed). -* `0x06` - TTL expired - The TTL value of the SYN packet from the proxy to the target server -has expired. This usually means that there are network problems causing the packet -to be caught in a router-to-router "ping-pong". -* `0x07` - Command not supported - For instance if the server does not support UDP. -* `0x08` - Address type not supported - The client has provided an invalid address type. -When using this module, this error should not occur. - -class `SOCKS4Error` - This will be raised for SOCKS4 errors. The parameter is a tuple -containing a code and a description of the error, as given by the server. The -possible error, according to the specification are: - -* `0x5B` - Request rejected or failed - Will be raised in the event of an failure for any -reason other then the two mentioned next. -* `0x5C` - request rejected because SOCKS server cannot connect to identd on the client - -The Socks server had tried an ident lookup on your computer and has failed. In this -case you should run an identd server and/or configure your firewall to allow incoming -connections to local port 113 from the remote server. -* `0x5D` - request rejected because the client program and identd report different user-ids - -The Socks server had performed an ident lookup on your computer and has received a -different userid than the one you have provided. Change your userid (through the -username parameter of the set_proxy method) to match and try again. - -class `HTTPError` - This will be raised for HTTP errors. The message will contain -the HTTP status code and provided error message. - -After establishing the connection, the object behaves like a standard socket. - -Methods like `makefile()` and `settimeout()` should behave just like regular sockets. -Call the `close()` method to close the connection. - -In addition to the `socksocket` class, an additional function worth mentioning is the -`set_default_proxy` function. The parameters are the same as the `set_proxy` method. -This function will set default proxy settings for newly created `socksocket` objects, -in which the proxy settings haven't been changed via the `set_proxy` method. -This is quite useful if you wish to force 3rd party modules to use a SOCKS proxy, -by overriding the socket object. -For example: - - >>> socks.set_default_proxy(socks.SOCKS5, "socks.example.com") - >>> socket.socket = socks.socksocket - >>> urllib.urlopen("http://www.sourceforge.net/") - - -PROBLEMS ---------- - -Please open a GitHub issue at https://github.com/Anorov/PySocks - - diff --git a/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/RECORD b/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/RECORD deleted file mode 100755 index 9b176216..00000000 --- a/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/RECORD +++ /dev/null @@ -1,9 +0,0 @@ -PySocks-1.7.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -PySocks-1.7.1.dist-info/LICENSE,sha256=cCfiFOAU63i3rcwc7aWspxOnn8T2oMUsnaWz5wfm_-k,1401 -PySocks-1.7.1.dist-info/METADATA,sha256=zbQMizjPOOP4DhEiEX24XXjNrYuIxF9UGUpN0uFDB6Y,13235 -PySocks-1.7.1.dist-info/RECORD,, -PySocks-1.7.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -PySocks-1.7.1.dist-info/WHEEL,sha256=t_MpApv386-8PVts2R6wsTifdIn0vbUDTVv61IbqFC8,92 -PySocks-1.7.1.dist-info/top_level.txt,sha256=TKSOIfCFBoK9EY8FBYbYqC3PWd3--G15ph9n8-QHPDk,19 -socks.py,sha256=xOYn27t9IGrbTBzWsUUuPa0YBuplgiUykzkOB5V5iFY,31086 -sockshandler.py,sha256=2SYGj-pwt1kjgLoZAmyeaEXCeZDWRmfVS_QG6kErGtY,3966 diff --git a/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/REQUESTED deleted file mode 100755 index e69de29b..00000000 diff --git a/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/WHEEL deleted file mode 100755 index 129a6735..00000000 --- a/apps/bitwarden_event_logs/lib/PySocks-1.7.1.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.33.3) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/apps/bitwarden_event_logs/lib/__pycache__/six.cpython-39.pyc b/apps/bitwarden_event_logs/lib/__pycache__/six.cpython-39.pyc deleted file mode 100755 index 5c0a6072..00000000 Binary files a/apps/bitwarden_event_logs/lib/__pycache__/six.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/__pycache__/socks.cpython-39.pyc b/apps/bitwarden_event_logs/lib/__pycache__/socks.cpython-39.pyc deleted file mode 100755 index a3e73f98..00000000 Binary files a/apps/bitwarden_event_logs/lib/__pycache__/socks.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/bin/normalizer b/apps/bitwarden_event_logs/lib/bin/normalizer deleted file mode 100755 index 87844099..00000000 --- a/apps/bitwarden_event_logs/lib/bin/normalizer +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/runner/.cache/pypoetry/virtualenvs/bitwarden-event-logs-tER4sFWd-py3.9/bin/python3 -import sys -from charset_normalizer.cli import cli_detect -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(cli_detect()) diff --git a/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/INSTALLER deleted file mode 100755 index a1b589e3..00000000 --- a/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/METADATA b/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/METADATA deleted file mode 100755 index 6939bac7..00000000 --- a/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/METADATA +++ /dev/null @@ -1,78 +0,0 @@ -Metadata-Version: 2.4 -Name: certifi -Version: 2025.11.12 -Summary: Python package for providing Mozilla's CA Bundle. -Home-page: https://github.com/certifi/python-certifi -Author: Kenneth Reitz -Author-email: me@kennethreitz.com -License: MPL-2.0 -Project-URL: Source, https://github.com/certifi/python-certifi -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) -Classifier: Natural Language :: English -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3.13 -Classifier: Programming Language :: Python :: 3.14 -Requires-Python: >=3.7 -License-File: LICENSE -Dynamic: author -Dynamic: author-email -Dynamic: classifier -Dynamic: description -Dynamic: home-page -Dynamic: license -Dynamic: license-file -Dynamic: project-url -Dynamic: requires-python -Dynamic: summary - -Certifi: Python SSL Certificates -================================ - -Certifi provides Mozilla's carefully curated collection of Root Certificates for -validating the trustworthiness of SSL certificates while verifying the identity -of TLS hosts. It has been extracted from the `Requests`_ project. - -Installation ------------- - -``certifi`` is available on PyPI. Simply install it with ``pip``:: - - $ pip install certifi - -Usage ------ - -To reference the installed certificate authority (CA) bundle, you can use the -built-in function:: - - >>> import certifi - - >>> certifi.where() - '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem' - -Or from the command line:: - - $ python -m certifi - /usr/local/lib/python3.7/site-packages/certifi/cacert.pem - -Enjoy! - -.. _`Requests`: https://requests.readthedocs.io/en/master/ - -Addition/Removal of Certificates --------------------------------- - -Certifi does not support any addition/removal or other modification of the -CA trust store content. This project is intended to provide a reliable and -highly portable root of trust to python deployments. Look to upstream projects -for methods to use alternate trust. diff --git a/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/RECORD b/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/RECORD deleted file mode 100755 index 6980ff43..00000000 --- a/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/RECORD +++ /dev/null @@ -1,12 +0,0 @@ -certifi-2025.11.12.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -certifi-2025.11.12.dist-info/METADATA,sha256=_JprGu_1lWSdHlruRBKcorXnrfvBDhvX_6KRr8HQbLc,2475 -certifi-2025.11.12.dist-info/RECORD,, -certifi-2025.11.12.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -certifi-2025.11.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91 -certifi-2025.11.12.dist-info/licenses/LICENSE,sha256=6TcW2mucDVpKHfYP5pWzcPBpVgPSH2-D8FPkLPwQyvc,989 -certifi-2025.11.12.dist-info/top_level.txt,sha256=KMu4vUCfsjLrkPbSNdgdekS-pVJzBAJFO__nI8NF6-U,8 -certifi/__init__.py,sha256=1BRSxNMnZW7CZ2oJtYWLoJgfHfcB9i273exwiPwfjJM,94 -certifi/__main__.py,sha256=xBBoj905TUWBLRGANOcf7oi6e-3dMP4cEoG9OyMs11g,243 -certifi/cacert.pem,sha256=oa1dZD4hxDtb7XTH4IkdzbWPavUcis4eTwINZUqlKhY,283932 -certifi/core.py,sha256=XFXycndG5pf37ayeF8N32HUuDafsyhkVMbO4BAPWHa0,3394 -certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/REQUESTED deleted file mode 100755 index e69de29b..00000000 diff --git a/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/WHEEL deleted file mode 100755 index e7fa31b6..00000000 --- a/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (80.9.0) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/licenses/LICENSE b/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/licenses/LICENSE deleted file mode 100755 index 62b076cd..00000000 --- a/apps/bitwarden_event_logs/lib/certifi-2025.11.12.dist-info/licenses/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -This package contains a modified version of ca-bundle.crt: - -ca-bundle.crt -- Bundle of CA Root Certificates - -This is a bundle of X.509 certificates of public Certificate Authorities -(CA). These were automatically extracted from Mozilla's root certificates -file (certdata.txt). This file can be found in the mozilla source tree: -https://hg.mozilla.org/mozilla-central/file/tip/security/nss/lib/ckfw/builtins/certdata.txt -It contains the certificates in PEM format and therefore -can be directly used with curl / libcurl / php_curl, or with -an Apache+mod_ssl webserver for SSL client authentication. -Just configure this file as the SSLCACertificateFile.# - -***** BEGIN LICENSE BLOCK ***** -This Source Code Form is subject to the terms of the Mozilla Public License, -v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain -one at http://mozilla.org/MPL/2.0/. - -***** END LICENSE BLOCK ***** -@(#) $RCSfile: certdata.txt,v $ $Revision: 1.80 $ $Date: 2011/11/03 15:11:58 $ diff --git a/apps/bitwarden_event_logs/lib/certifi/__init__.py b/apps/bitwarden_event_logs/lib/certifi/__init__.py deleted file mode 100755 index f11f5ae4..00000000 --- a/apps/bitwarden_event_logs/lib/certifi/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .core import contents, where - -__all__ = ["contents", "where"] -__version__ = "2025.11.12" diff --git a/apps/bitwarden_event_logs/lib/certifi/__main__.py b/apps/bitwarden_event_logs/lib/certifi/__main__.py deleted file mode 100755 index 8945b5da..00000000 --- a/apps/bitwarden_event_logs/lib/certifi/__main__.py +++ /dev/null @@ -1,12 +0,0 @@ -import argparse - -from certifi import contents, where - -parser = argparse.ArgumentParser() -parser.add_argument("-c", "--contents", action="store_true") -args = parser.parse_args() - -if args.contents: - print(contents()) -else: - print(where()) diff --git a/apps/bitwarden_event_logs/lib/certifi/__pycache__/__init__.cpython-39.pyc b/apps/bitwarden_event_logs/lib/certifi/__pycache__/__init__.cpython-39.pyc deleted file mode 100755 index 1dcf7dc7..00000000 Binary files a/apps/bitwarden_event_logs/lib/certifi/__pycache__/__init__.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/certifi/__pycache__/core.cpython-39.pyc b/apps/bitwarden_event_logs/lib/certifi/__pycache__/core.cpython-39.pyc deleted file mode 100755 index 118e908b..00000000 Binary files a/apps/bitwarden_event_logs/lib/certifi/__pycache__/core.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/certifi/cacert.pem b/apps/bitwarden_event_logs/lib/certifi/cacert.pem deleted file mode 100755 index ebcb66fe..00000000 --- a/apps/bitwarden_event_logs/lib/certifi/cacert.pem +++ /dev/null @@ -1,4678 +0,0 @@ - -# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. -# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. -# Label: "Entrust Root Certification Authority" -# Serial: 1164660820 -# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 -# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 -# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c ------BEGIN CERTIFICATE----- -MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 -Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW -KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw -NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw -NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy -ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV -BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo -Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 -4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 -KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI -rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi -94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB -sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi -gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo -kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE -vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t -O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua -AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP -9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ -eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m -0vdXcDazv/wor3ElhVsT/h5/WrQ8 ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited -# Label: "QuoVadis Root CA 2" -# Serial: 1289 -# MD5 Fingerprint: 5e:39:7b:dd:f8:ba:ec:82:e9:ac:62:ba:0c:54:00:2b -# SHA1 Fingerprint: ca:3a:fb:cf:12:40:36:4b:44:b2:16:20:88:80:48:39:19:93:7c:f7 -# SHA256 Fingerprint: 85:a0:dd:7d:d7:20:ad:b7:ff:05:f8:3d:54:2b:20:9d:c7:ff:45:28:f7:d6:77:b1:83:89:fe:a5:e5:c4:9e:86 ------BEGIN CERTIFICATE----- -MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x -GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv -b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV -BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W -YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa -GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg -Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J -WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB -rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp -+ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 -ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i -Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz -PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og -/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH -oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI -yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud -EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 -A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL -MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT -ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f -BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn -g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl -fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K -WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha -B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc -hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR -TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD -mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z -ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y -4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza -8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 3 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 3 O=QuoVadis Limited -# Label: "QuoVadis Root CA 3" -# Serial: 1478 -# MD5 Fingerprint: 31:85:3c:62:94:97:63:b9:aa:fd:89:4e:af:6f:e0:cf -# SHA1 Fingerprint: 1f:49:14:f7:d8:74:95:1d:dd:ae:02:c0:be:fd:3a:2d:82:75:51:85 -# SHA256 Fingerprint: 18:f1:fc:7f:20:5d:f8:ad:dd:eb:7f:e0:07:dd:57:e3:af:37:5a:9c:4d:8d:73:54:6b:f4:f1:fe:d1:e1:8d:35 ------BEGIN CERTIFICATE----- -MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x -GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv -b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV -BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W -YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM -V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB -4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr -H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd -8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv -vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT -mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe -btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc -T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt -WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ -c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A -4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD -VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG -CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 -aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 -aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu -dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw -czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G -A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg -Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 -7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem -d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd -+LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B -4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN -t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x -DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 -k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s -zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j -Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT -mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK -4SVhM7JZG+Ju1zdXtg2pEto= ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Assured ID Root CA" -# Serial: 17154717934120587862167794914071425081 -# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72 -# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43 -# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c ------BEGIN CERTIFICATE----- -MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c -JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP -mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ -wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 -VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ -AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB -AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun -pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC -dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf -fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm -NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx -H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Global Root CA" -# Serial: 10944719598952040374951832963794454346 -# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e -# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36 -# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61 ------BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE----- - -# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert High Assurance EV Root CA" -# Serial: 3553400076410547919724730734378100087 -# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a -# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25 -# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm -+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW -PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM -xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB -Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 -hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg -EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA -FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec -nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z -eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF -hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 -Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep -+OkuE6N36B9K ------END CERTIFICATE----- - -# Issuer: CN=SwissSign Gold CA - G2 O=SwissSign AG -# Subject: CN=SwissSign Gold CA - G2 O=SwissSign AG -# Label: "SwissSign Gold CA - G2" -# Serial: 13492815561806991280 -# MD5 Fingerprint: 24:77:d9:a8:91:d1:3b:fa:88:2d:c2:ff:f8:cd:33:93 -# SHA1 Fingerprint: d8:c5:38:8a:b7:30:1b:1b:6e:d4:7a:e6:45:25:3a:6f:9f:1a:27:61 -# SHA256 Fingerprint: 62:dd:0b:e9:b9:f5:0a:16:3e:a0:f8:e7:5c:05:3b:1e:ca:57:ea:55:c8:68:8f:64:7c:68:81:f2:c8:35:7b:95 ------BEGIN CERTIFICATE----- -MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV -BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln -biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF -MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT -d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 -76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ -bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c -6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE -emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd -MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt -MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y -MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y -FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi -aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM -gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB -qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 -lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn -8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov -L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 -45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO -UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 -O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC -bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv -GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a -77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC -hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 -92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp -Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w -ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt -Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ ------END CERTIFICATE----- - -# Issuer: CN=SecureTrust CA O=SecureTrust Corporation -# Subject: CN=SecureTrust CA O=SecureTrust Corporation -# Label: "SecureTrust CA" -# Serial: 17199774589125277788362757014266862032 -# MD5 Fingerprint: dc:32:c3:a7:6d:25:57:c7:68:09:9d:ea:2d:a9:a2:d1 -# SHA1 Fingerprint: 87:82:c6:c3:04:35:3b:cf:d2:96:92:d2:59:3e:7d:44:d9:34:ff:11 -# SHA256 Fingerprint: f1:c1:b5:0a:e5:a2:0d:d8:03:0e:c9:f6:bc:24:82:3d:d3:67:b5:25:57:59:b4:e7:1b:61:fc:e9:f7:37:5d:73 ------BEGIN CERTIFICATE----- -MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz -MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv -cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz -Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO -0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao -wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj -7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS -8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT -BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg -JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC -NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 -6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ -3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm -D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS -CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR -3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= ------END CERTIFICATE----- - -# Issuer: CN=Secure Global CA O=SecureTrust Corporation -# Subject: CN=Secure Global CA O=SecureTrust Corporation -# Label: "Secure Global CA" -# Serial: 9751836167731051554232119481456978597 -# MD5 Fingerprint: cf:f4:27:0d:d4:ed:dc:65:16:49:6d:3d:da:bf:6e:de -# SHA1 Fingerprint: 3a:44:73:5a:e5:81:90:1f:24:86:61:46:1e:3b:9c:c4:5f:f5:3a:1b -# SHA256 Fingerprint: 42:00:f5:04:3a:c8:59:0e:bb:52:7d:20:9e:d1:50:30:29:fb:cb:d4:1c:a1:b5:06:ec:27:f1:5a:de:7d:ac:69 ------BEGIN CERTIFICATE----- -MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx -MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg -Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ -iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa -/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ -jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI -HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 -sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w -gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw -KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG -AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L -URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO -H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm -I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY -iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc -f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW ------END CERTIFICATE----- - -# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO Certification Authority O=COMODO CA Limited -# Label: "COMODO Certification Authority" -# Serial: 104350513648249232941998508985834464573 -# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75 -# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b -# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66 ------BEGIN CERTIFICATE----- -MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB -gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV -BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw -MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl -YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P -RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 -UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI -2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 -Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp -+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ -DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O -nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW -/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g -PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u -QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY -SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv -IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ -RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 -zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd -BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB -ZQ== ------END CERTIFICATE----- - -# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited -# Label: "COMODO ECC Certification Authority" -# Serial: 41578283867086692638256921589707938090 -# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23 -# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11 -# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7 ------BEGIN CERTIFICATE----- -MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT -IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw -MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy -ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N -T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR -FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J -cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW -BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm -fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv -GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= ------END CERTIFICATE----- - -# Issuer: CN=Certigna O=Dhimyotis -# Subject: CN=Certigna O=Dhimyotis -# Label: "Certigna" -# Serial: 18364802974209362175 -# MD5 Fingerprint: ab:57:a6:5b:7d:42:82:19:b5:d8:58:26:28:5e:fd:ff -# SHA1 Fingerprint: b1:2e:13:63:45:86:a4:6f:1a:b2:60:68:37:58:2d:c4:ac:fd:94:97 -# SHA256 Fingerprint: e3:b6:a2:db:2e:d7:ce:48:84:2f:7a:c5:32:41:c7:b7:1d:54:14:4b:fb:40:c1:1f:3f:1d:0b:42:f5:ee:a1:2d ------BEGIN CERTIFICATE----- -MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV -BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X -DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ -BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 -QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny -gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw -zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q -130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 -JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw -ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT -AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj -AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG -9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h -bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc -fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu -HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w -t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw -WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== ------END CERTIFICATE----- - -# Issuer: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority -# Subject: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority -# Label: "ePKI Root Certification Authority" -# Serial: 28956088682735189655030529057352760477 -# MD5 Fingerprint: 1b:2e:00:ca:26:06:90:3d:ad:fe:6f:15:68:d3:6b:b3 -# SHA1 Fingerprint: 67:65:0d:f1:7e:8e:7e:5b:82:40:a4:f4:56:4b:cf:e2:3d:69:c6:f0 -# SHA256 Fingerprint: c0:a6:f4:dc:63:a2:4b:fd:cf:54:ef:2a:6a:08:2a:0a:72:de:35:80:3e:2f:f5:ff:52:7a:e5:d8:72:06:df:d5 ------BEGIN CERTIFICATE----- -MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe -MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 -ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw -IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL -SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH -SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh -ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X -DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 -TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ -fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA -sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU -WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS -nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH -dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip -NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC -AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF -MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH -ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB -uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl -PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP -JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ -gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 -j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 -5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB -o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS -/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z -Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE -W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D -hNQ+IIX3Sj0rnP0qCglN6oH4EZw= ------END CERTIFICATE----- - -# Issuer: O=certSIGN OU=certSIGN ROOT CA -# Subject: O=certSIGN OU=certSIGN ROOT CA -# Label: "certSIGN ROOT CA" -# Serial: 35210227249154 -# MD5 Fingerprint: 18:98:c0:d6:e9:3a:fc:f9:b0:f5:0c:f7:4b:01:44:17 -# SHA1 Fingerprint: fa:b7:ee:36:97:26:62:fb:2d:b0:2a:f6:bf:03:fd:e8:7c:4b:2f:9b -# SHA256 Fingerprint: ea:a9:62:c4:fa:4a:6b:af:eb:e4:15:19:6d:35:1c:cd:88:8d:4f:53:f3:fa:8a:e6:d7:c4:66:a9:4e:60:42:bb ------BEGIN CERTIFICATE----- -MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT -AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD -QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP -MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do -0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ -UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d -RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ -OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv -JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C -AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O -BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ -LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY -MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ -44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I -Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw -i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN -9u6wWk5JRFRYX0KD ------END CERTIFICATE----- - -# Issuer: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) -# Subject: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) -# Label: "NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny" -# Serial: 80544274841616 -# MD5 Fingerprint: c5:a1:b7:ff:73:dd:d6:d7:34:32:18:df:fc:3c:ad:88 -# SHA1 Fingerprint: 06:08:3f:59:3f:15:a1:04:a0:69:a4:6b:a9:03:d0:06:b7:97:09:91 -# SHA256 Fingerprint: 6c:61:da:c3:a2:de:f0:31:50:6b:e0:36:d2:a6:fe:40:19:94:fb:d1:3d:f9:c8:d4:66:59:92:74:c4:46:ec:98 ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG -EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 -MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl -cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR -dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB -pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM -b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm -aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz -IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT -lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz -AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 -VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG -ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 -BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG -AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M -U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh -bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C -+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC -bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F -uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 -XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= ------END CERTIFICATE----- - -# Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. -# Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. -# Label: "Microsec e-Szigno Root CA 2009" -# Serial: 14014712776195784473 -# MD5 Fingerprint: f8:49:f4:03:bc:44:2d:83:be:48:69:7d:29:64:fc:b1 -# SHA1 Fingerprint: 89:df:74:fe:5c:f4:0f:4a:80:f9:e3:37:7d:54:da:91:e1:01:31:8e -# SHA256 Fingerprint: 3c:5f:81:fe:a5:fa:b8:2c:64:bf:a2:ea:ec:af:cd:e8:e0:77:fc:86:20:a7:ca:e5:37:16:3d:f3:6e:db:f3:78 ------BEGIN CERTIFICATE----- -MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD -VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 -ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G -CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y -OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx -FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp -Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o -dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP -kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc -cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U -fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 -N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC -xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 -+rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G -A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM -Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG -SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h -mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk -ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 -tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c -2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t -HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 -# Label: "GlobalSign Root CA - R3" -# Serial: 4835703278459759426209954 -# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28 -# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad -# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b ------BEGIN CERTIFICATE----- -MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 -MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 -RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT -gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm -KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd -QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ -XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o -LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU -RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp -jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK -6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX -mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs -Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH -WD9f ------END CERTIFICATE----- - -# Issuer: CN=Izenpe.com O=IZENPE S.A. -# Subject: CN=Izenpe.com O=IZENPE S.A. -# Label: "Izenpe.com" -# Serial: 917563065490389241595536686991402621 -# MD5 Fingerprint: a6:b0:cd:85:80:da:5c:50:34:a3:39:90:2f:55:67:73 -# SHA1 Fingerprint: 2f:78:3d:25:52:18:a7:4a:65:39:71:b5:2c:a2:9c:45:15:6f:e9:19 -# SHA256 Fingerprint: 25:30:cc:8e:98:32:15:02:ba:d9:6f:9b:1f:ba:1b:09:9e:2d:29:9e:0f:45:48:bb:91:4f:36:3b:c0:d4:53:1f ------BEGIN CERTIFICATE----- -MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 -MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 -ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD -VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j -b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq -scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO -xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H -LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX -uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD -yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ -JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q -rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN -BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L -hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB -QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ -HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu -Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg -QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB -BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx -MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA -A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb -laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 -awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo -JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw -LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT -VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk -LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb -UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ -QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ -naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls -QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== ------END CERTIFICATE----- - -# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. -# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. -# Label: "Go Daddy Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01 -# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b -# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT -EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp -ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz -NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH -EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE -AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD -E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH -/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy -DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh -GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR -tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA -AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX -WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu -9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr -gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo -2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO -LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI -4uJEvlz36hz1 ------END CERTIFICATE----- - -# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Label: "Starfield Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96 -# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e -# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5 ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs -ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw -MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 -b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj -aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp -Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg -nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 -HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N -Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN -dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 -HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G -CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU -sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 -4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg -8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K -pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 -mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 ------END CERTIFICATE----- - -# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Label: "Starfield Services Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2 -# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f -# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5 ------BEGIN CERTIFICATE----- -MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs -ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 -MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD -VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy -ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy -dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p -OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 -8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K -Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe -hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk -6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw -DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q -AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI -bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB -ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z -qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd -iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn -0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN -sSi6 ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Commercial O=AffirmTrust -# Subject: CN=AffirmTrust Commercial O=AffirmTrust -# Label: "AffirmTrust Commercial" -# Serial: 8608355977964138876 -# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7 -# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7 -# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7 ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP -Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr -ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL -MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 -yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr -VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ -nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG -XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj -vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt -Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g -N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC -nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Networking O=AffirmTrust -# Subject: CN=AffirmTrust Networking O=AffirmTrust -# Label: "AffirmTrust Networking" -# Serial: 8957382827206547757 -# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f -# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f -# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y -YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua -kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL -QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp -6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG -yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i -QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO -tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu -QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ -Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u -olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 -x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Premium O=AffirmTrust -# Subject: CN=AffirmTrust Premium O=AffirmTrust -# Label: "AffirmTrust Premium" -# Serial: 7893706540734352110 -# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57 -# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27 -# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz -dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG -A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U -cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf -qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ -JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ -+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS -s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 -HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 -70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG -V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S -qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S -5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia -C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX -OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE -FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 -KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B -8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ -MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc -0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ -u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF -u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH -YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 -GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO -RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e -KeC2uAloGRwYQw== ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust -# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust -# Label: "AffirmTrust Premium ECC" -# Serial: 8401224907861490260 -# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d -# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb -# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23 ------BEGIN CERTIFICATE----- -MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC -VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ -cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ -BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt -VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D -0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 -ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G -A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs -aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I -flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== ------END CERTIFICATE----- - -# Issuer: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority -# Subject: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority -# Label: "Certum Trusted Network CA" -# Serial: 279744 -# MD5 Fingerprint: d5:e9:81:40:c5:18:69:fc:46:2c:89:75:62:0f:aa:78 -# SHA1 Fingerprint: 07:e0:32:e0:20:b7:2c:3f:19:2f:06:28:a2:59:3a:19:a7:0f:06:9e -# SHA256 Fingerprint: 5c:58:46:8d:55:f5:8e:49:7e:74:39:82:d2:b5:00:10:b6:d1:65:37:4a:cf:83:a7:d4:a3:2d:b7:68:c4:40:8e ------BEGIN CERTIFICATE----- -MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM -MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D -ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU -cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 -WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg -Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw -IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH -UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM -TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU -BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM -kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x -AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV -HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y -sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL -I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 -J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY -VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI -03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= ------END CERTIFICATE----- - -# Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA -# Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA -# Label: "TWCA Root Certification Authority" -# Serial: 1 -# MD5 Fingerprint: aa:08:8f:f6:f9:7b:b7:f2:b1:a7:1e:9b:ea:ea:bd:79 -# SHA1 Fingerprint: cf:9e:87:6d:d3:eb:fc:42:26:97:a3:b5:a3:7a:a0:76:a9:06:23:48 -# SHA256 Fingerprint: bf:d8:8f:e1:10:1c:41:ae:3e:80:1b:f8:be:56:35:0e:e9:ba:d1:a6:b9:bd:51:5e:dc:5c:6d:5b:87:11:ac:44 ------BEGIN CERTIFICATE----- -MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES -MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU -V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz -WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO -LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE -AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH -K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX -RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z -rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx -3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq -hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC -MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls -XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D -lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn -aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ -YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== ------END CERTIFICATE----- - -# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 -# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 -# Label: "Security Communication RootCA2" -# Serial: 0 -# MD5 Fingerprint: 6c:39:7d:a4:0e:55:59:b2:3f:d6:41:b1:12:50:de:43 -# SHA1 Fingerprint: 5f:3b:8c:f2:f8:10:b3:7d:78:b4:ce:ec:19:19:c3:73:34:b9:c7:74 -# SHA256 Fingerprint: 51:3b:2c:ec:b8:10:d4:cd:e5:dd:85:39:1a:df:c6:c2:dd:60:d8:7b:b7:36:d2:b5:21:48:4a:a4:7a:0e:be:f6 ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl -MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe -U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX -DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy -dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj -YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV -OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr -zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM -VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ -hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO -ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw -awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs -OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 -DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF -coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc -okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 -t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy -1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ -SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 ------END CERTIFICATE----- - -# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 -# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 -# Label: "Actalis Authentication Root CA" -# Serial: 6271844772424770508 -# MD5 Fingerprint: 69:c1:0d:4f:07:a3:1b:c3:fe:56:3d:04:bc:11:f6:a6 -# SHA1 Fingerprint: f3:73:b3:87:06:5a:28:84:8a:f2:f3:4a:ce:19:2b:dd:c7:8e:9c:ac -# SHA256 Fingerprint: 55:92:60:84:ec:96:3a:64:b9:6e:2a:be:01:ce:0b:a8:6a:64:fb:fe:bc:c7:aa:b5:af:c1:55:b3:7f:d7:60:66 ------BEGIN CERTIFICATE----- -MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE -BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w -MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 -IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC -SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 -ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv -UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX -4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 -KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ -gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb -rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ -51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F -be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe -KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F -v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn -fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 -jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz -ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt -ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL -e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 -jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz -WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V -SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j -pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX -X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok -fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R -K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU -ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU -LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT -LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== ------END CERTIFICATE----- - -# Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 -# Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 -# Label: "Buypass Class 2 Root CA" -# Serial: 2 -# MD5 Fingerprint: 46:a7:d2:fe:45:fb:64:5a:a8:59:90:9b:78:44:9b:29 -# SHA1 Fingerprint: 49:0a:75:74:de:87:0a:47:fe:58:ee:f6:c7:6b:eb:c6:0b:12:40:99 -# SHA256 Fingerprint: 9a:11:40:25:19:7c:5b:b9:5d:94:e6:3d:55:cd:43:79:08:47:b6:46:b2:3c:df:11:ad:a4:a0:0e:ff:15:fb:48 ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd -MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg -Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow -TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw -HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB -BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr -6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV -L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 -1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx -MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ -QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB -arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr -Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi -FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS -P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN -9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP -AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz -uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h -9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s -A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t -OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo -+fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 -KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 -DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us -H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ -I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 -5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h -3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz -Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= ------END CERTIFICATE----- - -# Issuer: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 -# Subject: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 -# Label: "Buypass Class 3 Root CA" -# Serial: 2 -# MD5 Fingerprint: 3d:3b:18:9e:2c:64:5a:e8:d5:88:ce:0e:f9:37:c2:ec -# SHA1 Fingerprint: da:fa:f7:fa:66:84:ec:06:8f:14:50:bd:c7:c2:81:a5:bc:a9:64:57 -# SHA256 Fingerprint: ed:f7:eb:bc:a2:7a:2a:38:4d:38:7b:7d:40:10:c6:66:e2:ed:b4:84:3e:4c:29:b4:ae:1d:5b:93:32:e6:b2:4d ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd -MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg -Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow -TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw -HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB -BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y -ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E -N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 -tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX -0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c -/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X -KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY -zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS -O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D -34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP -K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 -AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv -Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj -QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV -cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS -IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 -HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa -O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv -033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u -dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE -kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 -3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD -u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq -4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= ------END CERTIFICATE----- - -# Issuer: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center -# Subject: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center -# Label: "T-TeleSec GlobalRoot Class 3" -# Serial: 1 -# MD5 Fingerprint: ca:fb:40:a8:4e:39:92:8a:1d:fe:8e:2f:c4:27:ea:ef -# SHA1 Fingerprint: 55:a6:72:3e:cb:f2:ec:cd:c3:23:74:70:19:9d:2a:be:11:e3:81:d1 -# SHA256 Fingerprint: fd:73:da:d3:1c:64:4f:f1:b4:3b:ef:0c:cd:da:96:71:0b:9c:d9:87:5e:ca:7e:31:70:7a:f3:e9:6d:52:2b:bd ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx -KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd -BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl -YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 -OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy -aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 -ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN -8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ -RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 -hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 -ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM -EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj -QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 -A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy -WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ -1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 -6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT -91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml -e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p -TpPDpFQUWw== ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH -# Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH -# Label: "D-TRUST Root Class 3 CA 2 2009" -# Serial: 623603 -# MD5 Fingerprint: cd:e0:25:69:8d:47:ac:9c:89:35:90:f7:fd:51:3d:2f -# SHA1 Fingerprint: 58:e8:ab:b0:36:15:33:fb:80:f7:9b:1b:6d:29:d3:ff:8d:5f:00:f0 -# SHA256 Fingerprint: 49:e7:a4:42:ac:f0:ea:62:87:05:00:54:b5:25:64:b6:50:e4:f4:9e:42:e3:48:d6:aa:38:e0:39:e9:57:b1:c1 ------BEGIN CERTIFICATE----- -MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF -MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD -bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha -ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM -HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 -UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 -tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R -ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM -lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp -/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G -A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G -A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj -dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy -MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl -cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js -L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL -BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni -acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 -o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K -zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 -PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y -Johw1+qRzT65ysCQblrGXnRl11z+o+I= ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH -# Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH -# Label: "D-TRUST Root Class 3 CA 2 EV 2009" -# Serial: 623604 -# MD5 Fingerprint: aa:c6:43:2c:5e:2d:cd:c4:34:c0:50:4f:11:02:4f:b6 -# SHA1 Fingerprint: 96:c9:1b:0b:95:b4:10:98:42:fa:d0:d8:22:79:fe:60:fa:b9:16:83 -# SHA256 Fingerprint: ee:c5:49:6b:98:8c:e9:86:25:b9:34:09:2e:ec:29:08:be:d0:b0:f3:16:c2:d4:73:0c:84:ea:f1:f3:d3:48:81 ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF -MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD -bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw -NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV -BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn -ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 -3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z -qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR -p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 -HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw -ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea -HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw -Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh -c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E -RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt -dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku -Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp -3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 -nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF -CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na -xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX -KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 ------END CERTIFICATE----- - -# Issuer: CN=CA Disig Root R2 O=Disig a.s. -# Subject: CN=CA Disig Root R2 O=Disig a.s. -# Label: "CA Disig Root R2" -# Serial: 10572350602393338211 -# MD5 Fingerprint: 26:01:fb:d8:27:a7:17:9a:45:54:38:1a:43:01:3b:03 -# SHA1 Fingerprint: b5:61:eb:ea:a4:de:e4:25:4b:69:1a:98:a5:57:47:c2:34:c7:d9:71 -# SHA256 Fingerprint: e2:3d:4a:03:6d:7b:70:e9:f5:95:b1:42:20:79:d2:b9:1e:df:bb:1f:b6:51:a0:63:3e:aa:8a:9d:c5:f8:07:03 ------BEGIN CERTIFICATE----- -MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV -BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu -MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy -MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx -EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw -ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe -NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH -PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I -x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe -QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR -yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO -QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 -H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ -QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD -i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs -nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 -rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud -DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI -hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM -tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf -GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb -lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka -+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal -TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i -nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 -gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr -G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os -zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x -L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL ------END CERTIFICATE----- - -# Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV -# Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV -# Label: "ACCVRAIZ1" -# Serial: 6828503384748696800 -# MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02 -# SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17 -# SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13 ------BEGIN CERTIFICATE----- -MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE -AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw -CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ -BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND -VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb -qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY -HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo -G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA -lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr -IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ -0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH -k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 -4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO -m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa -cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl -uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI -KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls -ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG -AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 -VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT -VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG -CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA -cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA -QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA -7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA -cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA -QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA -czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu -aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt -aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud -DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF -BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp -D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU -JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m -AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD -vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms -tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH -7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h -I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA -h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF -d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H -pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 ------END CERTIFICATE----- - -# Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA -# Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA -# Label: "TWCA Global Root CA" -# Serial: 3262 -# MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96 -# SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65 -# SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx -EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT -VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 -NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT -B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF -10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz -0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh -MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH -zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc -46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 -yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi -laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP -oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA -BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE -qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm -4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL -1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn -LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF -H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo -RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ -nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh -15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW -6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW -nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j -wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz -aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy -KwbQBM0= ------END CERTIFICATE----- - -# Issuer: CN=TeliaSonera Root CA v1 O=TeliaSonera -# Subject: CN=TeliaSonera Root CA v1 O=TeliaSonera -# Label: "TeliaSonera Root CA v1" -# Serial: 199041966741090107964904287217786801558 -# MD5 Fingerprint: 37:41:49:1b:18:56:9a:26:f5:ad:c2:66:fb:40:a5:4c -# SHA1 Fingerprint: 43:13:bb:96:f1:d5:86:9b:c1:4e:6a:92:f6:cf:f6:34:69:87:82:37 -# SHA256 Fingerprint: dd:69:36:fe:21:f8:f0:77:c1:23:a1:a5:21:c1:22:24:f7:22:55:b7:3e:03:a7:26:06:93:e8:a2:4b:0f:a3:89 ------BEGIN CERTIFICATE----- -MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw -NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv -b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD -VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F -VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 -7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X -Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ -/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs -81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm -dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe -Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu -sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 -pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs -slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ -arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD -VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG -9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl -dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx -0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj -TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed -Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 -Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI -OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 -vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW -t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn -HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx -SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= ------END CERTIFICATE----- - -# Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center -# Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center -# Label: "T-TeleSec GlobalRoot Class 2" -# Serial: 1 -# MD5 Fingerprint: 2b:9b:9e:e4:7b:6c:1f:00:72:1a:cc:c1:77:79:df:6a -# SHA1 Fingerprint: 59:0d:2d:7d:88:4f:40:2e:61:7e:a5:62:32:17:65:cf:17:d8:94:e9 -# SHA256 Fingerprint: 91:e2:f5:78:8d:58:10:eb:a7:ba:58:73:7d:e1:54:8a:8e:ca:cd:01:45:98:bc:0b:14:3e:04:1b:17:05:25:52 ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx -KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd -BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl -YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 -OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy -aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 -ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd -AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC -FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi -1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq -jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ -wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj -QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ -WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy -NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC -uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw -IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 -g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN -9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP -BSeOE6Fuwg== ------END CERTIFICATE----- - -# Issuer: CN=Atos TrustedRoot 2011 O=Atos -# Subject: CN=Atos TrustedRoot 2011 O=Atos -# Label: "Atos TrustedRoot 2011" -# Serial: 6643877497813316402 -# MD5 Fingerprint: ae:b9:c4:32:4b:ac:7f:5d:66:cc:77:94:bb:2a:77:56 -# SHA1 Fingerprint: 2b:b1:f5:3e:55:0c:1d:c5:f1:d4:e6:b7:6a:46:4b:55:06:02:ac:21 -# SHA256 Fingerprint: f3:56:be:a2:44:b7:a9:1e:b3:5d:53:ca:9a:d7:86:4a:ce:01:8e:2d:35:d5:f8:f9:6d:df:68:a6:f4:1a:a4:74 ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE -AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG -EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM -FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC -REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp -Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM -VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ -SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ -4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L -cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi -eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV -HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG -A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 -DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j -vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP -DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc -maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D -lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv -KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited -# Label: "QuoVadis Root CA 1 G3" -# Serial: 687049649626669250736271037606554624078720034195 -# MD5 Fingerprint: a4:bc:5b:3f:fe:37:9a:fa:64:f0:e2:fa:05:3d:0b:ab -# SHA1 Fingerprint: 1b:8e:ea:57:96:29:1a:c9:39:ea:b8:0a:81:1a:73:73:c0:93:79:67 -# SHA256 Fingerprint: 8a:86:6f:d1:b2:76:b5:7e:57:8e:92:1c:65:82:8a:2b:ed:58:e9:f2:f2:88:05:41:34:b7:f1:f4:bf:c9:cc:74 ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL -BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 -MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV -wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe -rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 -68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh -4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp -UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o -abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc -3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G -KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt -hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO -Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt -zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD -ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC -MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 -cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN -qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 -YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv -b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 -8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k -NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj -ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp -q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt -nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited -# Label: "QuoVadis Root CA 2 G3" -# Serial: 390156079458959257446133169266079962026824725800 -# MD5 Fingerprint: af:0c:86:6e:bf:40:2d:7f:0b:3e:12:50:ba:12:3d:06 -# SHA1 Fingerprint: 09:3c:61:f3:8b:8b:dc:7d:55:df:75:38:02:05:00:e1:25:f5:c8:36 -# SHA256 Fingerprint: 8f:e4:fb:0a:f9:3a:4d:0d:67:db:0b:eb:b2:3e:37:c7:1b:f3:25:dc:bc:dd:24:0e:a0:4d:af:58:b4:7e:18:40 ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL -BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 -MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf -qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW -n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym -c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ -O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 -o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j -IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq -IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz -8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh -vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l -7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG -cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD -ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 -AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC -roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga -W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n -lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE -+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV -csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd -dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg -KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM -HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 -WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited -# Label: "QuoVadis Root CA 3 G3" -# Serial: 268090761170461462463995952157327242137089239581 -# MD5 Fingerprint: df:7d:b9:ad:54:6f:68:a1:df:89:57:03:97:43:b0:d7 -# SHA1 Fingerprint: 48:12:bd:92:3c:a8:c4:39:06:e7:30:6d:27:96:e6:a4:cf:22:2e:7d -# SHA256 Fingerprint: 88:ef:81:de:20:2e:b0:18:45:2e:43:f8:64:72:5c:ea:5f:bd:1f:c2:d9:d2:05:73:07:09:c5:d8:b8:69:0f:46 ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL -BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 -MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR -/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu -FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR -U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c -ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR -FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k -A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw -eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl -sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp -VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q -A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ -ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD -ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px -KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI -FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv -oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg -u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP -0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf -3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl -8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ -DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN -PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ -ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Assured ID Root G2" -# Serial: 15385348160840213938643033620894905419 -# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d -# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f -# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85 ------BEGIN CERTIFICATE----- -MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA -n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc -biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp -EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA -bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu -YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB -AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW -BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI -QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I -0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni -lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 -B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv -ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo -IhNzbM8m9Yop5w== ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Assured ID Root G3" -# Serial: 15459312981008553731928384953135426796 -# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb -# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89 -# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2 ------BEGIN CERTIFICATE----- -MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw -CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu -ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg -RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV -UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu -Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq -hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf -Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q -RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD -AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY -JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv -6pZjamVFkpUBtA== ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Global Root G2" -# Serial: 4293743540046975378534879503202253541 -# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44 -# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4 -# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f ------BEGIN CERTIFICATE----- -MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH -MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI -2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx -1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ -q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz -tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ -vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP -BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV -5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY -1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 -NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG -Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 -8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe -pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl -MrY= ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Global Root G3" -# Serial: 7089244469030293291760083333884364146 -# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca -# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e -# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0 ------BEGIN CERTIFICATE----- -MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw -CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu -ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe -Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw -EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x -IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF -K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG -fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO -Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd -BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx -AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ -oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 -sycX ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Trusted Root G4" -# Serial: 7451500558977370777930084869016614236 -# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49 -# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4 -# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88 ------BEGIN CERTIFICATE----- -MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg -RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV -UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu -Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y -ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If -xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV -ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO -DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ -jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ -CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi -EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM -fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY -uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK -chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t -9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD -ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 -SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd -+SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc -fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa -sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N -cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N -0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie -4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI -r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 -/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm -gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ ------END CERTIFICATE----- - -# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited -# Label: "COMODO RSA Certification Authority" -# Serial: 101909084537582093308941363524873193117 -# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18 -# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4 -# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34 ------BEGIN CERTIFICATE----- -MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB -hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV -BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 -MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT -EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR -Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR -6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X -pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC -9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV -/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf -Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z -+pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w -qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah -SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC -u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf -Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq -crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E -FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB -/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl -wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM -4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV -2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna -FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ -CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK -boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke -jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL -S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb -QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl -0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB -NVOFBkpdn627G190 ------END CERTIFICATE----- - -# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network -# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network -# Label: "USERTrust RSA Certification Authority" -# Serial: 2645093764781058787591871645665788717 -# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5 -# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e -# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2 ------BEGIN CERTIFICATE----- -MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB -iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl -cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV -BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw -MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV -BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU -aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy -dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B -3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY -tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ -Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 -VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT -79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 -c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT -Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l -c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee -UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE -Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd -BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G -A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF -Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO -VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 -ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs -8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR -iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze -Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ -XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ -qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB -VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB -L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG -jjxDah2nGN59PRbxYvnKkKj9 ------END CERTIFICATE----- - -# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network -# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network -# Label: "USERTrust ECC Certification Authority" -# Serial: 123013823720199481456569720443997572134 -# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1 -# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0 -# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a ------BEGIN CERTIFICATE----- -MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL -MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl -eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT -JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx -MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT -Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg -VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo -I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng -o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G -A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB -zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW -RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 -# Label: "GlobalSign ECC Root CA - R5" -# Serial: 32785792099990507226680698011560947931244 -# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08 -# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa -# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24 ------BEGIN CERTIFICATE----- -MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk -MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH -bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX -DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD -QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu -MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc -8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke -hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI -KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg -515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO -xwy8p2Fp8fc74SrL+SvzZpA3 ------END CERTIFICATE----- - -# Issuer: CN=IdenTrust Commercial Root CA 1 O=IdenTrust -# Subject: CN=IdenTrust Commercial Root CA 1 O=IdenTrust -# Label: "IdenTrust Commercial Root CA 1" -# Serial: 13298821034946342390520003877796839426 -# MD5 Fingerprint: b3:3e:77:73:75:ee:a0:d3:e3:7e:49:63:49:59:bb:c7 -# SHA1 Fingerprint: df:71:7e:aa:4a:d9:4e:c9:55:84:99:60:2d:48:de:5f:bc:f0:3a:25 -# SHA256 Fingerprint: 5d:56:49:9b:e4:d2:e0:8b:cf:ca:d0:8a:3e:38:72:3d:50:50:3b:de:70:69:48:e4:2f:55:60:30:19:e5:28:ae ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK -MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu -VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw -MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw -JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT -3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU -+ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp -S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 -bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi -T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL -vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK -Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK -dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT -c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv -l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N -iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD -ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH -6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt -LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 -nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 -+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK -W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT -AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq -l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG -4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ -mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A -7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H ------END CERTIFICATE----- - -# Issuer: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust -# Subject: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust -# Label: "IdenTrust Public Sector Root CA 1" -# Serial: 13298821034946342390521976156843933698 -# MD5 Fingerprint: 37:06:a5:b0:fc:89:9d:ba:f4:6b:8c:1a:64:cd:d5:ba -# SHA1 Fingerprint: ba:29:41:60:77:98:3f:f4:f3:ef:f2:31:05:3b:2e:ea:6d:4d:45:fd -# SHA256 Fingerprint: 30:d0:89:5a:9a:44:8a:26:20:91:63:55:22:d1:f5:20:10:b5:86:7a:ca:e1:2c:78:ef:95:8f:d4:f4:38:9f:2f ------BEGIN CERTIFICATE----- -MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN -MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu -VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN -MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 -MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 -ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy -RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS -bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF -/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R -3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw -EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy -9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V -GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ -2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV -WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD -W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN -AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj -t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV -DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 -TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G -lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW -mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df -WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 -+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ -tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA -GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv -8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c ------END CERTIFICATE----- - -# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only -# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only -# Label: "Entrust Root Certification Authority - G2" -# Serial: 1246989352 -# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2 -# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4 -# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39 ------BEGIN CERTIFICATE----- -MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 -cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs -IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz -dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy -NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu -dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt -dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 -aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T -RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN -cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW -wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 -U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 -jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP -BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN -BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ -jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ -Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v -1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R -nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH -VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== ------END CERTIFICATE----- - -# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only -# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only -# Label: "Entrust Root Certification Authority - EC1" -# Serial: 51543124481930649114116133369 -# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc -# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47 -# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5 ------BEGIN CERTIFICATE----- -MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG -A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 -d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu -dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq -RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy -MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD -VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 -L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g -Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi -A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt -ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH -Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O -BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC -R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX -hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G ------END CERTIFICATE----- - -# Issuer: CN=CFCA EV ROOT O=China Financial Certification Authority -# Subject: CN=CFCA EV ROOT O=China Financial Certification Authority -# Label: "CFCA EV ROOT" -# Serial: 407555286 -# MD5 Fingerprint: 74:e1:b6:ed:26:7a:7a:44:30:33:94:ab:7b:27:81:30 -# SHA1 Fingerprint: e2:b8:29:4b:55:84:ab:6b:58:c2:90:46:6c:ac:3f:b8:39:8f:84:83 -# SHA256 Fingerprint: 5c:c3:d7:8e:4e:1d:5e:45:54:7a:04:e6:87:3e:64:f9:0c:f9:53:6d:1c:cc:2e:f8:00:f3:55:c4:c5:fd:70:fd ------BEGIN CERTIFICATE----- -MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD -TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y -aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx -MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j -aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP -T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 -sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL -TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 -/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp -7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz -EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt -hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP -a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot -aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg -TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV -PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv -cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL -tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd -BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB -ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT -ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL -jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS -ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy -P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 -xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d -Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN -5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe -/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z -AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ -5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su ------END CERTIFICATE----- - -# Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed -# Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed -# Label: "OISTE WISeKey Global Root GB CA" -# Serial: 157768595616588414422159278966750757568 -# MD5 Fingerprint: a4:eb:b9:61:28:2e:b7:2f:98:b0:35:26:90:99:51:1d -# SHA1 Fingerprint: 0f:f9:40:76:18:d3:d7:6a:4b:98:f0:a8:35:9e:0c:fd:27:ac:cc:ed -# SHA256 Fingerprint: 6b:9c:08:e8:6e:b0:f7:67:cf:ad:65:cd:98:b6:21:49:e5:49:4a:67:f5:84:5e:7b:d1:ed:01:9f:27:b8:6b:d6 ------BEGIN CERTIFICATE----- -MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt -MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg -Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i -YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x -CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG -b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh -bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 -HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx -WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX -1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk -u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P -99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r -M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB -BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh -cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 -gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO -ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf -aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic -Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= ------END CERTIFICATE----- - -# Issuer: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. -# Subject: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. -# Label: "SZAFIR ROOT CA2" -# Serial: 357043034767186914217277344587386743377558296292 -# MD5 Fingerprint: 11:64:c1:89:b0:24:b1:8c:b1:07:7e:89:9e:51:9e:99 -# SHA1 Fingerprint: e2:52:fa:95:3f:ed:db:24:60:bd:6e:28:f3:9c:cc:cf:5e:b3:3f:de -# SHA256 Fingerprint: a1:33:9d:33:28:1a:0b:56:e5:57:d3:d3:2b:1c:e7:f9:36:7e:b0:94:bd:5f:a7:2a:7e:50:04:c8:de:d7:ca:fe ------BEGIN CERTIFICATE----- -MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL -BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 -ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw -NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L -cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg -Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN -QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT -3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw -3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 -3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 -BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN -XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF -AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw -8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG -nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP -oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy -d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg -LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== ------END CERTIFICATE----- - -# Issuer: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority -# Subject: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority -# Label: "Certum Trusted Network CA 2" -# Serial: 44979900017204383099463764357512596969 -# MD5 Fingerprint: 6d:46:9e:d9:25:6d:08:23:5b:5e:74:7d:1e:27:db:f2 -# SHA1 Fingerprint: d3:dd:48:3e:2b:bf:4c:05:e8:af:10:f5:fa:76:26:cf:d3:dc:30:92 -# SHA256 Fingerprint: b6:76:f2:ed:da:e8:77:5c:d3:6c:b0:f6:3c:d1:d4:60:39:61:f4:9e:62:65:ba:01:3a:2f:03:07:b6:d0:b8:04 ------BEGIN CERTIFICATE----- -MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB -gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu -QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG -A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz -OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ -VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 -b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA -DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn -0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB -OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE -fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E -Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m -o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i -sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW -OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez -Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS -adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n -3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC -AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ -F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf -CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 -XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm -djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ -WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb -AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq -P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko -b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj -XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P -5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi -DrW5viSP ------END CERTIFICATE----- - -# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority -# Subject: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority -# Label: "Hellenic Academic and Research Institutions RootCA 2015" -# Serial: 0 -# MD5 Fingerprint: ca:ff:e2:db:03:d9:cb:4b:e9:0f:ad:84:fd:7b:18:ce -# SHA1 Fingerprint: 01:0c:06:95:a6:98:19:14:ff:bf:5f:c6:b0:b6:95:ea:29:e9:12:a6 -# SHA256 Fingerprint: a0:40:92:9a:02:ce:53:b4:ac:f4:f2:ff:c6:98:1c:e4:49:6f:75:5e:6d:45:fe:0b:2a:69:2b:cd:52:52:3f:36 ------BEGIN CERTIFICATE----- -MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix -DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k -IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT -N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v -dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG -A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh -ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx -QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 -dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA -4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 -AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 -4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C -ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV -9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD -gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 -Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq -NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko -LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc -Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd -ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I -XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI -M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot -9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V -Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea -j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh -X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ -l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf -bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 -pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK -e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 -vm9qp/UsQu0yrbYhnr68 ------END CERTIFICATE----- - -# Issuer: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority -# Subject: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority -# Label: "Hellenic Academic and Research Institutions ECC RootCA 2015" -# Serial: 0 -# MD5 Fingerprint: 81:e5:b4:17:eb:c2:f5:e1:4b:0d:41:7b:49:92:fe:ef -# SHA1 Fingerprint: 9f:f1:71:8d:92:d5:9a:f3:7d:74:97:b4:bc:6f:84:68:0b:ba:b6:66 -# SHA256 Fingerprint: 44:b5:45:aa:8a:25:e6:5a:73:ca:15:dc:27:fc:36:d2:4c:1c:b9:95:3a:06:65:39:b1:15:82:dc:48:7b:48:33 ------BEGIN CERTIFICATE----- -MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN -BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl -c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl -bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv -b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ -BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj -YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 -MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 -dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg -QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa -jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi -C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep -lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof -TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR ------END CERTIFICATE----- - -# Issuer: CN=ISRG Root X1 O=Internet Security Research Group -# Subject: CN=ISRG Root X1 O=Internet Security Research Group -# Label: "ISRG Root X1" -# Serial: 172886928669790476064670243504169061120 -# MD5 Fingerprint: 0c:d2:f9:e0:da:17:73:e9:ed:86:4d:a5:e3:70:e7:4e -# SHA1 Fingerprint: ca:bd:2a:79:a1:07:6a:31:f2:1d:25:36:35:cb:03:9d:43:29:a5:e8 -# SHA256 Fingerprint: 96:bc:ec:06:26:49:76:f3:74:60:77:9a:cf:28:c5:a7:cf:e8:a3:c0:aa:e1:1a:8f:fc:ee:05:c0:bd:df:08:c6 ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- - -# Issuer: O=FNMT-RCM OU=AC RAIZ FNMT-RCM -# Subject: O=FNMT-RCM OU=AC RAIZ FNMT-RCM -# Label: "AC RAIZ FNMT-RCM" -# Serial: 485876308206448804701554682760554759 -# MD5 Fingerprint: e2:09:04:b4:d3:bd:d1:a0:14:fd:1a:d2:47:c4:57:1d -# SHA1 Fingerprint: ec:50:35:07:b2:15:c4:95:62:19:e2:a8:9a:5b:42:99:2c:4c:2c:20 -# SHA256 Fingerprint: eb:c5:57:0c:29:01:8c:4d:67:b1:aa:12:7b:af:12:f7:03:b4:61:1e:bc:17:b7:da:b5:57:38:94:17:9b:93:fa ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx -CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ -WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ -BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG -Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ -yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf -BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz -WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF -tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z -374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC -IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL -mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 -wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS -MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 -ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet -UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H -YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 -LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD -nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 -RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM -LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf -77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N -JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm -fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp -6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp -1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B -9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok -RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv -uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= ------END CERTIFICATE----- - -# Issuer: CN=Amazon Root CA 1 O=Amazon -# Subject: CN=Amazon Root CA 1 O=Amazon -# Label: "Amazon Root CA 1" -# Serial: 143266978916655856878034712317230054538369994 -# MD5 Fingerprint: 43:c6:bf:ae:ec:fe:ad:2f:18:c6:88:68:30:fc:c8:e6 -# SHA1 Fingerprint: 8d:a7:f9:65:ec:5e:fc:37:91:0f:1c:6e:59:fd:c1:cc:6a:6e:de:16 -# SHA256 Fingerprint: 8e:cd:e6:88:4f:3d:87:b1:12:5b:a3:1a:c3:fc:b1:3d:70:16:de:7f:57:cc:90:4f:e1:cb:97:c6:ae:98:19:6e ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- - -# Issuer: CN=Amazon Root CA 2 O=Amazon -# Subject: CN=Amazon Root CA 2 O=Amazon -# Label: "Amazon Root CA 2" -# Serial: 143266982885963551818349160658925006970653239 -# MD5 Fingerprint: c8:e5:8d:ce:a8:42:e2:7a:c0:2a:5c:7c:9e:26:bf:66 -# SHA1 Fingerprint: 5a:8c:ef:45:d7:a6:98:59:76:7a:8c:8b:44:96:b5:78:cf:47:4b:1a -# SHA256 Fingerprint: 1b:a5:b2:aa:8c:65:40:1a:82:96:01:18:f8:0b:ec:4f:62:30:4d:83:ce:c4:71:3a:19:c3:9c:01:1e:a4:6d:b4 ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK -gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ -W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg -1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K -8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r -2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me -z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR -8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj -mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz -7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 -+XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI -0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm -UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 -LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY -+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS -k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl -7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm -btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl -urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ -fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 -n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE -76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H -9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT -4PsJYGw= ------END CERTIFICATE----- - -# Issuer: CN=Amazon Root CA 3 O=Amazon -# Subject: CN=Amazon Root CA 3 O=Amazon -# Label: "Amazon Root CA 3" -# Serial: 143266986699090766294700635381230934788665930 -# MD5 Fingerprint: a0:d4:ef:0b:f7:b5:d8:49:95:2a:ec:f5:c4:fc:81:87 -# SHA1 Fingerprint: 0d:44:dd:8c:3c:8c:1a:1a:58:75:64:81:e9:0f:2e:2a:ff:b3:d2:6e -# SHA256 Fingerprint: 18:ce:6c:fe:7b:f1:4e:60:b2:e3:47:b8:df:e8:68:cb:31:d0:2e:bb:3a:da:27:15:69:f5:03:43:b4:6d:b3:a4 ------BEGIN CERTIFICATE----- -MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 -MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g -Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG -A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg -Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl -ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j -QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr -ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr -BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM -YyRIHN8wfdVoOw== ------END CERTIFICATE----- - -# Issuer: CN=Amazon Root CA 4 O=Amazon -# Subject: CN=Amazon Root CA 4 O=Amazon -# Label: "Amazon Root CA 4" -# Serial: 143266989758080763974105200630763877849284878 -# MD5 Fingerprint: 89:bc:27:d5:eb:17:8d:06:6a:69:d5:fd:89:47:b4:cd -# SHA1 Fingerprint: f6:10:84:07:d6:f8:bb:67:98:0c:c2:e2:44:c2:eb:ae:1c:ef:63:be -# SHA256 Fingerprint: e3:5d:28:41:9e:d0:20:25:cf:a6:90:38:cd:62:39:62:45:8d:a5:c6:95:fb:de:a3:c2:2b:0b:fb:25:89:70:92 ------BEGIN CERTIFICATE----- -MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 -MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g -Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG -A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg -Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi -9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk -M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB -/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB -MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw -CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW -1KyLa2tJElMzrdfkviT8tQp21KW8EA== ------END CERTIFICATE----- - -# Issuer: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM -# Subject: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM -# Label: "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1" -# Serial: 1 -# MD5 Fingerprint: dc:00:81:dc:69:2f:3e:2f:b0:3b:f6:3d:5a:91:8e:49 -# SHA1 Fingerprint: 31:43:64:9b:ec:ce:27:ec:ed:3a:3f:0b:8f:0d:e4:e8:91:dd:ee:ca -# SHA256 Fingerprint: 46:ed:c3:68:90:46:d5:3a:45:3f:b3:10:4a:b8:0d:ca:ec:65:8b:26:60:ea:16:29:dd:7e:86:79:90:64:87:16 ------BEGIN CERTIFICATE----- -MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx -GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp -bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w -KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 -BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy -dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG -EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll -IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU -QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT -TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg -LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 -a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr -LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr -N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X -YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ -iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f -AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH -V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh -AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf -IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 -lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c -8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf -lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= ------END CERTIFICATE----- - -# Issuer: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. -# Subject: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. -# Label: "GDCA TrustAUTH R5 ROOT" -# Serial: 9009899650740120186 -# MD5 Fingerprint: 63:cc:d9:3d:34:35:5c:6f:53:a3:e2:08:70:48:1f:b4 -# SHA1 Fingerprint: 0f:36:38:5b:81:1a:25:c3:9b:31:4e:83:ca:e9:34:66:70:cc:74:b4 -# SHA256 Fingerprint: bf:ff:8f:d0:44:33:48:7d:6a:8a:a6:0c:1a:29:76:7a:9f:c2:bb:b0:5e:42:0f:71:3a:13:b9:92:89:1d:38:93 ------BEGIN CERTIFICATE----- -MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE -BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ -IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 -MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV -BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w -HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj -Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj -TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u -KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj -qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm -MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 -ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP -zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk -L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC -jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA -HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC -AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg -p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm -DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 -COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry -L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf -JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg -IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io -2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV -09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ -XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq -T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe -MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== ------END CERTIFICATE----- - -# Issuer: CN=SSL.com Root Certification Authority RSA O=SSL Corporation -# Subject: CN=SSL.com Root Certification Authority RSA O=SSL Corporation -# Label: "SSL.com Root Certification Authority RSA" -# Serial: 8875640296558310041 -# MD5 Fingerprint: 86:69:12:c0:70:f1:ec:ac:ac:c2:d5:bc:a5:5b:a1:29 -# SHA1 Fingerprint: b7:ab:33:08:d1:ea:44:77:ba:14:80:12:5a:6f:bd:a9:36:49:0c:bb -# SHA256 Fingerprint: 85:66:6a:56:2e:e0:be:5c:e9:25:c1:d8:89:0a:6f:76:a8:7e:c1:6d:4d:7d:5f:29:ea:74:19:cf:20:12:3b:69 ------BEGIN CERTIFICATE----- -MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE -BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK -DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz -OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv -dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv -bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R -xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX -qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC -C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 -6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh -/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF -YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E -JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc -US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 -ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm -+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi -M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV -HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G -A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV -cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc -Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs -PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ -q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 -cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr -a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I -H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y -K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu -nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf -oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY -Ic2wBlX7Jz9TkHCpBB5XJ7k= ------END CERTIFICATE----- - -# Issuer: CN=SSL.com Root Certification Authority ECC O=SSL Corporation -# Subject: CN=SSL.com Root Certification Authority ECC O=SSL Corporation -# Label: "SSL.com Root Certification Authority ECC" -# Serial: 8495723813297216424 -# MD5 Fingerprint: 2e:da:e4:39:7f:9c:8f:37:d1:70:9f:26:17:51:3a:8e -# SHA1 Fingerprint: c3:19:7c:39:24:e6:54:af:1b:c4:ab:20:95:7a:e2:c3:0e:13:02:6a -# SHA256 Fingerprint: 34:17:bb:06:cc:60:07:da:1b:96:1c:92:0b:8a:b4:ce:3f:ad:82:0e:4a:a3:0b:9a:cb:c4:a7:4e:bd:ce:bc:65 ------BEGIN CERTIFICATE----- -MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC -VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T -U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 -aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz -WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 -b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS -b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB -BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI -7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg -CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud -EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD -VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T -kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ -gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl ------END CERTIFICATE----- - -# Issuer: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation -# Subject: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation -# Label: "SSL.com EV Root Certification Authority RSA R2" -# Serial: 6248227494352943350 -# MD5 Fingerprint: e1:1e:31:58:1a:ae:54:53:02:f6:17:6a:11:7b:4d:95 -# SHA1 Fingerprint: 74:3a:f0:52:9b:d0:32:a0:f4:4a:83:cd:d4:ba:a9:7b:7c:2e:c4:9a -# SHA256 Fingerprint: 2e:7b:f1:6c:c2:24:85:a7:bb:e2:aa:86:96:75:07:61:b0:ae:39:be:3b:2f:e9:d0:cc:6d:4e:f7:34:91:42:5c ------BEGIN CERTIFICATE----- -MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV -BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE -CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy -dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy -MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G -A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD -DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq -M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf -OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa -4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 -HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR -aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA -b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ -Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV -PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO -pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu -UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY -MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV -HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 -9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW -s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 -Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg -cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM -79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz -/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt -ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm -Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK -QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ -w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi -S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 -mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== ------END CERTIFICATE----- - -# Issuer: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation -# Subject: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation -# Label: "SSL.com EV Root Certification Authority ECC" -# Serial: 3182246526754555285 -# MD5 Fingerprint: 59:53:22:65:83:42:01:54:c0:ce:42:b9:5a:7c:f2:90 -# SHA1 Fingerprint: 4c:dd:51:a3:d1:f5:20:32:14:b0:c6:c5:32:23:03:91:c7:46:42:6d -# SHA256 Fingerprint: 22:a2:c1:f7:bd:ed:70:4c:c1:e7:01:b5:f4:08:c3:10:88:0f:e9:56:b5:de:2a:4a:44:f9:9c:87:3a:25:a7:c8 ------BEGIN CERTIFICATE----- -MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC -VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T -U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx -NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv -dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv -bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 -AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA -VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku -WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP -MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX -5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ -ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg -h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 -# Label: "GlobalSign Root CA - R6" -# Serial: 1417766617973444989252670301619537 -# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae -# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1 -# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69 ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg -MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh -bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx -MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET -MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI -xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k -ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD -aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw -LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw -1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX -k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 -SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h -bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n -WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY -rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce -MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD -AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu -bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN -nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt -Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 -55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj -vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf -cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz -oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp -nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs -pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v -JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R -8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 -5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= ------END CERTIFICATE----- - -# Issuer: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed -# Subject: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed -# Label: "OISTE WISeKey Global Root GC CA" -# Serial: 44084345621038548146064804565436152554 -# MD5 Fingerprint: a9:d6:b9:2d:2f:93:64:f8:a5:69:ca:91:e9:68:07:23 -# SHA1 Fingerprint: e0:11:84:5e:34:de:be:88:81:b9:9c:f6:16:26:d1:96:1f:c3:b9:31 -# SHA256 Fingerprint: 85:60:f9:1c:36:24:da:ba:95:70:b5:fe:a0:db:e3:6f:f1:1a:83:23:be:94:86:85:4f:b3:f3:4a:55:71:19:8d ------BEGIN CERTIFICATE----- -MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw -CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 -bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg -Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ -BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu -ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS -b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni -eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W -p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T -rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV -57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg -Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 ------END CERTIFICATE----- - -# Issuer: CN=UCA Global G2 Root O=UniTrust -# Subject: CN=UCA Global G2 Root O=UniTrust -# Label: "UCA Global G2 Root" -# Serial: 124779693093741543919145257850076631279 -# MD5 Fingerprint: 80:fe:f0:c4:4a:f0:5c:62:32:9f:1c:ba:78:a9:50:f8 -# SHA1 Fingerprint: 28:f9:78:16:19:7a:ff:18:25:18:aa:44:fe:c1:a0:ce:5c:b6:4c:8a -# SHA256 Fingerprint: 9b:ea:11:c9:76:fe:01:47:64:c1:be:56:a6:f9:14:b5:a5:60:31:7a:bd:99:88:39:33:82:e5:16:1a:a0:49:3c ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 -MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH -bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x -CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds -b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr -b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 -kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm -VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R -VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc -C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj -tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY -D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv -j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl -NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 -iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP -O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ -BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV -ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj -L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 -1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl -1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU -b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV -PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj -y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb -EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg -DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI -+Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy -YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX -UB+K+wb1whnw0A== ------END CERTIFICATE----- - -# Issuer: CN=UCA Extended Validation Root O=UniTrust -# Subject: CN=UCA Extended Validation Root O=UniTrust -# Label: "UCA Extended Validation Root" -# Serial: 106100277556486529736699587978573607008 -# MD5 Fingerprint: a1:f3:5f:43:c6:34:9b:da:bf:8c:7e:05:53:ad:96:e2 -# SHA1 Fingerprint: a3:a1:b0:6f:24:61:23:4a:e3:36:a5:c2:37:fc:a6:ff:dd:f0:d7:3a -# SHA256 Fingerprint: d4:3a:f9:b3:54:73:75:5c:96:84:fc:06:d7:d8:cb:70:ee:5c:28:e7:73:fb:29:4e:b4:1e:e7:17:22:92:4d:24 ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH -MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF -eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx -MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV -BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog -D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS -sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop -O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk -sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi -c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj -VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz -KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ -TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G -sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs -1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD -fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T -AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN -l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR -ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ -VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 -c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp -4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s -t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj -2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO -vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C -xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx -cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM -fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax ------END CERTIFICATE----- - -# Issuer: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 -# Subject: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 -# Label: "Certigna Root CA" -# Serial: 269714418870597844693661054334862075617 -# MD5 Fingerprint: 0e:5c:30:62:27:eb:5b:bc:d7:ae:62:ba:e9:d5:df:77 -# SHA1 Fingerprint: 2d:0d:52:14:ff:9e:ad:99:24:01:74:20:47:6e:6c:85:27:27:f5:43 -# SHA256 Fingerprint: d4:8d:3d:23:ee:db:50:a4:59:e5:51:97:60:1c:27:77:4b:9d:7b:18:c9:4d:5a:05:95:11:a1:02:50:b9:31:68 ------BEGIN CERTIFICATE----- -MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw -WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw -MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x -MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD -VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX -BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO -ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M -CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu -I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm -TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh -C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf -ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz -IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT -Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k -JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 -hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB -GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of -1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov -L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo -dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr -aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq -hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L -6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG -HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 -0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB -lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi -o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 -gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v -faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 -Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh -jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw -3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= ------END CERTIFICATE----- - -# Issuer: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI -# Subject: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI -# Label: "emSign Root CA - G1" -# Serial: 235931866688319308814040 -# MD5 Fingerprint: 9c:42:84:57:dd:cb:0b:a7:2e:95:ad:b6:f3:da:bc:ac -# SHA1 Fingerprint: 8a:c7:ad:8f:73:ac:4e:c1:b5:75:4d:a5:40:f4:fc:cf:7c:b5:8e:8c -# SHA256 Fingerprint: 40:f6:af:03:46:a9:9a:a1:cd:1d:55:5a:4e:9c:ce:62:c7:f9:63:46:03:ee:40:66:15:83:3d:c8:c8:d0:03:67 ------BEGIN CERTIFICATE----- -MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD -VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU -ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH -MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO -MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv -Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz -f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO -8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq -d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM -tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt -Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB -o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD -AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x -PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM -wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d -GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH -6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby -RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx -iN66zB+Afko= ------END CERTIFICATE----- - -# Issuer: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI -# Subject: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI -# Label: "emSign ECC Root CA - G3" -# Serial: 287880440101571086945156 -# MD5 Fingerprint: ce:0b:72:d1:9f:88:8e:d0:50:03:e8:e3:b8:8b:67:40 -# SHA1 Fingerprint: 30:43:fa:4f:f2:57:dc:a0:c3:80:ee:2e:58:ea:78:b2:3f:e6:bb:c1 -# SHA256 Fingerprint: 86:a1:ec:ba:08:9c:4a:8d:3b:be:27:34:c6:12:ba:34:1d:81:3e:04:3c:f9:e8:a8:62:cd:5c:57:a3:6b:be:6b ------BEGIN CERTIFICATE----- -MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG -EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo -bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g -RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ -TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s -b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw -djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0 -WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS -fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB -zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq -hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB -CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD -+JbNR6iC8hZVdyR+EhCVBCyj ------END CERTIFICATE----- - -# Issuer: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI -# Subject: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI -# Label: "emSign Root CA - C1" -# Serial: 825510296613316004955058 -# MD5 Fingerprint: d8:e3:5d:01:21:fa:78:5a:b0:df:ba:d2:ee:2a:5f:68 -# SHA1 Fingerprint: e7:2e:f1:df:fc:b2:09:28:cf:5d:d4:d5:67:37:b1:51:cb:86:4f:01 -# SHA256 Fingerprint: 12:56:09:aa:30:1d:a0:a2:49:b9:7a:82:39:cb:6a:34:21:6f:44:dc:ac:9f:39:54:b1:42:92:f2:e8:c8:60:8f ------BEGIN CERTIFICATE----- -MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG -A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg -SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw -MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln -biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v -dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ -BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ -HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH -3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH -GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c -xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1 -aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq -TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87 -/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4 -kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG -YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT -+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo -WXzhriKi4gp6D/piq1JM4fHfyr6DDUI= ------END CERTIFICATE----- - -# Issuer: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI -# Subject: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI -# Label: "emSign ECC Root CA - C3" -# Serial: 582948710642506000014504 -# MD5 Fingerprint: 3e:53:b3:a3:81:ee:d7:10:f8:d3:b0:1d:17:92:f5:d5 -# SHA1 Fingerprint: b6:af:43:c2:9b:81:53:7d:f6:ef:6b:c3:1f:1f:60:15:0c:ee:48:66 -# SHA256 Fingerprint: bc:4d:80:9b:15:18:9d:78:db:3e:1d:8c:f4:f9:72:6a:79:5d:a1:64:3c:a5:f1:35:8e:1d:db:0e:dc:0d:7e:b3 ------BEGIN CERTIFICATE----- -MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG -EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx -IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw -MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln -biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND -IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci -MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti -sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O -BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB -Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c -3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J -0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== ------END CERTIFICATE----- - -# Issuer: CN=Hongkong Post Root CA 3 O=Hongkong Post -# Subject: CN=Hongkong Post Root CA 3 O=Hongkong Post -# Label: "Hongkong Post Root CA 3" -# Serial: 46170865288971385588281144162979347873371282084 -# MD5 Fingerprint: 11:fc:9f:bd:73:30:02:8a:fd:3f:f3:58:b9:cb:20:f0 -# SHA1 Fingerprint: 58:a2:d0:ec:20:52:81:5b:c1:f3:f8:64:02:24:4e:c2:8e:02:4b:02 -# SHA256 Fingerprint: 5a:2f:c0:3f:0c:83:b0:90:bb:fa:40:60:4b:09:88:44:6c:76:36:18:3d:f9:84:6e:17:10:1a:44:7f:b8:ef:d6 ------BEGIN CERTIFICATE----- -MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQEL -BQAwbzELMAkGA1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJ -SG9uZyBLb25nMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25n -a29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2MDMwMjI5NDZaFw00MjA2MDMwMjI5 -NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxEjAQBgNVBAcT -CUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMXSG9u -Z2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQCziNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFO -dem1p+/l6TWZ5Mwc50tfjTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mI -VoBc+L0sPOFMV4i707mV78vH9toxdCim5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV -9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOesL4jpNrcyCse2m5FHomY -2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj0mRiikKY -vLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+Tt -bNe/JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZb -x39ri1UbSsUgYT2uy1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+ -l2oBlKN8W4UdKjk60FSh0Tlxnf0h+bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YK -TE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsGxVd7GYYKecsAyVKvQv83j+Gj -Hno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwIDAQABo2MwYTAP -BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e -i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEw -DQYJKoZIhvcNAQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG -7BJ8dNVI0lkUmcDrudHr9EgwW62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCk -MpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWldy8joRTnU+kLBEUx3XZL7av9YROXr -gZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov+BS5gLNdTaqX4fnk -GMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDceqFS -3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJm -Ozj/2ZQw9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+ -l6mc1X5VTMbeRRAc6uk7nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6c -JfTzPV4e0hz5sy229zdcxsshTrD3mUcYhcErulWuBurQB7Lcq9CClnXO0lD+mefP -L5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB60PZ2Pierc+xYw5F9KBa -LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG -mpv0 ------END CERTIFICATE----- - -# Issuer: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation -# Subject: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation -# Label: "Microsoft ECC Root Certificate Authority 2017" -# Serial: 136839042543790627607696632466672567020 -# MD5 Fingerprint: dd:a1:03:e6:4a:93:10:d1:bf:f0:19:42:cb:fe:ed:67 -# SHA1 Fingerprint: 99:9a:64:c3:7f:f4:7d:9f:ab:95:f1:47:69:89:14:60:ee:c4:c3:c5 -# SHA256 Fingerprint: 35:8d:f3:9d:76:4a:f9:e1:b7:66:e9:c9:72:df:35:2e:e1:5c:fa:c2:27:af:6a:d1:d7:0e:8e:4a:6e:dc:ba:02 ------BEGIN CERTIFICATE----- -MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw -CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD -VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw -MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV -UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy -b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq -hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR -ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb -hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E -BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3 -FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV -L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB -iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= ------END CERTIFICATE----- - -# Issuer: CN=Microsoft RSA Root Certificate Authority 2017 O=Microsoft Corporation -# Subject: CN=Microsoft RSA Root Certificate Authority 2017 O=Microsoft Corporation -# Label: "Microsoft RSA Root Certificate Authority 2017" -# Serial: 40975477897264996090493496164228220339 -# MD5 Fingerprint: 10:ff:00:ff:cf:c9:f8:c7:7a:c0:ee:35:8e:c9:0f:47 -# SHA1 Fingerprint: 73:a5:e6:4a:3b:ff:83:16:ff:0e:dc:cc:61:8a:90:6e:4e:ae:4d:74 -# SHA256 Fingerprint: c7:41:f7:0f:4b:2a:8d:88:bf:2e:71:c1:41:22:ef:53:ef:10:eb:a0:cf:a5:e6:4c:fa:20:f4:18:85:30:73:e0 ------BEGIN CERTIFICATE----- -MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl -MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw -NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 -IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG -EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N -aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ -Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0 -ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1 -HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm -gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ -jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc -aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG -YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6 -W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K -UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH -+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q -W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ -BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC -NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC -LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC -gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6 -tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh -SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2 -TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3 -pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR -xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp -GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9 -dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN -AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB -RA+GsCyRxj3qrg+E ------END CERTIFICATE----- - -# Issuer: CN=e-Szigno Root CA 2017 O=Microsec Ltd. -# Subject: CN=e-Szigno Root CA 2017 O=Microsec Ltd. -# Label: "e-Szigno Root CA 2017" -# Serial: 411379200276854331539784714 -# MD5 Fingerprint: de:1f:f6:9e:84:ae:a7:b4:21:ce:1e:58:7d:d1:84:98 -# SHA1 Fingerprint: 89:d4:83:03:4f:9e:9a:48:80:5f:72:37:d4:a9:a6:ef:cb:7c:1f:d1 -# SHA256 Fingerprint: be:b0:0b:30:83:9b:9b:c3:2c:32:e4:44:79:05:95:06:41:f2:64:21:b1:5e:d0:89:19:8b:51:8a:e2:ea:1b:99 ------BEGIN CERTIFICATE----- -MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV -BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk -LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv -b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ -BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg -THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v -IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv -xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H -Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G -A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB -eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo -jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ -+efcMQ== ------END CERTIFICATE----- - -# Issuer: O=CERTSIGN SA OU=certSIGN ROOT CA G2 -# Subject: O=CERTSIGN SA OU=certSIGN ROOT CA G2 -# Label: "certSIGN Root CA G2" -# Serial: 313609486401300475190 -# MD5 Fingerprint: 8c:f1:75:8a:c6:19:cf:94:b7:f7:65:20:87:c3:97:c7 -# SHA1 Fingerprint: 26:f9:93:b4:ed:3d:28:27:b0:b9:4b:a7:e9:15:1d:a3:8d:92:e5:32 -# SHA256 Fingerprint: 65:7c:fe:2f:a7:3f:aa:38:46:25:71:f3:32:a2:36:3a:46:fc:e7:02:09:51:71:07:02:cd:fb:b6:ee:da:33:05 ------BEGIN CERTIFICATE----- -MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV -BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g -Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ -BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ -R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF -dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw -vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ -uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp -n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs -cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW -xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P -rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF -DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx -DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy -LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C -eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ -d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq -kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC -b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl -qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0 -OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c -NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk -ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO -pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj -03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk -PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE -1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX -QRBdJ3NghVdJIgc= ------END CERTIFICATE----- - -# Issuer: CN=Trustwave Global Certification Authority O=Trustwave Holdings, Inc. -# Subject: CN=Trustwave Global Certification Authority O=Trustwave Holdings, Inc. -# Label: "Trustwave Global Certification Authority" -# Serial: 1846098327275375458322922162 -# MD5 Fingerprint: f8:1c:18:2d:2f:ba:5f:6d:a1:6c:bc:c7:ab:91:c7:0e -# SHA1 Fingerprint: 2f:8f:36:4f:e1:58:97:44:21:59:87:a5:2a:9a:d0:69:95:26:7f:b5 -# SHA256 Fingerprint: 97:55:20:15:f5:dd:fc:3c:87:88:c0:06:94:45:55:40:88:94:45:00:84:f1:00:86:70:86:bc:1a:2b:b5:8d:c8 ------BEGIN CERTIFICATE----- -MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw -CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x -ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1 -c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx -OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI -SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI -b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB -ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn -swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu -7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8 -1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW -80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP -JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l -RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw -hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10 -coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc -BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n -twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud -EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud -DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W -0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe -uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q -lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB -aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE -sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT -MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe -qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh -VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8 -h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9 -EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK -yeC2nOnOcXHebD8WpHk= ------END CERTIFICATE----- - -# Issuer: CN=Trustwave Global ECC P256 Certification Authority O=Trustwave Holdings, Inc. -# Subject: CN=Trustwave Global ECC P256 Certification Authority O=Trustwave Holdings, Inc. -# Label: "Trustwave Global ECC P256 Certification Authority" -# Serial: 4151900041497450638097112925 -# MD5 Fingerprint: 5b:44:e3:8d:5d:36:86:26:e8:0d:05:d2:59:a7:83:54 -# SHA1 Fingerprint: b4:90:82:dd:45:0c:be:8b:5b:b1:66:d3:e2:a4:08:26:cd:ed:42:cf -# SHA256 Fingerprint: 94:5b:bc:82:5e:a5:54:f4:89:d1:fd:51:a7:3d:df:2e:a6:24:ac:70:19:a0:52:05:22:5c:22:a7:8c:cf:a8:b4 ------BEGIN CERTIFICATE----- -MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD -VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf -BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 -YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x -NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G -A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 -d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF -Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG -SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN -FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w -DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw -CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh -DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 ------END CERTIFICATE----- - -# Issuer: CN=Trustwave Global ECC P384 Certification Authority O=Trustwave Holdings, Inc. -# Subject: CN=Trustwave Global ECC P384 Certification Authority O=Trustwave Holdings, Inc. -# Label: "Trustwave Global ECC P384 Certification Authority" -# Serial: 2704997926503831671788816187 -# MD5 Fingerprint: ea:cf:60:c4:3b:b9:15:29:40:a1:97:ed:78:27:93:d6 -# SHA1 Fingerprint: e7:f3:a3:c8:cf:6f:c3:04:2e:6d:0e:67:32:c5:9e:68:95:0d:5e:d2 -# SHA256 Fingerprint: 55:90:38:59:c8:c0:c3:eb:b8:75:9e:ce:4e:25:57:22:5f:f5:75:8b:bd:38:eb:d4:82:76:60:1e:1b:d5:80:97 ------BEGIN CERTIFICATE----- -MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD -VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf -BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 -YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x -NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G -A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 -d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF -Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB -BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ -j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF -1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G -A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3 -AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC -MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu -Sw== ------END CERTIFICATE----- - -# Issuer: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp. -# Subject: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp. -# Label: "NAVER Global Root Certification Authority" -# Serial: 9013692873798656336226253319739695165984492813 -# MD5 Fingerprint: c8:7e:41:f6:25:3b:f5:09:b3:17:e8:46:3d:bf:d0:9b -# SHA1 Fingerprint: 8f:6b:f2:a9:27:4a:da:14:a0:c4:f4:8e:61:27:f9:c0:1e:78:5d:d1 -# SHA256 Fingerprint: 88:f4:38:dc:f8:ff:d1:fa:8f:42:91:15:ff:e5:f8:2a:e1:e0:6e:0c:70:c3:75:fa:ad:71:7b:34:a4:9e:72:65 ------BEGIN CERTIFICATE----- -MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEM -BQAwaTELMAkGA1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRG -T1JNIENvcnAuMTIwMAYDVQQDDClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0 -aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4NDJaFw0zNzA4MTgyMzU5NTlaMGkx -CzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVTUyBQTEFURk9STSBD -b3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVA -iQqrDZBbUGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH -38dq6SZeWYp34+hInDEW+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lE -HoSTGEq0n+USZGnQJoViAbbJAh2+g1G7XNr4rRVqmfeSVPc0W+m/6imBEtRTkZaz -kVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2aacp+yPOiNgSnABIqKYP -szuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4Yb8Obtoq -vC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHf -nZ3zVHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaG -YQ5fG8Ir4ozVu53BA0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo -0es+nPxdGoMuK8u180SdOqcXYZaicdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3a -CJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejyYhbLgGvtPe31HzClrkvJE+2K -AQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNVHQ4EFgQU0p+I -36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB -Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoN -qo0hV4/GPnrK21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatj -cu3cvuzHV+YwIHHW1xDBE1UBjCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm -+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bxhYTeodoS76TiEJd6eN4MUZeoIUCL -hr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTgE34h5prCy8VCZLQe -lHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTHD8z7 -p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8 -piKCk5XQA76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLR -LBT/DShycpWbXgnbiUSYqqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX -5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oGI/hGoiLtk/bdmuYqh7GYVPEi92tF4+KO -dh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmgkpzNNIaRkPpkUZ3+/uul -9XXeifdy ------END CERTIFICATE----- - -# Issuer: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres -# Subject: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres -# Label: "AC RAIZ FNMT-RCM SERVIDORES SEGUROS" -# Serial: 131542671362353147877283741781055151509 -# MD5 Fingerprint: 19:36:9c:52:03:2f:d2:d1:bb:23:cc:dd:1e:12:55:bb -# SHA1 Fingerprint: 62:ff:d9:9e:c0:65:0d:03:ce:75:93:d2:ed:3f:2d:32:c9:e3:e5:4a -# SHA256 Fingerprint: 55:41:53:b1:3d:2c:f9:dd:b7:53:bf:be:1a:4e:0a:e0:8d:0a:a4:18:70:58:fe:60:a2:b8:62:b2:e4:b8:7b:cb ------BEGIN CERTIFICATE----- -MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw -CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw -FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S -Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5 -MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL -DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS -QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB -BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH -sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK -Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu -SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC -MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy -v+c= ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign Root R46 O=GlobalSign nv-sa -# Subject: CN=GlobalSign Root R46 O=GlobalSign nv-sa -# Label: "GlobalSign Root R46" -# Serial: 1552617688466950547958867513931858518042577 -# MD5 Fingerprint: c4:14:30:e4:fa:66:43:94:2a:6a:1b:24:5f:19:d0:ef -# SHA1 Fingerprint: 53:a2:b0:4b:ca:6b:d6:45:e6:39:8a:8e:c4:0d:d2:bf:77:c3:a2:90 -# SHA256 Fingerprint: 4f:a3:12:6d:8d:3a:11:d1:c4:85:5a:4f:80:7c:ba:d6:cf:91:9d:3a:5a:88:b0:3b:ea:2c:63:72:d9:3c:40:c9 ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA -MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD -VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy -MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt -c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ -OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG -vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud -316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo -0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE -y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF -zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE -+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN -I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs -x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa -ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC -4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4 -7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg -JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti -2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk -pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF -FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt -rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk -ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5 -u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP -4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6 -N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 -vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign Root E46 O=GlobalSign nv-sa -# Subject: CN=GlobalSign Root E46 O=GlobalSign nv-sa -# Label: "GlobalSign Root E46" -# Serial: 1552617690338932563915843282459653771421763 -# MD5 Fingerprint: b5:b8:66:ed:de:08:83:e3:c9:e2:01:34:06:ac:51:6f -# SHA1 Fingerprint: 39:b4:6c:d5:fe:80:06:eb:e2:2f:4a:bb:08:33:a0:af:db:b9:dd:84 -# SHA256 Fingerprint: cb:b9:c4:4d:84:b8:04:3e:10:50:ea:31:a6:9f:51:49:55:d7:bf:d2:e2:c6:b4:93:01:01:9a:d6:1d:9f:50:58 ------BEGIN CERTIFICATE----- -MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx -CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD -ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw -MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex -HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq -R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd -yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud -DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ -7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8 -+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= ------END CERTIFICATE----- - -# Issuer: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz -# Subject: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz -# Label: "ANF Secure Server Root CA" -# Serial: 996390341000653745 -# MD5 Fingerprint: 26:a6:44:5a:d9:af:4e:2f:b2:1d:b6:65:b0:4e:e8:96 -# SHA1 Fingerprint: 5b:6e:68:d0:cc:15:b6:a0:5f:1e:c1:5f:ae:02:fc:6b:2f:5d:6f:74 -# SHA256 Fingerprint: fb:8f:ec:75:91:69:b9:10:6b:1e:51:16:44:c6:18:c5:13:04:37:3f:6c:06:43:08:8d:8b:ef:fd:1b:99:75:99 ------BEGIN CERTIFICATE----- -MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNV -BAUTCUc2MzI4NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlk -YWQgZGUgQ2VydGlmaWNhY2lvbjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNV -BAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3QgQ0EwHhcNMTkwOTA0MTAwMDM4WhcN -MzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEwMQswCQYDVQQGEwJF -UzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQwEgYD -VQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9v -dCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCj -cqQZAZ2cC4Ffc0m6p6zzBE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9q -yGFOtibBTI3/TO80sh9l2Ll49a2pcbnvT1gdpd50IJeh7WhM3pIXS7yr/2WanvtH -2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcvB2VSAKduyK9o7PQUlrZX -H1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXsezx76W0OL -zc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyR -p1RMVwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQz -W7i1o0TJrH93PB0j7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/ -SiOL9V8BY9KHcyi1Swr1+KuCLH5zJTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJn -LNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe8TZBAQIvfXOn3kLMTOmJDVb3 -n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVOHj1tyRRM4y5B -u8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj -o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AgEATh65isagmD9uw2nAalxJUqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L -9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzxj6ptBZNscsdW699QIyjlRRA96Gej -rw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDtdD+4E5UGUcjohybK -pFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM5gf0 -vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjq -OknkJjCb5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ -/zo1PqVUSlJZS2Db7v54EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ9 -2zg/LFis6ELhDtjTO0wugumDLmsx2d1Hhk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI -+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGyg77FGr8H6lnco4g175x2 -MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3r5+qPeoo -tt7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw= ------END CERTIFICATE----- - -# Issuer: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority -# Subject: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority -# Label: "Certum EC-384 CA" -# Serial: 160250656287871593594747141429395092468 -# MD5 Fingerprint: b6:65:b3:96:60:97:12:a1:ec:4e:e1:3d:a3:c6:c9:f1 -# SHA1 Fingerprint: f3:3e:78:3c:ac:df:f4:a2:cc:ac:67:55:69:56:d7:e5:16:3c:e1:ed -# SHA256 Fingerprint: 6b:32:80:85:62:53:18:aa:50:d1:73:c9:8d:8b:da:09:d5:7e:27:41:3d:11:4c:f7:87:a0:f5:d0:6c:03:0c:f6 ------BEGIN CERTIFICATE----- -MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw -CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw -JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT -EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0 -WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT -LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX -BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE -KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm -Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj -QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8 -EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J -UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn -nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= ------END CERTIFICATE----- - -# Issuer: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority -# Subject: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority -# Label: "Certum Trusted Root CA" -# Serial: 40870380103424195783807378461123655149 -# MD5 Fingerprint: 51:e1:c2:e7:fe:4c:84:af:59:0e:2f:f4:54:6f:ea:29 -# SHA1 Fingerprint: c8:83:44:c0:18:ae:9f:cc:f1:87:b7:8f:22:d1:c5:d7:45:84:ba:e5 -# SHA256 Fingerprint: fe:76:96:57:38:55:77:3e:37:a9:5e:7a:d4:d9:cc:96:c3:01:57:c1:5d:31:76:5b:a9:b1:57:04:e1:ae:78:fd ------BEGIN CERTIFICATE----- -MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6 -MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu -MScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNV -BAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwHhcNMTgwMzE2MTIxMDEzWhcNNDMw -MzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEg -U3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRo -b3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZ -n0EGze2jusDbCSzBfN8pfktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/q -p1x4EaTByIVcJdPTsuclzxFUl6s1wB52HO8AU5853BSlLCIls3Jy/I2z5T4IHhQq -NwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2fJmItdUDmj0VDT06qKhF -8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGtg/BKEiJ3 -HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGa -mqi4NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi -7VdNIuJGmj8PkTQkfVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSF -ytKAQd8FqKPVhJBPC/PgP5sZ0jeJP/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0P -qafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSYnjYJdmZm/Bo/6khUHL4wvYBQ -v3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHKHRzQ+8S1h9E6 -Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1 -vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQAD -ggIBAEii1QALLtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4 -WxmB82M+w85bj/UvXgF2Ez8sALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvo -zMrnadyHncI013nR03e4qllY/p0m+jiGPp2Kh2RX5Rc64vmNueMzeMGQ2Ljdt4NR -5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8CYyqOhNf6DR5UMEQ -GfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA4kZf -5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq -0Uc9NneoWWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7D -P78v3DSk+yshzWePS/Tj6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTM -qJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmTOPQD8rv7gmsHINFSH5pkAnuYZttcTVoP -0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZckbxJF0WddCajJFdr60qZf -E2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb ------END CERTIFICATE----- - -# Issuer: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique -# Subject: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique -# Label: "TunTrust Root CA" -# Serial: 108534058042236574382096126452369648152337120275 -# MD5 Fingerprint: 85:13:b9:90:5b:36:5c:b6:5e:b8:5a:f8:e0:31:57:b4 -# SHA1 Fingerprint: cf:e9:70:84:0f:e0:73:0f:9d:f6:0c:7f:2c:4b:ee:20:46:34:9c:bb -# SHA256 Fingerprint: 2e:44:10:2a:b5:8c:b8:54:19:45:1c:8e:19:d9:ac:f3:66:2c:af:bc:61:4b:6a:53:96:0a:30:f7:d0:e2:eb:41 ------BEGIN CERTIFICATE----- -MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL -BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg -Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv -b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG -EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u -IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ -n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd -2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF -VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ -GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF -li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU -r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2 -eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb -MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg -jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB -7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW -5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE -ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 -90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z -xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu -QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4 -FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH -22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP -xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn -dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5 -Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b -nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ -CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH -u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj -d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= ------END CERTIFICATE----- - -# Issuer: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA -# Subject: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA -# Label: "HARICA TLS RSA Root CA 2021" -# Serial: 76817823531813593706434026085292783742 -# MD5 Fingerprint: 65:47:9b:58:86:dd:2c:f0:fc:a2:84:1f:1e:96:c4:91 -# SHA1 Fingerprint: 02:2d:05:82:fa:88:ce:14:0c:06:79:de:7f:14:10:e9:45:d7:a5:6d -# SHA256 Fingerprint: d9:5d:0e:8e:da:79:52:5b:f9:be:b1:1b:14:d2:10:0d:32:94:98:5f:0c:62:d9:fa:bd:9c:d9:99:ec:cb:7b:1d ------BEGIN CERTIFICATE----- -MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBs -MQswCQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl -c2VhcmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0Eg -Um9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUzOFoXDTQ1MDIxMzEwNTUzN1owbDEL -MAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl -YXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNBIFJv -b3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569l -mwVnlskNJLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE -4VGC/6zStGndLuwRo0Xua2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uv -a9of08WRiFukiZLRgeaMOVig1mlDqa2YUlhu2wr7a89o+uOkXjpFc5gH6l8Cct4M -pbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K5FrZx40d/JiZ+yykgmvw -Kh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEvdmn8kN3b -LW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcY -AuUR0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqB -AGMUuTNe3QvboEUHGjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYq -E613TBoYm5EPWNgGVMWX+Ko/IIqmhaZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHr -W2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQCPxrvrNQKlr9qEgYRtaQQJKQ -CoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE -AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAU -X15QvWiWkKQUEapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3 -f5Z2EMVGpdAgS1D0NTsY9FVqQRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxaja -H6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxDQpSbIPDRzbLrLFPCU3hKTwSUQZqP -JzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcRj88YxeMn/ibvBZ3P -zzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5vZSt -jBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0 -/L5H9MG0qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pT -BGIBnfHAT+7hOtSLIBD6Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79 -aPib8qXPMThcFarmlwDB31qlpzmq6YR/PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YW -xw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnnkf3/W9b3raYvAwtt41dU -63ZTGI0RmLo= ------END CERTIFICATE----- - -# Issuer: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA -# Subject: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA -# Label: "HARICA TLS ECC Root CA 2021" -# Serial: 137515985548005187474074462014555733966 -# MD5 Fingerprint: ae:f7:4c:e5:66:35:d1:b7:9b:8c:22:93:74:d3:4b:b0 -# SHA1 Fingerprint: bc:b0:c1:9d:e9:98:92:70:19:38:57:e9:8d:a7:b4:5d:6e:ee:01:48 -# SHA256 Fingerprint: 3f:99:cc:47:4a:cf:ce:4d:fe:d5:87:94:66:5e:47:8d:15:47:73:9f:2e:78:0f:1b:b4:ca:9b:13:30:97:d4:01 ------BEGIN CERTIFICATE----- -MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw -CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh -cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v -dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG -A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj -aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg -Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7 -KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y -STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD -AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw -SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN -nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps ------END CERTIFICATE----- - -# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 -# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 -# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068" -# Serial: 1977337328857672817 -# MD5 Fingerprint: 4e:6e:9b:54:4c:ca:b7:fa:48:e4:90:b1:15:4b:1c:a3 -# SHA1 Fingerprint: 0b:be:c2:27:22:49:cb:39:aa:db:35:5c:53:e3:8c:ae:78:ff:b6:fe -# SHA256 Fingerprint: 57:de:05:83:ef:d2:b2:6e:03:61:da:99:da:9d:f4:64:8d:ef:7e:e8:44:1c:3b:72:8a:fa:9b:cd:e0:f9:b2:6a ------BEGIN CERTIFICATE----- -MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE -BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h -cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1 -MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg -Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 -thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM -cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG -L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i -NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h -X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b -m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy -Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja -EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T -KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF -6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh -OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1UdDgQWBBRlzeurNR4APn7VdMAc -tHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4wgZswgZgGBFUd -IAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j -b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABC -AG8AbgBhAG4AbwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAw -ADEANzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9m -iWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL4QjbEwj4KKE1soCzC1HA01aajTNF -Sa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDbLIpgD7dvlAceHabJ -hfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1ilI45P -Vf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZE -EAEeiGaPcjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV -1aUsIC+nmCjuRfzxuIgALI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2t -CsvMo2ebKHTEm9caPARYpoKdrcd7b/+Alun4jWq9GJAd/0kakFI3ky88Al2CdgtR -5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH9IBk9W6VULgRfhVwOEqw -f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9 -ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK -GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV ------END CERTIFICATE----- - -# Issuer: CN=vTrus ECC Root CA O=iTrusChina Co.,Ltd. -# Subject: CN=vTrus ECC Root CA O=iTrusChina Co.,Ltd. -# Label: "vTrus ECC Root CA" -# Serial: 630369271402956006249506845124680065938238527194 -# MD5 Fingerprint: de:4b:c1:f5:52:8c:9b:43:e1:3e:8f:55:54:17:8d:85 -# SHA1 Fingerprint: f6:9c:db:b0:fc:f6:02:13:b6:52:32:a6:a3:91:3f:16:70:da:c3:e1 -# SHA256 Fingerprint: 30:fb:ba:2c:32:23:8e:2a:98:54:7a:f9:79:31:e5:50:42:8b:9b:3f:1c:8e:eb:66:33:dc:fa:86:c5:b2:7d:d3 ------BEGIN CERTIFICATE----- -MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMw -RzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAY -BgNVBAMTEXZUcnVzIEVDQyBSb290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDcz -MTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28u -LEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYwEAYHKoZIzj0CAQYF -K4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+cToL0 -v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUd -e4BdS49nTPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYD -VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIw -V53dVvHH4+m4SVBrm2nDb+zDfSXkV5UTQJtS0zvzQBm8JsctBp61ezaf9SXUY2sA -AjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQLYgmRWAD5Tfs0aNoJrSEG -GJTO ------END CERTIFICATE----- - -# Issuer: CN=vTrus Root CA O=iTrusChina Co.,Ltd. -# Subject: CN=vTrus Root CA O=iTrusChina Co.,Ltd. -# Label: "vTrus Root CA" -# Serial: 387574501246983434957692974888460947164905180485 -# MD5 Fingerprint: b8:c9:37:df:fa:6b:31:84:64:c5:ea:11:6a:1b:75:fc -# SHA1 Fingerprint: 84:1a:69:fb:f5:cd:1a:25:34:13:3d:e3:f8:fc:b8:99:d0:c9:14:b7 -# SHA256 Fingerprint: 8a:71:de:65:59:33:6f:42:6c:26:e5:38:80:d0:0d:88:a1:8d:a4:c6:a9:1f:0d:cb:61:94:e2:06:c5:c9:63:87 ------BEGIN CERTIFICATE----- -MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQEL -BQAwQzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4x -FjAUBgNVBAMTDXZUcnVzIFJvb3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMx -MDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoGA1UEChMTaVRydXNDaGluYSBDby4s -THRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZotsSKYc -IrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykU -AyyNJJrIZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+ -GrPSbcKvdmaVayqwlHeFXgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z9 -8Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KAYPxMvDVTAWqXcoKv8R1w6Jz1717CbMdH -flqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70kLJrxLT5ZOrpGgrIDajt -J8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2AXPKBlim -0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZN -pGvu/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQ -UqqzApVg+QxMaPnu1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHW -OXSuTEGC2/KmSNGzm/MzqvOmwMVO9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMB -AAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYgscasGrz2iTAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAKbqSSaet -8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd -nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1j -bhd47F18iMjrjld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvM -Kar5CKXiNxTKsbhm7xqC5PD48acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIiv -TDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJnxDHO2zTlJQNgJXtxmOTAGytfdELS -S8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554WgicEFOwE30z9J4nfr -I8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4sEb9 -b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNB -UvupLnKWnyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1P -Ti07NEPhmg4NpGaXutIcSkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929ven -sBxXVsFy6K2ir40zSbofitzmdHxghm+Hl3s= ------END CERTIFICATE----- - -# Issuer: CN=ISRG Root X2 O=Internet Security Research Group -# Subject: CN=ISRG Root X2 O=Internet Security Research Group -# Label: "ISRG Root X2" -# Serial: 87493402998870891108772069816698636114 -# MD5 Fingerprint: d3:9e:c4:1e:23:3c:a6:df:cf:a3:7e:6d:e0:14:e6:e5 -# SHA1 Fingerprint: bd:b1:b9:3c:d5:97:8d:45:c6:26:14:55:f8:db:95:c7:5a:d1:53:af -# SHA256 Fingerprint: 69:72:9b:8e:15:a8:6e:fc:17:7a:57:af:b7:17:1d:fc:64:ad:d2:8c:2f:ca:8c:f1:50:7e:34:45:3c:cb:14:70 ------BEGIN CERTIFICATE----- -MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw -CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg -R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00 -MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT -ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw -EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW -+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9 -ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI -zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW -tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1 -/q4AaOeMSQ+2b1tbFfLn ------END CERTIFICATE----- - -# Issuer: CN=HiPKI Root CA - G1 O=Chunghwa Telecom Co., Ltd. -# Subject: CN=HiPKI Root CA - G1 O=Chunghwa Telecom Co., Ltd. -# Label: "HiPKI Root CA - G1" -# Serial: 60966262342023497858655262305426234976 -# MD5 Fingerprint: 69:45:df:16:65:4b:e8:68:9a:8f:76:5f:ff:80:9e:d3 -# SHA1 Fingerprint: 6a:92:e4:a8:ee:1b:ec:96:45:37:e3:29:57:49:cd:96:e3:e5:d2:60 -# SHA256 Fingerprint: f0:15:ce:3c:c2:39:bf:ef:06:4b:e9:f1:d2:c4:17:e1:a0:26:4a:0a:94:be:1f:0c:8d:12:18:64:eb:69:49:cc ------BEGIN CERTIFICATE----- -MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBP -MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 -ZC4xGzAZBgNVBAMMEkhpUEtJIFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRa -Fw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3 -YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kgUm9vdCBDQSAtIEcx -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0o9Qw -qNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twv -Vcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6 -lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnz -Qs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRtU6M9/Aes1MU3guvklQgZ -KILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfdhSi8MEyr48KxRURHH+CK -FgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj1jOXTyFj -HluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDr -y+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ -/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgM -a/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6 -fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQDAgGGMA0GCSqG -SIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi -7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqc -SE5XCV0vrPSltJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6Fza -ZsT0pPBWGTMpWmWSBUdGSquEwx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9Tc -XzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07QJNBAsNB1CI69aO4I1258EHBGG3zg -iLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv5wiZqAxeJoBF1Pho -L5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+GpzjLrF -Ne85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wr -kkVbbiVghUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+ -vhV4nYWBSipX3tUZQ9rbyltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQU -YDksswBVLuT1sw5XxJFBAJw/6KXf6vb/yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 -# Label: "GlobalSign ECC Root CA - R4" -# Serial: 159662223612894884239637590694 -# MD5 Fingerprint: 26:29:f8:6d:e1:88:bf:a2:65:7f:aa:c4:cd:0f:7f:fc -# SHA1 Fingerprint: 6b:a0:b0:98:e1:71:ef:5a:ad:fe:48:15:80:77:10:f4:bd:6f:0b:28 -# SHA256 Fingerprint: b0:85:d7:0b:96:4f:19:1a:73:e4:af:0d:54:ae:7a:0e:07:aa:fd:af:9b:71:dd:08:62:13:8a:b7:32:5a:24:a2 ------BEGIN CERTIFICATE----- -MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD -VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh -bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw -MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g -UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT -BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx -uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV -HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/ -+wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147 -bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm ------END CERTIFICATE----- - -# Issuer: CN=GTS Root R1 O=Google Trust Services LLC -# Subject: CN=GTS Root R1 O=Google Trust Services LLC -# Label: "GTS Root R1" -# Serial: 159662320309726417404178440727 -# MD5 Fingerprint: 05:fe:d0:bf:71:a8:a3:76:63:da:01:e0:d8:52:dc:40 -# SHA1 Fingerprint: e5:8c:1c:c4:91:3b:38:63:4b:e9:10:6e:e3:ad:8e:6b:9d:d9:81:4a -# SHA256 Fingerprint: d9:47:43:2a:bd:e7:b7:fa:90:fc:2e:6b:59:10:1b:12:80:e0:e1:c7:e4:e4:0f:a3:c6:88:7f:ff:57:a7:f4:cf ------BEGIN CERTIFICATE----- -MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw -CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw -MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo -27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w -Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw -TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl -qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH -szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8 -Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk -MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 -wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p -aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN -VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID -AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb -C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe -QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy -h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4 -7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J -ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef -MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/ -Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT -6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ -0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm -2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb -bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c ------END CERTIFICATE----- - -# Issuer: CN=GTS Root R2 O=Google Trust Services LLC -# Subject: CN=GTS Root R2 O=Google Trust Services LLC -# Label: "GTS Root R2" -# Serial: 159662449406622349769042896298 -# MD5 Fingerprint: 1e:39:c0:53:e6:1e:29:82:0b:ca:52:55:36:5d:57:dc -# SHA1 Fingerprint: 9a:44:49:76:32:db:de:fa:d0:bc:fb:5a:7b:17:bd:9e:56:09:24:94 -# SHA256 Fingerprint: 8d:25:cd:97:22:9d:bf:70:35:6b:da:4e:b3:cc:73:40:31:e2:4c:f0:0f:af:cf:d3:2d:c7:6e:b5:84:1c:7e:a8 ------BEGIN CERTIFICATE----- -MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw -CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw -MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt -nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY -6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu -MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k -RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg -f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV -+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo -dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW -Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa -G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq -gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID -AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H -vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 -0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC -B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u -NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg -yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev -HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6 -xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR -TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg -JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV -7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl -6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL ------END CERTIFICATE----- - -# Issuer: CN=GTS Root R3 O=Google Trust Services LLC -# Subject: CN=GTS Root R3 O=Google Trust Services LLC -# Label: "GTS Root R3" -# Serial: 159662495401136852707857743206 -# MD5 Fingerprint: 3e:e7:9d:58:02:94:46:51:94:e5:e0:22:4a:8b:e7:73 -# SHA1 Fingerprint: ed:e5:71:80:2b:c8:92:b9:5b:83:3c:d2:32:68:3f:09:cd:a0:1e:46 -# SHA256 Fingerprint: 34:d8:a7:3e:e2:08:d9:bc:db:0d:95:65:20:93:4b:4e:40:e6:94:82:59:6e:8b:6f:73:c8:42:6b:01:0a:6f:48 ------BEGIN CERTIFICATE----- -MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD -VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG -A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw -WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz -IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi -AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G -jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2 -4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7 -VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm -ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X ------END CERTIFICATE----- - -# Issuer: CN=GTS Root R4 O=Google Trust Services LLC -# Subject: CN=GTS Root R4 O=Google Trust Services LLC -# Label: "GTS Root R4" -# Serial: 159662532700760215368942768210 -# MD5 Fingerprint: 43:96:83:77:19:4d:76:b3:9d:65:52:e4:1d:22:a5:e8 -# SHA1 Fingerprint: 77:d3:03:67:b5:e0:0c:15:f6:0c:38:61:df:7c:e1:3b:92:46:4d:47 -# SHA256 Fingerprint: 34:9d:fa:40:58:c5:e2:63:12:3b:39:8a:e7:95:57:3c:4e:13:13:c8:3f:e6:8f:93:55:6c:d5:e8:03:1b:3c:7d ------BEGIN CERTIFICATE----- -MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD -VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG -A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw -WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz -IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi -AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi -QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR -HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D -9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8 -p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD ------END CERTIFICATE----- - -# Issuer: CN=Telia Root CA v2 O=Telia Finland Oyj -# Subject: CN=Telia Root CA v2 O=Telia Finland Oyj -# Label: "Telia Root CA v2" -# Serial: 7288924052977061235122729490515358 -# MD5 Fingerprint: 0e:8f:ac:aa:82:df:85:b1:f4:dc:10:1c:fc:99:d9:48 -# SHA1 Fingerprint: b9:99:cd:d1:73:50:8a:c4:47:05:08:9c:8c:88:fb:be:a0:2b:40:cd -# SHA256 Fingerprint: 24:2b:69:74:2f:cb:1e:5b:2a:bf:98:89:8b:94:57:21:87:54:4e:5b:4d:99:11:78:65:73:62:1f:6a:74:b8:2c ------BEGIN CERTIFICATE----- -MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQx -CzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UE -AwwQVGVsaWEgUm9vdCBDQSB2MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1 -NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZ -MBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ76zBq -AMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9 -vVYiQJ3q9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9 -lRdU2HhE8Qx3FZLgmEKnpNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTOD -n3WhUidhOPFZPY5Q4L15POdslv5e2QJltI5c0BE0312/UqeBAMN/mUWZFdUXyApT -7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW5olWK8jjfN7j/4nlNW4o -6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNrRBH0pUPC -TEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6 -WT0EBXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63R -DolUK5X6wK0dmBR4M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZI -pEYslOqodmJHixBTB0hXbOKSTbauBcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGj -YzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7Wxy+G2CQ5MB0GA1UdDgQWBBRy -rOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw -AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ -8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi -0f6X+J8wfBj5tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMM -A8iZGok1GTzTyVR8qPAs5m4HeW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBS -SRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+Cy748fdHif64W1lZYudogsYMVoe+K -TTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygCQMez2P2ccGrGKMOF -6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15h2Er -3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMt -Ty3EHD70sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pT -VmBds9hCG1xLEooc6+t9xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAW -ysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQraVplI/owd8k+BsHMYeB2F326CjYSlKA -rBPuUBQemMc= ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST BR Root CA 1 2020 O=D-Trust GmbH -# Subject: CN=D-TRUST BR Root CA 1 2020 O=D-Trust GmbH -# Label: "D-TRUST BR Root CA 1 2020" -# Serial: 165870826978392376648679885835942448534 -# MD5 Fingerprint: b5:aa:4b:d5:ed:f7:e3:55:2e:8f:72:0a:f3:75:b8:ed -# SHA1 Fingerprint: 1f:5b:98:f0:e3:b5:f7:74:3c:ed:e6:b0:36:7d:32:cd:f4:09:41:67 -# SHA256 Fingerprint: e5:9a:aa:81:60:09:c2:2b:ff:5b:25:ba:d3:7d:f3:06:f0:49:79:7c:1f:81:d8:5a:b0:89:e6:57:bd:8f:00:44 ------BEGIN CERTIFICATE----- -MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQsw -CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS -VVNUIEJSIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5 -NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG -A1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB -BAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7dPYS -zuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0 -QVK5buXuQqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/ -VbNafAkl1bK6CKBrqx9tMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g -PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2JyX3Jvb3Rf -Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l -dC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 -c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO -PQQDAwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFW -wKrY7RjEsK70PvomAjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHV -dWNbFJWcHwHP2NVypw87 ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST EV Root CA 1 2020 O=D-Trust GmbH -# Subject: CN=D-TRUST EV Root CA 1 2020 O=D-Trust GmbH -# Label: "D-TRUST EV Root CA 1 2020" -# Serial: 126288379621884218666039612629459926992 -# MD5 Fingerprint: 8c:2d:9d:70:9f:48:99:11:06:11:fb:e9:cb:30:c0:6e -# SHA1 Fingerprint: 61:db:8c:21:59:69:03:90:d8:7c:9c:12:86:54:cf:9d:3d:f4:dd:07 -# SHA256 Fingerprint: 08:17:0d:1a:a3:64:53:90:1a:2f:95:92:45:e3:47:db:0c:8d:37:ab:aa:bc:56:b8:1a:a1:00:dc:95:89:70:db ------BEGIN CERTIFICATE----- -MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQsw -CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS -VVNUIEVWIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5 -NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG -A1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB -BAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8ZRCC -/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rD -wpdhQntJraOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3 -OqQo5FD4pPfsazK2/umLMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g -PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2V2X3Jvb3Rf -Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l -dC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 -c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO -PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA -y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb -gfM0agPnIjhQW+0ZT0MW ------END CERTIFICATE----- - -# Issuer: CN=DigiCert TLS ECC P384 Root G5 O=DigiCert, Inc. -# Subject: CN=DigiCert TLS ECC P384 Root G5 O=DigiCert, Inc. -# Label: "DigiCert TLS ECC P384 Root G5" -# Serial: 13129116028163249804115411775095713523 -# MD5 Fingerprint: d3:71:04:6a:43:1c:db:a6:59:e1:a8:a3:aa:c5:71:ed -# SHA1 Fingerprint: 17:f3:de:5e:9f:0f:19:e9:8e:f6:1f:32:26:6e:20:c4:07:ae:30:ee -# SHA256 Fingerprint: 01:8e:13:f0:77:25:32:cf:80:9b:d1:b1:72:81:86:72:83:fc:48:c6:e1:3b:e9:c6:98:12:85:4a:49:0c:1b:05 ------BEGIN CERTIFICATE----- -MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp -Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2 -MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ -bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG -ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS -7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp -0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS -B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49 -BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ -LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4 -DXZDjC5Ty3zfDBeWUA== ------END CERTIFICATE----- - -# Issuer: CN=DigiCert TLS RSA4096 Root G5 O=DigiCert, Inc. -# Subject: CN=DigiCert TLS RSA4096 Root G5 O=DigiCert, Inc. -# Label: "DigiCert TLS RSA4096 Root G5" -# Serial: 11930366277458970227240571539258396554 -# MD5 Fingerprint: ac:fe:f7:34:96:a9:f2:b3:b4:12:4b:e4:27:41:6f:e1 -# SHA1 Fingerprint: a7:88:49:dc:5d:7c:75:8c:8c:de:39:98:56:b3:aa:d0:b2:a5:71:35 -# SHA256 Fingerprint: 37:1a:00:dc:05:33:b3:72:1a:7e:eb:40:e8:41:9e:70:79:9d:2b:0a:0f:2c:1d:80:69:31:65:f7:ce:c4:ad:75 ------BEGIN CERTIFICATE----- -MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN -MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT -HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN -NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs -IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+ -ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0 -2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp -wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM -pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD -nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po -sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx -Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd -Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX -KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe -XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL -tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv -TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN -AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw -GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H -PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF -O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ -REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik -AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv -/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+ -p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw -MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF -qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK -ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+ ------END CERTIFICATE----- - -# Issuer: CN=Certainly Root R1 O=Certainly -# Subject: CN=Certainly Root R1 O=Certainly -# Label: "Certainly Root R1" -# Serial: 188833316161142517227353805653483829216 -# MD5 Fingerprint: 07:70:d4:3e:82:87:a0:fa:33:36:13:f4:fa:33:e7:12 -# SHA1 Fingerprint: a0:50:ee:0f:28:71:f4:27:b2:12:6d:6f:50:96:25:ba:cc:86:42:af -# SHA256 Fingerprint: 77:b8:2c:d8:64:4c:43:05:f7:ac:c5:cb:15:6b:45:67:50:04:03:3d:51:c6:0c:62:02:a8:e0:c3:34:67:d3:a0 ------BEGIN CERTIFICATE----- -MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw -PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy -dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9 -MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0 -YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA2 -1B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQT -vqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbed -aFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b0 -1C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5 -r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5 -cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQ -wHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ -6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA -2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyH -Wyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMR -eiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB -/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6u -d0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQr -PbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d -8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi -1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrd -rRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9di -taY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7 -lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVj -yTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYn -Kx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLy -yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n -wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6 -OV+KmalBWQewLK8= ------END CERTIFICATE----- - -# Issuer: CN=Certainly Root E1 O=Certainly -# Subject: CN=Certainly Root E1 O=Certainly -# Label: "Certainly Root E1" -# Serial: 8168531406727139161245376702891150584 -# MD5 Fingerprint: 0a:9e:ca:cd:3e:52:50:c6:36:f3:4b:a3:ed:a7:53:e9 -# SHA1 Fingerprint: f9:e1:6d:dc:01:89:cf:d5:82:45:63:3e:c5:37:7d:c2:eb:93:6f:2b -# SHA256 Fingerprint: b4:58:5f:22:e4:ac:75:6a:4e:86:12:a1:36:1c:5d:9d:03:1a:93:fd:84:fe:bb:77:8f:a3:06:8b:0f:c4:2d:c2 ------BEGIN CERTIFICATE----- -MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw -CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu -bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ -BgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5s -eSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK -+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2 -QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4 -hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm -ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG -BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR ------END CERTIFICATE----- - -# Issuer: CN=Security Communication ECC RootCA1 O=SECOM Trust Systems CO.,LTD. -# Subject: CN=Security Communication ECC RootCA1 O=SECOM Trust Systems CO.,LTD. -# Label: "Security Communication ECC RootCA1" -# Serial: 15446673492073852651 -# MD5 Fingerprint: 7e:43:b0:92:68:ec:05:43:4c:98:ab:5d:35:2e:7e:86 -# SHA1 Fingerprint: b8:0e:26:a9:bf:d2:b2:3b:c0:ef:46:c9:ba:c7:bb:f6:1d:0d:41:41 -# SHA256 Fingerprint: e7:4f:bd:a5:5b:d5:64:c4:73:a3:6b:44:1a:a7:99:c8:a6:8e:07:74:40:e8:28:8b:9f:a1:e5:0e:4b:ba:ca:11 ------BEGIN CERTIFICATE----- -MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYT -AkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYD -VQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYx -NjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTELMAkGA1UEBhMCSlAxJTAjBgNVBAoT -HFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNVBAMTIlNlY3VyaXR5 -IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNi -AASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+Cnnfdl -dB9sELLo5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpK -ULGjQjBAMB0GA1UdDgQWBBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu -9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O -be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k= ------END CERTIFICATE----- - -# Issuer: CN=BJCA Global Root CA1 O=BEIJING CERTIFICATE AUTHORITY -# Subject: CN=BJCA Global Root CA1 O=BEIJING CERTIFICATE AUTHORITY -# Label: "BJCA Global Root CA1" -# Serial: 113562791157148395269083148143378328608 -# MD5 Fingerprint: 42:32:99:76:43:33:36:24:35:07:82:9b:28:f9:d0:90 -# SHA1 Fingerprint: d5:ec:8d:7b:4c:ba:79:f4:e7:e8:cb:9d:6b:ae:77:83:10:03:21:6a -# SHA256 Fingerprint: f3:89:6f:88:fe:7c:0a:88:27:66:a7:fa:6a:d2:74:9f:b5:7a:7f:3e:98:fb:76:9c:1f:a7:b0:9c:2c:44:d5:ae ------BEGIN CERTIFICATE----- -MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBU -MQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRI -T1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAz -MTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJF -SUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2Jh -bCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFmCL3Z -xRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZ -spDyRhySsTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O5 -58dnJCNPYwpj9mZ9S1WnP3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgR -at7GGPZHOiJBhyL8xIkoVNiMpTAK+BcWyqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll -5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRjeulumijWML3mG90Vr4Tq -nMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNnMoH1V6XK -V0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/ -pj+bOT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZO -z2nxbkRs1CTqjSShGL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXn -jSXWgXSHRtQpdaJCbPdzied9v3pKH9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+ -WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMBAAGjQjBAMB0GA1UdDgQWBBTF -7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE -AwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 -YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3Kli -awLwQ8hOnThJdMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u -+2D2/VnGKhs/I0qUJDAnyIm860Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88 -X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuhTaRjAv04l5U/BXCga99igUOLtFkN -SoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW4AB+dAb/OMRyHdOo -P2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmpGQrI -+pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRz -znfSxqxx4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9 -eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2 -YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezy -r/6zcCwupvI= ------END CERTIFICATE----- - -# Issuer: CN=BJCA Global Root CA2 O=BEIJING CERTIFICATE AUTHORITY -# Subject: CN=BJCA Global Root CA2 O=BEIJING CERTIFICATE AUTHORITY -# Label: "BJCA Global Root CA2" -# Serial: 58605626836079930195615843123109055211 -# MD5 Fingerprint: 5e:0a:f6:47:5f:a6:14:e8:11:01:95:3f:4d:01:eb:3c -# SHA1 Fingerprint: f4:27:86:eb:6e:b8:6d:88:31:67:02:fb:ba:66:a4:53:00:aa:7a:a6 -# SHA256 Fingerprint: 57:4d:f6:93:1e:27:80:39:66:7b:72:0a:fd:c1:60:0f:c2:7e:b6:6d:d3:09:29:79:fb:73:85:64:87:21:28:82 ------BEGIN CERTIFICATE----- -MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQsw -CQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJ -VFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgy -MVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJ -TkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBS -b290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jlSR9B -IgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK+ -+kpRuDCK/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJK -sVF/BvDRgh9Obl+rg/xI1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA -94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B -43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== ------END CERTIFICATE----- - -# Issuer: CN=Sectigo Public Server Authentication Root E46 O=Sectigo Limited -# Subject: CN=Sectigo Public Server Authentication Root E46 O=Sectigo Limited -# Label: "Sectigo Public Server Authentication Root E46" -# Serial: 88989738453351742415770396670917916916 -# MD5 Fingerprint: 28:23:f8:b2:98:5c:37:16:3b:3e:46:13:4e:b0:b3:01 -# SHA1 Fingerprint: ec:8a:39:6c:40:f0:2e:bc:42:75:d4:9f:ab:1c:1a:5b:67:be:d2:9a -# SHA256 Fingerprint: c9:0f:26:f0:fb:1b:40:18:b2:22:27:51:9b:5c:a2:b5:3e:2c:a5:b3:be:5c:f1:8e:fe:1b:ef:47:38:0c:53:83 ------BEGIN CERTIFICATE----- -MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw -CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T -ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN -MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG -A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT -ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC -WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+ -6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B -Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa -qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q -4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw== ------END CERTIFICATE----- - -# Issuer: CN=Sectigo Public Server Authentication Root R46 O=Sectigo Limited -# Subject: CN=Sectigo Public Server Authentication Root R46 O=Sectigo Limited -# Label: "Sectigo Public Server Authentication Root R46" -# Serial: 156256931880233212765902055439220583700 -# MD5 Fingerprint: 32:10:09:52:00:d5:7e:6c:43:df:15:c0:b1:16:93:e5 -# SHA1 Fingerprint: ad:98:f9:f3:e4:7d:75:3b:65:d4:82:b3:a4:52:17:bb:6e:f5:e4:38 -# SHA256 Fingerprint: 7b:b6:47:a6:2a:ee:ac:88:bf:25:7a:a5:22:d0:1f:fe:a3:95:e0:ab:45:c7:3f:93:f6:56:54:ec:38:f2:5a:06 ------BEGIN CERTIFICATE----- -MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf -MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD -Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw -HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY -MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp -YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa -ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz -SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf -iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X -ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3 -IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS -VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE -SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu -+Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt -8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L -HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt -zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P -AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c -mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ -YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52 -gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA -Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB -JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX -DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui -TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5 -dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65 -LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp -0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY -QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL ------END CERTIFICATE----- - -# Issuer: CN=SSL.com TLS RSA Root CA 2022 O=SSL Corporation -# Subject: CN=SSL.com TLS RSA Root CA 2022 O=SSL Corporation -# Label: "SSL.com TLS RSA Root CA 2022" -# Serial: 148535279242832292258835760425842727825 -# MD5 Fingerprint: d8:4e:c6:59:30:d8:fe:a0:d6:7a:5a:2c:2c:69:78:da -# SHA1 Fingerprint: ec:2c:83:40:72:af:26:95:10:ff:0e:f2:03:ee:31:70:f6:78:9d:ca -# SHA256 Fingerprint: 8f:af:7d:2e:2c:b4:70:9b:b8:e0:b3:36:66:bf:75:a5:dd:45:b5:de:48:0f:8e:a8:d4:bf:e6:be:bc:17:f2:ed ------BEGIN CERTIFICATE----- -MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO -MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD -DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX -DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw -b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC -AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP -L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY -t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins -S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3 -PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO -L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3 -R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w -dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS -+YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS -d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG -AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f -gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j -BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z -NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt -hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM -QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf -R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ -DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW -P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy -lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq -bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w -AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q -r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji -Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU -98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= ------END CERTIFICATE----- - -# Issuer: CN=SSL.com TLS ECC Root CA 2022 O=SSL Corporation -# Subject: CN=SSL.com TLS ECC Root CA 2022 O=SSL Corporation -# Label: "SSL.com TLS ECC Root CA 2022" -# Serial: 26605119622390491762507526719404364228 -# MD5 Fingerprint: 99:d7:5c:f1:51:36:cc:e9:ce:d9:19:2e:77:71:56:c5 -# SHA1 Fingerprint: 9f:5f:d9:1a:54:6d:f5:0c:71:f0:ee:7a:bd:17:49:98:84:73:e2:39 -# SHA256 Fingerprint: c3:2f:fd:9f:46:f9:36:d1:6c:36:73:99:09:59:43:4b:9a:d6:0a:af:bb:9e:7c:f3:36:54:f1:44:cc:1b:a1:43 ------BEGIN CERTIFICATE----- -MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw -CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT -U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2 -MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh -dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG -ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm -acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN -SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME -GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW -uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp -15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN -b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g== ------END CERTIFICATE----- - -# Issuer: CN=Atos TrustedRoot Root CA ECC TLS 2021 O=Atos -# Subject: CN=Atos TrustedRoot Root CA ECC TLS 2021 O=Atos -# Label: "Atos TrustedRoot Root CA ECC TLS 2021" -# Serial: 81873346711060652204712539181482831616 -# MD5 Fingerprint: 16:9f:ad:f1:70:ad:79:d6:ed:29:b4:d1:c5:79:70:a8 -# SHA1 Fingerprint: 9e:bc:75:10:42:b3:02:f3:81:f4:f7:30:62:d4:8f:c3:a7:51:b2:dd -# SHA256 Fingerprint: b2:fa:e5:3e:14:cc:d7:ab:92:12:06:47:01:ae:27:9c:1d:89:88:fa:cb:77:5f:a8:a0:08:91:4e:66:39:88:a8 ------BEGIN CERTIFICATE----- -MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4w -LAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0w -CwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0 -MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBF -Q0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMHYwEAYHKoZI -zj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6KDP/X -tXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4 -AjJn8ZQSb+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2 -KCXWfeBmmnoJsmo7jjPXNtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMD -aAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtu -CCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo -9H1/IISpQuQo ------END CERTIFICATE----- - -# Issuer: CN=Atos TrustedRoot Root CA RSA TLS 2021 O=Atos -# Subject: CN=Atos TrustedRoot Root CA RSA TLS 2021 O=Atos -# Label: "Atos TrustedRoot Root CA RSA TLS 2021" -# Serial: 111436099570196163832749341232207667876 -# MD5 Fingerprint: d4:d3:46:b8:9a:c0:9c:76:5d:9e:3a:c3:b9:99:31:d2 -# SHA1 Fingerprint: 18:52:3b:0d:06:37:e4:d6:3a:df:23:e4:98:fb:5b:16:fb:86:74:48 -# SHA256 Fingerprint: 81:a9:08:8e:a5:9f:b3:64:c5:48:a6:f8:55:59:09:9b:6f:04:05:ef:bf:18:e5:32:4e:c9:f4:57:ba:00:11:2f ------BEGIN CERTIFICATE----- -MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBM -MS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIx -MQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00 -MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBD -QSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMIICIjAN -BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BBl01Z -4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYv -Ye+W/CBGvevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZ -kmGbzSoXfduP9LVq6hdKZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDs -GY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt0xU6kGpn8bRrZtkh68rZYnxGEFzedUln -nkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVKPNe0OwANwI8f4UDErmwh -3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMYsluMWuPD -0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzy -geBYBr3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8 -ANSbhqRAvNncTFd+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezB -c6eUWsuSZIKmAMFwoW4sKeFYV+xafJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lI -pw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU -dEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB -DAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS -4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPs -o0UvFJ/1TCplQ3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJ -qM7F78PRreBrAwA0JrRUITWXAdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuyw -xfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9GslA9hGCZcbUztVdF5kJHdWoOsAgM -rr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2VktafcxBPTy+av5EzH4 -AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9qTFsR -0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuY -o7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5 -dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcE -oji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ== ------END CERTIFICATE----- - -# Issuer: CN=TrustAsia Global Root CA G3 O=TrustAsia Technologies, Inc. -# Subject: CN=TrustAsia Global Root CA G3 O=TrustAsia Technologies, Inc. -# Label: "TrustAsia Global Root CA G3" -# Serial: 576386314500428537169965010905813481816650257167 -# MD5 Fingerprint: 30:42:1b:b7:bb:81:75:35:e4:16:4f:53:d2:94:de:04 -# SHA1 Fingerprint: 63:cf:b6:c1:27:2b:56:e4:88:8e:1c:23:9a:b6:2e:81:47:24:c3:c7 -# SHA256 Fingerprint: e0:d3:22:6a:eb:11:63:c2:e4:8f:f9:be:3b:50:b4:c6:43:1b:e7:bb:1e:ac:c5:c3:6b:5d:5e:c5:09:03:9a:08 ------BEGIN CERTIFICATE----- -MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEM -BQAwWjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dp -ZXMsIEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAe -Fw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEwMTlaMFoxCzAJBgNVBAYTAkNOMSUw -IwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtU -cnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUAA4IC -DwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNS -T1QY4SxzlZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqK -AtCWHwDNBSHvBm3dIZwZQ0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1 -nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/VP68czH5GX6zfZBCK70bwkPAPLfSIC7Ep -qq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1AgdB4SQXMeJNnKziyhWTXA -yB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm9WAPzJMs -hH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gX -zhqcD0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAv -kV34PmVACxmZySYgWmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msT -f9FkPz2ccEblooV7WIQn3MSAPmeamseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jA -uPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCFTIcQcf+eQxuulXUtgQIDAQAB -o2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj7zjKsK5Xf/Ih -MBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E -BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4 -wM8zAQLpw6o1D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2 -XFNFV1pF1AWZLy4jVe5jaN/TG3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1 -JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNjduMNhXJEIlU/HHzp/LgV6FL6qj6j -ITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstlcHboCoWASzY9M/eV -VHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys+TIx -xHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1on -AX1daBli2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d -7XB4tmBZrOFdRWOPyN9yaFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2Ntjj -gKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsASZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV -+Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFRJQJ6+N1rZdVtTTDIZbpo -FGWsJwt0ivKH ------END CERTIFICATE----- - -# Issuer: CN=TrustAsia Global Root CA G4 O=TrustAsia Technologies, Inc. -# Subject: CN=TrustAsia Global Root CA G4 O=TrustAsia Technologies, Inc. -# Label: "TrustAsia Global Root CA G4" -# Serial: 451799571007117016466790293371524403291602933463 -# MD5 Fingerprint: 54:dd:b2:d7:5f:d8:3e:ed:7c:e0:0b:2e:cc:ed:eb:eb -# SHA1 Fingerprint: 57:73:a5:61:5d:80:b2:e6:ac:38:82:fc:68:07:31:ac:9f:b5:92:5a -# SHA256 Fingerprint: be:4b:56:cb:50:56:c0:13:6a:52:6d:f4:44:50:8d:aa:36:a0:b5:4f:42:e4:ac:38:f7:2a:f4:70:e4:79:65:4c ------BEGIN CERTIFICATE----- -MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMw -WjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs -IEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0y -MTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJaMFoxCzAJBgNVBAYTAkNOMSUwIwYD -VQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtUcnVz -dEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATx -s8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbw -LxYI+hW8m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJij -YzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mD -pm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/pDHel4NZg6ZvccveMA4GA1UdDwEB/wQE -AwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AAbbd+NvBNEU/zy4k6LHiR -UKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xkdUfFVZDj -/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA== ------END CERTIFICATE----- - -# Issuer: CN=Telekom Security TLS ECC Root 2020 O=Deutsche Telekom Security GmbH -# Subject: CN=Telekom Security TLS ECC Root 2020 O=Deutsche Telekom Security GmbH -# Label: "Telekom Security TLS ECC Root 2020" -# Serial: 72082518505882327255703894282316633856 -# MD5 Fingerprint: c1:ab:fe:6a:10:2c:03:8d:bc:1c:22:32:c0:85:a7:fd -# SHA1 Fingerprint: c0:f8:96:c5:a9:3b:01:06:21:07:da:18:42:48:bc:e9:9d:88:d5:ec -# SHA256 Fingerprint: 57:8a:f4:de:d0:85:3f:4e:59:98:db:4a:ea:f9:cb:ea:8d:94:5f:60:b6:20:a3:8d:1a:3c:13:b2:bc:7b:a8:e1 ------BEGIN CERTIFICATE----- -MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQsw -CQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBH -bWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIw -MB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIzNTk1OVowYzELMAkGA1UEBhMCREUx -JzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkGA1UE -AwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqGSM49 -AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/O -tdKPD/M12kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDP -f8iAC8GXs7s1J8nCG6NCMEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6f -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2cA -MGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZMo7k+5Dck2TOrbRBR2Di -z6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdUga/sf+Rn -27iQ7t0l ------END CERTIFICATE----- - -# Issuer: CN=Telekom Security TLS RSA Root 2023 O=Deutsche Telekom Security GmbH -# Subject: CN=Telekom Security TLS RSA Root 2023 O=Deutsche Telekom Security GmbH -# Label: "Telekom Security TLS RSA Root 2023" -# Serial: 44676229530606711399881795178081572759 -# MD5 Fingerprint: bf:5b:eb:54:40:cd:48:71:c4:20:8d:7d:de:0a:42:f2 -# SHA1 Fingerprint: 54:d3:ac:b3:bd:57:56:f6:85:9d:ce:e5:c3:21:e2:d4:ad:83:d0:93 -# SHA256 Fingerprint: ef:c6:5c:ad:bb:59:ad:b6:ef:e8:4d:a2:23:11:b3:56:24:b7:1b:3b:1e:a0:da:8b:66:55:17:4e:c8:97:86:46 ------BEGIN CERTIFICATE----- -MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBj -MQswCQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0 -eSBHbWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAy -MDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMyNzIzNTk1OVowYzELMAkGA1UEBhMC -REUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkG -A1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9 -cUD/h3VCKSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHV -cp6R+SPWcHu79ZvB7JPPGeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMA -U6DksquDOFczJZSfvkgdmOGjup5czQRxUX11eKvzWarE4GC+j4NSuHUaQTXtvPM6 -Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWol8hHD/BeEIvnHRz+sTug -BTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9FIS3R/qy -8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73J -co4vzLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg -8qKrBC7m8kwOFjQgrIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8 -rFEz0ciD0cmfHdRHNCk+y7AO+oMLKFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12 -mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7SWWO/gLCMk3PLNaaZlSJhZQNg -+y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtqeX -gj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2 -p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQ -pGv7qHBFfLp+sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm -9S3ul0A8Yute1hTWjOKWi0FpkzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErw -M807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy/SKE8YXJN3nptT+/XOR0so8RYgDd -GGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4mZqTuXNnQkYRIer+ -CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtzaL1t -xKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+ -w6jv/naaoqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aK -L4x35bcF7DvB7L6Gs4a8wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+lj -X273CXE2whJdV/LItM3z7gLfEdxquVeEHVlNjM7IDiPCtyaaEBRx/pOyiriA8A4Q -ntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0o82bNSQ3+pCTE4FCxpgm -dTdmQRCsu/WU48IxK63nI1bMNSWSs1A= ------END CERTIFICATE----- - -# Issuer: CN=FIRMAPROFESIONAL CA ROOT-A WEB O=Firmaprofesional SA -# Subject: CN=FIRMAPROFESIONAL CA ROOT-A WEB O=Firmaprofesional SA -# Label: "FIRMAPROFESIONAL CA ROOT-A WEB" -# Serial: 65916896770016886708751106294915943533 -# MD5 Fingerprint: 82:b2:ad:45:00:82:b0:66:63:f8:5f:c3:67:4e:ce:a3 -# SHA1 Fingerprint: a8:31:11:74:a6:14:15:0d:ca:77:dd:0e:e4:0c:5d:58:fc:a0:72:a5 -# SHA256 Fingerprint: be:f2:56:da:f2:6e:9c:69:bd:ec:16:02:35:97:98:f3:ca:f7:18:21:a0:3e:01:82:57:c5:3c:65:61:7f:3d:4a ------BEGIN CERTIFICATE----- -MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQsw -CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE -YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB -IFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2WhcNNDcwMzMxMDkwMTM2WjBuMQsw -CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE -YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB -IFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zf -e9MEkVz6iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6C -cyvHZpsKjECcfIr28jlgst7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB -/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FDY1w8ndYn81LsF7Kpryz3dvgwHQYDVR0O -BBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO -PQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgLcFBTApFw -hVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dG -XSaQpYXFuXqUPoeovQA= ------END CERTIFICATE----- - -# Issuer: CN=TWCA CYBER Root CA O=TAIWAN-CA OU=Root CA -# Subject: CN=TWCA CYBER Root CA O=TAIWAN-CA OU=Root CA -# Label: "TWCA CYBER Root CA" -# Serial: 85076849864375384482682434040119489222 -# MD5 Fingerprint: 0b:33:a0:97:52:95:d4:a9:fd:bb:db:6e:a3:55:5b:51 -# SHA1 Fingerprint: f6:b1:1c:1a:83:38:e9:7b:db:b3:a8:c8:33:24:e0:2d:9c:7f:26:66 -# SHA256 Fingerprint: 3f:63:bb:28:14:be:17:4e:c8:b6:43:9c:f0:8d:6d:56:f0:b7:c4:05:88:3a:56:48:a3:34:42:4d:6b:3e:c5:58 ------BEGIN CERTIFICATE----- -MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQ -MQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290 -IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5 -WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FO -LUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3Qg -Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1sTs6P -40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxF -avcokPFhV8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/ -34bKS1PE2Y2yHer43CdTo0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684i -JkXXYJndzk834H/nY62wuFm40AZoNWDTNq5xQwTxaWV4fPMf88oon1oglWa0zbfu -j3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK/c/WMw+f+5eesRycnupf -Xtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkHIuNZW0CP -2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDA -S9TMfAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDA -oS/xUgXJP+92ZuJF2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzC -kHDXShi8fgGwsOsVHkQGzaRP6AzRwyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW -5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83QOGt4A1WNzAd -BgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB -AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0t -tGlTITVX1olNc79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn -68xDiBaiA9a5F/gZbG0jAn/xX9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNn -TKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDRIG4kqIQnoVesqlVYL9zZyvpoBJ7t -RCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq/p1hvIbZv97Tujqx -f36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0RFxbI -Qh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz -8ppy6rBePm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4 -NxKfKjLji7gh7MMrZQzvIt6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzX -xeSDwWrruoBa3lwtcHb4yOWHh8qgnaHlIhInD0Q9HWzq1MKLL295q39QpsQZp6F6 -t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X ------END CERTIFICATE----- - -# Issuer: CN=SecureSign Root CA12 O=Cybertrust Japan Co., Ltd. -# Subject: CN=SecureSign Root CA12 O=Cybertrust Japan Co., Ltd. -# Label: "SecureSign Root CA12" -# Serial: 587887345431707215246142177076162061960426065942 -# MD5 Fingerprint: c6:89:ca:64:42:9b:62:08:49:0b:1e:7f:e9:07:3d:e8 -# SHA1 Fingerprint: 7a:22:1e:3d:de:1b:06:ac:9e:c8:47:70:16:8e:3c:e5:f7:6b:06:f4 -# SHA256 Fingerprint: 3f:03:4b:b5:70:4d:44:b2:d0:85:45:a0:20:57:de:93:eb:f3:90:5f:ce:72:1a:cb:c7:30:c0:6d:da:ee:90:4e ------BEGIN CERTIFICATE----- -MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQEL -BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u -LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgw -NTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD -eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS -b290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3emhF -KxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mt -p7JIKwccJ/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zd -J1M3s6oYwlkm7Fsf0uZlfO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gur -FzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBFEaCeVESE99g2zvVQR9wsMJvuwPWW0v4J -hscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1UefNzFJM3IFTQy2VYzxV4+K -h9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsF -AAOCAQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6Ld -mmQOmFxv3Y67ilQiLUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJ -mBClnW8Zt7vPemVV2zfrPIpyMpcemik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA -8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPSvWKErI4cqc1avTc7bgoitPQV -55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhgaaaI5gdka9at/ -yOPiZwud9AzqVN/Ssq+xIvEg37xEHA== ------END CERTIFICATE----- - -# Issuer: CN=SecureSign Root CA14 O=Cybertrust Japan Co., Ltd. -# Subject: CN=SecureSign Root CA14 O=Cybertrust Japan Co., Ltd. -# Label: "SecureSign Root CA14" -# Serial: 575790784512929437950770173562378038616896959179 -# MD5 Fingerprint: 71:0d:72:fa:92:19:65:5e:89:04:ac:16:33:f0:bc:d5 -# SHA1 Fingerprint: dd:50:c0:f7:79:b3:64:2e:74:a2:b8:9d:9f:d3:40:dd:bb:f0:f2:4f -# SHA256 Fingerprint: 4b:00:9c:10:34:49:4f:9a:b5:6b:ba:3b:a1:d6:27:31:fc:4d:20:d8:95:5a:dc:ec:10:a9:25:60:72:61:e3:38 ------BEGIN CERTIFICATE----- -MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEM -BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u -LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgw -NzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD -eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS -b290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh1oq/ -FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOg -vlIfX8xnbacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy -6pJxaeQp8E+BgQQ8sqVb1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo -/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9J -kdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOEkJTRX45zGRBdAuVwpcAQ -0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSxjVIHvXib -y8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac -18izju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs -0Wq2XSqypWa9a4X0dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIAB -SMbHdPTGrMNASRZhdCyvjG817XsYAFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVL -ApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeqYR3r6/wtbyPk -86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E -rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ib -ed87hwriZLoAymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopT -zfFP7ELyk+OZpDc8h7hi2/DsHzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHS -DCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPGFrojutzdfhrGe0K22VoF3Jpf1d+4 -2kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6qnsb58Nn4DSEC5MUo -FlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/OfVy -K4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6 -dB7h7sxaOgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtl -Lor6CZpO2oYofaphNdgOpygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB -365jJ6UeTo3cKXhZ+PmhIIynJkBugnLNeLLIjzwec+fBH7/PzqUqm9tEZDKgu39c -JRNItX+S ------END CERTIFICATE----- - -# Issuer: CN=SecureSign Root CA15 O=Cybertrust Japan Co., Ltd. -# Subject: CN=SecureSign Root CA15 O=Cybertrust Japan Co., Ltd. -# Label: "SecureSign Root CA15" -# Serial: 126083514594751269499665114766174399806381178503 -# MD5 Fingerprint: 13:30:fc:c4:62:a6:a9:de:b5:c1:68:af:b5:d2:31:47 -# SHA1 Fingerprint: cb:ba:83:c8:c1:5a:5d:f1:f9:73:6f:ca:d7:ef:28:13:06:4a:07:7d -# SHA256 Fingerprint: e7:78:f0:f0:95:fe:84:37:29:cd:1a:00:82:17:9e:53:14:a9:c2:91:44:28:05:e1:fb:1d:8f:b6:b8:88:6c:3a ------BEGIN CERTIFICATE----- -MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMw -UTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBM -dGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMy -NTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJl -cnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290 -IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5GdCx4 -wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSR -ZHX+AezB2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT -9DAKBggqhkjOPQQDAwNoADBlAjEA2S6Jfl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp -4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJSwdLZrWeqrqgHkHZAXQ6 -bkU6iYAZezKYVWOr62Nuk22rGwlgMU4= ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST BR Root CA 2 2023 O=D-Trust GmbH -# Subject: CN=D-TRUST BR Root CA 2 2023 O=D-Trust GmbH -# Label: "D-TRUST BR Root CA 2 2023" -# Serial: 153168538924886464690566649552453098598 -# MD5 Fingerprint: e1:09:ed:d3:60:d4:56:1b:47:1f:b7:0c:5f:1b:5f:85 -# SHA1 Fingerprint: 2d:b0:70:ee:71:94:af:69:68:17:db:79:ce:58:9f:a0:6b:96:f7:87 -# SHA256 Fingerprint: 05:52:e6:f8:3f:df:65:e8:fa:96:70:e6:66:df:28:a4:e2:13:40:b5:10:cb:e5:25:66:f9:7c:4f:b9:4b:2b:d1 ------BEGIN CERTIFICATE----- -MIIFqTCCA5GgAwIBAgIQczswBEhb2U14LnNLyaHcZjANBgkqhkiG9w0BAQ0FADBI -MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE -LVRSVVNUIEJSIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA4NTYzMVoXDTM4MDUw -OTA4NTYzMFowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi -MCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBAK7/CVmRgApKaOYkP7in5Mg6CjoWzckjYaCTcfKr -i3OPoGdlYNJUa2NRb0kz4HIHE304zQaSBylSa053bATTlfrdTIzZXcFhfUvnKLNE -gXtRr90zsWh81k5M/itoucpmacTsXld/9w3HnDY25QdgrMBM6ghs7wZ8T1soegj8 -k12b9py0i4a6Ibn08OhZWiihNIQaJZG2tY/vsvmA+vk9PBFy2OMvhnbFeSzBqZCT -Rphny4NqoFAjpzv2gTng7fC5v2Xx2Mt6++9zA84A9H3X4F07ZrjcjrqDy4d2A/wl -2ecjbwb9Z/Pg/4S8R7+1FhhGaRTMBffb00msa8yr5LULQyReS2tNZ9/WtT5PeB+U -cSTq3nD88ZP+npNa5JRal1QMNXtfbO4AHyTsA7oC9Xb0n9Sa7YUsOCIvx9gvdhFP -/Wxc6PWOJ4d/GUohR5AdeY0cW/jPSoXk7bNbjb7EZChdQcRurDhaTyN0dKkSw/bS -uREVMweR2Ds3OmMwBtHFIjYoYiMQ4EbMl6zWK11kJNXuHA7e+whadSr2Y23OC0K+ -0bpwHJwh5Q8xaRfX/Aq03u2AnMuStIv13lmiWAmlY0cL4UEyNEHZmrHZqLAbWt4N -DfTisl01gLmB1IRpkQLLddCNxbU9CZEJjxShFHR5PtbJFR2kWVki3PaKRT08EtY+ -XTIvAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUZ5Dw1t61 -GNVGKX5cq/ieCLxklRAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG -OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfYnJfcm9vdF9jYV8y -XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQA097N3U9swFrktpSHxQCF16+tI -FoE9c+CeJyrrd6kTpGoKWloUMz1oH4Guaf2Mn2VsNELZLdB/eBaxOqwjMa1ef67n -riv6uvw8l5VAk1/DLQOj7aRvU9f6QA4w9QAgLABMjDu0ox+2v5Eyq6+SmNMW5tTR -VFxDWy6u71cqqLRvpO8NVhTaIasgdp4D/Ca4nj8+AybmTNudX0KEPUUDAxxZiMrc -LmEkWqTqJwtzEr5SswrPMhfiHocaFpVIbVrg0M8JkiZmkdijYQ6qgYF/6FKC0ULn -4B0Y+qSFNueG4A3rvNTJ1jxD8V1Jbn6Bm2m1iWKPiFLY1/4nwSPFyysCu7Ff/vtD -hQNGvl3GyiEm/9cCnnRK3PgTFbGBVzbLZVzRHTF36SXDw7IyN9XxmAnkbWOACKsG -koHU6XCPpz+y7YaMgmo1yEJagtFSGkUPFaUA8JR7ZSdXOUPPfH/mvTWze/EZTN46 -ls/pdu4D58JDUjxqgejBWoC9EV2Ta/vH5mQ/u2kc6d0li690yVRAysuTEwrt+2aS -Ecr1wPrYg1UDfNPFIkZ1cGt5SAYqgpq/5usWDiJFAbzdNpQ0qTUmiteXue4Icr80 -knCDgKs4qllo3UCkGJCy89UDyibK79XH4I9TjvAA46jtn/mtd+ArY0+ew+43u3gJ -hJ65bvspmZDogNOfJA== ------END CERTIFICATE----- - -# Issuer: CN=TrustAsia TLS ECC Root CA O=TrustAsia Technologies, Inc. -# Subject: CN=TrustAsia TLS ECC Root CA O=TrustAsia Technologies, Inc. -# Label: "TrustAsia TLS ECC Root CA" -# Serial: 310892014698942880364840003424242768478804666567 -# MD5 Fingerprint: 09:48:04:77:d2:fc:65:93:71:66:b1:11:95:4f:06:8c -# SHA1 Fingerprint: b5:ec:39:f3:a1:66:37:ae:c3:05:94:57:e2:be:11:be:b7:a1:7f:36 -# SHA256 Fingerprint: c0:07:6b:9e:f0:53:1f:b1:a6:56:d6:7c:4e:be:97:cd:5d:ba:a4:1e:f4:45:98:ac:c2:48:98:78:c9:2d:87:11 ------BEGIN CERTIFICATE----- -MIICMTCCAbegAwIBAgIUNnThTXxlE8msg1UloD5Sfi9QaMcwCgYIKoZIzj0EAwMw -WDELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs -IEluYy4xIjAgBgNVBAMTGVRydXN0QXNpYSBUTFMgRUNDIFJvb3QgQ0EwHhcNMjQw -NTE1MDU0MTU2WhcNNDQwNTE1MDU0MTU1WjBYMQswCQYDVQQGEwJDTjElMCMGA1UE -ChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5jLjEiMCAGA1UEAxMZVHJ1c3RB -c2lhIFRMUyBFQ0MgUm9vdCBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLh/pVs/ -AT598IhtrimY4ZtcU5nb9wj/1WrgjstEpvDBjL1P1M7UiFPoXlfXTr4sP/MSpwDp -guMqWzJ8S5sUKZ74LYO1644xST0mYekdcouJtgq7nDM1D9rs3qlKH8kzsaNCMEAw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQULIVTu7FDzTLqnqOH/qKYqKaT6RAw -DgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMFRH18MtYYZI9HlaVQ01 -L18N9mdsd0AaRuf4aFtOJx24mH1/k78ITcTaRTChD15KeAIxAKORh/IRM4PDwYqR -OkwrULG9IpRdNYlzg8WbGf60oenUoWa2AaU2+dhoYSi3dOGiMQ== ------END CERTIFICATE----- - -# Issuer: CN=TrustAsia TLS RSA Root CA O=TrustAsia Technologies, Inc. -# Subject: CN=TrustAsia TLS RSA Root CA O=TrustAsia Technologies, Inc. -# Label: "TrustAsia TLS RSA Root CA" -# Serial: 160405846464868906657516898462547310235378010780 -# MD5 Fingerprint: 3b:9e:c3:86:0f:34:3c:6b:c5:46:c4:8e:1d:e7:19:12 -# SHA1 Fingerprint: a5:46:50:c5:62:ea:95:9a:1a:a7:04:6f:17:58:c7:29:53:3d:03:fa -# SHA256 Fingerprint: 06:c0:8d:7d:af:d8:76:97:1e:b1:12:4f:e6:7f:84:7e:c0:c7:a1:58:d3:ea:53:cb:e9:40:e2:ea:97:91:f4:c3 ------BEGIN CERTIFICATE----- -MIIFgDCCA2igAwIBAgIUHBjYz+VTPyI1RlNUJDxsR9FcSpwwDQYJKoZIhvcNAQEM -BQAwWDELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dp -ZXMsIEluYy4xIjAgBgNVBAMTGVRydXN0QXNpYSBUTFMgUlNBIFJvb3QgQ0EwHhcN -MjQwNTE1MDU0MTU3WhcNNDQwNTE1MDU0MTU2WjBYMQswCQYDVQQGEwJDTjElMCMG -A1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5jLjEiMCAGA1UEAxMZVHJ1 -c3RBc2lhIFRMUyBSU0EgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC -AgoCggIBAMMWuBtqpERz5dZO9LnPWwvB0ZqB9WOwj0PBuwhaGnrhB3YmH49pVr7+ -NmDQDIPNlOrnxS1cLwUWAp4KqC/lYCZUlviYQB2srp10Zy9U+5RjmOMmSoPGlbYJ -Q1DNDX3eRA5gEk9bNb2/mThtfWza4mhzH/kxpRkQcwUqwzIZheo0qt1CHjCNP561 -HmHVb70AcnKtEj+qpklz8oYVlQwQX1Fkzv93uMltrOXVmPGZLmzjyUT5tUMnCE32 -ft5EebuyjBza00tsLtbDeLdM1aTk2tyKjg7/D8OmYCYozza/+lcK7Fs/6TAWe8Tb -xNRkoDD75f0dcZLdKY9BWN4ArTr9PXwaqLEX8E40eFgl1oUh63kd0Nyrz2I8sMeX -i9bQn9P+PN7F4/w6g3CEIR0JwqH8uyghZVNgepBtljhb//HXeltt08lwSUq6HTrQ -UNoyIBnkiz/r1RYmNzz7dZ6wB3C4FGB33PYPXFIKvF1tjVEK2sUYyJtt3LCDs3+j -TnhMmCWr8n4uIF6CFabW2I+s5c0yhsj55NqJ4js+k8UTav/H9xj8Z7XvGCxUq0DT -bE3txci3OE9kxJRMT6DNrqXGJyV1J23G2pyOsAWZ1SgRxSHUuPzHlqtKZFlhaxP8 -S8ySpg+kUb8OWJDZgoM5pl+z+m6Ss80zDoWo8SnTq1mt1tve1CuBAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLgHkXlcBvRG/XtZylomkadFK/hT -MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQwFAAOCAgEAIZtqBSBdGBanEqT3 -Rz/NyjuujsCCztxIJXgXbODgcMTWltnZ9r96nBO7U5WS/8+S4PPFJzVXqDuiGev4 -iqME3mmL5Dw8veWv0BIb5Ylrc5tvJQJLkIKvQMKtuppgJFqBTQUYo+IzeXoLH5Pt -7DlK9RME7I10nYEKqG/odv6LTytpEoYKNDbdgptvT+Bz3Ul/KD7JO6NXBNiT2Twp -2xIQaOHEibgGIOcberyxk2GaGUARtWqFVwHxtlotJnMnlvm5P1vQiJ3koP26TpUJ -g3933FEFlJ0gcXax7PqJtZwuhfG5WyRasQmr2soaB82G39tp27RIGAAtvKLEiUUj -pQ7hRGU+isFqMB3iYPg6qocJQrmBktwliJiJ8Xw18WLK7nn4GS/+X/jbh87qqA8M -pugLoDzga5SYnH+tBuYc6kIQX+ImFTw3OffXvO645e8D7r0i+yiGNFjEWn9hongP -XvPKnbwbPKfILfanIhHKA9jnZwqKDss1jjQ52MjqjZ9k4DewbNfFj8GQYSbbJIwe -SsCI3zWQzj8C9GRh3sfIB5XeMhg6j6JCQCTl1jNdfK7vsU1P1FeQNWrcrgSXSYk0 -ly4wBOeY99sLAZDBHwo/+ML+TvrbmnNzFrwFuHnYWa8G5z9nODmxfKuU4CkUpijy -323imttUQ/hHWKNddBWcwauwxzQ= ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST EV Root CA 2 2023 O=D-Trust GmbH -# Subject: CN=D-TRUST EV Root CA 2 2023 O=D-Trust GmbH -# Label: "D-TRUST EV Root CA 2 2023" -# Serial: 139766439402180512324132425437959641711 -# MD5 Fingerprint: 96:b4:78:09:f0:09:cb:77:eb:bb:1b:4d:6f:36:bc:b6 -# SHA1 Fingerprint: a5:5b:d8:47:6c:8f:19:f7:4c:f4:6d:6b:b6:c2:79:82:22:df:54:8b -# SHA256 Fingerprint: 8e:82:21:b2:e7:d4:00:78:36:a1:67:2f:0d:cc:29:9c:33:bc:07:d3:16:f1:32:fa:1a:20:6d:58:71:50:f1:ce ------BEGIN CERTIFICATE----- -MIIFqTCCA5GgAwIBAgIQaSYJfoBLTKCnjHhiU19abzANBgkqhkiG9w0BAQ0FADBI -MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE -LVRSVVNUIEVWIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA5MTAzM1oXDTM4MDUw -OTA5MTAzMlowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi -MCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBANiOo4mAC7JXUtypU0w3uX9jFxPvp1sjW2l1sJkK -F8GLxNuo4MwxusLyzV3pt/gdr2rElYfXR8mV2IIEUD2BCP/kPbOx1sWy/YgJ25yE -7CUXFId/MHibaljJtnMoPDT3mfd/06b4HEV8rSyMlD/YZxBTfiLNTiVR8CUkNRFe -EMbsh2aJgWi6zCudR3Mfvc2RpHJqnKIbGKBv7FD0fUDCqDDPvXPIEysQEx6Lmqg6 -lHPTGGkKSv/BAQP/eX+1SH977ugpbzZMlWGG2Pmic4ruri+W7mjNPU0oQvlFKzIb -RlUWaqZLKfm7lVa/Rh3sHZMdwGWyH6FDrlaeoLGPaxK3YG14C8qKXO0elg6DpkiV -jTujIcSuWMYAsoS0I6SWhjW42J7YrDRJmGOVxcttSEfi8i4YHtAxq9107PncjLgc -jmgjutDzUNzPZY9zOjLHfP7KgiJPvo5iR2blzYfi6NUPGJ/lBHJLRjwQ8kTCZFZx -TnXonMkmdMV9WdEKWw9t/p51HBjGGjp82A0EzM23RWV6sY+4roRIPrN6TagD4uJ+ -ARZZaBhDM7DS3LAaQzXupdqpRlyuhoFBAUp0JuyfBr/CBTdkdXgpaP3F9ev+R/nk -hbDhezGdpn9yo7nELC7MmVcOIQxFAZRl62UJxmMiCzNJkkg8/M3OsD6Onov4/knF -NXJHAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqvyREBuH -kV8Wub9PS5FeAByxMoAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG -OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfZXZfcm9vdF9jYV8y -XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQCTy6UfmRHsmg1fLBWTxj++EI14 -QvBukEdHjqOSMo1wj/Zbjb6JzkcBahsgIIlbyIIQbODnmaprxiqgYzWRaoUlrRc4 -pZt+UPJ26oUFKidBK7GB0aL2QHWpDsvxVUjY7NHss+jOFKE17MJeNRqrphYBBo7q -3C+jisosketSjl8MmxfPy3MHGcRqwnNU73xDUmPBEcrCRbH0O1P1aa4846XerOhU -t7KR/aypH/KH5BfGSah82ApB9PI+53c0BFLd6IHyTS9URZ0V4U/M5d40VxDJI3IX -cI1QcB9WbMy5/zpaT2N6w25lBx2Eof+pDGOJbbJAiDnXH3dotfyc1dZnaVuodNv8 -ifYbMvekJKZ2t0dT741Jj6m2g1qllpBFYfXeA08mD6iL8AOWsKwV0HFaanuU5nCT -2vFp4LJiTZ6P/4mdm13NRemUAiKN4DV/6PEEeXFsVIP4M7kFMhtYVRFP0OUnR3Hs -7dpn1mKmS00PaaLJvOwiS5THaJQXfuKOKD62xur1NGyfN4gHONuGcfrNlUhDbqNP -gofXNJhuS5N5YHVpD/Aa1VP6IQzCP+k/HxiMkl14p3ZnGbuy6n/pcAlWVqOwDAst -Nl7F6cTVg8uGF5csbBNvh1qvSaYd2804BC5f4ko1Di1L+KIkBI3Y4WNeApI02phh -XBxvWHZks/wCuPWdCg== ------END CERTIFICATE----- - -# Issuer: CN=SwissSign RSA TLS Root CA 2022 - 1 O=SwissSign AG -# Subject: CN=SwissSign RSA TLS Root CA 2022 - 1 O=SwissSign AG -# Label: "SwissSign RSA TLS Root CA 2022 - 1" -# Serial: 388078645722908516278762308316089881486363258315 -# MD5 Fingerprint: 16:2e:e4:19:76:81:85:ba:8e:91:58:f1:15:ef:72:39 -# SHA1 Fingerprint: 81:34:0a:be:4c:cd:ce:cc:e7:7d:cc:8a:d4:57:e2:45:a0:77:5d:ce -# SHA256 Fingerprint: 19:31:44:f4:31:e0:fd:db:74:07:17:d4:de:92:6a:57:11:33:88:4b:43:60:d3:0e:27:29:13:cb:e6:60:ce:41 ------BEGIN CERTIFICATE----- -MIIFkzCCA3ugAwIBAgIUQ/oMX04bgBhE79G0TzUfRPSA7cswDQYJKoZIhvcNAQEL -BQAwUTELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzErMCkGA1UE -AxMiU3dpc3NTaWduIFJTQSBUTFMgUm9vdCBDQSAyMDIyIC0gMTAeFw0yMjA2MDgx -MTA4MjJaFw00NzA2MDgxMTA4MjJaMFExCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxT -d2lzc1NpZ24gQUcxKzApBgNVBAMTIlN3aXNzU2lnbiBSU0EgVExTIFJvb3QgQ0Eg -MjAyMiAtIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDLKmjiC8NX -vDVjvHClO/OMPE5Xlm7DTjak9gLKHqquuN6orx122ro10JFwB9+zBvKK8i5VUXu7 -LCTLf5ImgKO0lPaCoaTo+nUdWfMHamFk4saMla+ju45vVs9xzF6BYQ1t8qsCLqSX -5XH8irCRIFucdFJtrhUnWXjyCcplDn/L9Ovn3KlMd/YrFgSVrpxxpT8q2kFC5zyE -EPThPYxr4iuRR1VPuFa+Rd4iUU1OKNlfGUEGjw5NBuBwQCMBauTLE5tzrE0USJIt -/m2n+IdreXXhvhCxqohAWVTXz8TQm0SzOGlkjIHRI36qOTw7D59Ke4LKa2/KIj4x -0LDQKhySio/YGZxH5D4MucLNvkEM+KRHBdvBFzA4OmnczcNpI/2aDwLOEGrOyvi5 -KaM2iYauC8BPY7kGWUleDsFpswrzd34unYyzJ5jSmY0lpx+Gs6ZUcDj8fV3oT4MM -0ZPlEuRU2j7yrTrePjxF8CgPBrnh25d7mUWe3f6VWQQvdT/TromZhqwUtKiE+shd -OxtYk8EXlFXIC+OCeYSf8wCENO7cMdWP8vpPlkwGqnj73mSiI80fPsWMvDdUDrta -clXvyFu1cvh43zcgTFeRc5JzrBh3Q4IgaezprClG5QtO+DdziZaKHG29777YtvTK -wP1H8K4LWCDFyB02rpeNUIMmJCn3nTsPBQIDAQABo2MwYTAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBRvjmKLk0Ow4UD2p8P98Q+4 -DxU4pTAdBgNVHQ4EFgQUb45ii5NDsOFA9qfD/fEPuA8VOKUwDQYJKoZIhvcNAQEL -BQADggIBAKwsKUF9+lz1GpUYvyypiqkkVHX1uECry6gkUSsYP2OprphWKwVDIqO3 -10aewCoSPY6WlkDfDDOLazeROpW7OSltwAJsipQLBwJNGD77+3v1dj2b9l4wBlgz -Hqp41eZUBDqyggmNzhYzWUUo8aWjlw5DI/0LIICQ/+Mmz7hkkeUFjxOgdg3XNwwQ -iJb0Pr6VvfHDffCjw3lHC1ySFWPtUnWK50Zpy1FVCypM9fJkT6lc/2cyjlUtMoIc -gC9qkfjLvH4YoiaoLqNTKIftV+Vlek4ASltOU8liNr3CjlvrzG4ngRhZi0Rjn9UM -ZfQpZX+RLOV/fuiJz48gy20HQhFRJjKKLjpHE7iNvUcNCfAWpO2Whi4Z2L6MOuhF -LhG6rlrnub+xzI/goP+4s9GFe3lmozm1O2bYQL7Pt2eLSMkZJVX8vY3PXtpOpvJp -zv1/THfQwUY1mFwjmwJFQ5Ra3bxHrSL+ul4vkSkphnsh3m5kt8sNjzdbowhq6/Td -Ao9QAwKxuDdollDruF/UKIqlIgyKhPBZLtU30WHlQnNYKoH3dtvi4k0NX/a3vgW0 -rk4N3hY9A4GzJl5LuEsAz/+MF7psYC0nhzck5npgL7XTgwSqT0N1osGDsieYK7EO -gLrAhV5Cud+xYJHT6xh+cHiudoO+cVrQkOPKwRYlZ0rwtnu64ZzZ ------END CERTIFICATE----- - -# Issuer: CN=OISTE Server Root ECC G1 O=OISTE Foundation -# Subject: CN=OISTE Server Root ECC G1 O=OISTE Foundation -# Label: "OISTE Server Root ECC G1" -# Serial: 47819833811561661340092227008453318557 -# MD5 Fingerprint: 42:a7:d2:35:ae:02:92:db:19:76:08:de:2f:05:b4:d4 -# SHA1 Fingerprint: 3b:f6:8b:09:ae:2a:92:7b:ba:e3:8d:3f:11:95:d9:e6:44:0c:45:e2 -# SHA256 Fingerprint: ee:c9:97:c0:c3:0f:21:6f:7e:3b:8b:30:7d:2b:ae:42:41:2d:75:3f:c8:21:9d:af:d1:52:0b:25:72:85:0f:49 ------BEGIN CERTIFICATE----- -MIICNTCCAbqgAwIBAgIQI/nD1jWvjyhLH/BU6n6XnTAKBggqhkjOPQQDAzBLMQsw -CQYDVQQGEwJDSDEZMBcGA1UECgwQT0lTVEUgRm91bmRhdGlvbjEhMB8GA1UEAwwY -T0lTVEUgU2VydmVyIFJvb3QgRUNDIEcxMB4XDTIzMDUzMTE0NDIyOFoXDTQ4MDUy -NDE0NDIyN1owSzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoMEE9JU1RFIEZvdW5kYXRp -b24xITAfBgNVBAMMGE9JU1RFIFNlcnZlciBSb290IEVDQyBHMTB2MBAGByqGSM49 -AgEGBSuBBAAiA2IABBcv+hK8rBjzCvRE1nZCnrPoH7d5qVi2+GXROiFPqOujvqQy -cvO2Ackr/XeFblPdreqqLiWStukhEaivtUwL85Zgmjvn6hp4LrQ95SjeHIC6XG4N -2xml4z+cKrhAS93mT6NjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBQ3 -TYhlz/w9itWj8UnATgwQb0K0nDAdBgNVHQ4EFgQUN02IZc/8PYrVo/FJwE4MEG9C -tJwwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYCMQCpKjAd0MKfkFFR -QD6VVCHNFmb3U2wIFjnQEnx/Yxvf4zgAOdktUyBFCxxgZzFDJe0CMQCSia7pXGKD -YmH5LVerVrkR3SW+ak5KGoJr3M/TvEqzPNcum9v4KGm8ay3sMaE641c= ------END CERTIFICATE----- - -# Issuer: CN=OISTE Server Root RSA G1 O=OISTE Foundation -# Subject: CN=OISTE Server Root RSA G1 O=OISTE Foundation -# Label: " OISTE Server Root RSA G1" -# Serial: 113845518112613905024960613408179309848 -# MD5 Fingerprint: 23:a7:9e:d4:70:b8:b9:14:57:41:8a:7e:44:59:e2:68 -# SHA1 Fingerprint: f7:00:34:25:94:88:68:31:e4:34:87:3f:70:fe:86:b3:86:9f:f0:6e -# SHA256 Fingerprint: 9a:e3:62:32:a5:18:9f:fd:db:35:3d:fd:26:52:0c:01:53:95:d2:27:77:da:c5:9d:b5:7b:98:c0:89:a6:51:e6 ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIQVaXZZ5Qoxu0M+ifdWwFNGDANBgkqhkiG9w0BAQwFADBL -MQswCQYDVQQGEwJDSDEZMBcGA1UECgwQT0lTVEUgRm91bmRhdGlvbjEhMB8GA1UE -AwwYT0lTVEUgU2VydmVyIFJvb3QgUlNBIEcxMB4XDTIzMDUzMTE0MzcxNloXDTQ4 -MDUyNDE0MzcxNVowSzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoMEE9JU1RFIEZvdW5k -YXRpb24xITAfBgNVBAMMGE9JU1RFIFNlcnZlciBSb290IFJTQSBHMTCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKqu9KuCz/vlNwvn1ZatkOhLKdxVYOPM -vLO8LZK55KN68YG0nnJyQ98/qwsmtO57Gmn7KNByXEptaZnwYx4M0rH/1ow00O7b -rEi56rAUjtgHqSSY3ekJvqgiG1k50SeH3BzN+Puz6+mTeO0Pzjd8JnduodgsIUzk -ik/HEzxux9UTl7Ko2yRpg1bTacuCErudG/L4NPKYKyqOBGf244ehHa1uzjZ0Dl4z -O8vbUZeUapU8zhhabkvG/AePLhq5SvdkNCncpo1Q4Y2LS+VIG24ugBA/5J8bZT8R -tOpXaZ+0AOuFJJkk9SGdl6r7NH8CaxWQrbueWhl/pIzY+m0o/DjH40ytas7ZTpOS -jswMZ78LS5bOZmdTaMsXEY5Z96ycG7mOaES3GK/m5Q9l3JUJsJMStR8+lKXHiHUh -sd4JJCpM4rzsTGdHwimIuQq6+cF0zowYJmXa92/GjHtoXAvuY8BeS/FOzJ8vD+Ho -mnqT8eDI278n5mUpezbgMxVz8p1rhAhoKzYHKyfMeNhqhw5HdPSqoBNdZH702xSu -+zrkL8Fl47l6QGzwBrd7KJvX4V84c5Ss2XCTLdyEr0YconosP4EmQufU2MVshGYR -i3drVByjtdgQ8K4p92cIiBdcuJd5z+orKu5YM+Vt6SmqZQENghPsJQtdLEByFSnT -kCz3GkPVavBpAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU -8snBDw1jALvsRQ5KH7WxszbNDo0wHQYDVR0OBBYEFPLJwQ8NYwC77EUOSh+1sbM2 -zQ6NMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQwFAAOCAgEANGd5sjrG5T33 -I3K5Ce+SrScfoE4KsvXaFwyihdJ+klH9FWXXXGtkFu6KRcoMQzZENdl//nk6HOjG -5D1rd9QhEOP28yBOqb6J8xycqd+8MDoX0TJD0KqKchxRKEzdNsjkLWd9kYccnbz8 -qyiWXmFcuCIzGEgWUOrKL+mlSdx/PKQZvDatkuK59EvV6wit53j+F8Bdh3foZ3dP -AGav9LEDOr4SfEE15fSmG0eLy3n31r8Xbk5l8PjaV8GUgeV6Vg27Rn9vkf195hfk -gSe7BYhW3SCl95gtkRlpMV+bMPKZrXJAlszYd2abtNUOshD+FKrDgHGdPY3ofRRs -YWSGRqbXVMW215AWRqWFyp464+YTFrYVI8ypKVL9AMb2kI5Wj4kI3Zaq5tNqqYY1 -9tVFeEJKRvwDyF7YZvZFZSS0vod7VSCd9521Kvy5YhnLbDuv0204bKt7ph6N/Ome -/msVuduCmsuY33OhkKCgxeDoAaijFJzIwZqsFVAzje18KotzlUBDJvyBpCpfOZC3 -J8tRd/iWkx7P8nd9H0aTolkelUTFLXVksNb54Dxp6gS1HAviRkRNQzuXSXERvSS2 -wq1yVAb+axj5d9spLFKebXd7Yv0PTY6YMjAwcRLWJTXjn/hvnLXrahut6hDTlhZy -BiElxky8j3C7DOReIoMt0r7+hVu05L0= ------END CERTIFICATE----- diff --git a/apps/bitwarden_event_logs/lib/certifi/core.py b/apps/bitwarden_event_logs/lib/certifi/core.py deleted file mode 100755 index 1c9661cc..00000000 --- a/apps/bitwarden_event_logs/lib/certifi/core.py +++ /dev/null @@ -1,83 +0,0 @@ -""" -certifi.py -~~~~~~~~~~ - -This module returns the installation location of cacert.pem or its contents. -""" -import sys -import atexit - -def exit_cacert_ctx() -> None: - _CACERT_CTX.__exit__(None, None, None) # type: ignore[union-attr] - - -if sys.version_info >= (3, 11): - - from importlib.resources import as_file, files - - _CACERT_CTX = None - _CACERT_PATH = None - - def where() -> str: - # This is slightly terrible, but we want to delay extracting the file - # in cases where we're inside of a zipimport situation until someone - # actually calls where(), but we don't want to re-extract the file - # on every call of where(), so we'll do it once then store it in a - # global variable. - global _CACERT_CTX - global _CACERT_PATH - if _CACERT_PATH is None: - # This is slightly janky, the importlib.resources API wants you to - # manage the cleanup of this file, so it doesn't actually return a - # path, it returns a context manager that will give you the path - # when you enter it and will do any cleanup when you leave it. In - # the common case of not needing a temporary file, it will just - # return the file system location and the __exit__() is a no-op. - # - # We also have to hold onto the actual context manager, because - # it will do the cleanup whenever it gets garbage collected, so - # we will also store that at the global level as well. - _CACERT_CTX = as_file(files("certifi").joinpath("cacert.pem")) - _CACERT_PATH = str(_CACERT_CTX.__enter__()) - atexit.register(exit_cacert_ctx) - - return _CACERT_PATH - - def contents() -> str: - return files("certifi").joinpath("cacert.pem").read_text(encoding="ascii") - -else: - - from importlib.resources import path as get_path, read_text - - _CACERT_CTX = None - _CACERT_PATH = None - - def where() -> str: - # This is slightly terrible, but we want to delay extracting the - # file in cases where we're inside of a zipimport situation until - # someone actually calls where(), but we don't want to re-extract - # the file on every call of where(), so we'll do it once then store - # it in a global variable. - global _CACERT_CTX - global _CACERT_PATH - if _CACERT_PATH is None: - # This is slightly janky, the importlib.resources API wants you - # to manage the cleanup of this file, so it doesn't actually - # return a path, it returns a context manager that will give - # you the path when you enter it and will do any cleanup when - # you leave it. In the common case of not needing a temporary - # file, it will just return the file system location and the - # __exit__() is a no-op. - # - # We also have to hold onto the actual context manager, because - # it will do the cleanup whenever it gets garbage collected, so - # we will also store that at the global level as well. - _CACERT_CTX = get_path("certifi", "cacert.pem") - _CACERT_PATH = str(_CACERT_CTX.__enter__()) - atexit.register(exit_cacert_ctx) - - return _CACERT_PATH - - def contents() -> str: - return read_text("certifi", "cacert.pem", encoding="ascii") diff --git a/apps/bitwarden_event_logs/lib/certifi/py.typed b/apps/bitwarden_event_logs/lib/certifi/py.typed deleted file mode 100755 index e69de29b..00000000 diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/INSTALLER deleted file mode 100755 index a1b589e3..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/METADATA b/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/METADATA deleted file mode 100755 index 8d32edcc..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/METADATA +++ /dev/null @@ -1,764 +0,0 @@ -Metadata-Version: 2.4 -Name: charset-normalizer -Version: 3.4.4 -Summary: The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet. -Author-email: "Ahmed R. TAHRI" -Maintainer-email: "Ahmed R. TAHRI" -License: MIT -Project-URL: Changelog, https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md -Project-URL: Documentation, https://charset-normalizer.readthedocs.io/ -Project-URL: Code, https://github.com/jawah/charset_normalizer -Project-URL: Issue tracker, https://github.com/jawah/charset_normalizer/issues -Keywords: encoding,charset,charset-detector,detector,normalization,unicode,chardet,detect -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3.13 -Classifier: Programming Language :: Python :: 3.14 -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Text Processing :: Linguistic -Classifier: Topic :: Utilities -Classifier: Typing :: Typed -Requires-Python: >=3.7 -Description-Content-Type: text/markdown -License-File: LICENSE -Provides-Extra: unicode-backport -Dynamic: license-file - -

Charset Detection, for Everyone 👋

- -

- The Real First Universal Charset Detector
- - - - - Download Count Total - - - - -

-

- Featured Packages
- - Static Badge - - - Static Badge - -

-

- In other language (unofficial port - by the community)
- - Static Badge - -

- -> A library that helps you read text from an unknown charset encoding.
Motivated by `chardet`, -> I'm trying to resolve the issue by taking a new approach. -> All IANA character set names for which the Python core library provides codecs are supported. - -

- >>>>> 👉 Try Me Online Now, Then Adopt Me 👈 <<<<< -

- -This project offers you an alternative to **Universal Charset Encoding Detector**, also known as **Chardet**. - -| Feature | [Chardet](https://github.com/chardet/chardet) | Charset Normalizer | [cChardet](https://github.com/PyYoshi/cChardet) | -|--------------------------------------------------|:---------------------------------------------:|:--------------------------------------------------------------------------------------------------:|:-----------------------------------------------:| -| `Fast` | ❌ | ✅ | ✅ | -| `Universal**` | ❌ | ✅ | ❌ | -| `Reliable` **without** distinguishable standards | ❌ | ✅ | ✅ | -| `Reliable` **with** distinguishable standards | ✅ | ✅ | ✅ | -| `License` | LGPL-2.1
_restrictive_ | MIT | MPL-1.1
_restrictive_ | -| `Native Python` | ✅ | ✅ | ❌ | -| `Detect spoken language` | ❌ | ✅ | N/A | -| `UnicodeDecodeError Safety` | ❌ | ✅ | ❌ | -| `Whl Size (min)` | 193.6 kB | 42 kB | ~200 kB | -| `Supported Encoding` | 33 | 🎉 [99](https://charset-normalizer.readthedocs.io/en/latest/user/support.html#supported-encodings) | 40 | - -

-Reading Normalized TextCat Reading Text -

- -*\*\* : They are clearly using specific code for a specific encoding even if covering most of used one*
- -## ⚡ Performance - -This package offer better performance than its counterpart Chardet. Here are some numbers. - -| Package | Accuracy | Mean per file (ms) | File per sec (est) | -|-----------------------------------------------|:--------:|:------------------:|:------------------:| -| [chardet](https://github.com/chardet/chardet) | 86 % | 63 ms | 16 file/sec | -| charset-normalizer | **98 %** | **10 ms** | 100 file/sec | - -| Package | 99th percentile | 95th percentile | 50th percentile | -|-----------------------------------------------|:---------------:|:---------------:|:---------------:| -| [chardet](https://github.com/chardet/chardet) | 265 ms | 71 ms | 7 ms | -| charset-normalizer | 100 ms | 50 ms | 5 ms | - -_updated as of december 2024 using CPython 3.12_ - -Chardet's performance on larger file (1MB+) are very poor. Expect huge difference on large payload. - -> Stats are generated using 400+ files using default parameters. More details on used files, see GHA workflows. -> And yes, these results might change at any time. The dataset can be updated to include more files. -> The actual delays heavily depends on your CPU capabilities. The factors should remain the same. -> Keep in mind that the stats are generous and that Chardet accuracy vs our is measured using Chardet initial capability -> (e.g. Supported Encoding) Challenge-them if you want. - -## ✨ Installation - -Using pip: - -```sh -pip install charset-normalizer -U -``` - -## 🚀 Basic Usage - -### CLI -This package comes with a CLI. - -``` -usage: normalizer [-h] [-v] [-a] [-n] [-m] [-r] [-f] [-t THRESHOLD] - file [file ...] - -The Real First Universal Charset Detector. Discover originating encoding used -on text file. Normalize text to unicode. - -positional arguments: - files File(s) to be analysed - -optional arguments: - -h, --help show this help message and exit - -v, --verbose Display complementary information about file if any. - Stdout will contain logs about the detection process. - -a, --with-alternative - Output complementary possibilities if any. Top-level - JSON WILL be a list. - -n, --normalize Permit to normalize input file. If not set, program - does not write anything. - -m, --minimal Only output the charset detected to STDOUT. Disabling - JSON output. - -r, --replace Replace file when trying to normalize it instead of - creating a new one. - -f, --force Replace file without asking if you are sure, use this - flag with caution. - -t THRESHOLD, --threshold THRESHOLD - Define a custom maximum amount of chaos allowed in - decoded content. 0. <= chaos <= 1. - --version Show version information and exit. -``` - -```bash -normalizer ./data/sample.1.fr.srt -``` - -or - -```bash -python -m charset_normalizer ./data/sample.1.fr.srt -``` - -🎉 Since version 1.4.0 the CLI produce easily usable stdout result in JSON format. - -```json -{ - "path": "/home/default/projects/charset_normalizer/data/sample.1.fr.srt", - "encoding": "cp1252", - "encoding_aliases": [ - "1252", - "windows_1252" - ], - "alternative_encodings": [ - "cp1254", - "cp1256", - "cp1258", - "iso8859_14", - "iso8859_15", - "iso8859_16", - "iso8859_3", - "iso8859_9", - "latin_1", - "mbcs" - ], - "language": "French", - "alphabets": [ - "Basic Latin", - "Latin-1 Supplement" - ], - "has_sig_or_bom": false, - "chaos": 0.149, - "coherence": 97.152, - "unicode_path": null, - "is_preferred": true -} -``` - -### Python -*Just print out normalized text* -```python -from charset_normalizer import from_path - -results = from_path('./my_subtitle.srt') - -print(str(results.best())) -``` - -*Upgrade your code without effort* -```python -from charset_normalizer import detect -``` - -The above code will behave the same as **chardet**. We ensure that we offer the best (reasonable) BC result possible. - -See the docs for advanced usage : [readthedocs.io](https://charset-normalizer.readthedocs.io/en/latest/) - -## 😇 Why - -When I started using Chardet, I noticed that it was not suited to my expectations, and I wanted to propose a -reliable alternative using a completely different method. Also! I never back down on a good challenge! - -I **don't care** about the **originating charset** encoding, because **two different tables** can -produce **two identical rendered string.** -What I want is to get readable text, the best I can. - -In a way, **I'm brute forcing text decoding.** How cool is that ? 😎 - -Don't confuse package **ftfy** with charset-normalizer or chardet. ftfy goal is to repair Unicode string whereas charset-normalizer to convert raw file in unknown encoding to unicode. - -## 🍰 How - - - Discard all charset encoding table that could not fit the binary content. - - Measure noise, or the mess once opened (by chunks) with a corresponding charset encoding. - - Extract matches with the lowest mess detected. - - Additionally, we measure coherence / probe for a language. - -**Wait a minute**, what is noise/mess and coherence according to **YOU ?** - -*Noise :* I opened hundred of text files, **written by humans**, with the wrong encoding table. **I observed**, then -**I established** some ground rules about **what is obvious** when **it seems like** a mess (aka. defining noise in rendered text). - I know that my interpretation of what is noise is probably incomplete, feel free to contribute in order to - improve or rewrite it. - -*Coherence :* For each language there is on earth, we have computed ranked letter appearance occurrences (the best we can). So I thought -that intel is worth something here. So I use those records against decoded text to check if I can detect intelligent design. - -## ⚡ Known limitations - - - Language detection is unreliable when text contains two or more languages sharing identical letters. (eg. HTML (english tags) + Turkish content (Sharing Latin characters)) - - Every charset detector heavily depends on sufficient content. In common cases, do not bother run detection on very tiny content. - -## ⚠️ About Python EOLs - -**If you are running:** - -- Python >=2.7,<3.5: Unsupported -- Python 3.5: charset-normalizer < 2.1 -- Python 3.6: charset-normalizer < 3.1 -- Python 3.7: charset-normalizer < 4.0 - -Upgrade your Python interpreter as soon as possible. - -## 👤 Contributing - -Contributions, issues and feature requests are very much welcome.
-Feel free to check [issues page](https://github.com/ousret/charset_normalizer/issues) if you want to contribute. - -## 📝 License - -Copyright © [Ahmed TAHRI @Ousret](https://github.com/Ousret).
-This project is [MIT](https://github.com/Ousret/charset_normalizer/blob/master/LICENSE) licensed. - -Characters frequencies used in this project © 2012 [Denny Vrandečić](http://simia.net/letters/) - -## 💼 For Enterprise - -Professional support for charset-normalizer is available as part of the [Tidelift -Subscription][1]. Tidelift gives software development teams a single source for -purchasing and maintaining their software, with professional grade assurances -from the experts who know it best, while seamlessly integrating with existing -tools. - -[1]: https://tidelift.com/subscription/pkg/pypi-charset-normalizer?utm_source=pypi-charset-normalizer&utm_medium=readme - -[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7297/badge)](https://www.bestpractices.dev/projects/7297) - -# Changelog -All notable changes to charset-normalizer will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - -## [3.4.4](https://github.com/Ousret/charset_normalizer/compare/3.4.2...3.4.4) (2025-10-13) - -### Changed -- Bound `setuptools` to a specific constraint `setuptools>=68,<=81`. -- Raised upper bound of mypyc for the optional pre-built extension to v1.18.2 - -### Removed -- `setuptools-scm` as a build dependency. - -### Misc -- Enforced hashes in `dev-requirements.txt` and created `ci-requirements.txt` for security purposes. -- Additional pre-built wheels for riscv64, s390x, and armv7l architectures. -- Restore ` multiple.intoto.jsonl` in GitHub releases in addition to individual attestation file per wheel. - -## [3.4.3](https://github.com/Ousret/charset_normalizer/compare/3.4.2...3.4.3) (2025-08-09) - -### Changed -- mypy(c) is no longer a required dependency at build time if `CHARSET_NORMALIZER_USE_MYPYC` isn't set to `1`. (#595) (#583) -- automatically lower confidence on small bytes samples that are not Unicode in `detect` output legacy function. (#391) - -### Added -- Custom build backend to overcome inability to mark mypy as an optional dependency in the build phase. -- Support for Python 3.14 - -### Fixed -- sdist archive contained useless directories. -- automatically fallback on valid UTF-16 or UTF-32 even if the md says it's noisy. (#633) - -### Misc -- SBOM are automatically published to the relevant GitHub release to comply with regulatory changes. - Each published wheel comes with its SBOM. We choose CycloneDX as the format. -- Prebuilt optimized wheel are no longer distributed by default for CPython 3.7 due to a change in cibuildwheel. - -## [3.4.2](https://github.com/Ousret/charset_normalizer/compare/3.4.1...3.4.2) (2025-05-02) - -### Fixed -- Addressed the DeprecationWarning in our CLI regarding `argparse.FileType` by backporting the target class into the package. (#591) -- Improved the overall reliability of the detector with CJK Ideographs. (#605) (#587) - -### Changed -- Optional mypyc compilation upgraded to version 1.15 for Python >= 3.8 - -## [3.4.1](https://github.com/Ousret/charset_normalizer/compare/3.4.0...3.4.1) (2024-12-24) - -### Changed -- Project metadata are now stored using `pyproject.toml` instead of `setup.cfg` using setuptools as the build backend. -- Enforce annotation delayed loading for a simpler and consistent types in the project. -- Optional mypyc compilation upgraded to version 1.14 for Python >= 3.8 - -### Added -- pre-commit configuration. -- noxfile. - -### Removed -- `build-requirements.txt` as per using `pyproject.toml` native build configuration. -- `bin/integration.py` and `bin/serve.py` in favor of downstream integration test (see noxfile). -- `setup.cfg` in favor of `pyproject.toml` metadata configuration. -- Unused `utils.range_scan` function. - -### Fixed -- Converting content to Unicode bytes may insert `utf_8` instead of preferred `utf-8`. (#572) -- Deprecation warning "'count' is passed as positional argument" when converting to Unicode bytes on Python 3.13+ - -## [3.4.0](https://github.com/Ousret/charset_normalizer/compare/3.3.2...3.4.0) (2024-10-08) - -### Added -- Argument `--no-preemptive` in the CLI to prevent the detector to search for hints. -- Support for Python 3.13 (#512) - -### Fixed -- Relax the TypeError exception thrown when trying to compare a CharsetMatch with anything else than a CharsetMatch. -- Improved the general reliability of the detector based on user feedbacks. (#520) (#509) (#498) (#407) (#537) -- Declared charset in content (preemptive detection) not changed when converting to utf-8 bytes. (#381) - -## [3.3.2](https://github.com/Ousret/charset_normalizer/compare/3.3.1...3.3.2) (2023-10-31) - -### Fixed -- Unintentional memory usage regression when using large payload that match several encoding (#376) -- Regression on some detection case showcased in the documentation (#371) - -### Added -- Noise (md) probe that identify malformed arabic representation due to the presence of letters in isolated form (credit to my wife) - -## [3.3.1](https://github.com/Ousret/charset_normalizer/compare/3.3.0...3.3.1) (2023-10-22) - -### Changed -- Optional mypyc compilation upgraded to version 1.6.1 for Python >= 3.8 -- Improved the general detection reliability based on reports from the community - -## [3.3.0](https://github.com/Ousret/charset_normalizer/compare/3.2.0...3.3.0) (2023-09-30) - -### Added -- Allow to execute the CLI (e.g. normalizer) through `python -m charset_normalizer.cli` or `python -m charset_normalizer` -- Support for 9 forgotten encoding that are supported by Python but unlisted in `encoding.aliases` as they have no alias (#323) - -### Removed -- (internal) Redundant utils.is_ascii function and unused function is_private_use_only -- (internal) charset_normalizer.assets is moved inside charset_normalizer.constant - -### Changed -- (internal) Unicode code blocks in constants are updated using the latest v15.0.0 definition to improve detection -- Optional mypyc compilation upgraded to version 1.5.1 for Python >= 3.8 - -### Fixed -- Unable to properly sort CharsetMatch when both chaos/noise and coherence were close due to an unreachable condition in \_\_lt\_\_ (#350) - -## [3.2.0](https://github.com/Ousret/charset_normalizer/compare/3.1.0...3.2.0) (2023-06-07) - -### Changed -- Typehint for function `from_path` no longer enforce `PathLike` as its first argument -- Minor improvement over the global detection reliability - -### Added -- Introduce function `is_binary` that relies on main capabilities, and optimized to detect binaries -- Propagate `enable_fallback` argument throughout `from_bytes`, `from_path`, and `from_fp` that allow a deeper control over the detection (default True) -- Explicit support for Python 3.12 - -### Fixed -- Edge case detection failure where a file would contain 'very-long' camel cased word (Issue #289) - -## [3.1.0](https://github.com/Ousret/charset_normalizer/compare/3.0.1...3.1.0) (2023-03-06) - -### Added -- Argument `should_rename_legacy` for legacy function `detect` and disregard any new arguments without errors (PR #262) - -### Removed -- Support for Python 3.6 (PR #260) - -### Changed -- Optional speedup provided by mypy/c 1.0.1 - -## [3.0.1](https://github.com/Ousret/charset_normalizer/compare/3.0.0...3.0.1) (2022-11-18) - -### Fixed -- Multi-bytes cutter/chunk generator did not always cut correctly (PR #233) - -### Changed -- Speedup provided by mypy/c 0.990 on Python >= 3.7 - -## [3.0.0](https://github.com/Ousret/charset_normalizer/compare/2.1.1...3.0.0) (2022-10-20) - -### Added -- Extend the capability of explain=True when cp_isolation contains at most two entries (min one), will log in details of the Mess-detector results -- Support for alternative language frequency set in charset_normalizer.assets.FREQUENCIES -- Add parameter `language_threshold` in `from_bytes`, `from_path` and `from_fp` to adjust the minimum expected coherence ratio -- `normalizer --version` now specify if current version provide extra speedup (meaning mypyc compilation whl) - -### Changed -- Build with static metadata using 'build' frontend -- Make the language detection stricter -- Optional: Module `md.py` can be compiled using Mypyc to provide an extra speedup up to 4x faster than v2.1 - -### Fixed -- CLI with opt --normalize fail when using full path for files -- TooManyAccentuatedPlugin induce false positive on the mess detection when too few alpha character have been fed to it -- Sphinx warnings when generating the documentation - -### Removed -- Coherence detector no longer return 'Simple English' instead return 'English' -- Coherence detector no longer return 'Classical Chinese' instead return 'Chinese' -- Breaking: Method `first()` and `best()` from CharsetMatch -- UTF-7 will no longer appear as "detected" without a recognized SIG/mark (is unreliable/conflict with ASCII) -- Breaking: Class aliases CharsetDetector, CharsetDoctor, CharsetNormalizerMatch and CharsetNormalizerMatches -- Breaking: Top-level function `normalize` -- Breaking: Properties `chaos_secondary_pass`, `coherence_non_latin` and `w_counter` from CharsetMatch -- Support for the backport `unicodedata2` - -## [3.0.0rc1](https://github.com/Ousret/charset_normalizer/compare/3.0.0b2...3.0.0rc1) (2022-10-18) - -### Added -- Extend the capability of explain=True when cp_isolation contains at most two entries (min one), will log in details of the Mess-detector results -- Support for alternative language frequency set in charset_normalizer.assets.FREQUENCIES -- Add parameter `language_threshold` in `from_bytes`, `from_path` and `from_fp` to adjust the minimum expected coherence ratio - -### Changed -- Build with static metadata using 'build' frontend -- Make the language detection stricter - -### Fixed -- CLI with opt --normalize fail when using full path for files -- TooManyAccentuatedPlugin induce false positive on the mess detection when too few alpha character have been fed to it - -### Removed -- Coherence detector no longer return 'Simple English' instead return 'English' -- Coherence detector no longer return 'Classical Chinese' instead return 'Chinese' - -## [3.0.0b2](https://github.com/Ousret/charset_normalizer/compare/3.0.0b1...3.0.0b2) (2022-08-21) - -### Added -- `normalizer --version` now specify if current version provide extra speedup (meaning mypyc compilation whl) - -### Removed -- Breaking: Method `first()` and `best()` from CharsetMatch -- UTF-7 will no longer appear as "detected" without a recognized SIG/mark (is unreliable/conflict with ASCII) - -### Fixed -- Sphinx warnings when generating the documentation - -## [3.0.0b1](https://github.com/Ousret/charset_normalizer/compare/2.1.0...3.0.0b1) (2022-08-15) - -### Changed -- Optional: Module `md.py` can be compiled using Mypyc to provide an extra speedup up to 4x faster than v2.1 - -### Removed -- Breaking: Class aliases CharsetDetector, CharsetDoctor, CharsetNormalizerMatch and CharsetNormalizerMatches -- Breaking: Top-level function `normalize` -- Breaking: Properties `chaos_secondary_pass`, `coherence_non_latin` and `w_counter` from CharsetMatch -- Support for the backport `unicodedata2` - -## [2.1.1](https://github.com/Ousret/charset_normalizer/compare/2.1.0...2.1.1) (2022-08-19) - -### Deprecated -- Function `normalize` scheduled for removal in 3.0 - -### Changed -- Removed useless call to decode in fn is_unprintable (#206) - -### Fixed -- Third-party library (i18n xgettext) crashing not recognizing utf_8 (PEP 263) with underscore from [@aleksandernovikov](https://github.com/aleksandernovikov) (#204) - -## [2.1.0](https://github.com/Ousret/charset_normalizer/compare/2.0.12...2.1.0) (2022-06-19) - -### Added -- Output the Unicode table version when running the CLI with `--version` (PR #194) - -### Changed -- Re-use decoded buffer for single byte character sets from [@nijel](https://github.com/nijel) (PR #175) -- Fixing some performance bottlenecks from [@deedy5](https://github.com/deedy5) (PR #183) - -### Fixed -- Workaround potential bug in cpython with Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space (PR #175) -- CLI default threshold aligned with the API threshold from [@oleksandr-kuzmenko](https://github.com/oleksandr-kuzmenko) (PR #181) - -### Removed -- Support for Python 3.5 (PR #192) - -### Deprecated -- Use of backport unicodedata from `unicodedata2` as Python is quickly catching up, scheduled for removal in 3.0 (PR #194) - -## [2.0.12](https://github.com/Ousret/charset_normalizer/compare/2.0.11...2.0.12) (2022-02-12) - -### Fixed -- ASCII miss-detection on rare cases (PR #170) - -## [2.0.11](https://github.com/Ousret/charset_normalizer/compare/2.0.10...2.0.11) (2022-01-30) - -### Added -- Explicit support for Python 3.11 (PR #164) - -### Changed -- The logging behavior have been completely reviewed, now using only TRACE and DEBUG levels (PR #163 #165) - -## [2.0.10](https://github.com/Ousret/charset_normalizer/compare/2.0.9...2.0.10) (2022-01-04) - -### Fixed -- Fallback match entries might lead to UnicodeDecodeError for large bytes sequence (PR #154) - -### Changed -- Skipping the language-detection (CD) on ASCII (PR #155) - -## [2.0.9](https://github.com/Ousret/charset_normalizer/compare/2.0.8...2.0.9) (2021-12-03) - -### Changed -- Moderating the logging impact (since 2.0.8) for specific environments (PR #147) - -### Fixed -- Wrong logging level applied when setting kwarg `explain` to True (PR #146) - -## [2.0.8](https://github.com/Ousret/charset_normalizer/compare/2.0.7...2.0.8) (2021-11-24) -### Changed -- Improvement over Vietnamese detection (PR #126) -- MD improvement on trailing data and long foreign (non-pure latin) data (PR #124) -- Efficiency improvements in cd/alphabet_languages from [@adbar](https://github.com/adbar) (PR #122) -- call sum() without an intermediary list following PEP 289 recommendations from [@adbar](https://github.com/adbar) (PR #129) -- Code style as refactored by Sourcery-AI (PR #131) -- Minor adjustment on the MD around european words (PR #133) -- Remove and replace SRTs from assets / tests (PR #139) -- Initialize the library logger with a `NullHandler` by default from [@nmaynes](https://github.com/nmaynes) (PR #135) -- Setting kwarg `explain` to True will add provisionally (bounded to function lifespan) a specific stream handler (PR #135) - -### Fixed -- Fix large (misleading) sequence giving UnicodeDecodeError (PR #137) -- Avoid using too insignificant chunk (PR #137) - -### Added -- Add and expose function `set_logging_handler` to configure a specific StreamHandler from [@nmaynes](https://github.com/nmaynes) (PR #135) -- Add `CHANGELOG.md` entries, format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) (PR #141) - -## [2.0.7](https://github.com/Ousret/charset_normalizer/compare/2.0.6...2.0.7) (2021-10-11) -### Added -- Add support for Kazakh (Cyrillic) language detection (PR #109) - -### Changed -- Further, improve inferring the language from a given single-byte code page (PR #112) -- Vainly trying to leverage PEP263 when PEP3120 is not supported (PR #116) -- Refactoring for potential performance improvements in loops from [@adbar](https://github.com/adbar) (PR #113) -- Various detection improvement (MD+CD) (PR #117) - -### Removed -- Remove redundant logging entry about detected language(s) (PR #115) - -### Fixed -- Fix a minor inconsistency between Python 3.5 and other versions regarding language detection (PR #117 #102) - -## [2.0.6](https://github.com/Ousret/charset_normalizer/compare/2.0.5...2.0.6) (2021-09-18) -### Fixed -- Unforeseen regression with the loss of the backward-compatibility with some older minor of Python 3.5.x (PR #100) -- Fix CLI crash when using --minimal output in certain cases (PR #103) - -### Changed -- Minor improvement to the detection efficiency (less than 1%) (PR #106 #101) - -## [2.0.5](https://github.com/Ousret/charset_normalizer/compare/2.0.4...2.0.5) (2021-09-14) -### Changed -- The project now comply with: flake8, mypy, isort and black to ensure a better overall quality (PR #81) -- The BC-support with v1.x was improved, the old staticmethods are restored (PR #82) -- The Unicode detection is slightly improved (PR #93) -- Add syntax sugar \_\_bool\_\_ for results CharsetMatches list-container (PR #91) - -### Removed -- The project no longer raise warning on tiny content given for detection, will be simply logged as warning instead (PR #92) - -### Fixed -- In some rare case, the chunks extractor could cut in the middle of a multi-byte character and could mislead the mess detection (PR #95) -- Some rare 'space' characters could trip up the UnprintablePlugin/Mess detection (PR #96) -- The MANIFEST.in was not exhaustive (PR #78) - -## [2.0.4](https://github.com/Ousret/charset_normalizer/compare/2.0.3...2.0.4) (2021-07-30) -### Fixed -- The CLI no longer raise an unexpected exception when no encoding has been found (PR #70) -- Fix accessing the 'alphabets' property when the payload contains surrogate characters (PR #68) -- The logger could mislead (explain=True) on detected languages and the impact of one MBCS match (PR #72) -- Submatch factoring could be wrong in rare edge cases (PR #72) -- Multiple files given to the CLI were ignored when publishing results to STDOUT. (After the first path) (PR #72) -- Fix line endings from CRLF to LF for certain project files (PR #67) - -### Changed -- Adjust the MD to lower the sensitivity, thus improving the global detection reliability (PR #69 #76) -- Allow fallback on specified encoding if any (PR #71) - -## [2.0.3](https://github.com/Ousret/charset_normalizer/compare/2.0.2...2.0.3) (2021-07-16) -### Changed -- Part of the detection mechanism has been improved to be less sensitive, resulting in more accurate detection results. Especially ASCII. (PR #63) -- According to the community wishes, the detection will fall back on ASCII or UTF-8 in a last-resort case. (PR #64) - -## [2.0.2](https://github.com/Ousret/charset_normalizer/compare/2.0.1...2.0.2) (2021-07-15) -### Fixed -- Empty/Too small JSON payload miss-detection fixed. Report from [@tseaver](https://github.com/tseaver) (PR #59) - -### Changed -- Don't inject unicodedata2 into sys.modules from [@akx](https://github.com/akx) (PR #57) - -## [2.0.1](https://github.com/Ousret/charset_normalizer/compare/2.0.0...2.0.1) (2021-07-13) -### Fixed -- Make it work where there isn't a filesystem available, dropping assets frequencies.json. Report from [@sethmlarson](https://github.com/sethmlarson). (PR #55) -- Using explain=False permanently disable the verbose output in the current runtime (PR #47) -- One log entry (language target preemptive) was not show in logs when using explain=True (PR #47) -- Fix undesired exception (ValueError) on getitem of instance CharsetMatches (PR #52) - -### Changed -- Public function normalize default args values were not aligned with from_bytes (PR #53) - -### Added -- You may now use charset aliases in cp_isolation and cp_exclusion arguments (PR #47) - -## [2.0.0](https://github.com/Ousret/charset_normalizer/compare/1.4.1...2.0.0) (2021-07-02) -### Changed -- 4x to 5 times faster than the previous 1.4.0 release. At least 2x faster than Chardet. -- Accent has been made on UTF-8 detection, should perform rather instantaneous. -- The backward compatibility with Chardet has been greatly improved. The legacy detect function returns an identical charset name whenever possible. -- The detection mechanism has been slightly improved, now Turkish content is detected correctly (most of the time) -- The program has been rewritten to ease the readability and maintainability. (+Using static typing)+ -- utf_7 detection has been reinstated. - -### Removed -- This package no longer require anything when used with Python 3.5 (Dropped cached_property) -- Removed support for these languages: Catalan, Esperanto, Kazakh, Baque, Volapük, Azeri, Galician, Nynorsk, Macedonian, and Serbocroatian. -- The exception hook on UnicodeDecodeError has been removed. - -### Deprecated -- Methods coherence_non_latin, w_counter, chaos_secondary_pass of the class CharsetMatch are now deprecated and scheduled for removal in v3.0 - -### Fixed -- The CLI output used the relative path of the file(s). Should be absolute. - -## [1.4.1](https://github.com/Ousret/charset_normalizer/compare/1.4.0...1.4.1) (2021-05-28) -### Fixed -- Logger configuration/usage no longer conflict with others (PR #44) - -## [1.4.0](https://github.com/Ousret/charset_normalizer/compare/1.3.9...1.4.0) (2021-05-21) -### Removed -- Using standard logging instead of using the package loguru. -- Dropping nose test framework in favor of the maintained pytest. -- Choose to not use dragonmapper package to help with gibberish Chinese/CJK text. -- Require cached_property only for Python 3.5 due to constraint. Dropping for every other interpreter version. -- Stop support for UTF-7 that does not contain a SIG. -- Dropping PrettyTable, replaced with pure JSON output in CLI. - -### Fixed -- BOM marker in a CharsetNormalizerMatch instance could be False in rare cases even if obviously present. Due to the sub-match factoring process. -- Not searching properly for the BOM when trying utf32/16 parent codec. - -### Changed -- Improving the package final size by compressing frequencies.json. -- Huge improvement over the larges payload. - -### Added -- CLI now produces JSON consumable output. -- Return ASCII if given sequences fit. Given reasonable confidence. - -## [1.3.9](https://github.com/Ousret/charset_normalizer/compare/1.3.8...1.3.9) (2021-05-13) - -### Fixed -- In some very rare cases, you may end up getting encode/decode errors due to a bad bytes payload (PR #40) - -## [1.3.8](https://github.com/Ousret/charset_normalizer/compare/1.3.7...1.3.8) (2021-05-12) - -### Fixed -- Empty given payload for detection may cause an exception if trying to access the `alphabets` property. (PR #39) - -## [1.3.7](https://github.com/Ousret/charset_normalizer/compare/1.3.6...1.3.7) (2021-05-12) - -### Fixed -- The legacy detect function should return UTF-8-SIG if sig is present in the payload. (PR #38) - -## [1.3.6](https://github.com/Ousret/charset_normalizer/compare/1.3.5...1.3.6) (2021-02-09) - -### Changed -- Amend the previous release to allow prettytable 2.0 (PR #35) - -## [1.3.5](https://github.com/Ousret/charset_normalizer/compare/1.3.4...1.3.5) (2021-02-08) - -### Fixed -- Fix error while using the package with a python pre-release interpreter (PR #33) - -### Changed -- Dependencies refactoring, constraints revised. - -### Added -- Add python 3.9 and 3.10 to the supported interpreters - -MIT License - -Copyright (c) 2025 TAHRI Ahmed R. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/RECORD b/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/RECORD deleted file mode 100755 index 98db0d97..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/RECORD +++ /dev/null @@ -1,24 +0,0 @@ -../../bin/normalizer,sha256=9v9CiM1SMj9hAM5YRMeRilB5D2s9HWSQ_qInrU2KpQU,253 -charset_normalizer-3.4.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -charset_normalizer-3.4.4.dist-info/METADATA,sha256=jVuUFBti8dav19YLvWissTihVdF2ozUY4KKMw7jdkBQ,37303 -charset_normalizer-3.4.4.dist-info/RECORD,, -charset_normalizer-3.4.4.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -charset_normalizer-3.4.4.dist-info/WHEEL,sha256=ylJURW79exB2C-59Cgd1o0-VkgYeH2GaNb8U43WRbwg,187 -charset_normalizer-3.4.4.dist-info/entry_points.txt,sha256=ADSTKrkXZ3hhdOVFi6DcUEHQRS0xfxDIE_pEz4wLIXA,65 -charset_normalizer-3.4.4.dist-info/licenses/LICENSE,sha256=bQ1Bv-FwrGx9wkjJpj4lTQ-0WmDVCoJX0K-SxuJJuIc,1071 -charset_normalizer-3.4.4.dist-info/top_level.txt,sha256=7ASyzePr8_xuZWJsnqJjIBtyV8vhEo0wBCv1MPRRi3Q,19 -charset_normalizer/__init__.py,sha256=OKRxRv2Zhnqk00tqkN0c1BtJjm165fWXLydE52IKuHc,1590 -charset_normalizer/__main__.py,sha256=yzYxMR-IhKRHYwcSlavEv8oGdwxsR89mr2X09qXGdps,109 -charset_normalizer/api.py,sha256=V07i8aVeCD8T2fSia3C-fn0i9t8qQguEBhsqszg32Ns,22668 -charset_normalizer/cd.py,sha256=WKTo1HDb-H9HfCDc3Bfwq5jzS25Ziy9SE2a74SgTq88,12522 -charset_normalizer/cli/__init__.py,sha256=D8I86lFk2-py45JvqxniTirSj_sFyE6sjaY_0-G1shc,136 -charset_normalizer/cli/__main__.py,sha256=dMaXG6IJXRvqq8z2tig7Qb83-BpWTln55ooiku5_uvg,12646 -charset_normalizer/constant.py,sha256=7UVY4ldYhmQMHUdgQ_sgZmzcQ0xxYxpBunqSZ-XJZ8U,42713 -charset_normalizer/legacy.py,sha256=sYBzSpzsRrg_wF4LP536pG64BItw7Tqtc3SMQAHvFLM,2731 -charset_normalizer/md.cpython-39-aarch64-linux-gnu.so,sha256=Fl5b5yFpdjEkjaOr3bUxLjAmBYD37YTHfMCVs6SBh6A,201304 -charset_normalizer/md.py,sha256=-_oN3h3_X99nkFfqamD3yu45DC_wfk5odH0Tr_CQiXs,20145 -charset_normalizer/md__mypyc.cpython-39-aarch64-linux-gnu.so,sha256=nAx9ZddHDN7KxsVUxkP8Qen7djjHdO1_0_bP_aqC34A,324120 -charset_normalizer/models.py,sha256=lKXhOnIPtiakbK3i__J9wpOfzx3JDTKj7Dn3Rg0VaRI,12394 -charset_normalizer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -charset_normalizer/utils.py,sha256=sTejPgrdlNsKNucZfJCxJ95lMTLA0ShHLLE3n5wpT9Q,12170 -charset_normalizer/version.py,sha256=nKE4qBNk5WA4LIJ_yIH_aSDfvtsyizkWMg-PUG-UZVk,115 diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/REQUESTED deleted file mode 100755 index e69de29b..00000000 diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/WHEEL deleted file mode 100755 index 739423f0..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/WHEEL +++ /dev/null @@ -1,7 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (80.9.0) -Root-Is-Purelib: false -Tag: cp39-cp39-manylinux_2_17_aarch64 -Tag: cp39-cp39-manylinux2014_aarch64 -Tag: cp39-cp39-manylinux_2_28_aarch64 - diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/licenses/LICENSE b/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/licenses/LICENSE deleted file mode 100755 index 9725772c..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer-3.4.4.dist-info/licenses/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 TAHRI Ahmed R. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/__init__.py b/apps/bitwarden_event_logs/lib/charset_normalizer/__init__.py deleted file mode 100755 index 0d3a3799..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer/__init__.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Charset-Normalizer -~~~~~~~~~~~~~~ -The Real First Universal Charset Detector. -A library that helps you read text from an unknown charset encoding. -Motivated by chardet, This package is trying to resolve the issue by taking a new approach. -All IANA character set names for which the Python core library provides codecs are supported. - -Basic usage: - >>> from charset_normalizer import from_bytes - >>> results = from_bytes('Bсеки човек има право на образование. Oбразованието!'.encode('utf_8')) - >>> best_guess = results.best() - >>> str(best_guess) - 'Bсеки човек има право на образование. Oбразованието!' - -Others methods and usages are available - see the full documentation -at . -:copyright: (c) 2021 by Ahmed TAHRI -:license: MIT, see LICENSE for more details. -""" - -from __future__ import annotations - -import logging - -from .api import from_bytes, from_fp, from_path, is_binary -from .legacy import detect -from .models import CharsetMatch, CharsetMatches -from .utils import set_logging_handler -from .version import VERSION, __version__ - -__all__ = ( - "from_fp", - "from_path", - "from_bytes", - "is_binary", - "detect", - "CharsetMatch", - "CharsetMatches", - "__version__", - "VERSION", - "set_logging_handler", -) - -# Attach a NullHandler to the top level logger by default -# https://docs.python.org/3.3/howto/logging.html#configuring-logging-for-a-library - -logging.getLogger("charset_normalizer").addHandler(logging.NullHandler()) diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/__main__.py b/apps/bitwarden_event_logs/lib/charset_normalizer/__main__.py deleted file mode 100755 index e0e76f7b..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer/__main__.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import annotations - -from .cli import cli_detect - -if __name__ == "__main__": - cli_detect() diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/__init__.cpython-39.pyc b/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/__init__.cpython-39.pyc deleted file mode 100755 index 96480862..00000000 Binary files a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/__init__.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/api.cpython-39.pyc b/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/api.cpython-39.pyc deleted file mode 100755 index 567d4f39..00000000 Binary files a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/api.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/cd.cpython-39.pyc b/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/cd.cpython-39.pyc deleted file mode 100755 index 63668e77..00000000 Binary files a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/cd.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/constant.cpython-39.pyc b/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/constant.cpython-39.pyc deleted file mode 100755 index 0c276ac2..00000000 Binary files a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/constant.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/legacy.cpython-39.pyc b/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/legacy.cpython-39.pyc deleted file mode 100755 index b9ddc1c5..00000000 Binary files a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/legacy.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/md.cpython-39.pyc b/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/md.cpython-39.pyc deleted file mode 100755 index 40aa659e..00000000 Binary files a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/md.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/models.cpython-39.pyc b/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/models.cpython-39.pyc deleted file mode 100755 index 0cdcc26a..00000000 Binary files a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/models.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/utils.cpython-39.pyc b/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/utils.cpython-39.pyc deleted file mode 100755 index c7aded9c..00000000 Binary files a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/utils.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/version.cpython-39.pyc b/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/version.cpython-39.pyc deleted file mode 100755 index ec02afaa..00000000 Binary files a/apps/bitwarden_event_logs/lib/charset_normalizer/__pycache__/version.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/api.py b/apps/bitwarden_event_logs/lib/charset_normalizer/api.py deleted file mode 100755 index ebd96390..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer/api.py +++ /dev/null @@ -1,669 +0,0 @@ -from __future__ import annotations - -import logging -from os import PathLike -from typing import BinaryIO - -from .cd import ( - coherence_ratio, - encoding_languages, - mb_encoding_languages, - merge_coherence_ratios, -) -from .constant import IANA_SUPPORTED, TOO_BIG_SEQUENCE, TOO_SMALL_SEQUENCE, TRACE -from .md import mess_ratio -from .models import CharsetMatch, CharsetMatches -from .utils import ( - any_specified_encoding, - cut_sequence_chunks, - iana_name, - identify_sig_or_bom, - is_cp_similar, - is_multi_byte_encoding, - should_strip_sig_or_bom, -) - -logger = logging.getLogger("charset_normalizer") -explain_handler = logging.StreamHandler() -explain_handler.setFormatter( - logging.Formatter("%(asctime)s | %(levelname)s | %(message)s") -) - - -def from_bytes( - sequences: bytes | bytearray, - steps: int = 5, - chunk_size: int = 512, - threshold: float = 0.2, - cp_isolation: list[str] | None = None, - cp_exclusion: list[str] | None = None, - preemptive_behaviour: bool = True, - explain: bool = False, - language_threshold: float = 0.1, - enable_fallback: bool = True, -) -> CharsetMatches: - """ - Given a raw bytes sequence, return the best possibles charset usable to render str objects. - If there is no results, it is a strong indicator that the source is binary/not text. - By default, the process will extract 5 blocks of 512o each to assess the mess and coherence of a given sequence. - And will give up a particular code page after 20% of measured mess. Those criteria are customizable at will. - - The preemptive behavior DOES NOT replace the traditional detection workflow, it prioritize a particular code page - but never take it for granted. Can improve the performance. - - You may want to focus your attention to some code page or/and not others, use cp_isolation and cp_exclusion for that - purpose. - - This function will strip the SIG in the payload/sequence every time except on UTF-16, UTF-32. - By default the library does not setup any handler other than the NullHandler, if you choose to set the 'explain' - toggle to True it will alter the logger configuration to add a StreamHandler that is suitable for debugging. - Custom logging format and handler can be set manually. - """ - - if not isinstance(sequences, (bytearray, bytes)): - raise TypeError( - "Expected object of type bytes or bytearray, got: {}".format( - type(sequences) - ) - ) - - if explain: - previous_logger_level: int = logger.level - logger.addHandler(explain_handler) - logger.setLevel(TRACE) - - length: int = len(sequences) - - if length == 0: - logger.debug("Encoding detection on empty bytes, assuming utf_8 intention.") - if explain: # Defensive: ensure exit path clean handler - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level or logging.WARNING) - return CharsetMatches([CharsetMatch(sequences, "utf_8", 0.0, False, [], "")]) - - if cp_isolation is not None: - logger.log( - TRACE, - "cp_isolation is set. use this flag for debugging purpose. " - "limited list of encoding allowed : %s.", - ", ".join(cp_isolation), - ) - cp_isolation = [iana_name(cp, False) for cp in cp_isolation] - else: - cp_isolation = [] - - if cp_exclusion is not None: - logger.log( - TRACE, - "cp_exclusion is set. use this flag for debugging purpose. " - "limited list of encoding excluded : %s.", - ", ".join(cp_exclusion), - ) - cp_exclusion = [iana_name(cp, False) for cp in cp_exclusion] - else: - cp_exclusion = [] - - if length <= (chunk_size * steps): - logger.log( - TRACE, - "override steps (%i) and chunk_size (%i) as content does not fit (%i byte(s) given) parameters.", - steps, - chunk_size, - length, - ) - steps = 1 - chunk_size = length - - if steps > 1 and length / steps < chunk_size: - chunk_size = int(length / steps) - - is_too_small_sequence: bool = len(sequences) < TOO_SMALL_SEQUENCE - is_too_large_sequence: bool = len(sequences) >= TOO_BIG_SEQUENCE - - if is_too_small_sequence: - logger.log( - TRACE, - "Trying to detect encoding from a tiny portion of ({}) byte(s).".format( - length - ), - ) - elif is_too_large_sequence: - logger.log( - TRACE, - "Using lazy str decoding because the payload is quite large, ({}) byte(s).".format( - length - ), - ) - - prioritized_encodings: list[str] = [] - - specified_encoding: str | None = ( - any_specified_encoding(sequences) if preemptive_behaviour else None - ) - - if specified_encoding is not None: - prioritized_encodings.append(specified_encoding) - logger.log( - TRACE, - "Detected declarative mark in sequence. Priority +1 given for %s.", - specified_encoding, - ) - - tested: set[str] = set() - tested_but_hard_failure: list[str] = [] - tested_but_soft_failure: list[str] = [] - - fallback_ascii: CharsetMatch | None = None - fallback_u8: CharsetMatch | None = None - fallback_specified: CharsetMatch | None = None - - results: CharsetMatches = CharsetMatches() - - early_stop_results: CharsetMatches = CharsetMatches() - - sig_encoding, sig_payload = identify_sig_or_bom(sequences) - - if sig_encoding is not None: - prioritized_encodings.append(sig_encoding) - logger.log( - TRACE, - "Detected a SIG or BOM mark on first %i byte(s). Priority +1 given for %s.", - len(sig_payload), - sig_encoding, - ) - - prioritized_encodings.append("ascii") - - if "utf_8" not in prioritized_encodings: - prioritized_encodings.append("utf_8") - - for encoding_iana in prioritized_encodings + IANA_SUPPORTED: - if cp_isolation and encoding_iana not in cp_isolation: - continue - - if cp_exclusion and encoding_iana in cp_exclusion: - continue - - if encoding_iana in tested: - continue - - tested.add(encoding_iana) - - decoded_payload: str | None = None - bom_or_sig_available: bool = sig_encoding == encoding_iana - strip_sig_or_bom: bool = bom_or_sig_available and should_strip_sig_or_bom( - encoding_iana - ) - - if encoding_iana in {"utf_16", "utf_32"} and not bom_or_sig_available: - logger.log( - TRACE, - "Encoding %s won't be tested as-is because it require a BOM. Will try some sub-encoder LE/BE.", - encoding_iana, - ) - continue - if encoding_iana in {"utf_7"} and not bom_or_sig_available: - logger.log( - TRACE, - "Encoding %s won't be tested as-is because detection is unreliable without BOM/SIG.", - encoding_iana, - ) - continue - - try: - is_multi_byte_decoder: bool = is_multi_byte_encoding(encoding_iana) - except (ModuleNotFoundError, ImportError): - logger.log( - TRACE, - "Encoding %s does not provide an IncrementalDecoder", - encoding_iana, - ) - continue - - try: - if is_too_large_sequence and is_multi_byte_decoder is False: - str( - ( - sequences[: int(50e4)] - if strip_sig_or_bom is False - else sequences[len(sig_payload) : int(50e4)] - ), - encoding=encoding_iana, - ) - else: - decoded_payload = str( - ( - sequences - if strip_sig_or_bom is False - else sequences[len(sig_payload) :] - ), - encoding=encoding_iana, - ) - except (UnicodeDecodeError, LookupError) as e: - if not isinstance(e, LookupError): - logger.log( - TRACE, - "Code page %s does not fit given bytes sequence at ALL. %s", - encoding_iana, - str(e), - ) - tested_but_hard_failure.append(encoding_iana) - continue - - similar_soft_failure_test: bool = False - - for encoding_soft_failed in tested_but_soft_failure: - if is_cp_similar(encoding_iana, encoding_soft_failed): - similar_soft_failure_test = True - break - - if similar_soft_failure_test: - logger.log( - TRACE, - "%s is deemed too similar to code page %s and was consider unsuited already. Continuing!", - encoding_iana, - encoding_soft_failed, - ) - continue - - r_ = range( - 0 if not bom_or_sig_available else len(sig_payload), - length, - int(length / steps), - ) - - multi_byte_bonus: bool = ( - is_multi_byte_decoder - and decoded_payload is not None - and len(decoded_payload) < length - ) - - if multi_byte_bonus: - logger.log( - TRACE, - "Code page %s is a multi byte encoding table and it appear that at least one character " - "was encoded using n-bytes.", - encoding_iana, - ) - - max_chunk_gave_up: int = int(len(r_) / 4) - - max_chunk_gave_up = max(max_chunk_gave_up, 2) - early_stop_count: int = 0 - lazy_str_hard_failure = False - - md_chunks: list[str] = [] - md_ratios = [] - - try: - for chunk in cut_sequence_chunks( - sequences, - encoding_iana, - r_, - chunk_size, - bom_or_sig_available, - strip_sig_or_bom, - sig_payload, - is_multi_byte_decoder, - decoded_payload, - ): - md_chunks.append(chunk) - - md_ratios.append( - mess_ratio( - chunk, - threshold, - explain is True and 1 <= len(cp_isolation) <= 2, - ) - ) - - if md_ratios[-1] >= threshold: - early_stop_count += 1 - - if (early_stop_count >= max_chunk_gave_up) or ( - bom_or_sig_available and strip_sig_or_bom is False - ): - break - except ( - UnicodeDecodeError - ) as e: # Lazy str loading may have missed something there - logger.log( - TRACE, - "LazyStr Loading: After MD chunk decode, code page %s does not fit given bytes sequence at ALL. %s", - encoding_iana, - str(e), - ) - early_stop_count = max_chunk_gave_up - lazy_str_hard_failure = True - - # We might want to check the sequence again with the whole content - # Only if initial MD tests passes - if ( - not lazy_str_hard_failure - and is_too_large_sequence - and not is_multi_byte_decoder - ): - try: - sequences[int(50e3) :].decode(encoding_iana, errors="strict") - except UnicodeDecodeError as e: - logger.log( - TRACE, - "LazyStr Loading: After final lookup, code page %s does not fit given bytes sequence at ALL. %s", - encoding_iana, - str(e), - ) - tested_but_hard_failure.append(encoding_iana) - continue - - mean_mess_ratio: float = sum(md_ratios) / len(md_ratios) if md_ratios else 0.0 - if mean_mess_ratio >= threshold or early_stop_count >= max_chunk_gave_up: - tested_but_soft_failure.append(encoding_iana) - logger.log( - TRACE, - "%s was excluded because of initial chaos probing. Gave up %i time(s). " - "Computed mean chaos is %f %%.", - encoding_iana, - early_stop_count, - round(mean_mess_ratio * 100, ndigits=3), - ) - # Preparing those fallbacks in case we got nothing. - if ( - enable_fallback - and encoding_iana - in ["ascii", "utf_8", specified_encoding, "utf_16", "utf_32"] - and not lazy_str_hard_failure - ): - fallback_entry = CharsetMatch( - sequences, - encoding_iana, - threshold, - bom_or_sig_available, - [], - decoded_payload, - preemptive_declaration=specified_encoding, - ) - if encoding_iana == specified_encoding: - fallback_specified = fallback_entry - elif encoding_iana == "ascii": - fallback_ascii = fallback_entry - else: - fallback_u8 = fallback_entry - continue - - logger.log( - TRACE, - "%s passed initial chaos probing. Mean measured chaos is %f %%", - encoding_iana, - round(mean_mess_ratio * 100, ndigits=3), - ) - - if not is_multi_byte_decoder: - target_languages: list[str] = encoding_languages(encoding_iana) - else: - target_languages = mb_encoding_languages(encoding_iana) - - if target_languages: - logger.log( - TRACE, - "{} should target any language(s) of {}".format( - encoding_iana, str(target_languages) - ), - ) - - cd_ratios = [] - - # We shall skip the CD when its about ASCII - # Most of the time its not relevant to run "language-detection" on it. - if encoding_iana != "ascii": - for chunk in md_chunks: - chunk_languages = coherence_ratio( - chunk, - language_threshold, - ",".join(target_languages) if target_languages else None, - ) - - cd_ratios.append(chunk_languages) - - cd_ratios_merged = merge_coherence_ratios(cd_ratios) - - if cd_ratios_merged: - logger.log( - TRACE, - "We detected language {} using {}".format( - cd_ratios_merged, encoding_iana - ), - ) - - current_match = CharsetMatch( - sequences, - encoding_iana, - mean_mess_ratio, - bom_or_sig_available, - cd_ratios_merged, - ( - decoded_payload - if ( - is_too_large_sequence is False - or encoding_iana in [specified_encoding, "ascii", "utf_8"] - ) - else None - ), - preemptive_declaration=specified_encoding, - ) - - results.append(current_match) - - if ( - encoding_iana in [specified_encoding, "ascii", "utf_8"] - and mean_mess_ratio < 0.1 - ): - # If md says nothing to worry about, then... stop immediately! - if mean_mess_ratio == 0.0: - logger.debug( - "Encoding detection: %s is most likely the one.", - current_match.encoding, - ) - if explain: # Defensive: ensure exit path clean handler - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - return CharsetMatches([current_match]) - - early_stop_results.append(current_match) - - if ( - len(early_stop_results) - and (specified_encoding is None or specified_encoding in tested) - and "ascii" in tested - and "utf_8" in tested - ): - probable_result: CharsetMatch = early_stop_results.best() # type: ignore[assignment] - logger.debug( - "Encoding detection: %s is most likely the one.", - probable_result.encoding, - ) - if explain: # Defensive: ensure exit path clean handler - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - - return CharsetMatches([probable_result]) - - if encoding_iana == sig_encoding: - logger.debug( - "Encoding detection: %s is most likely the one as we detected a BOM or SIG within " - "the beginning of the sequence.", - encoding_iana, - ) - if explain: # Defensive: ensure exit path clean handler - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - return CharsetMatches([results[encoding_iana]]) - - if len(results) == 0: - if fallback_u8 or fallback_ascii or fallback_specified: - logger.log( - TRACE, - "Nothing got out of the detection process. Using ASCII/UTF-8/Specified fallback.", - ) - - if fallback_specified: - logger.debug( - "Encoding detection: %s will be used as a fallback match", - fallback_specified.encoding, - ) - results.append(fallback_specified) - elif ( - (fallback_u8 and fallback_ascii is None) - or ( - fallback_u8 - and fallback_ascii - and fallback_u8.fingerprint != fallback_ascii.fingerprint - ) - or (fallback_u8 is not None) - ): - logger.debug("Encoding detection: utf_8 will be used as a fallback match") - results.append(fallback_u8) - elif fallback_ascii: - logger.debug("Encoding detection: ascii will be used as a fallback match") - results.append(fallback_ascii) - - if results: - logger.debug( - "Encoding detection: Found %s as plausible (best-candidate) for content. With %i alternatives.", - results.best().encoding, # type: ignore - len(results) - 1, - ) - else: - logger.debug("Encoding detection: Unable to determine any suitable charset.") - - if explain: - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - - return results - - -def from_fp( - fp: BinaryIO, - steps: int = 5, - chunk_size: int = 512, - threshold: float = 0.20, - cp_isolation: list[str] | None = None, - cp_exclusion: list[str] | None = None, - preemptive_behaviour: bool = True, - explain: bool = False, - language_threshold: float = 0.1, - enable_fallback: bool = True, -) -> CharsetMatches: - """ - Same thing than the function from_bytes but using a file pointer that is already ready. - Will not close the file pointer. - """ - return from_bytes( - fp.read(), - steps, - chunk_size, - threshold, - cp_isolation, - cp_exclusion, - preemptive_behaviour, - explain, - language_threshold, - enable_fallback, - ) - - -def from_path( - path: str | bytes | PathLike, # type: ignore[type-arg] - steps: int = 5, - chunk_size: int = 512, - threshold: float = 0.20, - cp_isolation: list[str] | None = None, - cp_exclusion: list[str] | None = None, - preemptive_behaviour: bool = True, - explain: bool = False, - language_threshold: float = 0.1, - enable_fallback: bool = True, -) -> CharsetMatches: - """ - Same thing than the function from_bytes but with one extra step. Opening and reading given file path in binary mode. - Can raise IOError. - """ - with open(path, "rb") as fp: - return from_fp( - fp, - steps, - chunk_size, - threshold, - cp_isolation, - cp_exclusion, - preemptive_behaviour, - explain, - language_threshold, - enable_fallback, - ) - - -def is_binary( - fp_or_path_or_payload: PathLike | str | BinaryIO | bytes, # type: ignore[type-arg] - steps: int = 5, - chunk_size: int = 512, - threshold: float = 0.20, - cp_isolation: list[str] | None = None, - cp_exclusion: list[str] | None = None, - preemptive_behaviour: bool = True, - explain: bool = False, - language_threshold: float = 0.1, - enable_fallback: bool = False, -) -> bool: - """ - Detect if the given input (file, bytes, or path) points to a binary file. aka. not a string. - Based on the same main heuristic algorithms and default kwargs at the sole exception that fallbacks match - are disabled to be stricter around ASCII-compatible but unlikely to be a string. - """ - if isinstance(fp_or_path_or_payload, (str, PathLike)): - guesses = from_path( - fp_or_path_or_payload, - steps=steps, - chunk_size=chunk_size, - threshold=threshold, - cp_isolation=cp_isolation, - cp_exclusion=cp_exclusion, - preemptive_behaviour=preemptive_behaviour, - explain=explain, - language_threshold=language_threshold, - enable_fallback=enable_fallback, - ) - elif isinstance( - fp_or_path_or_payload, - ( - bytes, - bytearray, - ), - ): - guesses = from_bytes( - fp_or_path_or_payload, - steps=steps, - chunk_size=chunk_size, - threshold=threshold, - cp_isolation=cp_isolation, - cp_exclusion=cp_exclusion, - preemptive_behaviour=preemptive_behaviour, - explain=explain, - language_threshold=language_threshold, - enable_fallback=enable_fallback, - ) - else: - guesses = from_fp( - fp_or_path_or_payload, - steps=steps, - chunk_size=chunk_size, - threshold=threshold, - cp_isolation=cp_isolation, - cp_exclusion=cp_exclusion, - preemptive_behaviour=preemptive_behaviour, - explain=explain, - language_threshold=language_threshold, - enable_fallback=enable_fallback, - ) - - return not guesses diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/cd.py b/apps/bitwarden_event_logs/lib/charset_normalizer/cd.py deleted file mode 100755 index 71a3ed51..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer/cd.py +++ /dev/null @@ -1,395 +0,0 @@ -from __future__ import annotations - -import importlib -from codecs import IncrementalDecoder -from collections import Counter -from functools import lru_cache -from typing import Counter as TypeCounter - -from .constant import ( - FREQUENCIES, - KO_NAMES, - LANGUAGE_SUPPORTED_COUNT, - TOO_SMALL_SEQUENCE, - ZH_NAMES, -) -from .md import is_suspiciously_successive_range -from .models import CoherenceMatches -from .utils import ( - is_accentuated, - is_latin, - is_multi_byte_encoding, - is_unicode_range_secondary, - unicode_range, -) - - -def encoding_unicode_range(iana_name: str) -> list[str]: - """ - Return associated unicode ranges in a single byte code page. - """ - if is_multi_byte_encoding(iana_name): - raise OSError("Function not supported on multi-byte code page") - - decoder = importlib.import_module(f"encodings.{iana_name}").IncrementalDecoder - - p: IncrementalDecoder = decoder(errors="ignore") - seen_ranges: dict[str, int] = {} - character_count: int = 0 - - for i in range(0x40, 0xFF): - chunk: str = p.decode(bytes([i])) - - if chunk: - character_range: str | None = unicode_range(chunk) - - if character_range is None: - continue - - if is_unicode_range_secondary(character_range) is False: - if character_range not in seen_ranges: - seen_ranges[character_range] = 0 - seen_ranges[character_range] += 1 - character_count += 1 - - return sorted( - [ - character_range - for character_range in seen_ranges - if seen_ranges[character_range] / character_count >= 0.15 - ] - ) - - -def unicode_range_languages(primary_range: str) -> list[str]: - """ - Return inferred languages used with a unicode range. - """ - languages: list[str] = [] - - for language, characters in FREQUENCIES.items(): - for character in characters: - if unicode_range(character) == primary_range: - languages.append(language) - break - - return languages - - -@lru_cache() -def encoding_languages(iana_name: str) -> list[str]: - """ - Single-byte encoding language association. Some code page are heavily linked to particular language(s). - This function does the correspondence. - """ - unicode_ranges: list[str] = encoding_unicode_range(iana_name) - primary_range: str | None = None - - for specified_range in unicode_ranges: - if "Latin" not in specified_range: - primary_range = specified_range - break - - if primary_range is None: - return ["Latin Based"] - - return unicode_range_languages(primary_range) - - -@lru_cache() -def mb_encoding_languages(iana_name: str) -> list[str]: - """ - Multi-byte encoding language association. Some code page are heavily linked to particular language(s). - This function does the correspondence. - """ - if ( - iana_name.startswith("shift_") - or iana_name.startswith("iso2022_jp") - or iana_name.startswith("euc_j") - or iana_name == "cp932" - ): - return ["Japanese"] - if iana_name.startswith("gb") or iana_name in ZH_NAMES: - return ["Chinese"] - if iana_name.startswith("iso2022_kr") or iana_name in KO_NAMES: - return ["Korean"] - - return [] - - -@lru_cache(maxsize=LANGUAGE_SUPPORTED_COUNT) -def get_target_features(language: str) -> tuple[bool, bool]: - """ - Determine main aspects from a supported language if it contains accents and if is pure Latin. - """ - target_have_accents: bool = False - target_pure_latin: bool = True - - for character in FREQUENCIES[language]: - if not target_have_accents and is_accentuated(character): - target_have_accents = True - if target_pure_latin and is_latin(character) is False: - target_pure_latin = False - - return target_have_accents, target_pure_latin - - -def alphabet_languages( - characters: list[str], ignore_non_latin: bool = False -) -> list[str]: - """ - Return associated languages associated to given characters. - """ - languages: list[tuple[str, float]] = [] - - source_have_accents = any(is_accentuated(character) for character in characters) - - for language, language_characters in FREQUENCIES.items(): - target_have_accents, target_pure_latin = get_target_features(language) - - if ignore_non_latin and target_pure_latin is False: - continue - - if target_have_accents is False and source_have_accents: - continue - - character_count: int = len(language_characters) - - character_match_count: int = len( - [c for c in language_characters if c in characters] - ) - - ratio: float = character_match_count / character_count - - if ratio >= 0.2: - languages.append((language, ratio)) - - languages = sorted(languages, key=lambda x: x[1], reverse=True) - - return [compatible_language[0] for compatible_language in languages] - - -def characters_popularity_compare( - language: str, ordered_characters: list[str] -) -> float: - """ - Determine if a ordered characters list (by occurrence from most appearance to rarest) match a particular language. - The result is a ratio between 0. (absolutely no correspondence) and 1. (near perfect fit). - Beware that is function is not strict on the match in order to ease the detection. (Meaning close match is 1.) - """ - if language not in FREQUENCIES: - raise ValueError(f"{language} not available") - - character_approved_count: int = 0 - FREQUENCIES_language_set = set(FREQUENCIES[language]) - - ordered_characters_count: int = len(ordered_characters) - target_language_characters_count: int = len(FREQUENCIES[language]) - - large_alphabet: bool = target_language_characters_count > 26 - - for character, character_rank in zip( - ordered_characters, range(0, ordered_characters_count) - ): - if character not in FREQUENCIES_language_set: - continue - - character_rank_in_language: int = FREQUENCIES[language].index(character) - expected_projection_ratio: float = ( - target_language_characters_count / ordered_characters_count - ) - character_rank_projection: int = int(character_rank * expected_projection_ratio) - - if ( - large_alphabet is False - and abs(character_rank_projection - character_rank_in_language) > 4 - ): - continue - - if ( - large_alphabet is True - and abs(character_rank_projection - character_rank_in_language) - < target_language_characters_count / 3 - ): - character_approved_count += 1 - continue - - characters_before_source: list[str] = FREQUENCIES[language][ - 0:character_rank_in_language - ] - characters_after_source: list[str] = FREQUENCIES[language][ - character_rank_in_language: - ] - characters_before: list[str] = ordered_characters[0:character_rank] - characters_after: list[str] = ordered_characters[character_rank:] - - before_match_count: int = len( - set(characters_before) & set(characters_before_source) - ) - - after_match_count: int = len( - set(characters_after) & set(characters_after_source) - ) - - if len(characters_before_source) == 0 and before_match_count <= 4: - character_approved_count += 1 - continue - - if len(characters_after_source) == 0 and after_match_count <= 4: - character_approved_count += 1 - continue - - if ( - before_match_count / len(characters_before_source) >= 0.4 - or after_match_count / len(characters_after_source) >= 0.4 - ): - character_approved_count += 1 - continue - - return character_approved_count / len(ordered_characters) - - -def alpha_unicode_split(decoded_sequence: str) -> list[str]: - """ - Given a decoded text sequence, return a list of str. Unicode range / alphabet separation. - Ex. a text containing English/Latin with a bit a Hebrew will return two items in the resulting list; - One containing the latin letters and the other hebrew. - """ - layers: dict[str, str] = {} - - for character in decoded_sequence: - if character.isalpha() is False: - continue - - character_range: str | None = unicode_range(character) - - if character_range is None: - continue - - layer_target_range: str | None = None - - for discovered_range in layers: - if ( - is_suspiciously_successive_range(discovered_range, character_range) - is False - ): - layer_target_range = discovered_range - break - - if layer_target_range is None: - layer_target_range = character_range - - if layer_target_range not in layers: - layers[layer_target_range] = character.lower() - continue - - layers[layer_target_range] += character.lower() - - return list(layers.values()) - - -def merge_coherence_ratios(results: list[CoherenceMatches]) -> CoherenceMatches: - """ - This function merge results previously given by the function coherence_ratio. - The return type is the same as coherence_ratio. - """ - per_language_ratios: dict[str, list[float]] = {} - for result in results: - for sub_result in result: - language, ratio = sub_result - if language not in per_language_ratios: - per_language_ratios[language] = [ratio] - continue - per_language_ratios[language].append(ratio) - - merge = [ - ( - language, - round( - sum(per_language_ratios[language]) / len(per_language_ratios[language]), - 4, - ), - ) - for language in per_language_ratios - ] - - return sorted(merge, key=lambda x: x[1], reverse=True) - - -def filter_alt_coherence_matches(results: CoherenceMatches) -> CoherenceMatches: - """ - We shall NOT return "English—" in CoherenceMatches because it is an alternative - of "English". This function only keeps the best match and remove the em-dash in it. - """ - index_results: dict[str, list[float]] = dict() - - for result in results: - language, ratio = result - no_em_name: str = language.replace("—", "") - - if no_em_name not in index_results: - index_results[no_em_name] = [] - - index_results[no_em_name].append(ratio) - - if any(len(index_results[e]) > 1 for e in index_results): - filtered_results: CoherenceMatches = [] - - for language in index_results: - filtered_results.append((language, max(index_results[language]))) - - return filtered_results - - return results - - -@lru_cache(maxsize=2048) -def coherence_ratio( - decoded_sequence: str, threshold: float = 0.1, lg_inclusion: str | None = None -) -> CoherenceMatches: - """ - Detect ANY language that can be identified in given sequence. The sequence will be analysed by layers. - A layer = Character extraction by alphabets/ranges. - """ - - results: list[tuple[str, float]] = [] - ignore_non_latin: bool = False - - sufficient_match_count: int = 0 - - lg_inclusion_list = lg_inclusion.split(",") if lg_inclusion is not None else [] - if "Latin Based" in lg_inclusion_list: - ignore_non_latin = True - lg_inclusion_list.remove("Latin Based") - - for layer in alpha_unicode_split(decoded_sequence): - sequence_frequencies: TypeCounter[str] = Counter(layer) - most_common = sequence_frequencies.most_common() - - character_count: int = sum(o for c, o in most_common) - - if character_count <= TOO_SMALL_SEQUENCE: - continue - - popular_character_ordered: list[str] = [c for c, o in most_common] - - for language in lg_inclusion_list or alphabet_languages( - popular_character_ordered, ignore_non_latin - ): - ratio: float = characters_popularity_compare( - language, popular_character_ordered - ) - - if ratio < threshold: - continue - elif ratio >= 0.8: - sufficient_match_count += 1 - - results.append((language, round(ratio, 4))) - - if sufficient_match_count >= 3: - break - - return sorted( - filter_alt_coherence_matches(results), key=lambda x: x[1], reverse=True - ) diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/cli/__init__.py b/apps/bitwarden_event_logs/lib/charset_normalizer/cli/__init__.py deleted file mode 100755 index 543a5a4d..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer/cli/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import annotations - -from .__main__ import cli_detect, query_yes_no - -__all__ = ( - "cli_detect", - "query_yes_no", -) diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/cli/__main__.py b/apps/bitwarden_event_logs/lib/charset_normalizer/cli/__main__.py deleted file mode 100755 index cb64156a..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer/cli/__main__.py +++ /dev/null @@ -1,381 +0,0 @@ -from __future__ import annotations - -import argparse -import sys -import typing -from json import dumps -from os.path import abspath, basename, dirname, join, realpath -from platform import python_version -from unicodedata import unidata_version - -import charset_normalizer.md as md_module -from charset_normalizer import from_fp -from charset_normalizer.models import CliDetectionResult -from charset_normalizer.version import __version__ - - -def query_yes_no(question: str, default: str = "yes") -> bool: - """Ask a yes/no question via input() and return their answer. - - "question" is a string that is presented to the user. - "default" is the presumed answer if the user just hits . - It must be "yes" (the default), "no" or None (meaning - an answer is required of the user). - - The "answer" return value is True for "yes" or False for "no". - - Credit goes to (c) https://stackoverflow.com/questions/3041986/apt-command-line-interface-like-yes-no-input - """ - valid = {"yes": True, "y": True, "ye": True, "no": False, "n": False} - if default is None: - prompt = " [y/n] " - elif default == "yes": - prompt = " [Y/n] " - elif default == "no": - prompt = " [y/N] " - else: - raise ValueError("invalid default answer: '%s'" % default) - - while True: - sys.stdout.write(question + prompt) - choice = input().lower() - if default is not None and choice == "": - return valid[default] - elif choice in valid: - return valid[choice] - else: - sys.stdout.write("Please respond with 'yes' or 'no' (or 'y' or 'n').\n") - - -class FileType: - """Factory for creating file object types - - Instances of FileType are typically passed as type= arguments to the - ArgumentParser add_argument() method. - - Keyword Arguments: - - mode -- A string indicating how the file is to be opened. Accepts the - same values as the builtin open() function. - - bufsize -- The file's desired buffer size. Accepts the same values as - the builtin open() function. - - encoding -- The file's encoding. Accepts the same values as the - builtin open() function. - - errors -- A string indicating how encoding and decoding errors are to - be handled. Accepts the same value as the builtin open() function. - - Backported from CPython 3.12 - """ - - def __init__( - self, - mode: str = "r", - bufsize: int = -1, - encoding: str | None = None, - errors: str | None = None, - ): - self._mode = mode - self._bufsize = bufsize - self._encoding = encoding - self._errors = errors - - def __call__(self, string: str) -> typing.IO: # type: ignore[type-arg] - # the special argument "-" means sys.std{in,out} - if string == "-": - if "r" in self._mode: - return sys.stdin.buffer if "b" in self._mode else sys.stdin - elif any(c in self._mode for c in "wax"): - return sys.stdout.buffer if "b" in self._mode else sys.stdout - else: - msg = f'argument "-" with mode {self._mode}' - raise ValueError(msg) - - # all other arguments are used as file names - try: - return open(string, self._mode, self._bufsize, self._encoding, self._errors) - except OSError as e: - message = f"can't open '{string}': {e}" - raise argparse.ArgumentTypeError(message) - - def __repr__(self) -> str: - args = self._mode, self._bufsize - kwargs = [("encoding", self._encoding), ("errors", self._errors)] - args_str = ", ".join( - [repr(arg) for arg in args if arg != -1] - + [f"{kw}={arg!r}" for kw, arg in kwargs if arg is not None] - ) - return f"{type(self).__name__}({args_str})" - - -def cli_detect(argv: list[str] | None = None) -> int: - """ - CLI assistant using ARGV and ArgumentParser - :param argv: - :return: 0 if everything is fine, anything else equal trouble - """ - parser = argparse.ArgumentParser( - description="The Real First Universal Charset Detector. " - "Discover originating encoding used on text file. " - "Normalize text to unicode." - ) - - parser.add_argument( - "files", type=FileType("rb"), nargs="+", help="File(s) to be analysed" - ) - parser.add_argument( - "-v", - "--verbose", - action="store_true", - default=False, - dest="verbose", - help="Display complementary information about file if any. " - "Stdout will contain logs about the detection process.", - ) - parser.add_argument( - "-a", - "--with-alternative", - action="store_true", - default=False, - dest="alternatives", - help="Output complementary possibilities if any. Top-level JSON WILL be a list.", - ) - parser.add_argument( - "-n", - "--normalize", - action="store_true", - default=False, - dest="normalize", - help="Permit to normalize input file. If not set, program does not write anything.", - ) - parser.add_argument( - "-m", - "--minimal", - action="store_true", - default=False, - dest="minimal", - help="Only output the charset detected to STDOUT. Disabling JSON output.", - ) - parser.add_argument( - "-r", - "--replace", - action="store_true", - default=False, - dest="replace", - help="Replace file when trying to normalize it instead of creating a new one.", - ) - parser.add_argument( - "-f", - "--force", - action="store_true", - default=False, - dest="force", - help="Replace file without asking if you are sure, use this flag with caution.", - ) - parser.add_argument( - "-i", - "--no-preemptive", - action="store_true", - default=False, - dest="no_preemptive", - help="Disable looking at a charset declaration to hint the detector.", - ) - parser.add_argument( - "-t", - "--threshold", - action="store", - default=0.2, - type=float, - dest="threshold", - help="Define a custom maximum amount of noise allowed in decoded content. 0. <= noise <= 1.", - ) - parser.add_argument( - "--version", - action="version", - version="Charset-Normalizer {} - Python {} - Unicode {} - SpeedUp {}".format( - __version__, - python_version(), - unidata_version, - "OFF" if md_module.__file__.lower().endswith(".py") else "ON", - ), - help="Show version information and exit.", - ) - - args = parser.parse_args(argv) - - if args.replace is True and args.normalize is False: - if args.files: - for my_file in args.files: - my_file.close() - print("Use --replace in addition of --normalize only.", file=sys.stderr) - return 1 - - if args.force is True and args.replace is False: - if args.files: - for my_file in args.files: - my_file.close() - print("Use --force in addition of --replace only.", file=sys.stderr) - return 1 - - if args.threshold < 0.0 or args.threshold > 1.0: - if args.files: - for my_file in args.files: - my_file.close() - print("--threshold VALUE should be between 0. AND 1.", file=sys.stderr) - return 1 - - x_ = [] - - for my_file in args.files: - matches = from_fp( - my_file, - threshold=args.threshold, - explain=args.verbose, - preemptive_behaviour=args.no_preemptive is False, - ) - - best_guess = matches.best() - - if best_guess is None: - print( - 'Unable to identify originating encoding for "{}". {}'.format( - my_file.name, - ( - "Maybe try increasing maximum amount of chaos." - if args.threshold < 1.0 - else "" - ), - ), - file=sys.stderr, - ) - x_.append( - CliDetectionResult( - abspath(my_file.name), - None, - [], - [], - "Unknown", - [], - False, - 1.0, - 0.0, - None, - True, - ) - ) - else: - x_.append( - CliDetectionResult( - abspath(my_file.name), - best_guess.encoding, - best_guess.encoding_aliases, - [ - cp - for cp in best_guess.could_be_from_charset - if cp != best_guess.encoding - ], - best_guess.language, - best_guess.alphabets, - best_guess.bom, - best_guess.percent_chaos, - best_guess.percent_coherence, - None, - True, - ) - ) - - if len(matches) > 1 and args.alternatives: - for el in matches: - if el != best_guess: - x_.append( - CliDetectionResult( - abspath(my_file.name), - el.encoding, - el.encoding_aliases, - [ - cp - for cp in el.could_be_from_charset - if cp != el.encoding - ], - el.language, - el.alphabets, - el.bom, - el.percent_chaos, - el.percent_coherence, - None, - False, - ) - ) - - if args.normalize is True: - if best_guess.encoding.startswith("utf") is True: - print( - '"{}" file does not need to be normalized, as it already came from unicode.'.format( - my_file.name - ), - file=sys.stderr, - ) - if my_file.closed is False: - my_file.close() - continue - - dir_path = dirname(realpath(my_file.name)) - file_name = basename(realpath(my_file.name)) - - o_: list[str] = file_name.split(".") - - if args.replace is False: - o_.insert(-1, best_guess.encoding) - if my_file.closed is False: - my_file.close() - elif ( - args.force is False - and query_yes_no( - 'Are you sure to normalize "{}" by replacing it ?'.format( - my_file.name - ), - "no", - ) - is False - ): - if my_file.closed is False: - my_file.close() - continue - - try: - x_[0].unicode_path = join(dir_path, ".".join(o_)) - - with open(x_[0].unicode_path, "wb") as fp: - fp.write(best_guess.output()) - except OSError as e: - print(str(e), file=sys.stderr) - if my_file.closed is False: - my_file.close() - return 2 - - if my_file.closed is False: - my_file.close() - - if args.minimal is False: - print( - dumps( - [el.__dict__ for el in x_] if len(x_) > 1 else x_[0].__dict__, - ensure_ascii=True, - indent=4, - ) - ) - else: - for my_file in args.files: - print( - ", ".join( - [ - el.encoding or "undefined" - for el in x_ - if el.path == abspath(my_file.name) - ] - ) - ) - - return 0 - - -if __name__ == "__main__": - cli_detect() diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/constant.py b/apps/bitwarden_event_logs/lib/charset_normalizer/constant.py deleted file mode 100755 index cc71a019..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer/constant.py +++ /dev/null @@ -1,2015 +0,0 @@ -from __future__ import annotations - -from codecs import BOM_UTF8, BOM_UTF16_BE, BOM_UTF16_LE, BOM_UTF32_BE, BOM_UTF32_LE -from encodings.aliases import aliases -from re import IGNORECASE -from re import compile as re_compile - -# Contain for each eligible encoding a list of/item bytes SIG/BOM -ENCODING_MARKS: dict[str, bytes | list[bytes]] = { - "utf_8": BOM_UTF8, - "utf_7": [ - b"\x2b\x2f\x76\x38", - b"\x2b\x2f\x76\x39", - b"\x2b\x2f\x76\x2b", - b"\x2b\x2f\x76\x2f", - b"\x2b\x2f\x76\x38\x2d", - ], - "gb18030": b"\x84\x31\x95\x33", - "utf_32": [BOM_UTF32_BE, BOM_UTF32_LE], - "utf_16": [BOM_UTF16_BE, BOM_UTF16_LE], -} - -TOO_SMALL_SEQUENCE: int = 32 -TOO_BIG_SEQUENCE: int = int(10e6) - -UTF8_MAXIMAL_ALLOCATION: int = 1_112_064 - -# Up-to-date Unicode ucd/15.0.0 -UNICODE_RANGES_COMBINED: dict[str, range] = { - "Control character": range(32), - "Basic Latin": range(32, 128), - "Latin-1 Supplement": range(128, 256), - "Latin Extended-A": range(256, 384), - "Latin Extended-B": range(384, 592), - "IPA Extensions": range(592, 688), - "Spacing Modifier Letters": range(688, 768), - "Combining Diacritical Marks": range(768, 880), - "Greek and Coptic": range(880, 1024), - "Cyrillic": range(1024, 1280), - "Cyrillic Supplement": range(1280, 1328), - "Armenian": range(1328, 1424), - "Hebrew": range(1424, 1536), - "Arabic": range(1536, 1792), - "Syriac": range(1792, 1872), - "Arabic Supplement": range(1872, 1920), - "Thaana": range(1920, 1984), - "NKo": range(1984, 2048), - "Samaritan": range(2048, 2112), - "Mandaic": range(2112, 2144), - "Syriac Supplement": range(2144, 2160), - "Arabic Extended-B": range(2160, 2208), - "Arabic Extended-A": range(2208, 2304), - "Devanagari": range(2304, 2432), - "Bengali": range(2432, 2560), - "Gurmukhi": range(2560, 2688), - "Gujarati": range(2688, 2816), - "Oriya": range(2816, 2944), - "Tamil": range(2944, 3072), - "Telugu": range(3072, 3200), - "Kannada": range(3200, 3328), - "Malayalam": range(3328, 3456), - "Sinhala": range(3456, 3584), - "Thai": range(3584, 3712), - "Lao": range(3712, 3840), - "Tibetan": range(3840, 4096), - "Myanmar": range(4096, 4256), - "Georgian": range(4256, 4352), - "Hangul Jamo": range(4352, 4608), - "Ethiopic": range(4608, 4992), - "Ethiopic Supplement": range(4992, 5024), - "Cherokee": range(5024, 5120), - "Unified Canadian Aboriginal Syllabics": range(5120, 5760), - "Ogham": range(5760, 5792), - "Runic": range(5792, 5888), - "Tagalog": range(5888, 5920), - "Hanunoo": range(5920, 5952), - "Buhid": range(5952, 5984), - "Tagbanwa": range(5984, 6016), - "Khmer": range(6016, 6144), - "Mongolian": range(6144, 6320), - "Unified Canadian Aboriginal Syllabics Extended": range(6320, 6400), - "Limbu": range(6400, 6480), - "Tai Le": range(6480, 6528), - "New Tai Lue": range(6528, 6624), - "Khmer Symbols": range(6624, 6656), - "Buginese": range(6656, 6688), - "Tai Tham": range(6688, 6832), - "Combining Diacritical Marks Extended": range(6832, 6912), - "Balinese": range(6912, 7040), - "Sundanese": range(7040, 7104), - "Batak": range(7104, 7168), - "Lepcha": range(7168, 7248), - "Ol Chiki": range(7248, 7296), - "Cyrillic Extended-C": range(7296, 7312), - "Georgian Extended": range(7312, 7360), - "Sundanese Supplement": range(7360, 7376), - "Vedic Extensions": range(7376, 7424), - "Phonetic Extensions": range(7424, 7552), - "Phonetic Extensions Supplement": range(7552, 7616), - "Combining Diacritical Marks Supplement": range(7616, 7680), - "Latin Extended Additional": range(7680, 7936), - "Greek Extended": range(7936, 8192), - "General Punctuation": range(8192, 8304), - "Superscripts and Subscripts": range(8304, 8352), - "Currency Symbols": range(8352, 8400), - "Combining Diacritical Marks for Symbols": range(8400, 8448), - "Letterlike Symbols": range(8448, 8528), - "Number Forms": range(8528, 8592), - "Arrows": range(8592, 8704), - "Mathematical Operators": range(8704, 8960), - "Miscellaneous Technical": range(8960, 9216), - "Control Pictures": range(9216, 9280), - "Optical Character Recognition": range(9280, 9312), - "Enclosed Alphanumerics": range(9312, 9472), - "Box Drawing": range(9472, 9600), - "Block Elements": range(9600, 9632), - "Geometric Shapes": range(9632, 9728), - "Miscellaneous Symbols": range(9728, 9984), - "Dingbats": range(9984, 10176), - "Miscellaneous Mathematical Symbols-A": range(10176, 10224), - "Supplemental Arrows-A": range(10224, 10240), - "Braille Patterns": range(10240, 10496), - "Supplemental Arrows-B": range(10496, 10624), - "Miscellaneous Mathematical Symbols-B": range(10624, 10752), - "Supplemental Mathematical Operators": range(10752, 11008), - "Miscellaneous Symbols and Arrows": range(11008, 11264), - "Glagolitic": range(11264, 11360), - "Latin Extended-C": range(11360, 11392), - "Coptic": range(11392, 11520), - "Georgian Supplement": range(11520, 11568), - "Tifinagh": range(11568, 11648), - "Ethiopic Extended": range(11648, 11744), - "Cyrillic Extended-A": range(11744, 11776), - "Supplemental Punctuation": range(11776, 11904), - "CJK Radicals Supplement": range(11904, 12032), - "Kangxi Radicals": range(12032, 12256), - "Ideographic Description Characters": range(12272, 12288), - "CJK Symbols and Punctuation": range(12288, 12352), - "Hiragana": range(12352, 12448), - "Katakana": range(12448, 12544), - "Bopomofo": range(12544, 12592), - "Hangul Compatibility Jamo": range(12592, 12688), - "Kanbun": range(12688, 12704), - "Bopomofo Extended": range(12704, 12736), - "CJK Strokes": range(12736, 12784), - "Katakana Phonetic Extensions": range(12784, 12800), - "Enclosed CJK Letters and Months": range(12800, 13056), - "CJK Compatibility": range(13056, 13312), - "CJK Unified Ideographs Extension A": range(13312, 19904), - "Yijing Hexagram Symbols": range(19904, 19968), - "CJK Unified Ideographs": range(19968, 40960), - "Yi Syllables": range(40960, 42128), - "Yi Radicals": range(42128, 42192), - "Lisu": range(42192, 42240), - "Vai": range(42240, 42560), - "Cyrillic Extended-B": range(42560, 42656), - "Bamum": range(42656, 42752), - "Modifier Tone Letters": range(42752, 42784), - "Latin Extended-D": range(42784, 43008), - "Syloti Nagri": range(43008, 43056), - "Common Indic Number Forms": range(43056, 43072), - "Phags-pa": range(43072, 43136), - "Saurashtra": range(43136, 43232), - "Devanagari Extended": range(43232, 43264), - "Kayah Li": range(43264, 43312), - "Rejang": range(43312, 43360), - "Hangul Jamo Extended-A": range(43360, 43392), - "Javanese": range(43392, 43488), - "Myanmar Extended-B": range(43488, 43520), - "Cham": range(43520, 43616), - "Myanmar Extended-A": range(43616, 43648), - "Tai Viet": range(43648, 43744), - "Meetei Mayek Extensions": range(43744, 43776), - "Ethiopic Extended-A": range(43776, 43824), - "Latin Extended-E": range(43824, 43888), - "Cherokee Supplement": range(43888, 43968), - "Meetei Mayek": range(43968, 44032), - "Hangul Syllables": range(44032, 55216), - "Hangul Jamo Extended-B": range(55216, 55296), - "High Surrogates": range(55296, 56192), - "High Private Use Surrogates": range(56192, 56320), - "Low Surrogates": range(56320, 57344), - "Private Use Area": range(57344, 63744), - "CJK Compatibility Ideographs": range(63744, 64256), - "Alphabetic Presentation Forms": range(64256, 64336), - "Arabic Presentation Forms-A": range(64336, 65024), - "Variation Selectors": range(65024, 65040), - "Vertical Forms": range(65040, 65056), - "Combining Half Marks": range(65056, 65072), - "CJK Compatibility Forms": range(65072, 65104), - "Small Form Variants": range(65104, 65136), - "Arabic Presentation Forms-B": range(65136, 65280), - "Halfwidth and Fullwidth Forms": range(65280, 65520), - "Specials": range(65520, 65536), - "Linear B Syllabary": range(65536, 65664), - "Linear B Ideograms": range(65664, 65792), - "Aegean Numbers": range(65792, 65856), - "Ancient Greek Numbers": range(65856, 65936), - "Ancient Symbols": range(65936, 66000), - "Phaistos Disc": range(66000, 66048), - "Lycian": range(66176, 66208), - "Carian": range(66208, 66272), - "Coptic Epact Numbers": range(66272, 66304), - "Old Italic": range(66304, 66352), - "Gothic": range(66352, 66384), - "Old Permic": range(66384, 66432), - "Ugaritic": range(66432, 66464), - "Old Persian": range(66464, 66528), - "Deseret": range(66560, 66640), - "Shavian": range(66640, 66688), - "Osmanya": range(66688, 66736), - "Osage": range(66736, 66816), - "Elbasan": range(66816, 66864), - "Caucasian Albanian": range(66864, 66928), - "Vithkuqi": range(66928, 67008), - "Linear A": range(67072, 67456), - "Latin Extended-F": range(67456, 67520), - "Cypriot Syllabary": range(67584, 67648), - "Imperial Aramaic": range(67648, 67680), - "Palmyrene": range(67680, 67712), - "Nabataean": range(67712, 67760), - "Hatran": range(67808, 67840), - "Phoenician": range(67840, 67872), - "Lydian": range(67872, 67904), - "Meroitic Hieroglyphs": range(67968, 68000), - "Meroitic Cursive": range(68000, 68096), - "Kharoshthi": range(68096, 68192), - "Old South Arabian": range(68192, 68224), - "Old North Arabian": range(68224, 68256), - "Manichaean": range(68288, 68352), - "Avestan": range(68352, 68416), - "Inscriptional Parthian": range(68416, 68448), - "Inscriptional Pahlavi": range(68448, 68480), - "Psalter Pahlavi": range(68480, 68528), - "Old Turkic": range(68608, 68688), - "Old Hungarian": range(68736, 68864), - "Hanifi Rohingya": range(68864, 68928), - "Rumi Numeral Symbols": range(69216, 69248), - "Yezidi": range(69248, 69312), - "Arabic Extended-C": range(69312, 69376), - "Old Sogdian": range(69376, 69424), - "Sogdian": range(69424, 69488), - "Old Uyghur": range(69488, 69552), - "Chorasmian": range(69552, 69600), - "Elymaic": range(69600, 69632), - "Brahmi": range(69632, 69760), - "Kaithi": range(69760, 69840), - "Sora Sompeng": range(69840, 69888), - "Chakma": range(69888, 69968), - "Mahajani": range(69968, 70016), - "Sharada": range(70016, 70112), - "Sinhala Archaic Numbers": range(70112, 70144), - "Khojki": range(70144, 70224), - "Multani": range(70272, 70320), - "Khudawadi": range(70320, 70400), - "Grantha": range(70400, 70528), - "Newa": range(70656, 70784), - "Tirhuta": range(70784, 70880), - "Siddham": range(71040, 71168), - "Modi": range(71168, 71264), - "Mongolian Supplement": range(71264, 71296), - "Takri": range(71296, 71376), - "Ahom": range(71424, 71504), - "Dogra": range(71680, 71760), - "Warang Citi": range(71840, 71936), - "Dives Akuru": range(71936, 72032), - "Nandinagari": range(72096, 72192), - "Zanabazar Square": range(72192, 72272), - "Soyombo": range(72272, 72368), - "Unified Canadian Aboriginal Syllabics Extended-A": range(72368, 72384), - "Pau Cin Hau": range(72384, 72448), - "Devanagari Extended-A": range(72448, 72544), - "Bhaiksuki": range(72704, 72816), - "Marchen": range(72816, 72896), - "Masaram Gondi": range(72960, 73056), - "Gunjala Gondi": range(73056, 73136), - "Makasar": range(73440, 73472), - "Kawi": range(73472, 73568), - "Lisu Supplement": range(73648, 73664), - "Tamil Supplement": range(73664, 73728), - "Cuneiform": range(73728, 74752), - "Cuneiform Numbers and Punctuation": range(74752, 74880), - "Early Dynastic Cuneiform": range(74880, 75088), - "Cypro-Minoan": range(77712, 77824), - "Egyptian Hieroglyphs": range(77824, 78896), - "Egyptian Hieroglyph Format Controls": range(78896, 78944), - "Anatolian Hieroglyphs": range(82944, 83584), - "Bamum Supplement": range(92160, 92736), - "Mro": range(92736, 92784), - "Tangsa": range(92784, 92880), - "Bassa Vah": range(92880, 92928), - "Pahawh Hmong": range(92928, 93072), - "Medefaidrin": range(93760, 93856), - "Miao": range(93952, 94112), - "Ideographic Symbols and Punctuation": range(94176, 94208), - "Tangut": range(94208, 100352), - "Tangut Components": range(100352, 101120), - "Khitan Small Script": range(101120, 101632), - "Tangut Supplement": range(101632, 101760), - "Kana Extended-B": range(110576, 110592), - "Kana Supplement": range(110592, 110848), - "Kana Extended-A": range(110848, 110896), - "Small Kana Extension": range(110896, 110960), - "Nushu": range(110960, 111360), - "Duployan": range(113664, 113824), - "Shorthand Format Controls": range(113824, 113840), - "Znamenny Musical Notation": range(118528, 118736), - "Byzantine Musical Symbols": range(118784, 119040), - "Musical Symbols": range(119040, 119296), - "Ancient Greek Musical Notation": range(119296, 119376), - "Kaktovik Numerals": range(119488, 119520), - "Mayan Numerals": range(119520, 119552), - "Tai Xuan Jing Symbols": range(119552, 119648), - "Counting Rod Numerals": range(119648, 119680), - "Mathematical Alphanumeric Symbols": range(119808, 120832), - "Sutton SignWriting": range(120832, 121520), - "Latin Extended-G": range(122624, 122880), - "Glagolitic Supplement": range(122880, 122928), - "Cyrillic Extended-D": range(122928, 123024), - "Nyiakeng Puachue Hmong": range(123136, 123216), - "Toto": range(123536, 123584), - "Wancho": range(123584, 123648), - "Nag Mundari": range(124112, 124160), - "Ethiopic Extended-B": range(124896, 124928), - "Mende Kikakui": range(124928, 125152), - "Adlam": range(125184, 125280), - "Indic Siyaq Numbers": range(126064, 126144), - "Ottoman Siyaq Numbers": range(126208, 126288), - "Arabic Mathematical Alphabetic Symbols": range(126464, 126720), - "Mahjong Tiles": range(126976, 127024), - "Domino Tiles": range(127024, 127136), - "Playing Cards": range(127136, 127232), - "Enclosed Alphanumeric Supplement": range(127232, 127488), - "Enclosed Ideographic Supplement": range(127488, 127744), - "Miscellaneous Symbols and Pictographs": range(127744, 128512), - "Emoticons range(Emoji)": range(128512, 128592), - "Ornamental Dingbats": range(128592, 128640), - "Transport and Map Symbols": range(128640, 128768), - "Alchemical Symbols": range(128768, 128896), - "Geometric Shapes Extended": range(128896, 129024), - "Supplemental Arrows-C": range(129024, 129280), - "Supplemental Symbols and Pictographs": range(129280, 129536), - "Chess Symbols": range(129536, 129648), - "Symbols and Pictographs Extended-A": range(129648, 129792), - "Symbols for Legacy Computing": range(129792, 130048), - "CJK Unified Ideographs Extension B": range(131072, 173792), - "CJK Unified Ideographs Extension C": range(173824, 177984), - "CJK Unified Ideographs Extension D": range(177984, 178208), - "CJK Unified Ideographs Extension E": range(178208, 183984), - "CJK Unified Ideographs Extension F": range(183984, 191472), - "CJK Compatibility Ideographs Supplement": range(194560, 195104), - "CJK Unified Ideographs Extension G": range(196608, 201552), - "CJK Unified Ideographs Extension H": range(201552, 205744), - "Tags": range(917504, 917632), - "Variation Selectors Supplement": range(917760, 918000), - "Supplementary Private Use Area-A": range(983040, 1048576), - "Supplementary Private Use Area-B": range(1048576, 1114112), -} - - -UNICODE_SECONDARY_RANGE_KEYWORD: list[str] = [ - "Supplement", - "Extended", - "Extensions", - "Modifier", - "Marks", - "Punctuation", - "Symbols", - "Forms", - "Operators", - "Miscellaneous", - "Drawing", - "Block", - "Shapes", - "Supplemental", - "Tags", -] - -RE_POSSIBLE_ENCODING_INDICATION = re_compile( - r"(?:(?:encoding)|(?:charset)|(?:coding))(?:[\:= ]{1,10})(?:[\"\']?)([a-zA-Z0-9\-_]+)(?:[\"\']?)", - IGNORECASE, -) - -IANA_NO_ALIASES = [ - "cp720", - "cp737", - "cp856", - "cp874", - "cp875", - "cp1006", - "koi8_r", - "koi8_t", - "koi8_u", -] - -IANA_SUPPORTED: list[str] = sorted( - filter( - lambda x: x.endswith("_codec") is False - and x not in {"rot_13", "tactis", "mbcs"}, - list(set(aliases.values())) + IANA_NO_ALIASES, - ) -) - -IANA_SUPPORTED_COUNT: int = len(IANA_SUPPORTED) - -# pre-computed code page that are similar using the function cp_similarity. -IANA_SUPPORTED_SIMILAR: dict[str, list[str]] = { - "cp037": ["cp1026", "cp1140", "cp273", "cp500"], - "cp1026": ["cp037", "cp1140", "cp273", "cp500"], - "cp1125": ["cp866"], - "cp1140": ["cp037", "cp1026", "cp273", "cp500"], - "cp1250": ["iso8859_2"], - "cp1251": ["kz1048", "ptcp154"], - "cp1252": ["iso8859_15", "iso8859_9", "latin_1"], - "cp1253": ["iso8859_7"], - "cp1254": ["iso8859_15", "iso8859_9", "latin_1"], - "cp1257": ["iso8859_13"], - "cp273": ["cp037", "cp1026", "cp1140", "cp500"], - "cp437": ["cp850", "cp858", "cp860", "cp861", "cp862", "cp863", "cp865"], - "cp500": ["cp037", "cp1026", "cp1140", "cp273"], - "cp850": ["cp437", "cp857", "cp858", "cp865"], - "cp857": ["cp850", "cp858", "cp865"], - "cp858": ["cp437", "cp850", "cp857", "cp865"], - "cp860": ["cp437", "cp861", "cp862", "cp863", "cp865"], - "cp861": ["cp437", "cp860", "cp862", "cp863", "cp865"], - "cp862": ["cp437", "cp860", "cp861", "cp863", "cp865"], - "cp863": ["cp437", "cp860", "cp861", "cp862", "cp865"], - "cp865": ["cp437", "cp850", "cp857", "cp858", "cp860", "cp861", "cp862", "cp863"], - "cp866": ["cp1125"], - "iso8859_10": ["iso8859_14", "iso8859_15", "iso8859_4", "iso8859_9", "latin_1"], - "iso8859_11": ["tis_620"], - "iso8859_13": ["cp1257"], - "iso8859_14": [ - "iso8859_10", - "iso8859_15", - "iso8859_16", - "iso8859_3", - "iso8859_9", - "latin_1", - ], - "iso8859_15": [ - "cp1252", - "cp1254", - "iso8859_10", - "iso8859_14", - "iso8859_16", - "iso8859_3", - "iso8859_9", - "latin_1", - ], - "iso8859_16": [ - "iso8859_14", - "iso8859_15", - "iso8859_2", - "iso8859_3", - "iso8859_9", - "latin_1", - ], - "iso8859_2": ["cp1250", "iso8859_16", "iso8859_4"], - "iso8859_3": ["iso8859_14", "iso8859_15", "iso8859_16", "iso8859_9", "latin_1"], - "iso8859_4": ["iso8859_10", "iso8859_2", "iso8859_9", "latin_1"], - "iso8859_7": ["cp1253"], - "iso8859_9": [ - "cp1252", - "cp1254", - "cp1258", - "iso8859_10", - "iso8859_14", - "iso8859_15", - "iso8859_16", - "iso8859_3", - "iso8859_4", - "latin_1", - ], - "kz1048": ["cp1251", "ptcp154"], - "latin_1": [ - "cp1252", - "cp1254", - "cp1258", - "iso8859_10", - "iso8859_14", - "iso8859_15", - "iso8859_16", - "iso8859_3", - "iso8859_4", - "iso8859_9", - ], - "mac_iceland": ["mac_roman", "mac_turkish"], - "mac_roman": ["mac_iceland", "mac_turkish"], - "mac_turkish": ["mac_iceland", "mac_roman"], - "ptcp154": ["cp1251", "kz1048"], - "tis_620": ["iso8859_11"], -} - - -CHARDET_CORRESPONDENCE: dict[str, str] = { - "iso2022_kr": "ISO-2022-KR", - "iso2022_jp": "ISO-2022-JP", - "euc_kr": "EUC-KR", - "tis_620": "TIS-620", - "utf_32": "UTF-32", - "euc_jp": "EUC-JP", - "koi8_r": "KOI8-R", - "iso8859_1": "ISO-8859-1", - "iso8859_2": "ISO-8859-2", - "iso8859_5": "ISO-8859-5", - "iso8859_6": "ISO-8859-6", - "iso8859_7": "ISO-8859-7", - "iso8859_8": "ISO-8859-8", - "utf_16": "UTF-16", - "cp855": "IBM855", - "mac_cyrillic": "MacCyrillic", - "gb2312": "GB2312", - "gb18030": "GB18030", - "cp932": "CP932", - "cp866": "IBM866", - "utf_8": "utf-8", - "utf_8_sig": "UTF-8-SIG", - "shift_jis": "SHIFT_JIS", - "big5": "Big5", - "cp1250": "windows-1250", - "cp1251": "windows-1251", - "cp1252": "Windows-1252", - "cp1253": "windows-1253", - "cp1255": "windows-1255", - "cp1256": "windows-1256", - "cp1254": "Windows-1254", - "cp949": "CP949", -} - - -COMMON_SAFE_ASCII_CHARACTERS: set[str] = { - "<", - ">", - "=", - ":", - "/", - "&", - ";", - "{", - "}", - "[", - "]", - ",", - "|", - '"', - "-", - "(", - ")", -} - -# Sample character sets — replace with full lists if needed -COMMON_CHINESE_CHARACTERS = "的一是在不了有和人这中大为上个国我以要他时来用们生到作地于出就分对成会可主发年动同工也能下过子说产种面而方后多定行学法所民得经十三之进着等部度家电力里如水化高自二理起小物现实加量都两体制机当使点从业本去把性好应开它合还因由其些然前外天政四日那社义事平形相全表间样与关各重新线内数正心反你明看原又么利比或但质气第向道命此变条只没结解问意建月公无系军很情者最立代想已通并提直题党程展五果料象员革位入常文总次品式活设及管特件长求老头基资边流路级少图山统接知较将组见计别她手角期根论运农指几九区强放决西被干做必战先回则任取据处队南给色光门即保治北造百规热领七海口东导器压志世金增争济阶油思术极交受联什认六共权收证改清己美再采转更单风切打白教速花带安场身车例真务具万每目至达走积示议声报斗完类八离华名确才科张信马节话米整空元况今集温传土许步群广石记需段研界拉林律叫且究观越织装影算低持音众书布复容儿须际商非验连断深难近矿千周委素技备半办青省列习响约支般史感劳便团往酸历市克何除消构府太准精值号率族维划选标写存候毛亲快效斯院查江型眼王按格养易置派层片始却专状育厂京识适属圆包火住调满县局照参红细引听该铁价严龙飞" - -COMMON_JAPANESE_CHARACTERS = "日一国年大十二本中長出三時行見月分後前生五間上東四今金九入学高円子外八六下来気小七山話女北午百書先名川千水半男西電校語土木聞食車何南万毎白天母火右読友左休父雨" - -COMMON_KOREAN_CHARACTERS = "一二三四五六七八九十百千萬上下左右中人女子大小山川日月火水木金土父母天地國名年時文校學生" - -# Combine all into a set -COMMON_CJK_CHARACTERS = set( - "".join( - [ - COMMON_CHINESE_CHARACTERS, - COMMON_JAPANESE_CHARACTERS, - COMMON_KOREAN_CHARACTERS, - ] - ) -) - -KO_NAMES: set[str] = {"johab", "cp949", "euc_kr"} -ZH_NAMES: set[str] = {"big5", "cp950", "big5hkscs", "hz"} - -# Logging LEVEL below DEBUG -TRACE: int = 5 - - -# Language label that contain the em dash "—" -# character are to be considered alternative seq to origin -FREQUENCIES: dict[str, list[str]] = { - "English": [ - "e", - "a", - "t", - "i", - "o", - "n", - "s", - "r", - "h", - "l", - "d", - "c", - "u", - "m", - "f", - "p", - "g", - "w", - "y", - "b", - "v", - "k", - "x", - "j", - "z", - "q", - ], - "English—": [ - "e", - "a", - "t", - "i", - "o", - "n", - "s", - "r", - "h", - "l", - "d", - "c", - "m", - "u", - "f", - "p", - "g", - "w", - "b", - "y", - "v", - "k", - "j", - "x", - "z", - "q", - ], - "German": [ - "e", - "n", - "i", - "r", - "s", - "t", - "a", - "d", - "h", - "u", - "l", - "g", - "o", - "c", - "m", - "b", - "f", - "k", - "w", - "z", - "p", - "v", - "ü", - "ä", - "ö", - "j", - ], - "French": [ - "e", - "a", - "s", - "n", - "i", - "t", - "r", - "l", - "u", - "o", - "d", - "c", - "p", - "m", - "é", - "v", - "g", - "f", - "b", - "h", - "q", - "à", - "x", - "è", - "y", - "j", - ], - "Dutch": [ - "e", - "n", - "a", - "i", - "r", - "t", - "o", - "d", - "s", - "l", - "g", - "h", - "v", - "m", - "u", - "k", - "c", - "p", - "b", - "w", - "j", - "z", - "f", - "y", - "x", - "ë", - ], - "Italian": [ - "e", - "i", - "a", - "o", - "n", - "l", - "t", - "r", - "s", - "c", - "d", - "u", - "p", - "m", - "g", - "v", - "f", - "b", - "z", - "h", - "q", - "è", - "à", - "k", - "y", - "ò", - ], - "Polish": [ - "a", - "i", - "o", - "e", - "n", - "r", - "z", - "w", - "s", - "c", - "t", - "k", - "y", - "d", - "p", - "m", - "u", - "l", - "j", - "ł", - "g", - "b", - "h", - "ą", - "ę", - "ó", - ], - "Spanish": [ - "e", - "a", - "o", - "n", - "s", - "r", - "i", - "l", - "d", - "t", - "c", - "u", - "m", - "p", - "b", - "g", - "v", - "f", - "y", - "ó", - "h", - "q", - "í", - "j", - "z", - "á", - ], - "Russian": [ - "о", - "а", - "е", - "и", - "н", - "с", - "т", - "р", - "в", - "л", - "к", - "м", - "д", - "п", - "у", - "г", - "я", - "ы", - "з", - "б", - "й", - "ь", - "ч", - "х", - "ж", - "ц", - ], - # Jap-Kanji - "Japanese": [ - "人", - "一", - "大", - "亅", - "丁", - "丨", - "竹", - "笑", - "口", - "日", - "今", - "二", - "彳", - "行", - "十", - "土", - "丶", - "寸", - "寺", - "時", - "乙", - "丿", - "乂", - "气", - "気", - "冂", - "巾", - "亠", - "市", - "目", - "儿", - "見", - "八", - "小", - "凵", - "県", - "月", - "彐", - "門", - "間", - "木", - "東", - "山", - "出", - "本", - "中", - "刀", - "分", - "耳", - "又", - "取", - "最", - "言", - "田", - "心", - "思", - "刂", - "前", - "京", - "尹", - "事", - "生", - "厶", - "云", - "会", - "未", - "来", - "白", - "冫", - "楽", - "灬", - "馬", - "尸", - "尺", - "駅", - "明", - "耂", - "者", - "了", - "阝", - "都", - "高", - "卜", - "占", - "厂", - "广", - "店", - "子", - "申", - "奄", - "亻", - "俺", - "上", - "方", - "冖", - "学", - "衣", - "艮", - "食", - "自", - ], - # Jap-Katakana - "Japanese—": [ - "ー", - "ン", - "ス", - "・", - "ル", - "ト", - "リ", - "イ", - "ア", - "ラ", - "ッ", - "ク", - "ド", - "シ", - "レ", - "ジ", - "タ", - "フ", - "ロ", - "カ", - "テ", - "マ", - "ィ", - "グ", - "バ", - "ム", - "プ", - "オ", - "コ", - "デ", - "ニ", - "ウ", - "メ", - "サ", - "ビ", - "ナ", - "ブ", - "ャ", - "エ", - "ュ", - "チ", - "キ", - "ズ", - "ダ", - "パ", - "ミ", - "ェ", - "ョ", - "ハ", - "セ", - "ベ", - "ガ", - "モ", - "ツ", - "ネ", - "ボ", - "ソ", - "ノ", - "ァ", - "ヴ", - "ワ", - "ポ", - "ペ", - "ピ", - "ケ", - "ゴ", - "ギ", - "ザ", - "ホ", - "ゲ", - "ォ", - "ヤ", - "ヒ", - "ユ", - "ヨ", - "ヘ", - "ゼ", - "ヌ", - "ゥ", - "ゾ", - "ヶ", - "ヂ", - "ヲ", - "ヅ", - "ヵ", - "ヱ", - "ヰ", - "ヮ", - "ヽ", - "゠", - "ヾ", - "ヷ", - "ヿ", - "ヸ", - "ヹ", - "ヺ", - ], - # Jap-Hiragana - "Japanese——": [ - "の", - "に", - "る", - "た", - "と", - "は", - "し", - "い", - "を", - "で", - "て", - "が", - "な", - "れ", - "か", - "ら", - "さ", - "っ", - "り", - "す", - "あ", - "も", - "こ", - "ま", - "う", - "く", - "よ", - "き", - "ん", - "め", - "お", - "け", - "そ", - "つ", - "だ", - "や", - "え", - "ど", - "わ", - "ち", - "み", - "せ", - "じ", - "ば", - "へ", - "び", - "ず", - "ろ", - "ほ", - "げ", - "む", - "べ", - "ひ", - "ょ", - "ゆ", - "ぶ", - "ご", - "ゃ", - "ね", - "ふ", - "ぐ", - "ぎ", - "ぼ", - "ゅ", - "づ", - "ざ", - "ぞ", - "ぬ", - "ぜ", - "ぱ", - "ぽ", - "ぷ", - "ぴ", - "ぃ", - "ぁ", - "ぇ", - "ぺ", - "ゞ", - "ぢ", - "ぉ", - "ぅ", - "ゐ", - "ゝ", - "ゑ", - "゛", - "゜", - "ゎ", - "ゔ", - "゚", - "ゟ", - "゙", - "ゕ", - "ゖ", - ], - "Portuguese": [ - "a", - "e", - "o", - "s", - "i", - "r", - "d", - "n", - "t", - "m", - "u", - "c", - "l", - "p", - "g", - "v", - "b", - "f", - "h", - "ã", - "q", - "é", - "ç", - "á", - "z", - "í", - ], - "Swedish": [ - "e", - "a", - "n", - "r", - "t", - "s", - "i", - "l", - "d", - "o", - "m", - "k", - "g", - "v", - "h", - "f", - "u", - "p", - "ä", - "c", - "b", - "ö", - "å", - "y", - "j", - "x", - ], - "Chinese": [ - "的", - "一", - "是", - "不", - "了", - "在", - "人", - "有", - "我", - "他", - "这", - "个", - "们", - "中", - "来", - "上", - "大", - "为", - "和", - "国", - "地", - "到", - "以", - "说", - "时", - "要", - "就", - "出", - "会", - "可", - "也", - "你", - "对", - "生", - "能", - "而", - "子", - "那", - "得", - "于", - "着", - "下", - "自", - "之", - "年", - "过", - "发", - "后", - "作", - "里", - "用", - "道", - "行", - "所", - "然", - "家", - "种", - "事", - "成", - "方", - "多", - "经", - "么", - "去", - "法", - "学", - "如", - "都", - "同", - "现", - "当", - "没", - "动", - "面", - "起", - "看", - "定", - "天", - "分", - "还", - "进", - "好", - "小", - "部", - "其", - "些", - "主", - "样", - "理", - "心", - "她", - "本", - "前", - "开", - "但", - "因", - "只", - "从", - "想", - "实", - ], - "Ukrainian": [ - "о", - "а", - "н", - "і", - "и", - "р", - "в", - "т", - "е", - "с", - "к", - "л", - "у", - "д", - "м", - "п", - "з", - "я", - "ь", - "б", - "г", - "й", - "ч", - "х", - "ц", - "ї", - ], - "Norwegian": [ - "e", - "r", - "n", - "t", - "a", - "s", - "i", - "o", - "l", - "d", - "g", - "k", - "m", - "v", - "f", - "p", - "u", - "b", - "h", - "å", - "y", - "j", - "ø", - "c", - "æ", - "w", - ], - "Finnish": [ - "a", - "i", - "n", - "t", - "e", - "s", - "l", - "o", - "u", - "k", - "ä", - "m", - "r", - "v", - "j", - "h", - "p", - "y", - "d", - "ö", - "g", - "c", - "b", - "f", - "w", - "z", - ], - "Vietnamese": [ - "n", - "h", - "t", - "i", - "c", - "g", - "a", - "o", - "u", - "m", - "l", - "r", - "à", - "đ", - "s", - "e", - "v", - "p", - "b", - "y", - "ư", - "d", - "á", - "k", - "ộ", - "ế", - ], - "Czech": [ - "o", - "e", - "a", - "n", - "t", - "s", - "i", - "l", - "v", - "r", - "k", - "d", - "u", - "m", - "p", - "í", - "c", - "h", - "z", - "á", - "y", - "j", - "b", - "ě", - "é", - "ř", - ], - "Hungarian": [ - "e", - "a", - "t", - "l", - "s", - "n", - "k", - "r", - "i", - "o", - "z", - "á", - "é", - "g", - "m", - "b", - "y", - "v", - "d", - "h", - "u", - "p", - "j", - "ö", - "f", - "c", - ], - "Korean": [ - "이", - "다", - "에", - "의", - "는", - "로", - "하", - "을", - "가", - "고", - "지", - "서", - "한", - "은", - "기", - "으", - "년", - "대", - "사", - "시", - "를", - "리", - "도", - "인", - "스", - "일", - ], - "Indonesian": [ - "a", - "n", - "e", - "i", - "r", - "t", - "u", - "s", - "d", - "k", - "m", - "l", - "g", - "p", - "b", - "o", - "h", - "y", - "j", - "c", - "w", - "f", - "v", - "z", - "x", - "q", - ], - "Turkish": [ - "a", - "e", - "i", - "n", - "r", - "l", - "ı", - "k", - "d", - "t", - "s", - "m", - "y", - "u", - "o", - "b", - "ü", - "ş", - "v", - "g", - "z", - "h", - "c", - "p", - "ç", - "ğ", - ], - "Romanian": [ - "e", - "i", - "a", - "r", - "n", - "t", - "u", - "l", - "o", - "c", - "s", - "d", - "p", - "m", - "ă", - "f", - "v", - "î", - "g", - "b", - "ș", - "ț", - "z", - "h", - "â", - "j", - ], - "Farsi": [ - "ا", - "ی", - "ر", - "د", - "ن", - "ه", - "و", - "م", - "ت", - "ب", - "س", - "ل", - "ک", - "ش", - "ز", - "ف", - "گ", - "ع", - "خ", - "ق", - "ج", - "آ", - "پ", - "ح", - "ط", - "ص", - ], - "Arabic": [ - "ا", - "ل", - "ي", - "م", - "و", - "ن", - "ر", - "ت", - "ب", - "ة", - "ع", - "د", - "س", - "ف", - "ه", - "ك", - "ق", - "أ", - "ح", - "ج", - "ش", - "ط", - "ص", - "ى", - "خ", - "إ", - ], - "Danish": [ - "e", - "r", - "n", - "t", - "a", - "i", - "s", - "d", - "l", - "o", - "g", - "m", - "k", - "f", - "v", - "u", - "b", - "h", - "p", - "å", - "y", - "ø", - "æ", - "c", - "j", - "w", - ], - "Serbian": [ - "а", - "и", - "о", - "е", - "н", - "р", - "с", - "у", - "т", - "к", - "ј", - "в", - "д", - "м", - "п", - "л", - "г", - "з", - "б", - "a", - "i", - "e", - "o", - "n", - "ц", - "ш", - ], - "Lithuanian": [ - "i", - "a", - "s", - "o", - "r", - "e", - "t", - "n", - "u", - "k", - "m", - "l", - "p", - "v", - "d", - "j", - "g", - "ė", - "b", - "y", - "ų", - "š", - "ž", - "c", - "ą", - "į", - ], - "Slovene": [ - "e", - "a", - "i", - "o", - "n", - "r", - "s", - "l", - "t", - "j", - "v", - "k", - "d", - "p", - "m", - "u", - "z", - "b", - "g", - "h", - "č", - "c", - "š", - "ž", - "f", - "y", - ], - "Slovak": [ - "o", - "a", - "e", - "n", - "i", - "r", - "v", - "t", - "s", - "l", - "k", - "d", - "m", - "p", - "u", - "c", - "h", - "j", - "b", - "z", - "á", - "y", - "ý", - "í", - "č", - "é", - ], - "Hebrew": [ - "י", - "ו", - "ה", - "ל", - "ר", - "ב", - "ת", - "מ", - "א", - "ש", - "נ", - "ע", - "ם", - "ד", - "ק", - "ח", - "פ", - "ס", - "כ", - "ג", - "ט", - "צ", - "ן", - "ז", - "ך", - ], - "Bulgarian": [ - "а", - "и", - "о", - "е", - "н", - "т", - "р", - "с", - "в", - "л", - "к", - "д", - "п", - "м", - "з", - "г", - "я", - "ъ", - "у", - "б", - "ч", - "ц", - "й", - "ж", - "щ", - "х", - ], - "Croatian": [ - "a", - "i", - "o", - "e", - "n", - "r", - "j", - "s", - "t", - "u", - "k", - "l", - "v", - "d", - "m", - "p", - "g", - "z", - "b", - "c", - "č", - "h", - "š", - "ž", - "ć", - "f", - ], - "Hindi": [ - "क", - "र", - "स", - "न", - "त", - "म", - "ह", - "प", - "य", - "ल", - "व", - "ज", - "द", - "ग", - "ब", - "श", - "ट", - "अ", - "ए", - "थ", - "भ", - "ड", - "च", - "ध", - "ष", - "इ", - ], - "Estonian": [ - "a", - "i", - "e", - "s", - "t", - "l", - "u", - "n", - "o", - "k", - "r", - "d", - "m", - "v", - "g", - "p", - "j", - "h", - "ä", - "b", - "õ", - "ü", - "f", - "c", - "ö", - "y", - ], - "Thai": [ - "า", - "น", - "ร", - "อ", - "ก", - "เ", - "ง", - "ม", - "ย", - "ล", - "ว", - "ด", - "ท", - "ส", - "ต", - "ะ", - "ป", - "บ", - "ค", - "ห", - "แ", - "จ", - "พ", - "ช", - "ข", - "ใ", - ], - "Greek": [ - "α", - "τ", - "ο", - "ι", - "ε", - "ν", - "ρ", - "σ", - "κ", - "η", - "π", - "ς", - "υ", - "μ", - "λ", - "ί", - "ό", - "ά", - "γ", - "έ", - "δ", - "ή", - "ω", - "χ", - "θ", - "ύ", - ], - "Tamil": [ - "க", - "த", - "ப", - "ட", - "ர", - "ம", - "ல", - "ன", - "வ", - "ற", - "ய", - "ள", - "ச", - "ந", - "இ", - "ண", - "அ", - "ஆ", - "ழ", - "ங", - "எ", - "உ", - "ஒ", - "ஸ", - ], - "Kazakh": [ - "а", - "ы", - "е", - "н", - "т", - "р", - "л", - "і", - "д", - "с", - "м", - "қ", - "к", - "о", - "б", - "и", - "у", - "ғ", - "ж", - "ң", - "з", - "ш", - "й", - "п", - "г", - "ө", - ], -} - -LANGUAGE_SUPPORTED_COUNT: int = len(FREQUENCIES) diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/legacy.py b/apps/bitwarden_event_logs/lib/charset_normalizer/legacy.py deleted file mode 100755 index 360a3107..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer/legacy.py +++ /dev/null @@ -1,80 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING, Any -from warnings import warn - -from .api import from_bytes -from .constant import CHARDET_CORRESPONDENCE, TOO_SMALL_SEQUENCE - -# TODO: remove this check when dropping Python 3.7 support -if TYPE_CHECKING: - from typing_extensions import TypedDict - - class ResultDict(TypedDict): - encoding: str | None - language: str - confidence: float | None - - -def detect( - byte_str: bytes, should_rename_legacy: bool = False, **kwargs: Any -) -> ResultDict: - """ - chardet legacy method - Detect the encoding of the given byte string. It should be mostly backward-compatible. - Encoding name will match Chardet own writing whenever possible. (Not on encoding name unsupported by it) - This function is deprecated and should be used to migrate your project easily, consult the documentation for - further information. Not planned for removal. - - :param byte_str: The byte sequence to examine. - :param should_rename_legacy: Should we rename legacy encodings - to their more modern equivalents? - """ - if len(kwargs): - warn( - f"charset-normalizer disregard arguments '{','.join(list(kwargs.keys()))}' in legacy function detect()" - ) - - if not isinstance(byte_str, (bytearray, bytes)): - raise TypeError( # pragma: nocover - f"Expected object of type bytes or bytearray, got: {type(byte_str)}" - ) - - if isinstance(byte_str, bytearray): - byte_str = bytes(byte_str) - - r = from_bytes(byte_str).best() - - encoding = r.encoding if r is not None else None - language = r.language if r is not None and r.language != "Unknown" else "" - confidence = 1.0 - r.chaos if r is not None else None - - # automatically lower confidence - # on small bytes samples. - # https://github.com/jawah/charset_normalizer/issues/391 - if ( - confidence is not None - and confidence >= 0.9 - and encoding - not in { - "utf_8", - "ascii", - } - and r.bom is False # type: ignore[union-attr] - and len(byte_str) < TOO_SMALL_SEQUENCE - ): - confidence -= 0.2 - - # Note: CharsetNormalizer does not return 'UTF-8-SIG' as the sig get stripped in the detection/normalization process - # but chardet does return 'utf-8-sig' and it is a valid codec name. - if r is not None and encoding == "utf_8" and r.bom: - encoding += "_sig" - - if should_rename_legacy is False and encoding in CHARDET_CORRESPONDENCE: - encoding = CHARDET_CORRESPONDENCE[encoding] - - return { - "encoding": encoding, - "language": language, - "confidence": confidence, - } diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/md.cpython-39-aarch64-linux-gnu.so b/apps/bitwarden_event_logs/lib/charset_normalizer/md.cpython-39-aarch64-linux-gnu.so deleted file mode 100755 index 821ffe28..00000000 Binary files a/apps/bitwarden_event_logs/lib/charset_normalizer/md.cpython-39-aarch64-linux-gnu.so and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/md.py b/apps/bitwarden_event_logs/lib/charset_normalizer/md.py deleted file mode 100755 index 12ce024b..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer/md.py +++ /dev/null @@ -1,635 +0,0 @@ -from __future__ import annotations - -from functools import lru_cache -from logging import getLogger - -from .constant import ( - COMMON_SAFE_ASCII_CHARACTERS, - TRACE, - UNICODE_SECONDARY_RANGE_KEYWORD, -) -from .utils import ( - is_accentuated, - is_arabic, - is_arabic_isolated_form, - is_case_variable, - is_cjk, - is_emoticon, - is_hangul, - is_hiragana, - is_katakana, - is_latin, - is_punctuation, - is_separator, - is_symbol, - is_thai, - is_unprintable, - remove_accent, - unicode_range, - is_cjk_uncommon, -) - - -class MessDetectorPlugin: - """ - Base abstract class used for mess detection plugins. - All detectors MUST extend and implement given methods. - """ - - def eligible(self, character: str) -> bool: - """ - Determine if given character should be fed in. - """ - raise NotImplementedError # pragma: nocover - - def feed(self, character: str) -> None: - """ - The main routine to be executed upon character. - Insert the logic in witch the text would be considered chaotic. - """ - raise NotImplementedError # pragma: nocover - - def reset(self) -> None: # pragma: no cover - """ - Permit to reset the plugin to the initial state. - """ - raise NotImplementedError - - @property - def ratio(self) -> float: - """ - Compute the chaos ratio based on what your feed() has seen. - Must NOT be lower than 0.; No restriction gt 0. - """ - raise NotImplementedError # pragma: nocover - - -class TooManySymbolOrPunctuationPlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._punctuation_count: int = 0 - self._symbol_count: int = 0 - self._character_count: int = 0 - - self._last_printable_char: str | None = None - self._frenzy_symbol_in_word: bool = False - - def eligible(self, character: str) -> bool: - return character.isprintable() - - def feed(self, character: str) -> None: - self._character_count += 1 - - if ( - character != self._last_printable_char - and character not in COMMON_SAFE_ASCII_CHARACTERS - ): - if is_punctuation(character): - self._punctuation_count += 1 - elif ( - character.isdigit() is False - and is_symbol(character) - and is_emoticon(character) is False - ): - self._symbol_count += 2 - - self._last_printable_char = character - - def reset(self) -> None: # Abstract - self._punctuation_count = 0 - self._character_count = 0 - self._symbol_count = 0 - - @property - def ratio(self) -> float: - if self._character_count == 0: - return 0.0 - - ratio_of_punctuation: float = ( - self._punctuation_count + self._symbol_count - ) / self._character_count - - return ratio_of_punctuation if ratio_of_punctuation >= 0.3 else 0.0 - - -class TooManyAccentuatedPlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._character_count: int = 0 - self._accentuated_count: int = 0 - - def eligible(self, character: str) -> bool: - return character.isalpha() - - def feed(self, character: str) -> None: - self._character_count += 1 - - if is_accentuated(character): - self._accentuated_count += 1 - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._accentuated_count = 0 - - @property - def ratio(self) -> float: - if self._character_count < 8: - return 0.0 - - ratio_of_accentuation: float = self._accentuated_count / self._character_count - return ratio_of_accentuation if ratio_of_accentuation >= 0.35 else 0.0 - - -class UnprintablePlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._unprintable_count: int = 0 - self._character_count: int = 0 - - def eligible(self, character: str) -> bool: - return True - - def feed(self, character: str) -> None: - if is_unprintable(character): - self._unprintable_count += 1 - self._character_count += 1 - - def reset(self) -> None: # Abstract - self._unprintable_count = 0 - - @property - def ratio(self) -> float: - if self._character_count == 0: - return 0.0 - - return (self._unprintable_count * 8) / self._character_count - - -class SuspiciousDuplicateAccentPlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._successive_count: int = 0 - self._character_count: int = 0 - - self._last_latin_character: str | None = None - - def eligible(self, character: str) -> bool: - return character.isalpha() and is_latin(character) - - def feed(self, character: str) -> None: - self._character_count += 1 - if ( - self._last_latin_character is not None - and is_accentuated(character) - and is_accentuated(self._last_latin_character) - ): - if character.isupper() and self._last_latin_character.isupper(): - self._successive_count += 1 - # Worse if its the same char duplicated with different accent. - if remove_accent(character) == remove_accent(self._last_latin_character): - self._successive_count += 1 - self._last_latin_character = character - - def reset(self) -> None: # Abstract - self._successive_count = 0 - self._character_count = 0 - self._last_latin_character = None - - @property - def ratio(self) -> float: - if self._character_count == 0: - return 0.0 - - return (self._successive_count * 2) / self._character_count - - -class SuspiciousRange(MessDetectorPlugin): - def __init__(self) -> None: - self._suspicious_successive_range_count: int = 0 - self._character_count: int = 0 - self._last_printable_seen: str | None = None - - def eligible(self, character: str) -> bool: - return character.isprintable() - - def feed(self, character: str) -> None: - self._character_count += 1 - - if ( - character.isspace() - or is_punctuation(character) - or character in COMMON_SAFE_ASCII_CHARACTERS - ): - self._last_printable_seen = None - return - - if self._last_printable_seen is None: - self._last_printable_seen = character - return - - unicode_range_a: str | None = unicode_range(self._last_printable_seen) - unicode_range_b: str | None = unicode_range(character) - - if is_suspiciously_successive_range(unicode_range_a, unicode_range_b): - self._suspicious_successive_range_count += 1 - - self._last_printable_seen = character - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._suspicious_successive_range_count = 0 - self._last_printable_seen = None - - @property - def ratio(self) -> float: - if self._character_count <= 13: - return 0.0 - - ratio_of_suspicious_range_usage: float = ( - self._suspicious_successive_range_count * 2 - ) / self._character_count - - return ratio_of_suspicious_range_usage - - -class SuperWeirdWordPlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._word_count: int = 0 - self._bad_word_count: int = 0 - self._foreign_long_count: int = 0 - - self._is_current_word_bad: bool = False - self._foreign_long_watch: bool = False - - self._character_count: int = 0 - self._bad_character_count: int = 0 - - self._buffer: str = "" - self._buffer_accent_count: int = 0 - self._buffer_glyph_count: int = 0 - - def eligible(self, character: str) -> bool: - return True - - def feed(self, character: str) -> None: - if character.isalpha(): - self._buffer += character - if is_accentuated(character): - self._buffer_accent_count += 1 - if ( - self._foreign_long_watch is False - and (is_latin(character) is False or is_accentuated(character)) - and is_cjk(character) is False - and is_hangul(character) is False - and is_katakana(character) is False - and is_hiragana(character) is False - and is_thai(character) is False - ): - self._foreign_long_watch = True - if ( - is_cjk(character) - or is_hangul(character) - or is_katakana(character) - or is_hiragana(character) - or is_thai(character) - ): - self._buffer_glyph_count += 1 - return - if not self._buffer: - return - if ( - character.isspace() or is_punctuation(character) or is_separator(character) - ) and self._buffer: - self._word_count += 1 - buffer_length: int = len(self._buffer) - - self._character_count += buffer_length - - if buffer_length >= 4: - if self._buffer_accent_count / buffer_length >= 0.5: - self._is_current_word_bad = True - # Word/Buffer ending with an upper case accentuated letter are so rare, - # that we will consider them all as suspicious. Same weight as foreign_long suspicious. - elif ( - is_accentuated(self._buffer[-1]) - and self._buffer[-1].isupper() - and all(_.isupper() for _ in self._buffer) is False - ): - self._foreign_long_count += 1 - self._is_current_word_bad = True - elif self._buffer_glyph_count == 1: - self._is_current_word_bad = True - self._foreign_long_count += 1 - if buffer_length >= 24 and self._foreign_long_watch: - camel_case_dst = [ - i - for c, i in zip(self._buffer, range(0, buffer_length)) - if c.isupper() - ] - probable_camel_cased: bool = False - - if camel_case_dst and (len(camel_case_dst) / buffer_length <= 0.3): - probable_camel_cased = True - - if not probable_camel_cased: - self._foreign_long_count += 1 - self._is_current_word_bad = True - - if self._is_current_word_bad: - self._bad_word_count += 1 - self._bad_character_count += len(self._buffer) - self._is_current_word_bad = False - - self._foreign_long_watch = False - self._buffer = "" - self._buffer_accent_count = 0 - self._buffer_glyph_count = 0 - elif ( - character not in {"<", ">", "-", "=", "~", "|", "_"} - and character.isdigit() is False - and is_symbol(character) - ): - self._is_current_word_bad = True - self._buffer += character - - def reset(self) -> None: # Abstract - self._buffer = "" - self._is_current_word_bad = False - self._foreign_long_watch = False - self._bad_word_count = 0 - self._word_count = 0 - self._character_count = 0 - self._bad_character_count = 0 - self._foreign_long_count = 0 - - @property - def ratio(self) -> float: - if self._word_count <= 10 and self._foreign_long_count == 0: - return 0.0 - - return self._bad_character_count / self._character_count - - -class CjkUncommonPlugin(MessDetectorPlugin): - """ - Detect messy CJK text that probably means nothing. - """ - - def __init__(self) -> None: - self._character_count: int = 0 - self._uncommon_count: int = 0 - - def eligible(self, character: str) -> bool: - return is_cjk(character) - - def feed(self, character: str) -> None: - self._character_count += 1 - - if is_cjk_uncommon(character): - self._uncommon_count += 1 - return - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._uncommon_count = 0 - - @property - def ratio(self) -> float: - if self._character_count < 8: - return 0.0 - - uncommon_form_usage: float = self._uncommon_count / self._character_count - - # we can be pretty sure it's garbage when uncommon characters are widely - # used. otherwise it could just be traditional chinese for example. - return uncommon_form_usage / 10 if uncommon_form_usage > 0.5 else 0.0 - - -class ArchaicUpperLowerPlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._buf: bool = False - - self._character_count_since_last_sep: int = 0 - - self._successive_upper_lower_count: int = 0 - self._successive_upper_lower_count_final: int = 0 - - self._character_count: int = 0 - - self._last_alpha_seen: str | None = None - self._current_ascii_only: bool = True - - def eligible(self, character: str) -> bool: - return True - - def feed(self, character: str) -> None: - is_concerned = character.isalpha() and is_case_variable(character) - chunk_sep = is_concerned is False - - if chunk_sep and self._character_count_since_last_sep > 0: - if ( - self._character_count_since_last_sep <= 64 - and character.isdigit() is False - and self._current_ascii_only is False - ): - self._successive_upper_lower_count_final += ( - self._successive_upper_lower_count - ) - - self._successive_upper_lower_count = 0 - self._character_count_since_last_sep = 0 - self._last_alpha_seen = None - self._buf = False - self._character_count += 1 - self._current_ascii_only = True - - return - - if self._current_ascii_only is True and character.isascii() is False: - self._current_ascii_only = False - - if self._last_alpha_seen is not None: - if (character.isupper() and self._last_alpha_seen.islower()) or ( - character.islower() and self._last_alpha_seen.isupper() - ): - if self._buf is True: - self._successive_upper_lower_count += 2 - self._buf = False - else: - self._buf = True - else: - self._buf = False - - self._character_count += 1 - self._character_count_since_last_sep += 1 - self._last_alpha_seen = character - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._character_count_since_last_sep = 0 - self._successive_upper_lower_count = 0 - self._successive_upper_lower_count_final = 0 - self._last_alpha_seen = None - self._buf = False - self._current_ascii_only = True - - @property - def ratio(self) -> float: - if self._character_count == 0: - return 0.0 - - return self._successive_upper_lower_count_final / self._character_count - - -class ArabicIsolatedFormPlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._character_count: int = 0 - self._isolated_form_count: int = 0 - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._isolated_form_count = 0 - - def eligible(self, character: str) -> bool: - return is_arabic(character) - - def feed(self, character: str) -> None: - self._character_count += 1 - - if is_arabic_isolated_form(character): - self._isolated_form_count += 1 - - @property - def ratio(self) -> float: - if self._character_count < 8: - return 0.0 - - isolated_form_usage: float = self._isolated_form_count / self._character_count - - return isolated_form_usage - - -@lru_cache(maxsize=1024) -def is_suspiciously_successive_range( - unicode_range_a: str | None, unicode_range_b: str | None -) -> bool: - """ - Determine if two Unicode range seen next to each other can be considered as suspicious. - """ - if unicode_range_a is None or unicode_range_b is None: - return True - - if unicode_range_a == unicode_range_b: - return False - - if "Latin" in unicode_range_a and "Latin" in unicode_range_b: - return False - - if "Emoticons" in unicode_range_a or "Emoticons" in unicode_range_b: - return False - - # Latin characters can be accompanied with a combining diacritical mark - # eg. Vietnamese. - if ("Latin" in unicode_range_a or "Latin" in unicode_range_b) and ( - "Combining" in unicode_range_a or "Combining" in unicode_range_b - ): - return False - - keywords_range_a, keywords_range_b = ( - unicode_range_a.split(" "), - unicode_range_b.split(" "), - ) - - for el in keywords_range_a: - if el in UNICODE_SECONDARY_RANGE_KEYWORD: - continue - if el in keywords_range_b: - return False - - # Japanese Exception - range_a_jp_chars, range_b_jp_chars = ( - unicode_range_a - in ( - "Hiragana", - "Katakana", - ), - unicode_range_b in ("Hiragana", "Katakana"), - ) - if (range_a_jp_chars or range_b_jp_chars) and ( - "CJK" in unicode_range_a or "CJK" in unicode_range_b - ): - return False - if range_a_jp_chars and range_b_jp_chars: - return False - - if "Hangul" in unicode_range_a or "Hangul" in unicode_range_b: - if "CJK" in unicode_range_a or "CJK" in unicode_range_b: - return False - if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin": - return False - - # Chinese/Japanese use dedicated range for punctuation and/or separators. - if ("CJK" in unicode_range_a or "CJK" in unicode_range_b) or ( - unicode_range_a in ["Katakana", "Hiragana"] - and unicode_range_b in ["Katakana", "Hiragana"] - ): - if "Punctuation" in unicode_range_a or "Punctuation" in unicode_range_b: - return False - if "Forms" in unicode_range_a or "Forms" in unicode_range_b: - return False - if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin": - return False - - return True - - -@lru_cache(maxsize=2048) -def mess_ratio( - decoded_sequence: str, maximum_threshold: float = 0.2, debug: bool = False -) -> float: - """ - Compute a mess ratio given a decoded bytes sequence. The maximum threshold does stop the computation earlier. - """ - - detectors: list[MessDetectorPlugin] = [ - md_class() for md_class in MessDetectorPlugin.__subclasses__() - ] - - length: int = len(decoded_sequence) + 1 - - mean_mess_ratio: float = 0.0 - - if length < 512: - intermediary_mean_mess_ratio_calc: int = 32 - elif length <= 1024: - intermediary_mean_mess_ratio_calc = 64 - else: - intermediary_mean_mess_ratio_calc = 128 - - for character, index in zip(decoded_sequence + "\n", range(length)): - for detector in detectors: - if detector.eligible(character): - detector.feed(character) - - if ( - index > 0 and index % intermediary_mean_mess_ratio_calc == 0 - ) or index == length - 1: - mean_mess_ratio = sum(dt.ratio for dt in detectors) - - if mean_mess_ratio >= maximum_threshold: - break - - if debug: - logger = getLogger("charset_normalizer") - - logger.log( - TRACE, - "Mess-detector extended-analysis start. " - f"intermediary_mean_mess_ratio_calc={intermediary_mean_mess_ratio_calc} mean_mess_ratio={mean_mess_ratio} " - f"maximum_threshold={maximum_threshold}", - ) - - if len(decoded_sequence) > 16: - logger.log(TRACE, f"Starting with: {decoded_sequence[:16]}") - logger.log(TRACE, f"Ending with: {decoded_sequence[-16::]}") - - for dt in detectors: - logger.log(TRACE, f"{dt.__class__}: {dt.ratio}") - - return round(mean_mess_ratio, 3) diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/md__mypyc.cpython-39-aarch64-linux-gnu.so b/apps/bitwarden_event_logs/lib/charset_normalizer/md__mypyc.cpython-39-aarch64-linux-gnu.so deleted file mode 100755 index a9018a17..00000000 Binary files a/apps/bitwarden_event_logs/lib/charset_normalizer/md__mypyc.cpython-39-aarch64-linux-gnu.so and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/models.py b/apps/bitwarden_event_logs/lib/charset_normalizer/models.py deleted file mode 100755 index 1042758f..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer/models.py +++ /dev/null @@ -1,360 +0,0 @@ -from __future__ import annotations - -from encodings.aliases import aliases -from hashlib import sha256 -from json import dumps -from re import sub -from typing import Any, Iterator, List, Tuple - -from .constant import RE_POSSIBLE_ENCODING_INDICATION, TOO_BIG_SEQUENCE -from .utils import iana_name, is_multi_byte_encoding, unicode_range - - -class CharsetMatch: - def __init__( - self, - payload: bytes, - guessed_encoding: str, - mean_mess_ratio: float, - has_sig_or_bom: bool, - languages: CoherenceMatches, - decoded_payload: str | None = None, - preemptive_declaration: str | None = None, - ): - self._payload: bytes = payload - - self._encoding: str = guessed_encoding - self._mean_mess_ratio: float = mean_mess_ratio - self._languages: CoherenceMatches = languages - self._has_sig_or_bom: bool = has_sig_or_bom - self._unicode_ranges: list[str] | None = None - - self._leaves: list[CharsetMatch] = [] - self._mean_coherence_ratio: float = 0.0 - - self._output_payload: bytes | None = None - self._output_encoding: str | None = None - - self._string: str | None = decoded_payload - - self._preemptive_declaration: str | None = preemptive_declaration - - def __eq__(self, other: object) -> bool: - if not isinstance(other, CharsetMatch): - if isinstance(other, str): - return iana_name(other) == self.encoding - return False - return self.encoding == other.encoding and self.fingerprint == other.fingerprint - - def __lt__(self, other: object) -> bool: - """ - Implemented to make sorted available upon CharsetMatches items. - """ - if not isinstance(other, CharsetMatch): - raise ValueError - - chaos_difference: float = abs(self.chaos - other.chaos) - coherence_difference: float = abs(self.coherence - other.coherence) - - # Below 1% difference --> Use Coherence - if chaos_difference < 0.01 and coherence_difference > 0.02: - return self.coherence > other.coherence - elif chaos_difference < 0.01 and coherence_difference <= 0.02: - # When having a difficult decision, use the result that decoded as many multi-byte as possible. - # preserve RAM usage! - if len(self._payload) >= TOO_BIG_SEQUENCE: - return self.chaos < other.chaos - return self.multi_byte_usage > other.multi_byte_usage - - return self.chaos < other.chaos - - @property - def multi_byte_usage(self) -> float: - return 1.0 - (len(str(self)) / len(self.raw)) - - def __str__(self) -> str: - # Lazy Str Loading - if self._string is None: - self._string = str(self._payload, self._encoding, "strict") - return self._string - - def __repr__(self) -> str: - return f"" - - def add_submatch(self, other: CharsetMatch) -> None: - if not isinstance(other, CharsetMatch) or other == self: - raise ValueError( - "Unable to add instance <{}> as a submatch of a CharsetMatch".format( - other.__class__ - ) - ) - - other._string = None # Unload RAM usage; dirty trick. - self._leaves.append(other) - - @property - def encoding(self) -> str: - return self._encoding - - @property - def encoding_aliases(self) -> list[str]: - """ - Encoding name are known by many name, using this could help when searching for IBM855 when it's listed as CP855. - """ - also_known_as: list[str] = [] - for u, p in aliases.items(): - if self.encoding == u: - also_known_as.append(p) - elif self.encoding == p: - also_known_as.append(u) - return also_known_as - - @property - def bom(self) -> bool: - return self._has_sig_or_bom - - @property - def byte_order_mark(self) -> bool: - return self._has_sig_or_bom - - @property - def languages(self) -> list[str]: - """ - Return the complete list of possible languages found in decoded sequence. - Usually not really useful. Returned list may be empty even if 'language' property return something != 'Unknown'. - """ - return [e[0] for e in self._languages] - - @property - def language(self) -> str: - """ - Most probable language found in decoded sequence. If none were detected or inferred, the property will return - "Unknown". - """ - if not self._languages: - # Trying to infer the language based on the given encoding - # Its either English or we should not pronounce ourselves in certain cases. - if "ascii" in self.could_be_from_charset: - return "English" - - # doing it there to avoid circular import - from charset_normalizer.cd import encoding_languages, mb_encoding_languages - - languages = ( - mb_encoding_languages(self.encoding) - if is_multi_byte_encoding(self.encoding) - else encoding_languages(self.encoding) - ) - - if len(languages) == 0 or "Latin Based" in languages: - return "Unknown" - - return languages[0] - - return self._languages[0][0] - - @property - def chaos(self) -> float: - return self._mean_mess_ratio - - @property - def coherence(self) -> float: - if not self._languages: - return 0.0 - return self._languages[0][1] - - @property - def percent_chaos(self) -> float: - return round(self.chaos * 100, ndigits=3) - - @property - def percent_coherence(self) -> float: - return round(self.coherence * 100, ndigits=3) - - @property - def raw(self) -> bytes: - """ - Original untouched bytes. - """ - return self._payload - - @property - def submatch(self) -> list[CharsetMatch]: - return self._leaves - - @property - def has_submatch(self) -> bool: - return len(self._leaves) > 0 - - @property - def alphabets(self) -> list[str]: - if self._unicode_ranges is not None: - return self._unicode_ranges - # list detected ranges - detected_ranges: list[str | None] = [unicode_range(char) for char in str(self)] - # filter and sort - self._unicode_ranges = sorted(list({r for r in detected_ranges if r})) - return self._unicode_ranges - - @property - def could_be_from_charset(self) -> list[str]: - """ - The complete list of encoding that output the exact SAME str result and therefore could be the originating - encoding. - This list does include the encoding available in property 'encoding'. - """ - return [self._encoding] + [m.encoding for m in self._leaves] - - def output(self, encoding: str = "utf_8") -> bytes: - """ - Method to get re-encoded bytes payload using given target encoding. Default to UTF-8. - Any errors will be simply ignored by the encoder NOT replaced. - """ - if self._output_encoding is None or self._output_encoding != encoding: - self._output_encoding = encoding - decoded_string = str(self) - if ( - self._preemptive_declaration is not None - and self._preemptive_declaration.lower() - not in ["utf-8", "utf8", "utf_8"] - ): - patched_header = sub( - RE_POSSIBLE_ENCODING_INDICATION, - lambda m: m.string[m.span()[0] : m.span()[1]].replace( - m.groups()[0], - iana_name(self._output_encoding).replace("_", "-"), # type: ignore[arg-type] - ), - decoded_string[:8192], - count=1, - ) - - decoded_string = patched_header + decoded_string[8192:] - - self._output_payload = decoded_string.encode(encoding, "replace") - - return self._output_payload # type: ignore - - @property - def fingerprint(self) -> str: - """ - Retrieve the unique SHA256 computed using the transformed (re-encoded) payload. Not the original one. - """ - return sha256(self.output()).hexdigest() - - -class CharsetMatches: - """ - Container with every CharsetMatch items ordered by default from most probable to the less one. - Act like a list(iterable) but does not implements all related methods. - """ - - def __init__(self, results: list[CharsetMatch] | None = None): - self._results: list[CharsetMatch] = sorted(results) if results else [] - - def __iter__(self) -> Iterator[CharsetMatch]: - yield from self._results - - def __getitem__(self, item: int | str) -> CharsetMatch: - """ - Retrieve a single item either by its position or encoding name (alias may be used here). - Raise KeyError upon invalid index or encoding not present in results. - """ - if isinstance(item, int): - return self._results[item] - if isinstance(item, str): - item = iana_name(item, False) - for result in self._results: - if item in result.could_be_from_charset: - return result - raise KeyError - - def __len__(self) -> int: - return len(self._results) - - def __bool__(self) -> bool: - return len(self._results) > 0 - - def append(self, item: CharsetMatch) -> None: - """ - Insert a single match. Will be inserted accordingly to preserve sort. - Can be inserted as a submatch. - """ - if not isinstance(item, CharsetMatch): - raise ValueError( - "Cannot append instance '{}' to CharsetMatches".format( - str(item.__class__) - ) - ) - # We should disable the submatch factoring when the input file is too heavy (conserve RAM usage) - if len(item.raw) < TOO_BIG_SEQUENCE: - for match in self._results: - if match.fingerprint == item.fingerprint and match.chaos == item.chaos: - match.add_submatch(item) - return - self._results.append(item) - self._results = sorted(self._results) - - def best(self) -> CharsetMatch | None: - """ - Simply return the first match. Strict equivalent to matches[0]. - """ - if not self._results: - return None - return self._results[0] - - def first(self) -> CharsetMatch | None: - """ - Redundant method, call the method best(). Kept for BC reasons. - """ - return self.best() - - -CoherenceMatch = Tuple[str, float] -CoherenceMatches = List[CoherenceMatch] - - -class CliDetectionResult: - def __init__( - self, - path: str, - encoding: str | None, - encoding_aliases: list[str], - alternative_encodings: list[str], - language: str, - alphabets: list[str], - has_sig_or_bom: bool, - chaos: float, - coherence: float, - unicode_path: str | None, - is_preferred: bool, - ): - self.path: str = path - self.unicode_path: str | None = unicode_path - self.encoding: str | None = encoding - self.encoding_aliases: list[str] = encoding_aliases - self.alternative_encodings: list[str] = alternative_encodings - self.language: str = language - self.alphabets: list[str] = alphabets - self.has_sig_or_bom: bool = has_sig_or_bom - self.chaos: float = chaos - self.coherence: float = coherence - self.is_preferred: bool = is_preferred - - @property - def __dict__(self) -> dict[str, Any]: # type: ignore - return { - "path": self.path, - "encoding": self.encoding, - "encoding_aliases": self.encoding_aliases, - "alternative_encodings": self.alternative_encodings, - "language": self.language, - "alphabets": self.alphabets, - "has_sig_or_bom": self.has_sig_or_bom, - "chaos": self.chaos, - "coherence": self.coherence, - "unicode_path": self.unicode_path, - "is_preferred": self.is_preferred, - } - - def to_json(self) -> str: - return dumps(self.__dict__, ensure_ascii=True, indent=4) diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/py.typed b/apps/bitwarden_event_logs/lib/charset_normalizer/py.typed deleted file mode 100755 index e69de29b..00000000 diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/utils.py b/apps/bitwarden_event_logs/lib/charset_normalizer/utils.py deleted file mode 100755 index 6bf0384c..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer/utils.py +++ /dev/null @@ -1,414 +0,0 @@ -from __future__ import annotations - -import importlib -import logging -import unicodedata -from codecs import IncrementalDecoder -from encodings.aliases import aliases -from functools import lru_cache -from re import findall -from typing import Generator - -from _multibytecodec import ( # type: ignore[import-not-found,import] - MultibyteIncrementalDecoder, -) - -from .constant import ( - ENCODING_MARKS, - IANA_SUPPORTED_SIMILAR, - RE_POSSIBLE_ENCODING_INDICATION, - UNICODE_RANGES_COMBINED, - UNICODE_SECONDARY_RANGE_KEYWORD, - UTF8_MAXIMAL_ALLOCATION, - COMMON_CJK_CHARACTERS, -) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_accentuated(character: str) -> bool: - try: - description: str = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - return ( - "WITH GRAVE" in description - or "WITH ACUTE" in description - or "WITH CEDILLA" in description - or "WITH DIAERESIS" in description - or "WITH CIRCUMFLEX" in description - or "WITH TILDE" in description - or "WITH MACRON" in description - or "WITH RING ABOVE" in description - ) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def remove_accent(character: str) -> str: - decomposed: str = unicodedata.decomposition(character) - if not decomposed: - return character - - codes: list[str] = decomposed.split(" ") - - return chr(int(codes[0], 16)) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def unicode_range(character: str) -> str | None: - """ - Retrieve the Unicode range official name from a single character. - """ - character_ord: int = ord(character) - - for range_name, ord_range in UNICODE_RANGES_COMBINED.items(): - if character_ord in ord_range: - return range_name - - return None - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_latin(character: str) -> bool: - try: - description: str = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - return "LATIN" in description - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_punctuation(character: str) -> bool: - character_category: str = unicodedata.category(character) - - if "P" in character_category: - return True - - character_range: str | None = unicode_range(character) - - if character_range is None: - return False - - return "Punctuation" in character_range - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_symbol(character: str) -> bool: - character_category: str = unicodedata.category(character) - - if "S" in character_category or "N" in character_category: - return True - - character_range: str | None = unicode_range(character) - - if character_range is None: - return False - - return "Forms" in character_range and character_category != "Lo" - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_emoticon(character: str) -> bool: - character_range: str | None = unicode_range(character) - - if character_range is None: - return False - - return "Emoticons" in character_range or "Pictographs" in character_range - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_separator(character: str) -> bool: - if character.isspace() or character in {"|", "+", "<", ">"}: - return True - - character_category: str = unicodedata.category(character) - - return "Z" in character_category or character_category in {"Po", "Pd", "Pc"} - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_case_variable(character: str) -> bool: - return character.islower() != character.isupper() - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_cjk(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "CJK" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_hiragana(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "HIRAGANA" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_katakana(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "KATAKANA" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_hangul(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "HANGUL" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_thai(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "THAI" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_arabic(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "ARABIC" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_arabic_isolated_form(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "ARABIC" in character_name and "ISOLATED FORM" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_cjk_uncommon(character: str) -> bool: - return character not in COMMON_CJK_CHARACTERS - - -@lru_cache(maxsize=len(UNICODE_RANGES_COMBINED)) -def is_unicode_range_secondary(range_name: str) -> bool: - return any(keyword in range_name for keyword in UNICODE_SECONDARY_RANGE_KEYWORD) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_unprintable(character: str) -> bool: - return ( - character.isspace() is False # includes \n \t \r \v - and character.isprintable() is False - and character != "\x1a" # Why? Its the ASCII substitute character. - and character != "\ufeff" # bug discovered in Python, - # Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space. - ) - - -def any_specified_encoding(sequence: bytes, search_zone: int = 8192) -> str | None: - """ - Extract using ASCII-only decoder any specified encoding in the first n-bytes. - """ - if not isinstance(sequence, bytes): - raise TypeError - - seq_len: int = len(sequence) - - results: list[str] = findall( - RE_POSSIBLE_ENCODING_INDICATION, - sequence[: min(seq_len, search_zone)].decode("ascii", errors="ignore"), - ) - - if len(results) == 0: - return None - - for specified_encoding in results: - specified_encoding = specified_encoding.lower().replace("-", "_") - - encoding_alias: str - encoding_iana: str - - for encoding_alias, encoding_iana in aliases.items(): - if encoding_alias == specified_encoding: - return encoding_iana - if encoding_iana == specified_encoding: - return encoding_iana - - return None - - -@lru_cache(maxsize=128) -def is_multi_byte_encoding(name: str) -> bool: - """ - Verify is a specific encoding is a multi byte one based on it IANA name - """ - return name in { - "utf_8", - "utf_8_sig", - "utf_16", - "utf_16_be", - "utf_16_le", - "utf_32", - "utf_32_le", - "utf_32_be", - "utf_7", - } or issubclass( - importlib.import_module(f"encodings.{name}").IncrementalDecoder, - MultibyteIncrementalDecoder, - ) - - -def identify_sig_or_bom(sequence: bytes) -> tuple[str | None, bytes]: - """ - Identify and extract SIG/BOM in given sequence. - """ - - for iana_encoding in ENCODING_MARKS: - marks: bytes | list[bytes] = ENCODING_MARKS[iana_encoding] - - if isinstance(marks, bytes): - marks = [marks] - - for mark in marks: - if sequence.startswith(mark): - return iana_encoding, mark - - return None, b"" - - -def should_strip_sig_or_bom(iana_encoding: str) -> bool: - return iana_encoding not in {"utf_16", "utf_32"} - - -def iana_name(cp_name: str, strict: bool = True) -> str: - """Returns the Python normalized encoding name (Not the IANA official name).""" - cp_name = cp_name.lower().replace("-", "_") - - encoding_alias: str - encoding_iana: str - - for encoding_alias, encoding_iana in aliases.items(): - if cp_name in [encoding_alias, encoding_iana]: - return encoding_iana - - if strict: - raise ValueError(f"Unable to retrieve IANA for '{cp_name}'") - - return cp_name - - -def cp_similarity(iana_name_a: str, iana_name_b: str) -> float: - if is_multi_byte_encoding(iana_name_a) or is_multi_byte_encoding(iana_name_b): - return 0.0 - - decoder_a = importlib.import_module(f"encodings.{iana_name_a}").IncrementalDecoder - decoder_b = importlib.import_module(f"encodings.{iana_name_b}").IncrementalDecoder - - id_a: IncrementalDecoder = decoder_a(errors="ignore") - id_b: IncrementalDecoder = decoder_b(errors="ignore") - - character_match_count: int = 0 - - for i in range(255): - to_be_decoded: bytes = bytes([i]) - if id_a.decode(to_be_decoded) == id_b.decode(to_be_decoded): - character_match_count += 1 - - return character_match_count / 254 - - -def is_cp_similar(iana_name_a: str, iana_name_b: str) -> bool: - """ - Determine if two code page are at least 80% similar. IANA_SUPPORTED_SIMILAR dict was generated using - the function cp_similarity. - """ - return ( - iana_name_a in IANA_SUPPORTED_SIMILAR - and iana_name_b in IANA_SUPPORTED_SIMILAR[iana_name_a] - ) - - -def set_logging_handler( - name: str = "charset_normalizer", - level: int = logging.INFO, - format_string: str = "%(asctime)s | %(levelname)s | %(message)s", -) -> None: - logger = logging.getLogger(name) - logger.setLevel(level) - - handler = logging.StreamHandler() - handler.setFormatter(logging.Formatter(format_string)) - logger.addHandler(handler) - - -def cut_sequence_chunks( - sequences: bytes, - encoding_iana: str, - offsets: range, - chunk_size: int, - bom_or_sig_available: bool, - strip_sig_or_bom: bool, - sig_payload: bytes, - is_multi_byte_decoder: bool, - decoded_payload: str | None = None, -) -> Generator[str, None, None]: - if decoded_payload and is_multi_byte_decoder is False: - for i in offsets: - chunk = decoded_payload[i : i + chunk_size] - if not chunk: - break - yield chunk - else: - for i in offsets: - chunk_end = i + chunk_size - if chunk_end > len(sequences) + 8: - continue - - cut_sequence = sequences[i : i + chunk_size] - - if bom_or_sig_available and strip_sig_or_bom is False: - cut_sequence = sig_payload + cut_sequence - - chunk = cut_sequence.decode( - encoding_iana, - errors="ignore" if is_multi_byte_decoder else "strict", - ) - - # multi-byte bad cutting detector and adjustment - # not the cleanest way to perform that fix but clever enough for now. - if is_multi_byte_decoder and i > 0: - chunk_partial_size_chk: int = min(chunk_size, 16) - - if ( - decoded_payload - and chunk[:chunk_partial_size_chk] not in decoded_payload - ): - for j in range(i, i - 4, -1): - cut_sequence = sequences[j:chunk_end] - - if bom_or_sig_available and strip_sig_or_bom is False: - cut_sequence = sig_payload + cut_sequence - - chunk = cut_sequence.decode(encoding_iana, errors="ignore") - - if chunk[:chunk_partial_size_chk] in decoded_payload: - break - - yield chunk diff --git a/apps/bitwarden_event_logs/lib/charset_normalizer/version.py b/apps/bitwarden_event_logs/lib/charset_normalizer/version.py deleted file mode 100755 index c843e533..00000000 --- a/apps/bitwarden_event_logs/lib/charset_normalizer/version.py +++ /dev/null @@ -1,8 +0,0 @@ -""" -Expose version -""" - -from __future__ import annotations - -__version__ = "3.4.4" -VERSION = __version__.split(".") diff --git a/apps/bitwarden_event_logs/lib/dateutil/__init__.py b/apps/bitwarden_event_logs/lib/dateutil/__init__.py deleted file mode 100755 index a2c19c06..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -import sys - -try: - from ._version import version as __version__ -except ImportError: - __version__ = 'unknown' - -__all__ = ['easter', 'parser', 'relativedelta', 'rrule', 'tz', - 'utils', 'zoneinfo'] - -def __getattr__(name): - import importlib - - if name in __all__: - return importlib.import_module("." + name, __name__) - raise AttributeError( - "module {!r} has not attribute {!r}".format(__name__, name) - ) - - -def __dir__(): - # __dir__ should include all the lazy-importable modules as well. - return [x for x in globals() if x not in sys.modules] + __all__ diff --git a/apps/bitwarden_event_logs/lib/dateutil/__pycache__/__init__.cpython-39.pyc b/apps/bitwarden_event_logs/lib/dateutil/__pycache__/__init__.cpython-39.pyc deleted file mode 100755 index 8bc7d1e0..00000000 Binary files a/apps/bitwarden_event_logs/lib/dateutil/__pycache__/__init__.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/dateutil/__pycache__/_common.cpython-39.pyc b/apps/bitwarden_event_logs/lib/dateutil/__pycache__/_common.cpython-39.pyc deleted file mode 100755 index 8102f5b5..00000000 Binary files a/apps/bitwarden_event_logs/lib/dateutil/__pycache__/_common.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/dateutil/__pycache__/_version.cpython-39.pyc b/apps/bitwarden_event_logs/lib/dateutil/__pycache__/_version.cpython-39.pyc deleted file mode 100755 index 5dddbd7e..00000000 Binary files a/apps/bitwarden_event_logs/lib/dateutil/__pycache__/_version.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/dateutil/__pycache__/relativedelta.cpython-39.pyc b/apps/bitwarden_event_logs/lib/dateutil/__pycache__/relativedelta.cpython-39.pyc deleted file mode 100755 index 6676c8ba..00000000 Binary files a/apps/bitwarden_event_logs/lib/dateutil/__pycache__/relativedelta.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/dateutil/_common.py b/apps/bitwarden_event_logs/lib/dateutil/_common.py deleted file mode 100755 index 4eb2659b..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/_common.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Common code used in multiple modules. -""" - - -class weekday(object): - __slots__ = ["weekday", "n"] - - def __init__(self, weekday, n=None): - self.weekday = weekday - self.n = n - - def __call__(self, n): - if n == self.n: - return self - else: - return self.__class__(self.weekday, n) - - def __eq__(self, other): - try: - if self.weekday != other.weekday or self.n != other.n: - return False - except AttributeError: - return False - return True - - def __hash__(self): - return hash(( - self.weekday, - self.n, - )) - - def __ne__(self, other): - return not (self == other) - - def __repr__(self): - s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday] - if not self.n: - return s - else: - return "%s(%+d)" % (s, self.n) - -# vim:ts=4:sw=4:et diff --git a/apps/bitwarden_event_logs/lib/dateutil/_version.py b/apps/bitwarden_event_logs/lib/dateutil/_version.py deleted file mode 100755 index ddda9809..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/_version.py +++ /dev/null @@ -1,4 +0,0 @@ -# file generated by setuptools_scm -# don't change, don't track in version control -__version__ = version = '2.9.0.post0' -__version_tuple__ = version_tuple = (2, 9, 0) diff --git a/apps/bitwarden_event_logs/lib/dateutil/easter.py b/apps/bitwarden_event_logs/lib/dateutil/easter.py deleted file mode 100755 index f74d1f74..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/easter.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module offers a generic Easter computing method for any given year, using -Western, Orthodox or Julian algorithms. -""" - -import datetime - -__all__ = ["easter", "EASTER_JULIAN", "EASTER_ORTHODOX", "EASTER_WESTERN"] - -EASTER_JULIAN = 1 -EASTER_ORTHODOX = 2 -EASTER_WESTERN = 3 - - -def easter(year, method=EASTER_WESTERN): - """ - This method was ported from the work done by GM Arts, - on top of the algorithm by Claus Tondering, which was - based in part on the algorithm of Ouding (1940), as - quoted in "Explanatory Supplement to the Astronomical - Almanac", P. Kenneth Seidelmann, editor. - - This algorithm implements three different Easter - calculation methods: - - 1. Original calculation in Julian calendar, valid in - dates after 326 AD - 2. Original method, with date converted to Gregorian - calendar, valid in years 1583 to 4099 - 3. Revised method, in Gregorian calendar, valid in - years 1583 to 4099 as well - - These methods are represented by the constants: - - * ``EASTER_JULIAN = 1`` - * ``EASTER_ORTHODOX = 2`` - * ``EASTER_WESTERN = 3`` - - The default method is method 3. - - More about the algorithm may be found at: - - `GM Arts: Easter Algorithms `_ - - and - - `The Calendar FAQ: Easter `_ - - """ - - if not (1 <= method <= 3): - raise ValueError("invalid method") - - # g - Golden year - 1 - # c - Century - # h - (23 - Epact) mod 30 - # i - Number of days from March 21 to Paschal Full Moon - # j - Weekday for PFM (0=Sunday, etc) - # p - Number of days from March 21 to Sunday on or before PFM - # (-6 to 28 methods 1 & 3, to 56 for method 2) - # e - Extra days to add for method 2 (converting Julian - # date to Gregorian date) - - y = year - g = y % 19 - e = 0 - if method < 3: - # Old method - i = (19*g + 15) % 30 - j = (y + y//4 + i) % 7 - if method == 2: - # Extra dates to convert Julian to Gregorian date - e = 10 - if y > 1600: - e = e + y//100 - 16 - (y//100 - 16)//4 - else: - # New method - c = y//100 - h = (c - c//4 - (8*c + 13)//25 + 19*g + 15) % 30 - i = h - (h//28)*(1 - (h//28)*(29//(h + 1))*((21 - g)//11)) - j = (y + y//4 + i + 2 - c + c//4) % 7 - - # p can be from -6 to 56 corresponding to dates 22 March to 23 May - # (later dates apply to method 2, although 23 May never actually occurs) - p = i - j + e - d = 1 + (p + 27 + (p + 6)//40) % 31 - m = 3 + (p + 26)//30 - return datetime.date(int(y), int(m), int(d)) diff --git a/apps/bitwarden_event_logs/lib/dateutil/parser/__init__.py b/apps/bitwarden_event_logs/lib/dateutil/parser/__init__.py deleted file mode 100755 index d174b0e4..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/parser/__init__.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- -from ._parser import parse, parser, parserinfo, ParserError -from ._parser import DEFAULTPARSER, DEFAULTTZPARSER -from ._parser import UnknownTimezoneWarning - -from ._parser import __doc__ - -from .isoparser import isoparser, isoparse - -__all__ = ['parse', 'parser', 'parserinfo', - 'isoparse', 'isoparser', - 'ParserError', - 'UnknownTimezoneWarning'] - - -### -# Deprecate portions of the private interface so that downstream code that -# is improperly relying on it is given *some* notice. - - -def __deprecated_private_func(f): - from functools import wraps - import warnings - - msg = ('{name} is a private function and may break without warning, ' - 'it will be moved and or renamed in future versions.') - msg = msg.format(name=f.__name__) - - @wraps(f) - def deprecated_func(*args, **kwargs): - warnings.warn(msg, DeprecationWarning) - return f(*args, **kwargs) - - return deprecated_func - -def __deprecate_private_class(c): - import warnings - - msg = ('{name} is a private class and may break without warning, ' - 'it will be moved and or renamed in future versions.') - msg = msg.format(name=c.__name__) - - class private_class(c): - __doc__ = c.__doc__ - - def __init__(self, *args, **kwargs): - warnings.warn(msg, DeprecationWarning) - super(private_class, self).__init__(*args, **kwargs) - - private_class.__name__ = c.__name__ - - return private_class - - -from ._parser import _timelex, _resultbase -from ._parser import _tzparser, _parsetz - -_timelex = __deprecate_private_class(_timelex) -_tzparser = __deprecate_private_class(_tzparser) -_resultbase = __deprecate_private_class(_resultbase) -_parsetz = __deprecated_private_func(_parsetz) diff --git a/apps/bitwarden_event_logs/lib/dateutil/parser/__pycache__/__init__.cpython-39.pyc b/apps/bitwarden_event_logs/lib/dateutil/parser/__pycache__/__init__.cpython-39.pyc deleted file mode 100755 index 26b0b2fe..00000000 Binary files a/apps/bitwarden_event_logs/lib/dateutil/parser/__pycache__/__init__.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/dateutil/parser/__pycache__/_parser.cpython-39.pyc b/apps/bitwarden_event_logs/lib/dateutil/parser/__pycache__/_parser.cpython-39.pyc deleted file mode 100755 index 75c55d87..00000000 Binary files a/apps/bitwarden_event_logs/lib/dateutil/parser/__pycache__/_parser.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/dateutil/parser/__pycache__/isoparser.cpython-39.pyc b/apps/bitwarden_event_logs/lib/dateutil/parser/__pycache__/isoparser.cpython-39.pyc deleted file mode 100755 index 69aa4c43..00000000 Binary files a/apps/bitwarden_event_logs/lib/dateutil/parser/__pycache__/isoparser.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/dateutil/parser/_parser.py b/apps/bitwarden_event_logs/lib/dateutil/parser/_parser.py deleted file mode 100755 index 37d1663b..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/parser/_parser.py +++ /dev/null @@ -1,1613 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module offers a generic date/time string parser which is able to parse -most known formats to represent a date and/or time. - -This module attempts to be forgiving with regards to unlikely input formats, -returning a datetime object even for dates which are ambiguous. If an element -of a date/time stamp is omitted, the following rules are applied: - -- If AM or PM is left unspecified, a 24-hour clock is assumed, however, an hour - on a 12-hour clock (``0 <= hour <= 12``) *must* be specified if AM or PM is - specified. -- If a time zone is omitted, a timezone-naive datetime is returned. - -If any other elements are missing, they are taken from the -:class:`datetime.datetime` object passed to the parameter ``default``. If this -results in a day number exceeding the valid number of days per month, the -value falls back to the end of the month. - -Additional resources about date/time string formats can be found below: - -- `A summary of the international standard date and time notation - `_ -- `W3C Date and Time Formats `_ -- `Time Formats (Planetary Rings Node) `_ -- `CPAN ParseDate module - `_ -- `Java SimpleDateFormat Class - `_ -""" -from __future__ import unicode_literals - -import datetime -import re -import string -import time -import warnings - -from calendar import monthrange -from io import StringIO - -import six -from six import integer_types, text_type - -from decimal import Decimal - -from warnings import warn - -from .. import relativedelta -from .. import tz - -__all__ = ["parse", "parserinfo", "ParserError"] - - -# TODO: pandas.core.tools.datetimes imports this explicitly. Might be worth -# making public and/or figuring out if there is something we can -# take off their plate. -class _timelex(object): - # Fractional seconds are sometimes split by a comma - _split_decimal = re.compile("([.,])") - - def __init__(self, instream): - if isinstance(instream, (bytes, bytearray)): - instream = instream.decode() - - if isinstance(instream, text_type): - instream = StringIO(instream) - elif getattr(instream, 'read', None) is None: - raise TypeError('Parser must be a string or character stream, not ' - '{itype}'.format(itype=instream.__class__.__name__)) - - self.instream = instream - self.charstack = [] - self.tokenstack = [] - self.eof = False - - def get_token(self): - """ - This function breaks the time string into lexical units (tokens), which - can be parsed by the parser. Lexical units are demarcated by changes in - the character set, so any continuous string of letters is considered - one unit, any continuous string of numbers is considered one unit. - - The main complication arises from the fact that dots ('.') can be used - both as separators (e.g. "Sep.20.2009") or decimal points (e.g. - "4:30:21.447"). As such, it is necessary to read the full context of - any dot-separated strings before breaking it into tokens; as such, this - function maintains a "token stack", for when the ambiguous context - demands that multiple tokens be parsed at once. - """ - if self.tokenstack: - return self.tokenstack.pop(0) - - seenletters = False - token = None - state = None - - while not self.eof: - # We only realize that we've reached the end of a token when we - # find a character that's not part of the current token - since - # that character may be part of the next token, it's stored in the - # charstack. - if self.charstack: - nextchar = self.charstack.pop(0) - else: - nextchar = self.instream.read(1) - while nextchar == '\x00': - nextchar = self.instream.read(1) - - if not nextchar: - self.eof = True - break - elif not state: - # First character of the token - determines if we're starting - # to parse a word, a number or something else. - token = nextchar - if self.isword(nextchar): - state = 'a' - elif self.isnum(nextchar): - state = '0' - elif self.isspace(nextchar): - token = ' ' - break # emit token - else: - break # emit token - elif state == 'a': - # If we've already started reading a word, we keep reading - # letters until we find something that's not part of a word. - seenletters = True - if self.isword(nextchar): - token += nextchar - elif nextchar == '.': - token += nextchar - state = 'a.' - else: - self.charstack.append(nextchar) - break # emit token - elif state == '0': - # If we've already started reading a number, we keep reading - # numbers until we find something that doesn't fit. - if self.isnum(nextchar): - token += nextchar - elif nextchar == '.' or (nextchar == ',' and len(token) >= 2): - token += nextchar - state = '0.' - else: - self.charstack.append(nextchar) - break # emit token - elif state == 'a.': - # If we've seen some letters and a dot separator, continue - # parsing, and the tokens will be broken up later. - seenletters = True - if nextchar == '.' or self.isword(nextchar): - token += nextchar - elif self.isnum(nextchar) and token[-1] == '.': - token += nextchar - state = '0.' - else: - self.charstack.append(nextchar) - break # emit token - elif state == '0.': - # If we've seen at least one dot separator, keep going, we'll - # break up the tokens later. - if nextchar == '.' or self.isnum(nextchar): - token += nextchar - elif self.isword(nextchar) and token[-1] == '.': - token += nextchar - state = 'a.' - else: - self.charstack.append(nextchar) - break # emit token - - if (state in ('a.', '0.') and (seenletters or token.count('.') > 1 or - token[-1] in '.,')): - l = self._split_decimal.split(token) - token = l[0] - for tok in l[1:]: - if tok: - self.tokenstack.append(tok) - - if state == '0.' and token.count('.') == 0: - token = token.replace(',', '.') - - return token - - def __iter__(self): - return self - - def __next__(self): - token = self.get_token() - if token is None: - raise StopIteration - - return token - - def next(self): - return self.__next__() # Python 2.x support - - @classmethod - def split(cls, s): - return list(cls(s)) - - @classmethod - def isword(cls, nextchar): - """ Whether or not the next character is part of a word """ - return nextchar.isalpha() - - @classmethod - def isnum(cls, nextchar): - """ Whether the next character is part of a number """ - return nextchar.isdigit() - - @classmethod - def isspace(cls, nextchar): - """ Whether the next character is whitespace """ - return nextchar.isspace() - - -class _resultbase(object): - - def __init__(self): - for attr in self.__slots__: - setattr(self, attr, None) - - def _repr(self, classname): - l = [] - for attr in self.__slots__: - value = getattr(self, attr) - if value is not None: - l.append("%s=%s" % (attr, repr(value))) - return "%s(%s)" % (classname, ", ".join(l)) - - def __len__(self): - return (sum(getattr(self, attr) is not None - for attr in self.__slots__)) - - def __repr__(self): - return self._repr(self.__class__.__name__) - - -class parserinfo(object): - """ - Class which handles what inputs are accepted. Subclass this to customize - the language and acceptable values for each parameter. - - :param dayfirst: - Whether to interpret the first value in an ambiguous 3-integer date - (e.g. 01/05/09) as the day (``True``) or month (``False``). If - ``yearfirst`` is set to ``True``, this distinguishes between YDM - and YMD. Default is ``False``. - - :param yearfirst: - Whether to interpret the first value in an ambiguous 3-integer date - (e.g. 01/05/09) as the year. If ``True``, the first number is taken - to be the year, otherwise the last number is taken to be the year. - Default is ``False``. - """ - - # m from a.m/p.m, t from ISO T separator - JUMP = [" ", ".", ",", ";", "-", "/", "'", - "at", "on", "and", "ad", "m", "t", "of", - "st", "nd", "rd", "th"] - - WEEKDAYS = [("Mon", "Monday"), - ("Tue", "Tuesday"), # TODO: "Tues" - ("Wed", "Wednesday"), - ("Thu", "Thursday"), # TODO: "Thurs" - ("Fri", "Friday"), - ("Sat", "Saturday"), - ("Sun", "Sunday")] - MONTHS = [("Jan", "January"), - ("Feb", "February"), # TODO: "Febr" - ("Mar", "March"), - ("Apr", "April"), - ("May", "May"), - ("Jun", "June"), - ("Jul", "July"), - ("Aug", "August"), - ("Sep", "Sept", "September"), - ("Oct", "October"), - ("Nov", "November"), - ("Dec", "December")] - HMS = [("h", "hour", "hours"), - ("m", "minute", "minutes"), - ("s", "second", "seconds")] - AMPM = [("am", "a"), - ("pm", "p")] - UTCZONE = ["UTC", "GMT", "Z", "z"] - PERTAIN = ["of"] - TZOFFSET = {} - # TODO: ERA = ["AD", "BC", "CE", "BCE", "Stardate", - # "Anno Domini", "Year of Our Lord"] - - def __init__(self, dayfirst=False, yearfirst=False): - self._jump = self._convert(self.JUMP) - self._weekdays = self._convert(self.WEEKDAYS) - self._months = self._convert(self.MONTHS) - self._hms = self._convert(self.HMS) - self._ampm = self._convert(self.AMPM) - self._utczone = self._convert(self.UTCZONE) - self._pertain = self._convert(self.PERTAIN) - - self.dayfirst = dayfirst - self.yearfirst = yearfirst - - self._year = time.localtime().tm_year - self._century = self._year // 100 * 100 - - def _convert(self, lst): - dct = {} - for i, v in enumerate(lst): - if isinstance(v, tuple): - for v in v: - dct[v.lower()] = i - else: - dct[v.lower()] = i - return dct - - def jump(self, name): - return name.lower() in self._jump - - def weekday(self, name): - try: - return self._weekdays[name.lower()] - except KeyError: - pass - return None - - def month(self, name): - try: - return self._months[name.lower()] + 1 - except KeyError: - pass - return None - - def hms(self, name): - try: - return self._hms[name.lower()] - except KeyError: - return None - - def ampm(self, name): - try: - return self._ampm[name.lower()] - except KeyError: - return None - - def pertain(self, name): - return name.lower() in self._pertain - - def utczone(self, name): - return name.lower() in self._utczone - - def tzoffset(self, name): - if name in self._utczone: - return 0 - - return self.TZOFFSET.get(name) - - def convertyear(self, year, century_specified=False): - """ - Converts two-digit years to year within [-50, 49] - range of self._year (current local time) - """ - - # Function contract is that the year is always positive - assert year >= 0 - - if year < 100 and not century_specified: - # assume current century to start - year += self._century - - if year >= self._year + 50: # if too far in future - year -= 100 - elif year < self._year - 50: # if too far in past - year += 100 - - return year - - def validate(self, res): - # move to info - if res.year is not None: - res.year = self.convertyear(res.year, res.century_specified) - - if ((res.tzoffset == 0 and not res.tzname) or - (res.tzname == 'Z' or res.tzname == 'z')): - res.tzname = "UTC" - res.tzoffset = 0 - elif res.tzoffset != 0 and res.tzname and self.utczone(res.tzname): - res.tzoffset = 0 - return True - - -class _ymd(list): - def __init__(self, *args, **kwargs): - super(self.__class__, self).__init__(*args, **kwargs) - self.century_specified = False - self.dstridx = None - self.mstridx = None - self.ystridx = None - - @property - def has_year(self): - return self.ystridx is not None - - @property - def has_month(self): - return self.mstridx is not None - - @property - def has_day(self): - return self.dstridx is not None - - def could_be_day(self, value): - if self.has_day: - return False - elif not self.has_month: - return 1 <= value <= 31 - elif not self.has_year: - # Be permissive, assume leap year - month = self[self.mstridx] - return 1 <= value <= monthrange(2000, month)[1] - else: - month = self[self.mstridx] - year = self[self.ystridx] - return 1 <= value <= monthrange(year, month)[1] - - def append(self, val, label=None): - if hasattr(val, '__len__'): - if val.isdigit() and len(val) > 2: - self.century_specified = True - if label not in [None, 'Y']: # pragma: no cover - raise ValueError(label) - label = 'Y' - elif val > 100: - self.century_specified = True - if label not in [None, 'Y']: # pragma: no cover - raise ValueError(label) - label = 'Y' - - super(self.__class__, self).append(int(val)) - - if label == 'M': - if self.has_month: - raise ValueError('Month is already set') - self.mstridx = len(self) - 1 - elif label == 'D': - if self.has_day: - raise ValueError('Day is already set') - self.dstridx = len(self) - 1 - elif label == 'Y': - if self.has_year: - raise ValueError('Year is already set') - self.ystridx = len(self) - 1 - - def _resolve_from_stridxs(self, strids): - """ - Try to resolve the identities of year/month/day elements using - ystridx, mstridx, and dstridx, if enough of these are specified. - """ - if len(self) == 3 and len(strids) == 2: - # we can back out the remaining stridx value - missing = [x for x in range(3) if x not in strids.values()] - key = [x for x in ['y', 'm', 'd'] if x not in strids] - assert len(missing) == len(key) == 1 - key = key[0] - val = missing[0] - strids[key] = val - - assert len(self) == len(strids) # otherwise this should not be called - out = {key: self[strids[key]] for key in strids} - return (out.get('y'), out.get('m'), out.get('d')) - - def resolve_ymd(self, yearfirst, dayfirst): - len_ymd = len(self) - year, month, day = (None, None, None) - - strids = (('y', self.ystridx), - ('m', self.mstridx), - ('d', self.dstridx)) - - strids = {key: val for key, val in strids if val is not None} - if (len(self) == len(strids) > 0 or - (len(self) == 3 and len(strids) == 2)): - return self._resolve_from_stridxs(strids) - - mstridx = self.mstridx - - if len_ymd > 3: - raise ValueError("More than three YMD values") - elif len_ymd == 1 or (mstridx is not None and len_ymd == 2): - # One member, or two members with a month string - if mstridx is not None: - month = self[mstridx] - # since mstridx is 0 or 1, self[mstridx-1] always - # looks up the other element - other = self[mstridx - 1] - else: - other = self[0] - - if len_ymd > 1 or mstridx is None: - if other > 31: - year = other - else: - day = other - - elif len_ymd == 2: - # Two members with numbers - if self[0] > 31: - # 99-01 - year, month = self - elif self[1] > 31: - # 01-99 - month, year = self - elif dayfirst and self[1] <= 12: - # 13-01 - day, month = self - else: - # 01-13 - month, day = self - - elif len_ymd == 3: - # Three members - if mstridx == 0: - if self[1] > 31: - # Apr-2003-25 - month, year, day = self - else: - month, day, year = self - elif mstridx == 1: - if self[0] > 31 or (yearfirst and self[2] <= 31): - # 99-Jan-01 - year, month, day = self - else: - # 01-Jan-01 - # Give precedence to day-first, since - # two-digit years is usually hand-written. - day, month, year = self - - elif mstridx == 2: - # WTF!? - if self[1] > 31: - # 01-99-Jan - day, year, month = self - else: - # 99-01-Jan - year, day, month = self - - else: - if (self[0] > 31 or - self.ystridx == 0 or - (yearfirst and self[1] <= 12 and self[2] <= 31)): - # 99-01-01 - if dayfirst and self[2] <= 12: - year, day, month = self - else: - year, month, day = self - elif self[0] > 12 or (dayfirst and self[1] <= 12): - # 13-01-01 - day, month, year = self - else: - # 01-13-01 - month, day, year = self - - return year, month, day - - -class parser(object): - def __init__(self, info=None): - self.info = info or parserinfo() - - def parse(self, timestr, default=None, - ignoretz=False, tzinfos=None, **kwargs): - """ - Parse the date/time string into a :class:`datetime.datetime` object. - - :param timestr: - Any date/time string using the supported formats. - - :param default: - The default datetime object, if this is a datetime object and not - ``None``, elements specified in ``timestr`` replace elements in the - default object. - - :param ignoretz: - If set ``True``, time zones in parsed strings are ignored and a - naive :class:`datetime.datetime` object is returned. - - :param tzinfos: - Additional time zone names / aliases which may be present in the - string. This argument maps time zone names (and optionally offsets - from those time zones) to time zones. This parameter can be a - dictionary with timezone aliases mapping time zone names to time - zones or a function taking two parameters (``tzname`` and - ``tzoffset``) and returning a time zone. - - The timezones to which the names are mapped can be an integer - offset from UTC in seconds or a :class:`tzinfo` object. - - .. doctest:: - :options: +NORMALIZE_WHITESPACE - - >>> from dateutil.parser import parse - >>> from dateutil.tz import gettz - >>> tzinfos = {"BRST": -7200, "CST": gettz("America/Chicago")} - >>> parse("2012-01-19 17:21:00 BRST", tzinfos=tzinfos) - datetime.datetime(2012, 1, 19, 17, 21, tzinfo=tzoffset(u'BRST', -7200)) - >>> parse("2012-01-19 17:21:00 CST", tzinfos=tzinfos) - datetime.datetime(2012, 1, 19, 17, 21, - tzinfo=tzfile('/usr/share/zoneinfo/America/Chicago')) - - This parameter is ignored if ``ignoretz`` is set. - - :param \\*\\*kwargs: - Keyword arguments as passed to ``_parse()``. - - :return: - Returns a :class:`datetime.datetime` object or, if the - ``fuzzy_with_tokens`` option is ``True``, returns a tuple, the - first element being a :class:`datetime.datetime` object, the second - a tuple containing the fuzzy tokens. - - :raises ParserError: - Raised for invalid or unknown string format, if the provided - :class:`tzinfo` is not in a valid format, or if an invalid date - would be created. - - :raises TypeError: - Raised for non-string or character stream input. - - :raises OverflowError: - Raised if the parsed date exceeds the largest valid C integer on - your system. - """ - - if default is None: - default = datetime.datetime.now().replace(hour=0, minute=0, - second=0, microsecond=0) - - res, skipped_tokens = self._parse(timestr, **kwargs) - - if res is None: - raise ParserError("Unknown string format: %s", timestr) - - if len(res) == 0: - raise ParserError("String does not contain a date: %s", timestr) - - try: - ret = self._build_naive(res, default) - except ValueError as e: - six.raise_from(ParserError(str(e) + ": %s", timestr), e) - - if not ignoretz: - ret = self._build_tzaware(ret, res, tzinfos) - - if kwargs.get('fuzzy_with_tokens', False): - return ret, skipped_tokens - else: - return ret - - class _result(_resultbase): - __slots__ = ["year", "month", "day", "weekday", - "hour", "minute", "second", "microsecond", - "tzname", "tzoffset", "ampm","any_unused_tokens"] - - def _parse(self, timestr, dayfirst=None, yearfirst=None, fuzzy=False, - fuzzy_with_tokens=False): - """ - Private method which performs the heavy lifting of parsing, called from - ``parse()``, which passes on its ``kwargs`` to this function. - - :param timestr: - The string to parse. - - :param dayfirst: - Whether to interpret the first value in an ambiguous 3-integer date - (e.g. 01/05/09) as the day (``True``) or month (``False``). If - ``yearfirst`` is set to ``True``, this distinguishes between YDM - and YMD. If set to ``None``, this value is retrieved from the - current :class:`parserinfo` object (which itself defaults to - ``False``). - - :param yearfirst: - Whether to interpret the first value in an ambiguous 3-integer date - (e.g. 01/05/09) as the year. If ``True``, the first number is taken - to be the year, otherwise the last number is taken to be the year. - If this is set to ``None``, the value is retrieved from the current - :class:`parserinfo` object (which itself defaults to ``False``). - - :param fuzzy: - Whether to allow fuzzy parsing, allowing for string like "Today is - January 1, 2047 at 8:21:00AM". - - :param fuzzy_with_tokens: - If ``True``, ``fuzzy`` is automatically set to True, and the parser - will return a tuple where the first element is the parsed - :class:`datetime.datetime` datetimestamp and the second element is - a tuple containing the portions of the string which were ignored: - - .. doctest:: - - >>> from dateutil.parser import parse - >>> parse("Today is January 1, 2047 at 8:21:00AM", fuzzy_with_tokens=True) - (datetime.datetime(2047, 1, 1, 8, 21), (u'Today is ', u' ', u'at ')) - - """ - if fuzzy_with_tokens: - fuzzy = True - - info = self.info - - if dayfirst is None: - dayfirst = info.dayfirst - - if yearfirst is None: - yearfirst = info.yearfirst - - res = self._result() - l = _timelex.split(timestr) # Splits the timestr into tokens - - skipped_idxs = [] - - # year/month/day list - ymd = _ymd() - - len_l = len(l) - i = 0 - try: - while i < len_l: - - # Check if it's a number - value_repr = l[i] - try: - value = float(value_repr) - except ValueError: - value = None - - if value is not None: - # Numeric token - i = self._parse_numeric_token(l, i, info, ymd, res, fuzzy) - - # Check weekday - elif info.weekday(l[i]) is not None: - value = info.weekday(l[i]) - res.weekday = value - - # Check month name - elif info.month(l[i]) is not None: - value = info.month(l[i]) - ymd.append(value, 'M') - - if i + 1 < len_l: - if l[i + 1] in ('-', '/'): - # Jan-01[-99] - sep = l[i + 1] - ymd.append(l[i + 2]) - - if i + 3 < len_l and l[i + 3] == sep: - # Jan-01-99 - ymd.append(l[i + 4]) - i += 2 - - i += 2 - - elif (i + 4 < len_l and l[i + 1] == l[i + 3] == ' ' and - info.pertain(l[i + 2])): - # Jan of 01 - # In this case, 01 is clearly year - if l[i + 4].isdigit(): - # Convert it here to become unambiguous - value = int(l[i + 4]) - year = str(info.convertyear(value)) - ymd.append(year, 'Y') - else: - # Wrong guess - pass - # TODO: not hit in tests - i += 4 - - # Check am/pm - elif info.ampm(l[i]) is not None: - value = info.ampm(l[i]) - val_is_ampm = self._ampm_valid(res.hour, res.ampm, fuzzy) - - if val_is_ampm: - res.hour = self._adjust_ampm(res.hour, value) - res.ampm = value - - elif fuzzy: - skipped_idxs.append(i) - - # Check for a timezone name - elif self._could_be_tzname(res.hour, res.tzname, res.tzoffset, l[i]): - res.tzname = l[i] - res.tzoffset = info.tzoffset(res.tzname) - - # Check for something like GMT+3, or BRST+3. Notice - # that it doesn't mean "I am 3 hours after GMT", but - # "my time +3 is GMT". If found, we reverse the - # logic so that timezone parsing code will get it - # right. - if i + 1 < len_l and l[i + 1] in ('+', '-'): - l[i + 1] = ('+', '-')[l[i + 1] == '+'] - res.tzoffset = None - if info.utczone(res.tzname): - # With something like GMT+3, the timezone - # is *not* GMT. - res.tzname = None - - # Check for a numbered timezone - elif res.hour is not None and l[i] in ('+', '-'): - signal = (-1, 1)[l[i] == '+'] - len_li = len(l[i + 1]) - - # TODO: check that l[i + 1] is integer? - if len_li == 4: - # -0300 - hour_offset = int(l[i + 1][:2]) - min_offset = int(l[i + 1][2:]) - elif i + 2 < len_l and l[i + 2] == ':': - # -03:00 - hour_offset = int(l[i + 1]) - min_offset = int(l[i + 3]) # TODO: Check that l[i+3] is minute-like? - i += 2 - elif len_li <= 2: - # -[0]3 - hour_offset = int(l[i + 1][:2]) - min_offset = 0 - else: - raise ValueError(timestr) - - res.tzoffset = signal * (hour_offset * 3600 + min_offset * 60) - - # Look for a timezone name between parenthesis - if (i + 5 < len_l and - info.jump(l[i + 2]) and l[i + 3] == '(' and - l[i + 5] == ')' and - 3 <= len(l[i + 4]) and - self._could_be_tzname(res.hour, res.tzname, - None, l[i + 4])): - # -0300 (BRST) - res.tzname = l[i + 4] - i += 4 - - i += 1 - - # Check jumps - elif not (info.jump(l[i]) or fuzzy): - raise ValueError(timestr) - - else: - skipped_idxs.append(i) - i += 1 - - # Process year/month/day - year, month, day = ymd.resolve_ymd(yearfirst, dayfirst) - - res.century_specified = ymd.century_specified - res.year = year - res.month = month - res.day = day - - except (IndexError, ValueError): - return None, None - - if not info.validate(res): - return None, None - - if fuzzy_with_tokens: - skipped_tokens = self._recombine_skipped(l, skipped_idxs) - return res, tuple(skipped_tokens) - else: - return res, None - - def _parse_numeric_token(self, tokens, idx, info, ymd, res, fuzzy): - # Token is a number - value_repr = tokens[idx] - try: - value = self._to_decimal(value_repr) - except Exception as e: - six.raise_from(ValueError('Unknown numeric token'), e) - - len_li = len(value_repr) - - len_l = len(tokens) - - if (len(ymd) == 3 and len_li in (2, 4) and - res.hour is None and - (idx + 1 >= len_l or - (tokens[idx + 1] != ':' and - info.hms(tokens[idx + 1]) is None))): - # 19990101T23[59] - s = tokens[idx] - res.hour = int(s[:2]) - - if len_li == 4: - res.minute = int(s[2:]) - - elif len_li == 6 or (len_li > 6 and tokens[idx].find('.') == 6): - # YYMMDD or HHMMSS[.ss] - s = tokens[idx] - - if not ymd and '.' not in tokens[idx]: - ymd.append(s[:2]) - ymd.append(s[2:4]) - ymd.append(s[4:]) - else: - # 19990101T235959[.59] - - # TODO: Check if res attributes already set. - res.hour = int(s[:2]) - res.minute = int(s[2:4]) - res.second, res.microsecond = self._parsems(s[4:]) - - elif len_li in (8, 12, 14): - # YYYYMMDD - s = tokens[idx] - ymd.append(s[:4], 'Y') - ymd.append(s[4:6]) - ymd.append(s[6:8]) - - if len_li > 8: - res.hour = int(s[8:10]) - res.minute = int(s[10:12]) - - if len_li > 12: - res.second = int(s[12:]) - - elif self._find_hms_idx(idx, tokens, info, allow_jump=True) is not None: - # HH[ ]h or MM[ ]m or SS[.ss][ ]s - hms_idx = self._find_hms_idx(idx, tokens, info, allow_jump=True) - (idx, hms) = self._parse_hms(idx, tokens, info, hms_idx) - if hms is not None: - # TODO: checking that hour/minute/second are not - # already set? - self._assign_hms(res, value_repr, hms) - - elif idx + 2 < len_l and tokens[idx + 1] == ':': - # HH:MM[:SS[.ss]] - res.hour = int(value) - value = self._to_decimal(tokens[idx + 2]) # TODO: try/except for this? - (res.minute, res.second) = self._parse_min_sec(value) - - if idx + 4 < len_l and tokens[idx + 3] == ':': - res.second, res.microsecond = self._parsems(tokens[idx + 4]) - - idx += 2 - - idx += 2 - - elif idx + 1 < len_l and tokens[idx + 1] in ('-', '/', '.'): - sep = tokens[idx + 1] - ymd.append(value_repr) - - if idx + 2 < len_l and not info.jump(tokens[idx + 2]): - if tokens[idx + 2].isdigit(): - # 01-01[-01] - ymd.append(tokens[idx + 2]) - else: - # 01-Jan[-01] - value = info.month(tokens[idx + 2]) - - if value is not None: - ymd.append(value, 'M') - else: - raise ValueError() - - if idx + 3 < len_l and tokens[idx + 3] == sep: - # We have three members - value = info.month(tokens[idx + 4]) - - if value is not None: - ymd.append(value, 'M') - else: - ymd.append(tokens[idx + 4]) - idx += 2 - - idx += 1 - idx += 1 - - elif idx + 1 >= len_l or info.jump(tokens[idx + 1]): - if idx + 2 < len_l and info.ampm(tokens[idx + 2]) is not None: - # 12 am - hour = int(value) - res.hour = self._adjust_ampm(hour, info.ampm(tokens[idx + 2])) - idx += 1 - else: - # Year, month or day - ymd.append(value) - idx += 1 - - elif info.ampm(tokens[idx + 1]) is not None and (0 <= value < 24): - # 12am - hour = int(value) - res.hour = self._adjust_ampm(hour, info.ampm(tokens[idx + 1])) - idx += 1 - - elif ymd.could_be_day(value): - ymd.append(value) - - elif not fuzzy: - raise ValueError() - - return idx - - def _find_hms_idx(self, idx, tokens, info, allow_jump): - len_l = len(tokens) - - if idx+1 < len_l and info.hms(tokens[idx+1]) is not None: - # There is an "h", "m", or "s" label following this token. We take - # assign the upcoming label to the current token. - # e.g. the "12" in 12h" - hms_idx = idx + 1 - - elif (allow_jump and idx+2 < len_l and tokens[idx+1] == ' ' and - info.hms(tokens[idx+2]) is not None): - # There is a space and then an "h", "m", or "s" label. - # e.g. the "12" in "12 h" - hms_idx = idx + 2 - - elif idx > 0 and info.hms(tokens[idx-1]) is not None: - # There is a "h", "m", or "s" preceding this token. Since neither - # of the previous cases was hit, there is no label following this - # token, so we use the previous label. - # e.g. the "04" in "12h04" - hms_idx = idx-1 - - elif (1 < idx == len_l-1 and tokens[idx-1] == ' ' and - info.hms(tokens[idx-2]) is not None): - # If we are looking at the final token, we allow for a - # backward-looking check to skip over a space. - # TODO: Are we sure this is the right condition here? - hms_idx = idx - 2 - - else: - hms_idx = None - - return hms_idx - - def _assign_hms(self, res, value_repr, hms): - # See GH issue #427, fixing float rounding - value = self._to_decimal(value_repr) - - if hms == 0: - # Hour - res.hour = int(value) - if value % 1: - res.minute = int(60*(value % 1)) - - elif hms == 1: - (res.minute, res.second) = self._parse_min_sec(value) - - elif hms == 2: - (res.second, res.microsecond) = self._parsems(value_repr) - - def _could_be_tzname(self, hour, tzname, tzoffset, token): - return (hour is not None and - tzname is None and - tzoffset is None and - len(token) <= 5 and - (all(x in string.ascii_uppercase for x in token) - or token in self.info.UTCZONE)) - - def _ampm_valid(self, hour, ampm, fuzzy): - """ - For fuzzy parsing, 'a' or 'am' (both valid English words) - may erroneously trigger the AM/PM flag. Deal with that - here. - """ - val_is_ampm = True - - # If there's already an AM/PM flag, this one isn't one. - if fuzzy and ampm is not None: - val_is_ampm = False - - # If AM/PM is found and hour is not, raise a ValueError - if hour is None: - if fuzzy: - val_is_ampm = False - else: - raise ValueError('No hour specified with AM or PM flag.') - elif not 0 <= hour <= 12: - # If AM/PM is found, it's a 12 hour clock, so raise - # an error for invalid range - if fuzzy: - val_is_ampm = False - else: - raise ValueError('Invalid hour specified for 12-hour clock.') - - return val_is_ampm - - def _adjust_ampm(self, hour, ampm): - if hour < 12 and ampm == 1: - hour += 12 - elif hour == 12 and ampm == 0: - hour = 0 - return hour - - def _parse_min_sec(self, value): - # TODO: Every usage of this function sets res.second to the return - # value. Are there any cases where second will be returned as None and - # we *don't* want to set res.second = None? - minute = int(value) - second = None - - sec_remainder = value % 1 - if sec_remainder: - second = int(60 * sec_remainder) - return (minute, second) - - def _parse_hms(self, idx, tokens, info, hms_idx): - # TODO: Is this going to admit a lot of false-positives for when we - # just happen to have digits and "h", "m" or "s" characters in non-date - # text? I guess hex hashes won't have that problem, but there's plenty - # of random junk out there. - if hms_idx is None: - hms = None - new_idx = idx - elif hms_idx > idx: - hms = info.hms(tokens[hms_idx]) - new_idx = hms_idx - else: - # Looking backwards, increment one. - hms = info.hms(tokens[hms_idx]) + 1 - new_idx = idx - - return (new_idx, hms) - - # ------------------------------------------------------------------ - # Handling for individual tokens. These are kept as methods instead - # of functions for the sake of customizability via subclassing. - - def _parsems(self, value): - """Parse a I[.F] seconds value into (seconds, microseconds).""" - if "." not in value: - return int(value), 0 - else: - i, f = value.split(".") - return int(i), int(f.ljust(6, "0")[:6]) - - def _to_decimal(self, val): - try: - decimal_value = Decimal(val) - # See GH 662, edge case, infinite value should not be converted - # via `_to_decimal` - if not decimal_value.is_finite(): - raise ValueError("Converted decimal value is infinite or NaN") - except Exception as e: - msg = "Could not convert %s to decimal" % val - six.raise_from(ValueError(msg), e) - else: - return decimal_value - - # ------------------------------------------------------------------ - # Post-Parsing construction of datetime output. These are kept as - # methods instead of functions for the sake of customizability via - # subclassing. - - def _build_tzinfo(self, tzinfos, tzname, tzoffset): - if callable(tzinfos): - tzdata = tzinfos(tzname, tzoffset) - else: - tzdata = tzinfos.get(tzname) - # handle case where tzinfo is paased an options that returns None - # eg tzinfos = {'BRST' : None} - if isinstance(tzdata, datetime.tzinfo) or tzdata is None: - tzinfo = tzdata - elif isinstance(tzdata, text_type): - tzinfo = tz.tzstr(tzdata) - elif isinstance(tzdata, integer_types): - tzinfo = tz.tzoffset(tzname, tzdata) - else: - raise TypeError("Offset must be tzinfo subclass, tz string, " - "or int offset.") - return tzinfo - - def _build_tzaware(self, naive, res, tzinfos): - if (callable(tzinfos) or (tzinfos and res.tzname in tzinfos)): - tzinfo = self._build_tzinfo(tzinfos, res.tzname, res.tzoffset) - aware = naive.replace(tzinfo=tzinfo) - aware = self._assign_tzname(aware, res.tzname) - - elif res.tzname and res.tzname in time.tzname: - aware = naive.replace(tzinfo=tz.tzlocal()) - - # Handle ambiguous local datetime - aware = self._assign_tzname(aware, res.tzname) - - # This is mostly relevant for winter GMT zones parsed in the UK - if (aware.tzname() != res.tzname and - res.tzname in self.info.UTCZONE): - aware = aware.replace(tzinfo=tz.UTC) - - elif res.tzoffset == 0: - aware = naive.replace(tzinfo=tz.UTC) - - elif res.tzoffset: - aware = naive.replace(tzinfo=tz.tzoffset(res.tzname, res.tzoffset)) - - elif not res.tzname and not res.tzoffset: - # i.e. no timezone information was found. - aware = naive - - elif res.tzname: - # tz-like string was parsed but we don't know what to do - # with it - warnings.warn("tzname {tzname} identified but not understood. " - "Pass `tzinfos` argument in order to correctly " - "return a timezone-aware datetime. In a future " - "version, this will raise an " - "exception.".format(tzname=res.tzname), - category=UnknownTimezoneWarning) - aware = naive - - return aware - - def _build_naive(self, res, default): - repl = {} - for attr in ("year", "month", "day", "hour", - "minute", "second", "microsecond"): - value = getattr(res, attr) - if value is not None: - repl[attr] = value - - if 'day' not in repl: - # If the default day exceeds the last day of the month, fall back - # to the end of the month. - cyear = default.year if res.year is None else res.year - cmonth = default.month if res.month is None else res.month - cday = default.day if res.day is None else res.day - - if cday > monthrange(cyear, cmonth)[1]: - repl['day'] = monthrange(cyear, cmonth)[1] - - naive = default.replace(**repl) - - if res.weekday is not None and not res.day: - naive = naive + relativedelta.relativedelta(weekday=res.weekday) - - return naive - - def _assign_tzname(self, dt, tzname): - if dt.tzname() != tzname: - new_dt = tz.enfold(dt, fold=1) - if new_dt.tzname() == tzname: - return new_dt - - return dt - - def _recombine_skipped(self, tokens, skipped_idxs): - """ - >>> tokens = ["foo", " ", "bar", " ", "19June2000", "baz"] - >>> skipped_idxs = [0, 1, 2, 5] - >>> _recombine_skipped(tokens, skipped_idxs) - ["foo bar", "baz"] - """ - skipped_tokens = [] - for i, idx in enumerate(sorted(skipped_idxs)): - if i > 0 and idx - 1 == skipped_idxs[i - 1]: - skipped_tokens[-1] = skipped_tokens[-1] + tokens[idx] - else: - skipped_tokens.append(tokens[idx]) - - return skipped_tokens - - -DEFAULTPARSER = parser() - - -def parse(timestr, parserinfo=None, **kwargs): - """ - - Parse a string in one of the supported formats, using the - ``parserinfo`` parameters. - - :param timestr: - A string containing a date/time stamp. - - :param parserinfo: - A :class:`parserinfo` object containing parameters for the parser. - If ``None``, the default arguments to the :class:`parserinfo` - constructor are used. - - The ``**kwargs`` parameter takes the following keyword arguments: - - :param default: - The default datetime object, if this is a datetime object and not - ``None``, elements specified in ``timestr`` replace elements in the - default object. - - :param ignoretz: - If set ``True``, time zones in parsed strings are ignored and a naive - :class:`datetime` object is returned. - - :param tzinfos: - Additional time zone names / aliases which may be present in the - string. This argument maps time zone names (and optionally offsets - from those time zones) to time zones. This parameter can be a - dictionary with timezone aliases mapping time zone names to time - zones or a function taking two parameters (``tzname`` and - ``tzoffset``) and returning a time zone. - - The timezones to which the names are mapped can be an integer - offset from UTC in seconds or a :class:`tzinfo` object. - - .. doctest:: - :options: +NORMALIZE_WHITESPACE - - >>> from dateutil.parser import parse - >>> from dateutil.tz import gettz - >>> tzinfos = {"BRST": -7200, "CST": gettz("America/Chicago")} - >>> parse("2012-01-19 17:21:00 BRST", tzinfos=tzinfos) - datetime.datetime(2012, 1, 19, 17, 21, tzinfo=tzoffset(u'BRST', -7200)) - >>> parse("2012-01-19 17:21:00 CST", tzinfos=tzinfos) - datetime.datetime(2012, 1, 19, 17, 21, - tzinfo=tzfile('/usr/share/zoneinfo/America/Chicago')) - - This parameter is ignored if ``ignoretz`` is set. - - :param dayfirst: - Whether to interpret the first value in an ambiguous 3-integer date - (e.g. 01/05/09) as the day (``True``) or month (``False``). If - ``yearfirst`` is set to ``True``, this distinguishes between YDM and - YMD. If set to ``None``, this value is retrieved from the current - :class:`parserinfo` object (which itself defaults to ``False``). - - :param yearfirst: - Whether to interpret the first value in an ambiguous 3-integer date - (e.g. 01/05/09) as the year. If ``True``, the first number is taken to - be the year, otherwise the last number is taken to be the year. If - this is set to ``None``, the value is retrieved from the current - :class:`parserinfo` object (which itself defaults to ``False``). - - :param fuzzy: - Whether to allow fuzzy parsing, allowing for string like "Today is - January 1, 2047 at 8:21:00AM". - - :param fuzzy_with_tokens: - If ``True``, ``fuzzy`` is automatically set to True, and the parser - will return a tuple where the first element is the parsed - :class:`datetime.datetime` datetimestamp and the second element is - a tuple containing the portions of the string which were ignored: - - .. doctest:: - - >>> from dateutil.parser import parse - >>> parse("Today is January 1, 2047 at 8:21:00AM", fuzzy_with_tokens=True) - (datetime.datetime(2047, 1, 1, 8, 21), (u'Today is ', u' ', u'at ')) - - :return: - Returns a :class:`datetime.datetime` object or, if the - ``fuzzy_with_tokens`` option is ``True``, returns a tuple, the - first element being a :class:`datetime.datetime` object, the second - a tuple containing the fuzzy tokens. - - :raises ParserError: - Raised for invalid or unknown string formats, if the provided - :class:`tzinfo` is not in a valid format, or if an invalid date would - be created. - - :raises OverflowError: - Raised if the parsed date exceeds the largest valid C integer on - your system. - """ - if parserinfo: - return parser(parserinfo).parse(timestr, **kwargs) - else: - return DEFAULTPARSER.parse(timestr, **kwargs) - - -class _tzparser(object): - - class _result(_resultbase): - - __slots__ = ["stdabbr", "stdoffset", "dstabbr", "dstoffset", - "start", "end"] - - class _attr(_resultbase): - __slots__ = ["month", "week", "weekday", - "yday", "jyday", "day", "time"] - - def __repr__(self): - return self._repr("") - - def __init__(self): - _resultbase.__init__(self) - self.start = self._attr() - self.end = self._attr() - - def parse(self, tzstr): - res = self._result() - l = [x for x in re.split(r'([,:.]|[a-zA-Z]+|[0-9]+)',tzstr) if x] - used_idxs = list() - try: - - len_l = len(l) - - i = 0 - while i < len_l: - # BRST+3[BRDT[+2]] - j = i - while j < len_l and not [x for x in l[j] - if x in "0123456789:,-+"]: - j += 1 - if j != i: - if not res.stdabbr: - offattr = "stdoffset" - res.stdabbr = "".join(l[i:j]) - else: - offattr = "dstoffset" - res.dstabbr = "".join(l[i:j]) - - for ii in range(j): - used_idxs.append(ii) - i = j - if (i < len_l and (l[i] in ('+', '-') or l[i][0] in - "0123456789")): - if l[i] in ('+', '-'): - # Yes, that's right. See the TZ variable - # documentation. - signal = (1, -1)[l[i] == '+'] - used_idxs.append(i) - i += 1 - else: - signal = -1 - len_li = len(l[i]) - if len_li == 4: - # -0300 - setattr(res, offattr, (int(l[i][:2]) * 3600 + - int(l[i][2:]) * 60) * signal) - elif i + 1 < len_l and l[i + 1] == ':': - # -03:00 - setattr(res, offattr, - (int(l[i]) * 3600 + - int(l[i + 2]) * 60) * signal) - used_idxs.append(i) - i += 2 - elif len_li <= 2: - # -[0]3 - setattr(res, offattr, - int(l[i][:2]) * 3600 * signal) - else: - return None - used_idxs.append(i) - i += 1 - if res.dstabbr: - break - else: - break - - - if i < len_l: - for j in range(i, len_l): - if l[j] == ';': - l[j] = ',' - - assert l[i] == ',' - - i += 1 - - if i >= len_l: - pass - elif (8 <= l.count(',') <= 9 and - not [y for x in l[i:] if x != ',' - for y in x if y not in "0123456789+-"]): - # GMT0BST,3,0,30,3600,10,0,26,7200[,3600] - for x in (res.start, res.end): - x.month = int(l[i]) - used_idxs.append(i) - i += 2 - if l[i] == '-': - value = int(l[i + 1]) * -1 - used_idxs.append(i) - i += 1 - else: - value = int(l[i]) - used_idxs.append(i) - i += 2 - if value: - x.week = value - x.weekday = (int(l[i]) - 1) % 7 - else: - x.day = int(l[i]) - used_idxs.append(i) - i += 2 - x.time = int(l[i]) - used_idxs.append(i) - i += 2 - if i < len_l: - if l[i] in ('-', '+'): - signal = (-1, 1)[l[i] == "+"] - used_idxs.append(i) - i += 1 - else: - signal = 1 - used_idxs.append(i) - res.dstoffset = (res.stdoffset + int(l[i]) * signal) - - # This was a made-up format that is not in normal use - warn(('Parsed time zone "%s"' % tzstr) + - 'is in a non-standard dateutil-specific format, which ' + - 'is now deprecated; support for parsing this format ' + - 'will be removed in future versions. It is recommended ' + - 'that you switch to a standard format like the GNU ' + - 'TZ variable format.', tz.DeprecatedTzFormatWarning) - elif (l.count(',') == 2 and l[i:].count('/') <= 2 and - not [y for x in l[i:] if x not in (',', '/', 'J', 'M', - '.', '-', ':') - for y in x if y not in "0123456789"]): - for x in (res.start, res.end): - if l[i] == 'J': - # non-leap year day (1 based) - used_idxs.append(i) - i += 1 - x.jyday = int(l[i]) - elif l[i] == 'M': - # month[-.]week[-.]weekday - used_idxs.append(i) - i += 1 - x.month = int(l[i]) - used_idxs.append(i) - i += 1 - assert l[i] in ('-', '.') - used_idxs.append(i) - i += 1 - x.week = int(l[i]) - if x.week == 5: - x.week = -1 - used_idxs.append(i) - i += 1 - assert l[i] in ('-', '.') - used_idxs.append(i) - i += 1 - x.weekday = (int(l[i]) - 1) % 7 - else: - # year day (zero based) - x.yday = int(l[i]) + 1 - - used_idxs.append(i) - i += 1 - - if i < len_l and l[i] == '/': - used_idxs.append(i) - i += 1 - # start time - len_li = len(l[i]) - if len_li == 4: - # -0300 - x.time = (int(l[i][:2]) * 3600 + - int(l[i][2:]) * 60) - elif i + 1 < len_l and l[i + 1] == ':': - # -03:00 - x.time = int(l[i]) * 3600 + int(l[i + 2]) * 60 - used_idxs.append(i) - i += 2 - if i + 1 < len_l and l[i + 1] == ':': - used_idxs.append(i) - i += 2 - x.time += int(l[i]) - elif len_li <= 2: - # -[0]3 - x.time = (int(l[i][:2]) * 3600) - else: - return None - used_idxs.append(i) - i += 1 - - assert i == len_l or l[i] == ',' - - i += 1 - - assert i >= len_l - - except (IndexError, ValueError, AssertionError): - return None - - unused_idxs = set(range(len_l)).difference(used_idxs) - res.any_unused_tokens = not {l[n] for n in unused_idxs}.issubset({",",":"}) - return res - - -DEFAULTTZPARSER = _tzparser() - - -def _parsetz(tzstr): - return DEFAULTTZPARSER.parse(tzstr) - - -class ParserError(ValueError): - """Exception subclass used for any failure to parse a datetime string. - - This is a subclass of :py:exc:`ValueError`, and should be raised any time - earlier versions of ``dateutil`` would have raised ``ValueError``. - - .. versionadded:: 2.8.1 - """ - def __str__(self): - try: - return self.args[0] % self.args[1:] - except (TypeError, IndexError): - return super(ParserError, self).__str__() - - def __repr__(self): - args = ", ".join("'%s'" % arg for arg in self.args) - return "%s(%s)" % (self.__class__.__name__, args) - - -class UnknownTimezoneWarning(RuntimeWarning): - """Raised when the parser finds a timezone it cannot parse into a tzinfo. - - .. versionadded:: 2.7.0 - """ -# vim:ts=4:sw=4:et diff --git a/apps/bitwarden_event_logs/lib/dateutil/parser/isoparser.py b/apps/bitwarden_event_logs/lib/dateutil/parser/isoparser.py deleted file mode 100755 index 7060087d..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/parser/isoparser.py +++ /dev/null @@ -1,416 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module offers a parser for ISO-8601 strings - -It is intended to support all valid date, time and datetime formats per the -ISO-8601 specification. - -..versionadded:: 2.7.0 -""" -from datetime import datetime, timedelta, time, date -import calendar -from dateutil import tz - -from functools import wraps - -import re -import six - -__all__ = ["isoparse", "isoparser"] - - -def _takes_ascii(f): - @wraps(f) - def func(self, str_in, *args, **kwargs): - # If it's a stream, read the whole thing - str_in = getattr(str_in, 'read', lambda: str_in)() - - # If it's unicode, turn it into bytes, since ISO-8601 only covers ASCII - if isinstance(str_in, six.text_type): - # ASCII is the same in UTF-8 - try: - str_in = str_in.encode('ascii') - except UnicodeEncodeError as e: - msg = 'ISO-8601 strings should contain only ASCII characters' - six.raise_from(ValueError(msg), e) - - return f(self, str_in, *args, **kwargs) - - return func - - -class isoparser(object): - def __init__(self, sep=None): - """ - :param sep: - A single character that separates date and time portions. If - ``None``, the parser will accept any single character. - For strict ISO-8601 adherence, pass ``'T'``. - """ - if sep is not None: - if (len(sep) != 1 or ord(sep) >= 128 or sep in '0123456789'): - raise ValueError('Separator must be a single, non-numeric ' + - 'ASCII character') - - sep = sep.encode('ascii') - - self._sep = sep - - @_takes_ascii - def isoparse(self, dt_str): - """ - Parse an ISO-8601 datetime string into a :class:`datetime.datetime`. - - An ISO-8601 datetime string consists of a date portion, followed - optionally by a time portion - the date and time portions are separated - by a single character separator, which is ``T`` in the official - standard. Incomplete date formats (such as ``YYYY-MM``) may *not* be - combined with a time portion. - - Supported date formats are: - - Common: - - - ``YYYY`` - - ``YYYY-MM`` - - ``YYYY-MM-DD`` or ``YYYYMMDD`` - - Uncommon: - - - ``YYYY-Www`` or ``YYYYWww`` - ISO week (day defaults to 0) - - ``YYYY-Www-D`` or ``YYYYWwwD`` - ISO week and day - - The ISO week and day numbering follows the same logic as - :func:`datetime.date.isocalendar`. - - Supported time formats are: - - - ``hh`` - - ``hh:mm`` or ``hhmm`` - - ``hh:mm:ss`` or ``hhmmss`` - - ``hh:mm:ss.ssssss`` (Up to 6 sub-second digits) - - Midnight is a special case for `hh`, as the standard supports both - 00:00 and 24:00 as a representation. The decimal separator can be - either a dot or a comma. - - - .. caution:: - - Support for fractional components other than seconds is part of the - ISO-8601 standard, but is not currently implemented in this parser. - - Supported time zone offset formats are: - - - `Z` (UTC) - - `±HH:MM` - - `±HHMM` - - `±HH` - - Offsets will be represented as :class:`dateutil.tz.tzoffset` objects, - with the exception of UTC, which will be represented as - :class:`dateutil.tz.tzutc`. Time zone offsets equivalent to UTC (such - as `+00:00`) will also be represented as :class:`dateutil.tz.tzutc`. - - :param dt_str: - A string or stream containing only an ISO-8601 datetime string - - :return: - Returns a :class:`datetime.datetime` representing the string. - Unspecified components default to their lowest value. - - .. warning:: - - As of version 2.7.0, the strictness of the parser should not be - considered a stable part of the contract. Any valid ISO-8601 string - that parses correctly with the default settings will continue to - parse correctly in future versions, but invalid strings that - currently fail (e.g. ``2017-01-01T00:00+00:00:00``) are not - guaranteed to continue failing in future versions if they encode - a valid date. - - .. versionadded:: 2.7.0 - """ - components, pos = self._parse_isodate(dt_str) - - if len(dt_str) > pos: - if self._sep is None or dt_str[pos:pos + 1] == self._sep: - components += self._parse_isotime(dt_str[pos + 1:]) - else: - raise ValueError('String contains unknown ISO components') - - if len(components) > 3 and components[3] == 24: - components[3] = 0 - return datetime(*components) + timedelta(days=1) - - return datetime(*components) - - @_takes_ascii - def parse_isodate(self, datestr): - """ - Parse the date portion of an ISO string. - - :param datestr: - The string portion of an ISO string, without a separator - - :return: - Returns a :class:`datetime.date` object - """ - components, pos = self._parse_isodate(datestr) - if pos < len(datestr): - raise ValueError('String contains unknown ISO ' + - 'components: {!r}'.format(datestr.decode('ascii'))) - return date(*components) - - @_takes_ascii - def parse_isotime(self, timestr): - """ - Parse the time portion of an ISO string. - - :param timestr: - The time portion of an ISO string, without a separator - - :return: - Returns a :class:`datetime.time` object - """ - components = self._parse_isotime(timestr) - if components[0] == 24: - components[0] = 0 - return time(*components) - - @_takes_ascii - def parse_tzstr(self, tzstr, zero_as_utc=True): - """ - Parse a valid ISO time zone string. - - See :func:`isoparser.isoparse` for details on supported formats. - - :param tzstr: - A string representing an ISO time zone offset - - :param zero_as_utc: - Whether to return :class:`dateutil.tz.tzutc` for zero-offset zones - - :return: - Returns :class:`dateutil.tz.tzoffset` for offsets and - :class:`dateutil.tz.tzutc` for ``Z`` and (if ``zero_as_utc`` is - specified) offsets equivalent to UTC. - """ - return self._parse_tzstr(tzstr, zero_as_utc=zero_as_utc) - - # Constants - _DATE_SEP = b'-' - _TIME_SEP = b':' - _FRACTION_REGEX = re.compile(b'[\\.,]([0-9]+)') - - def _parse_isodate(self, dt_str): - try: - return self._parse_isodate_common(dt_str) - except ValueError: - return self._parse_isodate_uncommon(dt_str) - - def _parse_isodate_common(self, dt_str): - len_str = len(dt_str) - components = [1, 1, 1] - - if len_str < 4: - raise ValueError('ISO string too short') - - # Year - components[0] = int(dt_str[0:4]) - pos = 4 - if pos >= len_str: - return components, pos - - has_sep = dt_str[pos:pos + 1] == self._DATE_SEP - if has_sep: - pos += 1 - - # Month - if len_str - pos < 2: - raise ValueError('Invalid common month') - - components[1] = int(dt_str[pos:pos + 2]) - pos += 2 - - if pos >= len_str: - if has_sep: - return components, pos - else: - raise ValueError('Invalid ISO format') - - if has_sep: - if dt_str[pos:pos + 1] != self._DATE_SEP: - raise ValueError('Invalid separator in ISO string') - pos += 1 - - # Day - if len_str - pos < 2: - raise ValueError('Invalid common day') - components[2] = int(dt_str[pos:pos + 2]) - return components, pos + 2 - - def _parse_isodate_uncommon(self, dt_str): - if len(dt_str) < 4: - raise ValueError('ISO string too short') - - # All ISO formats start with the year - year = int(dt_str[0:4]) - - has_sep = dt_str[4:5] == self._DATE_SEP - - pos = 4 + has_sep # Skip '-' if it's there - if dt_str[pos:pos + 1] == b'W': - # YYYY-?Www-?D? - pos += 1 - weekno = int(dt_str[pos:pos + 2]) - pos += 2 - - dayno = 1 - if len(dt_str) > pos: - if (dt_str[pos:pos + 1] == self._DATE_SEP) != has_sep: - raise ValueError('Inconsistent use of dash separator') - - pos += has_sep - - dayno = int(dt_str[pos:pos + 1]) - pos += 1 - - base_date = self._calculate_weekdate(year, weekno, dayno) - else: - # YYYYDDD or YYYY-DDD - if len(dt_str) - pos < 3: - raise ValueError('Invalid ordinal day') - - ordinal_day = int(dt_str[pos:pos + 3]) - pos += 3 - - if ordinal_day < 1 or ordinal_day > (365 + calendar.isleap(year)): - raise ValueError('Invalid ordinal day' + - ' {} for year {}'.format(ordinal_day, year)) - - base_date = date(year, 1, 1) + timedelta(days=ordinal_day - 1) - - components = [base_date.year, base_date.month, base_date.day] - return components, pos - - def _calculate_weekdate(self, year, week, day): - """ - Calculate the day of corresponding to the ISO year-week-day calendar. - - This function is effectively the inverse of - :func:`datetime.date.isocalendar`. - - :param year: - The year in the ISO calendar - - :param week: - The week in the ISO calendar - range is [1, 53] - - :param day: - The day in the ISO calendar - range is [1 (MON), 7 (SUN)] - - :return: - Returns a :class:`datetime.date` - """ - if not 0 < week < 54: - raise ValueError('Invalid week: {}'.format(week)) - - if not 0 < day < 8: # Range is 1-7 - raise ValueError('Invalid weekday: {}'.format(day)) - - # Get week 1 for the specific year: - jan_4 = date(year, 1, 4) # Week 1 always has January 4th in it - week_1 = jan_4 - timedelta(days=jan_4.isocalendar()[2] - 1) - - # Now add the specific number of weeks and days to get what we want - week_offset = (week - 1) * 7 + (day - 1) - return week_1 + timedelta(days=week_offset) - - def _parse_isotime(self, timestr): - len_str = len(timestr) - components = [0, 0, 0, 0, None] - pos = 0 - comp = -1 - - if len_str < 2: - raise ValueError('ISO time too short') - - has_sep = False - - while pos < len_str and comp < 5: - comp += 1 - - if timestr[pos:pos + 1] in b'-+Zz': - # Detect time zone boundary - components[-1] = self._parse_tzstr(timestr[pos:]) - pos = len_str - break - - if comp == 1 and timestr[pos:pos+1] == self._TIME_SEP: - has_sep = True - pos += 1 - elif comp == 2 and has_sep: - if timestr[pos:pos+1] != self._TIME_SEP: - raise ValueError('Inconsistent use of colon separator') - pos += 1 - - if comp < 3: - # Hour, minute, second - components[comp] = int(timestr[pos:pos + 2]) - pos += 2 - - if comp == 3: - # Fraction of a second - frac = self._FRACTION_REGEX.match(timestr[pos:]) - if not frac: - continue - - us_str = frac.group(1)[:6] # Truncate to microseconds - components[comp] = int(us_str) * 10**(6 - len(us_str)) - pos += len(frac.group()) - - if pos < len_str: - raise ValueError('Unused components in ISO string') - - if components[0] == 24: - # Standard supports 00:00 and 24:00 as representations of midnight - if any(component != 0 for component in components[1:4]): - raise ValueError('Hour may only be 24 at 24:00:00.000') - - return components - - def _parse_tzstr(self, tzstr, zero_as_utc=True): - if tzstr == b'Z' or tzstr == b'z': - return tz.UTC - - if len(tzstr) not in {3, 5, 6}: - raise ValueError('Time zone offset must be 1, 3, 5 or 6 characters') - - if tzstr[0:1] == b'-': - mult = -1 - elif tzstr[0:1] == b'+': - mult = 1 - else: - raise ValueError('Time zone offset requires sign') - - hours = int(tzstr[1:3]) - if len(tzstr) == 3: - minutes = 0 - else: - minutes = int(tzstr[(4 if tzstr[3:4] == self._TIME_SEP else 3):]) - - if zero_as_utc and hours == 0 and minutes == 0: - return tz.UTC - else: - if minutes > 59: - raise ValueError('Invalid minutes in time zone offset') - - if hours > 23: - raise ValueError('Invalid hours in time zone offset') - - return tz.tzoffset(None, mult * (hours * 60 + minutes) * 60) - - -DEFAULT_ISOPARSER = isoparser() -isoparse = DEFAULT_ISOPARSER.isoparse diff --git a/apps/bitwarden_event_logs/lib/dateutil/relativedelta.py b/apps/bitwarden_event_logs/lib/dateutil/relativedelta.py deleted file mode 100755 index cd323a54..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/relativedelta.py +++ /dev/null @@ -1,599 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -import calendar - -import operator -from math import copysign - -from six import integer_types -from warnings import warn - -from ._common import weekday - -MO, TU, WE, TH, FR, SA, SU = weekdays = tuple(weekday(x) for x in range(7)) - -__all__ = ["relativedelta", "MO", "TU", "WE", "TH", "FR", "SA", "SU"] - - -class relativedelta(object): - """ - The relativedelta type is designed to be applied to an existing datetime and - can replace specific components of that datetime, or represents an interval - of time. - - It is based on the specification of the excellent work done by M.-A. Lemburg - in his - `mx.DateTime `_ extension. - However, notice that this type does *NOT* implement the same algorithm as - his work. Do *NOT* expect it to behave like mx.DateTime's counterpart. - - There are two different ways to build a relativedelta instance. The - first one is passing it two date/datetime classes:: - - relativedelta(datetime1, datetime2) - - The second one is passing it any number of the following keyword arguments:: - - relativedelta(arg1=x,arg2=y,arg3=z...) - - year, month, day, hour, minute, second, microsecond: - Absolute information (argument is singular); adding or subtracting a - relativedelta with absolute information does not perform an arithmetic - operation, but rather REPLACES the corresponding value in the - original datetime with the value(s) in relativedelta. - - years, months, weeks, days, hours, minutes, seconds, microseconds: - Relative information, may be negative (argument is plural); adding - or subtracting a relativedelta with relative information performs - the corresponding arithmetic operation on the original datetime value - with the information in the relativedelta. - - weekday: - One of the weekday instances (MO, TU, etc) available in the - relativedelta module. These instances may receive a parameter N, - specifying the Nth weekday, which could be positive or negative - (like MO(+1) or MO(-2)). Not specifying it is the same as specifying - +1. You can also use an integer, where 0=MO. This argument is always - relative e.g. if the calculated date is already Monday, using MO(1) - or MO(-1) won't change the day. To effectively make it absolute, use - it in combination with the day argument (e.g. day=1, MO(1) for first - Monday of the month). - - leapdays: - Will add given days to the date found, if year is a leap - year, and the date found is post 28 of february. - - yearday, nlyearday: - Set the yearday or the non-leap year day (jump leap days). - These are converted to day/month/leapdays information. - - There are relative and absolute forms of the keyword - arguments. The plural is relative, and the singular is - absolute. For each argument in the order below, the absolute form - is applied first (by setting each attribute to that value) and - then the relative form (by adding the value to the attribute). - - The order of attributes considered when this relativedelta is - added to a datetime is: - - 1. Year - 2. Month - 3. Day - 4. Hours - 5. Minutes - 6. Seconds - 7. Microseconds - - Finally, weekday is applied, using the rule described above. - - For example - - >>> from datetime import datetime - >>> from dateutil.relativedelta import relativedelta, MO - >>> dt = datetime(2018, 4, 9, 13, 37, 0) - >>> delta = relativedelta(hours=25, day=1, weekday=MO(1)) - >>> dt + delta - datetime.datetime(2018, 4, 2, 14, 37) - - First, the day is set to 1 (the first of the month), then 25 hours - are added, to get to the 2nd day and 14th hour, finally the - weekday is applied, but since the 2nd is already a Monday there is - no effect. - - """ - - def __init__(self, dt1=None, dt2=None, - years=0, months=0, days=0, leapdays=0, weeks=0, - hours=0, minutes=0, seconds=0, microseconds=0, - year=None, month=None, day=None, weekday=None, - yearday=None, nlyearday=None, - hour=None, minute=None, second=None, microsecond=None): - - if dt1 and dt2: - # datetime is a subclass of date. So both must be date - if not (isinstance(dt1, datetime.date) and - isinstance(dt2, datetime.date)): - raise TypeError("relativedelta only diffs datetime/date") - - # We allow two dates, or two datetimes, so we coerce them to be - # of the same type - if (isinstance(dt1, datetime.datetime) != - isinstance(dt2, datetime.datetime)): - if not isinstance(dt1, datetime.datetime): - dt1 = datetime.datetime.fromordinal(dt1.toordinal()) - elif not isinstance(dt2, datetime.datetime): - dt2 = datetime.datetime.fromordinal(dt2.toordinal()) - - self.years = 0 - self.months = 0 - self.days = 0 - self.leapdays = 0 - self.hours = 0 - self.minutes = 0 - self.seconds = 0 - self.microseconds = 0 - self.year = None - self.month = None - self.day = None - self.weekday = None - self.hour = None - self.minute = None - self.second = None - self.microsecond = None - self._has_time = 0 - - # Get year / month delta between the two - months = (dt1.year - dt2.year) * 12 + (dt1.month - dt2.month) - self._set_months(months) - - # Remove the year/month delta so the timedelta is just well-defined - # time units (seconds, days and microseconds) - dtm = self.__radd__(dt2) - - # If we've overshot our target, make an adjustment - if dt1 < dt2: - compare = operator.gt - increment = 1 - else: - compare = operator.lt - increment = -1 - - while compare(dt1, dtm): - months += increment - self._set_months(months) - dtm = self.__radd__(dt2) - - # Get the timedelta between the "months-adjusted" date and dt1 - delta = dt1 - dtm - self.seconds = delta.seconds + delta.days * 86400 - self.microseconds = delta.microseconds - else: - # Check for non-integer values in integer-only quantities - if any(x is not None and x != int(x) for x in (years, months)): - raise ValueError("Non-integer years and months are " - "ambiguous and not currently supported.") - - # Relative information - self.years = int(years) - self.months = int(months) - self.days = days + weeks * 7 - self.leapdays = leapdays - self.hours = hours - self.minutes = minutes - self.seconds = seconds - self.microseconds = microseconds - - # Absolute information - self.year = year - self.month = month - self.day = day - self.hour = hour - self.minute = minute - self.second = second - self.microsecond = microsecond - - if any(x is not None and int(x) != x - for x in (year, month, day, hour, - minute, second, microsecond)): - # For now we'll deprecate floats - later it'll be an error. - warn("Non-integer value passed as absolute information. " + - "This is not a well-defined condition and will raise " + - "errors in future versions.", DeprecationWarning) - - if isinstance(weekday, integer_types): - self.weekday = weekdays[weekday] - else: - self.weekday = weekday - - yday = 0 - if nlyearday: - yday = nlyearday - elif yearday: - yday = yearday - if yearday > 59: - self.leapdays = -1 - if yday: - ydayidx = [31, 59, 90, 120, 151, 181, 212, - 243, 273, 304, 334, 366] - for idx, ydays in enumerate(ydayidx): - if yday <= ydays: - self.month = idx+1 - if idx == 0: - self.day = yday - else: - self.day = yday-ydayidx[idx-1] - break - else: - raise ValueError("invalid year day (%d)" % yday) - - self._fix() - - def _fix(self): - if abs(self.microseconds) > 999999: - s = _sign(self.microseconds) - div, mod = divmod(self.microseconds * s, 1000000) - self.microseconds = mod * s - self.seconds += div * s - if abs(self.seconds) > 59: - s = _sign(self.seconds) - div, mod = divmod(self.seconds * s, 60) - self.seconds = mod * s - self.minutes += div * s - if abs(self.minutes) > 59: - s = _sign(self.minutes) - div, mod = divmod(self.minutes * s, 60) - self.minutes = mod * s - self.hours += div * s - if abs(self.hours) > 23: - s = _sign(self.hours) - div, mod = divmod(self.hours * s, 24) - self.hours = mod * s - self.days += div * s - if abs(self.months) > 11: - s = _sign(self.months) - div, mod = divmod(self.months * s, 12) - self.months = mod * s - self.years += div * s - if (self.hours or self.minutes or self.seconds or self.microseconds - or self.hour is not None or self.minute is not None or - self.second is not None or self.microsecond is not None): - self._has_time = 1 - else: - self._has_time = 0 - - @property - def weeks(self): - return int(self.days / 7.0) - - @weeks.setter - def weeks(self, value): - self.days = self.days - (self.weeks * 7) + value * 7 - - def _set_months(self, months): - self.months = months - if abs(self.months) > 11: - s = _sign(self.months) - div, mod = divmod(self.months * s, 12) - self.months = mod * s - self.years = div * s - else: - self.years = 0 - - def normalized(self): - """ - Return a version of this object represented entirely using integer - values for the relative attributes. - - >>> relativedelta(days=1.5, hours=2).normalized() - relativedelta(days=+1, hours=+14) - - :return: - Returns a :class:`dateutil.relativedelta.relativedelta` object. - """ - # Cascade remainders down (rounding each to roughly nearest microsecond) - days = int(self.days) - - hours_f = round(self.hours + 24 * (self.days - days), 11) - hours = int(hours_f) - - minutes_f = round(self.minutes + 60 * (hours_f - hours), 10) - minutes = int(minutes_f) - - seconds_f = round(self.seconds + 60 * (minutes_f - minutes), 8) - seconds = int(seconds_f) - - microseconds = round(self.microseconds + 1e6 * (seconds_f - seconds)) - - # Constructor carries overflow back up with call to _fix() - return self.__class__(years=self.years, months=self.months, - days=days, hours=hours, minutes=minutes, - seconds=seconds, microseconds=microseconds, - leapdays=self.leapdays, year=self.year, - month=self.month, day=self.day, - weekday=self.weekday, hour=self.hour, - minute=self.minute, second=self.second, - microsecond=self.microsecond) - - def __add__(self, other): - if isinstance(other, relativedelta): - return self.__class__(years=other.years + self.years, - months=other.months + self.months, - days=other.days + self.days, - hours=other.hours + self.hours, - minutes=other.minutes + self.minutes, - seconds=other.seconds + self.seconds, - microseconds=(other.microseconds + - self.microseconds), - leapdays=other.leapdays or self.leapdays, - year=(other.year if other.year is not None - else self.year), - month=(other.month if other.month is not None - else self.month), - day=(other.day if other.day is not None - else self.day), - weekday=(other.weekday if other.weekday is not None - else self.weekday), - hour=(other.hour if other.hour is not None - else self.hour), - minute=(other.minute if other.minute is not None - else self.minute), - second=(other.second if other.second is not None - else self.second), - microsecond=(other.microsecond if other.microsecond - is not None else - self.microsecond)) - if isinstance(other, datetime.timedelta): - return self.__class__(years=self.years, - months=self.months, - days=self.days + other.days, - hours=self.hours, - minutes=self.minutes, - seconds=self.seconds + other.seconds, - microseconds=self.microseconds + other.microseconds, - leapdays=self.leapdays, - year=self.year, - month=self.month, - day=self.day, - weekday=self.weekday, - hour=self.hour, - minute=self.minute, - second=self.second, - microsecond=self.microsecond) - if not isinstance(other, datetime.date): - return NotImplemented - elif self._has_time and not isinstance(other, datetime.datetime): - other = datetime.datetime.fromordinal(other.toordinal()) - year = (self.year or other.year)+self.years - month = self.month or other.month - if self.months: - assert 1 <= abs(self.months) <= 12 - month += self.months - if month > 12: - year += 1 - month -= 12 - elif month < 1: - year -= 1 - month += 12 - day = min(calendar.monthrange(year, month)[1], - self.day or other.day) - repl = {"year": year, "month": month, "day": day} - for attr in ["hour", "minute", "second", "microsecond"]: - value = getattr(self, attr) - if value is not None: - repl[attr] = value - days = self.days - if self.leapdays and month > 2 and calendar.isleap(year): - days += self.leapdays - ret = (other.replace(**repl) - + datetime.timedelta(days=days, - hours=self.hours, - minutes=self.minutes, - seconds=self.seconds, - microseconds=self.microseconds)) - if self.weekday: - weekday, nth = self.weekday.weekday, self.weekday.n or 1 - jumpdays = (abs(nth) - 1) * 7 - if nth > 0: - jumpdays += (7 - ret.weekday() + weekday) % 7 - else: - jumpdays += (ret.weekday() - weekday) % 7 - jumpdays *= -1 - ret += datetime.timedelta(days=jumpdays) - return ret - - def __radd__(self, other): - return self.__add__(other) - - def __rsub__(self, other): - return self.__neg__().__radd__(other) - - def __sub__(self, other): - if not isinstance(other, relativedelta): - return NotImplemented # In case the other object defines __rsub__ - return self.__class__(years=self.years - other.years, - months=self.months - other.months, - days=self.days - other.days, - hours=self.hours - other.hours, - minutes=self.minutes - other.minutes, - seconds=self.seconds - other.seconds, - microseconds=self.microseconds - other.microseconds, - leapdays=self.leapdays or other.leapdays, - year=(self.year if self.year is not None - else other.year), - month=(self.month if self.month is not None else - other.month), - day=(self.day if self.day is not None else - other.day), - weekday=(self.weekday if self.weekday is not None else - other.weekday), - hour=(self.hour if self.hour is not None else - other.hour), - minute=(self.minute if self.minute is not None else - other.minute), - second=(self.second if self.second is not None else - other.second), - microsecond=(self.microsecond if self.microsecond - is not None else - other.microsecond)) - - def __abs__(self): - return self.__class__(years=abs(self.years), - months=abs(self.months), - days=abs(self.days), - hours=abs(self.hours), - minutes=abs(self.minutes), - seconds=abs(self.seconds), - microseconds=abs(self.microseconds), - leapdays=self.leapdays, - year=self.year, - month=self.month, - day=self.day, - weekday=self.weekday, - hour=self.hour, - minute=self.minute, - second=self.second, - microsecond=self.microsecond) - - def __neg__(self): - return self.__class__(years=-self.years, - months=-self.months, - days=-self.days, - hours=-self.hours, - minutes=-self.minutes, - seconds=-self.seconds, - microseconds=-self.microseconds, - leapdays=self.leapdays, - year=self.year, - month=self.month, - day=self.day, - weekday=self.weekday, - hour=self.hour, - minute=self.minute, - second=self.second, - microsecond=self.microsecond) - - def __bool__(self): - return not (not self.years and - not self.months and - not self.days and - not self.hours and - not self.minutes and - not self.seconds and - not self.microseconds and - not self.leapdays and - self.year is None and - self.month is None and - self.day is None and - self.weekday is None and - self.hour is None and - self.minute is None and - self.second is None and - self.microsecond is None) - # Compatibility with Python 2.x - __nonzero__ = __bool__ - - def __mul__(self, other): - try: - f = float(other) - except TypeError: - return NotImplemented - - return self.__class__(years=int(self.years * f), - months=int(self.months * f), - days=int(self.days * f), - hours=int(self.hours * f), - minutes=int(self.minutes * f), - seconds=int(self.seconds * f), - microseconds=int(self.microseconds * f), - leapdays=self.leapdays, - year=self.year, - month=self.month, - day=self.day, - weekday=self.weekday, - hour=self.hour, - minute=self.minute, - second=self.second, - microsecond=self.microsecond) - - __rmul__ = __mul__ - - def __eq__(self, other): - if not isinstance(other, relativedelta): - return NotImplemented - if self.weekday or other.weekday: - if not self.weekday or not other.weekday: - return False - if self.weekday.weekday != other.weekday.weekday: - return False - n1, n2 = self.weekday.n, other.weekday.n - if n1 != n2 and not ((not n1 or n1 == 1) and (not n2 or n2 == 1)): - return False - return (self.years == other.years and - self.months == other.months and - self.days == other.days and - self.hours == other.hours and - self.minutes == other.minutes and - self.seconds == other.seconds and - self.microseconds == other.microseconds and - self.leapdays == other.leapdays and - self.year == other.year and - self.month == other.month and - self.day == other.day and - self.hour == other.hour and - self.minute == other.minute and - self.second == other.second and - self.microsecond == other.microsecond) - - def __hash__(self): - return hash(( - self.weekday, - self.years, - self.months, - self.days, - self.hours, - self.minutes, - self.seconds, - self.microseconds, - self.leapdays, - self.year, - self.month, - self.day, - self.hour, - self.minute, - self.second, - self.microsecond, - )) - - def __ne__(self, other): - return not self.__eq__(other) - - def __div__(self, other): - try: - reciprocal = 1 / float(other) - except TypeError: - return NotImplemented - - return self.__mul__(reciprocal) - - __truediv__ = __div__ - - def __repr__(self): - l = [] - for attr in ["years", "months", "days", "leapdays", - "hours", "minutes", "seconds", "microseconds"]: - value = getattr(self, attr) - if value: - l.append("{attr}={value:+g}".format(attr=attr, value=value)) - for attr in ["year", "month", "day", "weekday", - "hour", "minute", "second", "microsecond"]: - value = getattr(self, attr) - if value is not None: - l.append("{attr}={value}".format(attr=attr, value=repr(value))) - return "{classname}({attrs})".format(classname=self.__class__.__name__, - attrs=", ".join(l)) - - -def _sign(x): - return int(copysign(1, x)) - -# vim:ts=4:sw=4:et diff --git a/apps/bitwarden_event_logs/lib/dateutil/rrule.py b/apps/bitwarden_event_logs/lib/dateutil/rrule.py deleted file mode 100755 index 571a0d2b..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/rrule.py +++ /dev/null @@ -1,1737 +0,0 @@ -# -*- coding: utf-8 -*- -""" -The rrule module offers a small, complete, and very fast, implementation of -the recurrence rules documented in the -`iCalendar RFC `_, -including support for caching of results. -""" -import calendar -import datetime -import heapq -import itertools -import re -import sys -from functools import wraps -# For warning about deprecation of until and count -from warnings import warn - -from six import advance_iterator, integer_types - -from six.moves import _thread, range - -from ._common import weekday as weekdaybase - -try: - from math import gcd -except ImportError: - from fractions import gcd - -__all__ = ["rrule", "rruleset", "rrulestr", - "YEARLY", "MONTHLY", "WEEKLY", "DAILY", - "HOURLY", "MINUTELY", "SECONDLY", - "MO", "TU", "WE", "TH", "FR", "SA", "SU"] - -# Every mask is 7 days longer to handle cross-year weekly periods. -M366MASK = tuple([1]*31+[2]*29+[3]*31+[4]*30+[5]*31+[6]*30 + - [7]*31+[8]*31+[9]*30+[10]*31+[11]*30+[12]*31+[1]*7) -M365MASK = list(M366MASK) -M29, M30, M31 = list(range(1, 30)), list(range(1, 31)), list(range(1, 32)) -MDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) -MDAY365MASK = list(MDAY366MASK) -M29, M30, M31 = list(range(-29, 0)), list(range(-30, 0)), list(range(-31, 0)) -NMDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) -NMDAY365MASK = list(NMDAY366MASK) -M366RANGE = (0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366) -M365RANGE = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365) -WDAYMASK = [0, 1, 2, 3, 4, 5, 6]*55 -del M29, M30, M31, M365MASK[59], MDAY365MASK[59], NMDAY365MASK[31] -MDAY365MASK = tuple(MDAY365MASK) -M365MASK = tuple(M365MASK) - -FREQNAMES = ['YEARLY', 'MONTHLY', 'WEEKLY', 'DAILY', 'HOURLY', 'MINUTELY', 'SECONDLY'] - -(YEARLY, - MONTHLY, - WEEKLY, - DAILY, - HOURLY, - MINUTELY, - SECONDLY) = list(range(7)) - -# Imported on demand. -easter = None -parser = None - - -class weekday(weekdaybase): - """ - This version of weekday does not allow n = 0. - """ - def __init__(self, wkday, n=None): - if n == 0: - raise ValueError("Can't create weekday with n==0") - - super(weekday, self).__init__(wkday, n) - - -MO, TU, WE, TH, FR, SA, SU = weekdays = tuple(weekday(x) for x in range(7)) - - -def _invalidates_cache(f): - """ - Decorator for rruleset methods which may invalidate the - cached length. - """ - @wraps(f) - def inner_func(self, *args, **kwargs): - rv = f(self, *args, **kwargs) - self._invalidate_cache() - return rv - - return inner_func - - -class rrulebase(object): - def __init__(self, cache=False): - if cache: - self._cache = [] - self._cache_lock = _thread.allocate_lock() - self._invalidate_cache() - else: - self._cache = None - self._cache_complete = False - self._len = None - - def __iter__(self): - if self._cache_complete: - return iter(self._cache) - elif self._cache is None: - return self._iter() - else: - return self._iter_cached() - - def _invalidate_cache(self): - if self._cache is not None: - self._cache = [] - self._cache_complete = False - self._cache_gen = self._iter() - - if self._cache_lock.locked(): - self._cache_lock.release() - - self._len = None - - def _iter_cached(self): - i = 0 - gen = self._cache_gen - cache = self._cache - acquire = self._cache_lock.acquire - release = self._cache_lock.release - while gen: - if i == len(cache): - acquire() - if self._cache_complete: - break - try: - for j in range(10): - cache.append(advance_iterator(gen)) - except StopIteration: - self._cache_gen = gen = None - self._cache_complete = True - break - release() - yield cache[i] - i += 1 - while i < self._len: - yield cache[i] - i += 1 - - def __getitem__(self, item): - if self._cache_complete: - return self._cache[item] - elif isinstance(item, slice): - if item.step and item.step < 0: - return list(iter(self))[item] - else: - return list(itertools.islice(self, - item.start or 0, - item.stop or sys.maxsize, - item.step or 1)) - elif item >= 0: - gen = iter(self) - try: - for i in range(item+1): - res = advance_iterator(gen) - except StopIteration: - raise IndexError - return res - else: - return list(iter(self))[item] - - def __contains__(self, item): - if self._cache_complete: - return item in self._cache - else: - for i in self: - if i == item: - return True - elif i > item: - return False - return False - - # __len__() introduces a large performance penalty. - def count(self): - """ Returns the number of recurrences in this set. It will have go - through the whole recurrence, if this hasn't been done before. """ - if self._len is None: - for x in self: - pass - return self._len - - def before(self, dt, inc=False): - """ Returns the last recurrence before the given datetime instance. The - inc keyword defines what happens if dt is an occurrence. With - inc=True, if dt itself is an occurrence, it will be returned. """ - if self._cache_complete: - gen = self._cache - else: - gen = self - last = None - if inc: - for i in gen: - if i > dt: - break - last = i - else: - for i in gen: - if i >= dt: - break - last = i - return last - - def after(self, dt, inc=False): - """ Returns the first recurrence after the given datetime instance. The - inc keyword defines what happens if dt is an occurrence. With - inc=True, if dt itself is an occurrence, it will be returned. """ - if self._cache_complete: - gen = self._cache - else: - gen = self - if inc: - for i in gen: - if i >= dt: - return i - else: - for i in gen: - if i > dt: - return i - return None - - def xafter(self, dt, count=None, inc=False): - """ - Generator which yields up to `count` recurrences after the given - datetime instance, equivalent to `after`. - - :param dt: - The datetime at which to start generating recurrences. - - :param count: - The maximum number of recurrences to generate. If `None` (default), - dates are generated until the recurrence rule is exhausted. - - :param inc: - If `dt` is an instance of the rule and `inc` is `True`, it is - included in the output. - - :yields: Yields a sequence of `datetime` objects. - """ - - if self._cache_complete: - gen = self._cache - else: - gen = self - - # Select the comparison function - if inc: - comp = lambda dc, dtc: dc >= dtc - else: - comp = lambda dc, dtc: dc > dtc - - # Generate dates - n = 0 - for d in gen: - if comp(d, dt): - if count is not None: - n += 1 - if n > count: - break - - yield d - - def between(self, after, before, inc=False, count=1): - """ Returns all the occurrences of the rrule between after and before. - The inc keyword defines what happens if after and/or before are - themselves occurrences. With inc=True, they will be included in the - list, if they are found in the recurrence set. """ - if self._cache_complete: - gen = self._cache - else: - gen = self - started = False - l = [] - if inc: - for i in gen: - if i > before: - break - elif not started: - if i >= after: - started = True - l.append(i) - else: - l.append(i) - else: - for i in gen: - if i >= before: - break - elif not started: - if i > after: - started = True - l.append(i) - else: - l.append(i) - return l - - -class rrule(rrulebase): - """ - That's the base of the rrule operation. It accepts all the keywords - defined in the RFC as its constructor parameters (except byday, - which was renamed to byweekday) and more. The constructor prototype is:: - - rrule(freq) - - Where freq must be one of YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, - or SECONDLY. - - .. note:: - Per RFC section 3.3.10, recurrence instances falling on invalid dates - and times are ignored rather than coerced: - - Recurrence rules may generate recurrence instances with an invalid - date (e.g., February 30) or nonexistent local time (e.g., 1:30 AM - on a day where the local time is moved forward by an hour at 1:00 - AM). Such recurrence instances MUST be ignored and MUST NOT be - counted as part of the recurrence set. - - This can lead to possibly surprising behavior when, for example, the - start date occurs at the end of the month: - - >>> from dateutil.rrule import rrule, MONTHLY - >>> from datetime import datetime - >>> start_date = datetime(2014, 12, 31) - >>> list(rrule(freq=MONTHLY, count=4, dtstart=start_date)) - ... # doctest: +NORMALIZE_WHITESPACE - [datetime.datetime(2014, 12, 31, 0, 0), - datetime.datetime(2015, 1, 31, 0, 0), - datetime.datetime(2015, 3, 31, 0, 0), - datetime.datetime(2015, 5, 31, 0, 0)] - - Additionally, it supports the following keyword arguments: - - :param dtstart: - The recurrence start. Besides being the base for the recurrence, - missing parameters in the final recurrence instances will also be - extracted from this date. If not given, datetime.now() will be used - instead. - :param interval: - The interval between each freq iteration. For example, when using - YEARLY, an interval of 2 means once every two years, but with HOURLY, - it means once every two hours. The default interval is 1. - :param wkst: - The week start day. Must be one of the MO, TU, WE constants, or an - integer, specifying the first day of the week. This will affect - recurrences based on weekly periods. The default week start is got - from calendar.firstweekday(), and may be modified by - calendar.setfirstweekday(). - :param count: - If given, this determines how many occurrences will be generated. - - .. note:: - As of version 2.5.0, the use of the keyword ``until`` in conjunction - with ``count`` is deprecated, to make sure ``dateutil`` is fully - compliant with `RFC-5545 Sec. 3.3.10 `_. Therefore, ``until`` and ``count`` - **must not** occur in the same call to ``rrule``. - :param until: - If given, this must be a datetime instance specifying the upper-bound - limit of the recurrence. The last recurrence in the rule is the greatest - datetime that is less than or equal to the value specified in the - ``until`` parameter. - - .. note:: - As of version 2.5.0, the use of the keyword ``until`` in conjunction - with ``count`` is deprecated, to make sure ``dateutil`` is fully - compliant with `RFC-5545 Sec. 3.3.10 `_. Therefore, ``until`` and ``count`` - **must not** occur in the same call to ``rrule``. - :param bysetpos: - If given, it must be either an integer, or a sequence of integers, - positive or negative. Each given integer will specify an occurrence - number, corresponding to the nth occurrence of the rule inside the - frequency period. For example, a bysetpos of -1 if combined with a - MONTHLY frequency, and a byweekday of (MO, TU, WE, TH, FR), will - result in the last work day of every month. - :param bymonth: - If given, it must be either an integer, or a sequence of integers, - meaning the months to apply the recurrence to. - :param bymonthday: - If given, it must be either an integer, or a sequence of integers, - meaning the month days to apply the recurrence to. - :param byyearday: - If given, it must be either an integer, or a sequence of integers, - meaning the year days to apply the recurrence to. - :param byeaster: - If given, it must be either an integer, or a sequence of integers, - positive or negative. Each integer will define an offset from the - Easter Sunday. Passing the offset 0 to byeaster will yield the Easter - Sunday itself. This is an extension to the RFC specification. - :param byweekno: - If given, it must be either an integer, or a sequence of integers, - meaning the week numbers to apply the recurrence to. Week numbers - have the meaning described in ISO8601, that is, the first week of - the year is that containing at least four days of the new year. - :param byweekday: - If given, it must be either an integer (0 == MO), a sequence of - integers, one of the weekday constants (MO, TU, etc), or a sequence - of these constants. When given, these variables will define the - weekdays where the recurrence will be applied. It's also possible to - use an argument n for the weekday instances, which will mean the nth - occurrence of this weekday in the period. For example, with MONTHLY, - or with YEARLY and BYMONTH, using FR(+1) in byweekday will specify the - first friday of the month where the recurrence happens. Notice that in - the RFC documentation, this is specified as BYDAY, but was renamed to - avoid the ambiguity of that keyword. - :param byhour: - If given, it must be either an integer, or a sequence of integers, - meaning the hours to apply the recurrence to. - :param byminute: - If given, it must be either an integer, or a sequence of integers, - meaning the minutes to apply the recurrence to. - :param bysecond: - If given, it must be either an integer, or a sequence of integers, - meaning the seconds to apply the recurrence to. - :param cache: - If given, it must be a boolean value specifying to enable or disable - caching of results. If you will use the same rrule instance multiple - times, enabling caching will improve the performance considerably. - """ - def __init__(self, freq, dtstart=None, - interval=1, wkst=None, count=None, until=None, bysetpos=None, - bymonth=None, bymonthday=None, byyearday=None, byeaster=None, - byweekno=None, byweekday=None, - byhour=None, byminute=None, bysecond=None, - cache=False): - super(rrule, self).__init__(cache) - global easter - if not dtstart: - if until and until.tzinfo: - dtstart = datetime.datetime.now(tz=until.tzinfo).replace(microsecond=0) - else: - dtstart = datetime.datetime.now().replace(microsecond=0) - elif not isinstance(dtstart, datetime.datetime): - dtstart = datetime.datetime.fromordinal(dtstart.toordinal()) - else: - dtstart = dtstart.replace(microsecond=0) - self._dtstart = dtstart - self._tzinfo = dtstart.tzinfo - self._freq = freq - self._interval = interval - self._count = count - - # Cache the original byxxx rules, if they are provided, as the _byxxx - # attributes do not necessarily map to the inputs, and this can be - # a problem in generating the strings. Only store things if they've - # been supplied (the string retrieval will just use .get()) - self._original_rule = {} - - if until and not isinstance(until, datetime.datetime): - until = datetime.datetime.fromordinal(until.toordinal()) - self._until = until - - if self._dtstart and self._until: - if (self._dtstart.tzinfo is not None) != (self._until.tzinfo is not None): - # According to RFC5545 Section 3.3.10: - # https://tools.ietf.org/html/rfc5545#section-3.3.10 - # - # > If the "DTSTART" property is specified as a date with UTC - # > time or a date with local time and time zone reference, - # > then the UNTIL rule part MUST be specified as a date with - # > UTC time. - raise ValueError( - 'RRULE UNTIL values must be specified in UTC when DTSTART ' - 'is timezone-aware' - ) - - if count is not None and until: - warn("Using both 'count' and 'until' is inconsistent with RFC 5545" - " and has been deprecated in dateutil. Future versions will " - "raise an error.", DeprecationWarning) - - if wkst is None: - self._wkst = calendar.firstweekday() - elif isinstance(wkst, integer_types): - self._wkst = wkst - else: - self._wkst = wkst.weekday - - if bysetpos is None: - self._bysetpos = None - elif isinstance(bysetpos, integer_types): - if bysetpos == 0 or not (-366 <= bysetpos <= 366): - raise ValueError("bysetpos must be between 1 and 366, " - "or between -366 and -1") - self._bysetpos = (bysetpos,) - else: - self._bysetpos = tuple(bysetpos) - for pos in self._bysetpos: - if pos == 0 or not (-366 <= pos <= 366): - raise ValueError("bysetpos must be between 1 and 366, " - "or between -366 and -1") - - if self._bysetpos: - self._original_rule['bysetpos'] = self._bysetpos - - if (byweekno is None and byyearday is None and bymonthday is None and - byweekday is None and byeaster is None): - if freq == YEARLY: - if bymonth is None: - bymonth = dtstart.month - self._original_rule['bymonth'] = None - bymonthday = dtstart.day - self._original_rule['bymonthday'] = None - elif freq == MONTHLY: - bymonthday = dtstart.day - self._original_rule['bymonthday'] = None - elif freq == WEEKLY: - byweekday = dtstart.weekday() - self._original_rule['byweekday'] = None - - # bymonth - if bymonth is None: - self._bymonth = None - else: - if isinstance(bymonth, integer_types): - bymonth = (bymonth,) - - self._bymonth = tuple(sorted(set(bymonth))) - - if 'bymonth' not in self._original_rule: - self._original_rule['bymonth'] = self._bymonth - - # byyearday - if byyearday is None: - self._byyearday = None - else: - if isinstance(byyearday, integer_types): - byyearday = (byyearday,) - - self._byyearday = tuple(sorted(set(byyearday))) - self._original_rule['byyearday'] = self._byyearday - - # byeaster - if byeaster is not None: - if not easter: - from dateutil import easter - if isinstance(byeaster, integer_types): - self._byeaster = (byeaster,) - else: - self._byeaster = tuple(sorted(byeaster)) - - self._original_rule['byeaster'] = self._byeaster - else: - self._byeaster = None - - # bymonthday - if bymonthday is None: - self._bymonthday = () - self._bynmonthday = () - else: - if isinstance(bymonthday, integer_types): - bymonthday = (bymonthday,) - - bymonthday = set(bymonthday) # Ensure it's unique - - self._bymonthday = tuple(sorted(x for x in bymonthday if x > 0)) - self._bynmonthday = tuple(sorted(x for x in bymonthday if x < 0)) - - # Storing positive numbers first, then negative numbers - if 'bymonthday' not in self._original_rule: - self._original_rule['bymonthday'] = tuple( - itertools.chain(self._bymonthday, self._bynmonthday)) - - # byweekno - if byweekno is None: - self._byweekno = None - else: - if isinstance(byweekno, integer_types): - byweekno = (byweekno,) - - self._byweekno = tuple(sorted(set(byweekno))) - - self._original_rule['byweekno'] = self._byweekno - - # byweekday / bynweekday - if byweekday is None: - self._byweekday = None - self._bynweekday = None - else: - # If it's one of the valid non-sequence types, convert to a - # single-element sequence before the iterator that builds the - # byweekday set. - if isinstance(byweekday, integer_types) or hasattr(byweekday, "n"): - byweekday = (byweekday,) - - self._byweekday = set() - self._bynweekday = set() - for wday in byweekday: - if isinstance(wday, integer_types): - self._byweekday.add(wday) - elif not wday.n or freq > MONTHLY: - self._byweekday.add(wday.weekday) - else: - self._bynweekday.add((wday.weekday, wday.n)) - - if not self._byweekday: - self._byweekday = None - elif not self._bynweekday: - self._bynweekday = None - - if self._byweekday is not None: - self._byweekday = tuple(sorted(self._byweekday)) - orig_byweekday = [weekday(x) for x in self._byweekday] - else: - orig_byweekday = () - - if self._bynweekday is not None: - self._bynweekday = tuple(sorted(self._bynweekday)) - orig_bynweekday = [weekday(*x) for x in self._bynweekday] - else: - orig_bynweekday = () - - if 'byweekday' not in self._original_rule: - self._original_rule['byweekday'] = tuple(itertools.chain( - orig_byweekday, orig_bynweekday)) - - # byhour - if byhour is None: - if freq < HOURLY: - self._byhour = {dtstart.hour} - else: - self._byhour = None - else: - if isinstance(byhour, integer_types): - byhour = (byhour,) - - if freq == HOURLY: - self._byhour = self.__construct_byset(start=dtstart.hour, - byxxx=byhour, - base=24) - else: - self._byhour = set(byhour) - - self._byhour = tuple(sorted(self._byhour)) - self._original_rule['byhour'] = self._byhour - - # byminute - if byminute is None: - if freq < MINUTELY: - self._byminute = {dtstart.minute} - else: - self._byminute = None - else: - if isinstance(byminute, integer_types): - byminute = (byminute,) - - if freq == MINUTELY: - self._byminute = self.__construct_byset(start=dtstart.minute, - byxxx=byminute, - base=60) - else: - self._byminute = set(byminute) - - self._byminute = tuple(sorted(self._byminute)) - self._original_rule['byminute'] = self._byminute - - # bysecond - if bysecond is None: - if freq < SECONDLY: - self._bysecond = ((dtstart.second,)) - else: - self._bysecond = None - else: - if isinstance(bysecond, integer_types): - bysecond = (bysecond,) - - self._bysecond = set(bysecond) - - if freq == SECONDLY: - self._bysecond = self.__construct_byset(start=dtstart.second, - byxxx=bysecond, - base=60) - else: - self._bysecond = set(bysecond) - - self._bysecond = tuple(sorted(self._bysecond)) - self._original_rule['bysecond'] = self._bysecond - - if self._freq >= HOURLY: - self._timeset = None - else: - self._timeset = [] - for hour in self._byhour: - for minute in self._byminute: - for second in self._bysecond: - self._timeset.append( - datetime.time(hour, minute, second, - tzinfo=self._tzinfo)) - self._timeset.sort() - self._timeset = tuple(self._timeset) - - def __str__(self): - """ - Output a string that would generate this RRULE if passed to rrulestr. - This is mostly compatible with RFC5545, except for the - dateutil-specific extension BYEASTER. - """ - - output = [] - h, m, s = [None] * 3 - if self._dtstart: - output.append(self._dtstart.strftime('DTSTART:%Y%m%dT%H%M%S')) - h, m, s = self._dtstart.timetuple()[3:6] - - parts = ['FREQ=' + FREQNAMES[self._freq]] - if self._interval != 1: - parts.append('INTERVAL=' + str(self._interval)) - - if self._wkst: - parts.append('WKST=' + repr(weekday(self._wkst))[0:2]) - - if self._count is not None: - parts.append('COUNT=' + str(self._count)) - - if self._until: - parts.append(self._until.strftime('UNTIL=%Y%m%dT%H%M%S')) - - if self._original_rule.get('byweekday') is not None: - # The str() method on weekday objects doesn't generate - # RFC5545-compliant strings, so we should modify that. - original_rule = dict(self._original_rule) - wday_strings = [] - for wday in original_rule['byweekday']: - if wday.n: - wday_strings.append('{n:+d}{wday}'.format( - n=wday.n, - wday=repr(wday)[0:2])) - else: - wday_strings.append(repr(wday)) - - original_rule['byweekday'] = wday_strings - else: - original_rule = self._original_rule - - partfmt = '{name}={vals}' - for name, key in [('BYSETPOS', 'bysetpos'), - ('BYMONTH', 'bymonth'), - ('BYMONTHDAY', 'bymonthday'), - ('BYYEARDAY', 'byyearday'), - ('BYWEEKNO', 'byweekno'), - ('BYDAY', 'byweekday'), - ('BYHOUR', 'byhour'), - ('BYMINUTE', 'byminute'), - ('BYSECOND', 'bysecond'), - ('BYEASTER', 'byeaster')]: - value = original_rule.get(key) - if value: - parts.append(partfmt.format(name=name, vals=(','.join(str(v) - for v in value)))) - - output.append('RRULE:' + ';'.join(parts)) - return '\n'.join(output) - - def replace(self, **kwargs): - """Return new rrule with same attributes except for those attributes given new - values by whichever keyword arguments are specified.""" - new_kwargs = {"interval": self._interval, - "count": self._count, - "dtstart": self._dtstart, - "freq": self._freq, - "until": self._until, - "wkst": self._wkst, - "cache": False if self._cache is None else True } - new_kwargs.update(self._original_rule) - new_kwargs.update(kwargs) - return rrule(**new_kwargs) - - def _iter(self): - year, month, day, hour, minute, second, weekday, yearday, _ = \ - self._dtstart.timetuple() - - # Some local variables to speed things up a bit - freq = self._freq - interval = self._interval - wkst = self._wkst - until = self._until - bymonth = self._bymonth - byweekno = self._byweekno - byyearday = self._byyearday - byweekday = self._byweekday - byeaster = self._byeaster - bymonthday = self._bymonthday - bynmonthday = self._bynmonthday - bysetpos = self._bysetpos - byhour = self._byhour - byminute = self._byminute - bysecond = self._bysecond - - ii = _iterinfo(self) - ii.rebuild(year, month) - - getdayset = {YEARLY: ii.ydayset, - MONTHLY: ii.mdayset, - WEEKLY: ii.wdayset, - DAILY: ii.ddayset, - HOURLY: ii.ddayset, - MINUTELY: ii.ddayset, - SECONDLY: ii.ddayset}[freq] - - if freq < HOURLY: - timeset = self._timeset - else: - gettimeset = {HOURLY: ii.htimeset, - MINUTELY: ii.mtimeset, - SECONDLY: ii.stimeset}[freq] - if ((freq >= HOURLY and - self._byhour and hour not in self._byhour) or - (freq >= MINUTELY and - self._byminute and minute not in self._byminute) or - (freq >= SECONDLY and - self._bysecond and second not in self._bysecond)): - timeset = () - else: - timeset = gettimeset(hour, minute, second) - - total = 0 - count = self._count - while True: - # Get dayset with the right frequency - dayset, start, end = getdayset(year, month, day) - - # Do the "hard" work ;-) - filtered = False - for i in dayset[start:end]: - if ((bymonth and ii.mmask[i] not in bymonth) or - (byweekno and not ii.wnomask[i]) or - (byweekday and ii.wdaymask[i] not in byweekday) or - (ii.nwdaymask and not ii.nwdaymask[i]) or - (byeaster and not ii.eastermask[i]) or - ((bymonthday or bynmonthday) and - ii.mdaymask[i] not in bymonthday and - ii.nmdaymask[i] not in bynmonthday) or - (byyearday and - ((i < ii.yearlen and i+1 not in byyearday and - -ii.yearlen+i not in byyearday) or - (i >= ii.yearlen and i+1-ii.yearlen not in byyearday and - -ii.nextyearlen+i-ii.yearlen not in byyearday)))): - dayset[i] = None - filtered = True - - # Output results - if bysetpos and timeset: - poslist = [] - for pos in bysetpos: - if pos < 0: - daypos, timepos = divmod(pos, len(timeset)) - else: - daypos, timepos = divmod(pos-1, len(timeset)) - try: - i = [x for x in dayset[start:end] - if x is not None][daypos] - time = timeset[timepos] - except IndexError: - pass - else: - date = datetime.date.fromordinal(ii.yearordinal+i) - res = datetime.datetime.combine(date, time) - if res not in poslist: - poslist.append(res) - poslist.sort() - for res in poslist: - if until and res > until: - self._len = total - return - elif res >= self._dtstart: - if count is not None: - count -= 1 - if count < 0: - self._len = total - return - total += 1 - yield res - else: - for i in dayset[start:end]: - if i is not None: - date = datetime.date.fromordinal(ii.yearordinal + i) - for time in timeset: - res = datetime.datetime.combine(date, time) - if until and res > until: - self._len = total - return - elif res >= self._dtstart: - if count is not None: - count -= 1 - if count < 0: - self._len = total - return - - total += 1 - yield res - - # Handle frequency and interval - fixday = False - if freq == YEARLY: - year += interval - if year > datetime.MAXYEAR: - self._len = total - return - ii.rebuild(year, month) - elif freq == MONTHLY: - month += interval - if month > 12: - div, mod = divmod(month, 12) - month = mod - year += div - if month == 0: - month = 12 - year -= 1 - if year > datetime.MAXYEAR: - self._len = total - return - ii.rebuild(year, month) - elif freq == WEEKLY: - if wkst > weekday: - day += -(weekday+1+(6-wkst))+self._interval*7 - else: - day += -(weekday-wkst)+self._interval*7 - weekday = wkst - fixday = True - elif freq == DAILY: - day += interval - fixday = True - elif freq == HOURLY: - if filtered: - # Jump to one iteration before next day - hour += ((23-hour)//interval)*interval - - if byhour: - ndays, hour = self.__mod_distance(value=hour, - byxxx=self._byhour, - base=24) - else: - ndays, hour = divmod(hour+interval, 24) - - if ndays: - day += ndays - fixday = True - - timeset = gettimeset(hour, minute, second) - elif freq == MINUTELY: - if filtered: - # Jump to one iteration before next day - minute += ((1439-(hour*60+minute))//interval)*interval - - valid = False - rep_rate = (24*60) - for j in range(rep_rate // gcd(interval, rep_rate)): - if byminute: - nhours, minute = \ - self.__mod_distance(value=minute, - byxxx=self._byminute, - base=60) - else: - nhours, minute = divmod(minute+interval, 60) - - div, hour = divmod(hour+nhours, 24) - if div: - day += div - fixday = True - filtered = False - - if not byhour or hour in byhour: - valid = True - break - - if not valid: - raise ValueError('Invalid combination of interval and ' + - 'byhour resulting in empty rule.') - - timeset = gettimeset(hour, minute, second) - elif freq == SECONDLY: - if filtered: - # Jump to one iteration before next day - second += (((86399 - (hour * 3600 + minute * 60 + second)) - // interval) * interval) - - rep_rate = (24 * 3600) - valid = False - for j in range(0, rep_rate // gcd(interval, rep_rate)): - if bysecond: - nminutes, second = \ - self.__mod_distance(value=second, - byxxx=self._bysecond, - base=60) - else: - nminutes, second = divmod(second+interval, 60) - - div, minute = divmod(minute+nminutes, 60) - if div: - hour += div - div, hour = divmod(hour, 24) - if div: - day += div - fixday = True - - if ((not byhour or hour in byhour) and - (not byminute or minute in byminute) and - (not bysecond or second in bysecond)): - valid = True - break - - if not valid: - raise ValueError('Invalid combination of interval, ' + - 'byhour and byminute resulting in empty' + - ' rule.') - - timeset = gettimeset(hour, minute, second) - - if fixday and day > 28: - daysinmonth = calendar.monthrange(year, month)[1] - if day > daysinmonth: - while day > daysinmonth: - day -= daysinmonth - month += 1 - if month == 13: - month = 1 - year += 1 - if year > datetime.MAXYEAR: - self._len = total - return - daysinmonth = calendar.monthrange(year, month)[1] - ii.rebuild(year, month) - - def __construct_byset(self, start, byxxx, base): - """ - If a `BYXXX` sequence is passed to the constructor at the same level as - `FREQ` (e.g. `FREQ=HOURLY,BYHOUR={2,4,7},INTERVAL=3`), there are some - specifications which cannot be reached given some starting conditions. - - This occurs whenever the interval is not coprime with the base of a - given unit and the difference between the starting position and the - ending position is not coprime with the greatest common denominator - between the interval and the base. For example, with a FREQ of hourly - starting at 17:00 and an interval of 4, the only valid values for - BYHOUR would be {21, 1, 5, 9, 13, 17}, because 4 and 24 are not - coprime. - - :param start: - Specifies the starting position. - :param byxxx: - An iterable containing the list of allowed values. - :param base: - The largest allowable value for the specified frequency (e.g. - 24 hours, 60 minutes). - - This does not preserve the type of the iterable, returning a set, since - the values should be unique and the order is irrelevant, this will - speed up later lookups. - - In the event of an empty set, raises a :exception:`ValueError`, as this - results in an empty rrule. - """ - - cset = set() - - # Support a single byxxx value. - if isinstance(byxxx, integer_types): - byxxx = (byxxx, ) - - for num in byxxx: - i_gcd = gcd(self._interval, base) - # Use divmod rather than % because we need to wrap negative nums. - if i_gcd == 1 or divmod(num - start, i_gcd)[1] == 0: - cset.add(num) - - if len(cset) == 0: - raise ValueError("Invalid rrule byxxx generates an empty set.") - - return cset - - def __mod_distance(self, value, byxxx, base): - """ - Calculates the next value in a sequence where the `FREQ` parameter is - specified along with a `BYXXX` parameter at the same "level" - (e.g. `HOURLY` specified with `BYHOUR`). - - :param value: - The old value of the component. - :param byxxx: - The `BYXXX` set, which should have been generated by - `rrule._construct_byset`, or something else which checks that a - valid rule is present. - :param base: - The largest allowable value for the specified frequency (e.g. - 24 hours, 60 minutes). - - If a valid value is not found after `base` iterations (the maximum - number before the sequence would start to repeat), this raises a - :exception:`ValueError`, as no valid values were found. - - This returns a tuple of `divmod(n*interval, base)`, where `n` is the - smallest number of `interval` repetitions until the next specified - value in `byxxx` is found. - """ - accumulator = 0 - for ii in range(1, base + 1): - # Using divmod() over % to account for negative intervals - div, value = divmod(value + self._interval, base) - accumulator += div - if value in byxxx: - return (accumulator, value) - - -class _iterinfo(object): - __slots__ = ["rrule", "lastyear", "lastmonth", - "yearlen", "nextyearlen", "yearordinal", "yearweekday", - "mmask", "mrange", "mdaymask", "nmdaymask", - "wdaymask", "wnomask", "nwdaymask", "eastermask"] - - def __init__(self, rrule): - for attr in self.__slots__: - setattr(self, attr, None) - self.rrule = rrule - - def rebuild(self, year, month): - # Every mask is 7 days longer to handle cross-year weekly periods. - rr = self.rrule - if year != self.lastyear: - self.yearlen = 365 + calendar.isleap(year) - self.nextyearlen = 365 + calendar.isleap(year + 1) - firstyday = datetime.date(year, 1, 1) - self.yearordinal = firstyday.toordinal() - self.yearweekday = firstyday.weekday() - - wday = datetime.date(year, 1, 1).weekday() - if self.yearlen == 365: - self.mmask = M365MASK - self.mdaymask = MDAY365MASK - self.nmdaymask = NMDAY365MASK - self.wdaymask = WDAYMASK[wday:] - self.mrange = M365RANGE - else: - self.mmask = M366MASK - self.mdaymask = MDAY366MASK - self.nmdaymask = NMDAY366MASK - self.wdaymask = WDAYMASK[wday:] - self.mrange = M366RANGE - - if not rr._byweekno: - self.wnomask = None - else: - self.wnomask = [0]*(self.yearlen+7) - # no1wkst = firstwkst = self.wdaymask.index(rr._wkst) - no1wkst = firstwkst = (7-self.yearweekday+rr._wkst) % 7 - if no1wkst >= 4: - no1wkst = 0 - # Number of days in the year, plus the days we got - # from last year. - wyearlen = self.yearlen+(self.yearweekday-rr._wkst) % 7 - else: - # Number of days in the year, minus the days we - # left in last year. - wyearlen = self.yearlen-no1wkst - div, mod = divmod(wyearlen, 7) - numweeks = div+mod//4 - for n in rr._byweekno: - if n < 0: - n += numweeks+1 - if not (0 < n <= numweeks): - continue - if n > 1: - i = no1wkst+(n-1)*7 - if no1wkst != firstwkst: - i -= 7-firstwkst - else: - i = no1wkst - for j in range(7): - self.wnomask[i] = 1 - i += 1 - if self.wdaymask[i] == rr._wkst: - break - if 1 in rr._byweekno: - # Check week number 1 of next year as well - # TODO: Check -numweeks for next year. - i = no1wkst+numweeks*7 - if no1wkst != firstwkst: - i -= 7-firstwkst - if i < self.yearlen: - # If week starts in next year, we - # don't care about it. - for j in range(7): - self.wnomask[i] = 1 - i += 1 - if self.wdaymask[i] == rr._wkst: - break - if no1wkst: - # Check last week number of last year as - # well. If no1wkst is 0, either the year - # started on week start, or week number 1 - # got days from last year, so there are no - # days from last year's last week number in - # this year. - if -1 not in rr._byweekno: - lyearweekday = datetime.date(year-1, 1, 1).weekday() - lno1wkst = (7-lyearweekday+rr._wkst) % 7 - lyearlen = 365+calendar.isleap(year-1) - if lno1wkst >= 4: - lno1wkst = 0 - lnumweeks = 52+(lyearlen + - (lyearweekday-rr._wkst) % 7) % 7//4 - else: - lnumweeks = 52+(self.yearlen-no1wkst) % 7//4 - else: - lnumweeks = -1 - if lnumweeks in rr._byweekno: - for i in range(no1wkst): - self.wnomask[i] = 1 - - if (rr._bynweekday and (month != self.lastmonth or - year != self.lastyear)): - ranges = [] - if rr._freq == YEARLY: - if rr._bymonth: - for month in rr._bymonth: - ranges.append(self.mrange[month-1:month+1]) - else: - ranges = [(0, self.yearlen)] - elif rr._freq == MONTHLY: - ranges = [self.mrange[month-1:month+1]] - if ranges: - # Weekly frequency won't get here, so we may not - # care about cross-year weekly periods. - self.nwdaymask = [0]*self.yearlen - for first, last in ranges: - last -= 1 - for wday, n in rr._bynweekday: - if n < 0: - i = last+(n+1)*7 - i -= (self.wdaymask[i]-wday) % 7 - else: - i = first+(n-1)*7 - i += (7-self.wdaymask[i]+wday) % 7 - if first <= i <= last: - self.nwdaymask[i] = 1 - - if rr._byeaster: - self.eastermask = [0]*(self.yearlen+7) - eyday = easter.easter(year).toordinal()-self.yearordinal - for offset in rr._byeaster: - self.eastermask[eyday+offset] = 1 - - self.lastyear = year - self.lastmonth = month - - def ydayset(self, year, month, day): - return list(range(self.yearlen)), 0, self.yearlen - - def mdayset(self, year, month, day): - dset = [None]*self.yearlen - start, end = self.mrange[month-1:month+1] - for i in range(start, end): - dset[i] = i - return dset, start, end - - def wdayset(self, year, month, day): - # We need to handle cross-year weeks here. - dset = [None]*(self.yearlen+7) - i = datetime.date(year, month, day).toordinal()-self.yearordinal - start = i - for j in range(7): - dset[i] = i - i += 1 - # if (not (0 <= i < self.yearlen) or - # self.wdaymask[i] == self.rrule._wkst): - # This will cross the year boundary, if necessary. - if self.wdaymask[i] == self.rrule._wkst: - break - return dset, start, i - - def ddayset(self, year, month, day): - dset = [None] * self.yearlen - i = datetime.date(year, month, day).toordinal() - self.yearordinal - dset[i] = i - return dset, i, i + 1 - - def htimeset(self, hour, minute, second): - tset = [] - rr = self.rrule - for minute in rr._byminute: - for second in rr._bysecond: - tset.append(datetime.time(hour, minute, second, - tzinfo=rr._tzinfo)) - tset.sort() - return tset - - def mtimeset(self, hour, minute, second): - tset = [] - rr = self.rrule - for second in rr._bysecond: - tset.append(datetime.time(hour, minute, second, tzinfo=rr._tzinfo)) - tset.sort() - return tset - - def stimeset(self, hour, minute, second): - return (datetime.time(hour, minute, second, - tzinfo=self.rrule._tzinfo),) - - -class rruleset(rrulebase): - """ The rruleset type allows more complex recurrence setups, mixing - multiple rules, dates, exclusion rules, and exclusion dates. The type - constructor takes the following keyword arguments: - - :param cache: If True, caching of results will be enabled, improving - performance of multiple queries considerably. """ - - class _genitem(object): - def __init__(self, genlist, gen): - try: - self.dt = advance_iterator(gen) - genlist.append(self) - except StopIteration: - pass - self.genlist = genlist - self.gen = gen - - def __next__(self): - try: - self.dt = advance_iterator(self.gen) - except StopIteration: - if self.genlist[0] is self: - heapq.heappop(self.genlist) - else: - self.genlist.remove(self) - heapq.heapify(self.genlist) - - next = __next__ - - def __lt__(self, other): - return self.dt < other.dt - - def __gt__(self, other): - return self.dt > other.dt - - def __eq__(self, other): - return self.dt == other.dt - - def __ne__(self, other): - return self.dt != other.dt - - def __init__(self, cache=False): - super(rruleset, self).__init__(cache) - self._rrule = [] - self._rdate = [] - self._exrule = [] - self._exdate = [] - - @_invalidates_cache - def rrule(self, rrule): - """ Include the given :py:class:`rrule` instance in the recurrence set - generation. """ - self._rrule.append(rrule) - - @_invalidates_cache - def rdate(self, rdate): - """ Include the given :py:class:`datetime` instance in the recurrence - set generation. """ - self._rdate.append(rdate) - - @_invalidates_cache - def exrule(self, exrule): - """ Include the given rrule instance in the recurrence set exclusion - list. Dates which are part of the given recurrence rules will not - be generated, even if some inclusive rrule or rdate matches them. - """ - self._exrule.append(exrule) - - @_invalidates_cache - def exdate(self, exdate): - """ Include the given datetime instance in the recurrence set - exclusion list. Dates included that way will not be generated, - even if some inclusive rrule or rdate matches them. """ - self._exdate.append(exdate) - - def _iter(self): - rlist = [] - self._rdate.sort() - self._genitem(rlist, iter(self._rdate)) - for gen in [iter(x) for x in self._rrule]: - self._genitem(rlist, gen) - exlist = [] - self._exdate.sort() - self._genitem(exlist, iter(self._exdate)) - for gen in [iter(x) for x in self._exrule]: - self._genitem(exlist, gen) - lastdt = None - total = 0 - heapq.heapify(rlist) - heapq.heapify(exlist) - while rlist: - ritem = rlist[0] - if not lastdt or lastdt != ritem.dt: - while exlist and exlist[0] < ritem: - exitem = exlist[0] - advance_iterator(exitem) - if exlist and exlist[0] is exitem: - heapq.heapreplace(exlist, exitem) - if not exlist or ritem != exlist[0]: - total += 1 - yield ritem.dt - lastdt = ritem.dt - advance_iterator(ritem) - if rlist and rlist[0] is ritem: - heapq.heapreplace(rlist, ritem) - self._len = total - - - - -class _rrulestr(object): - """ Parses a string representation of a recurrence rule or set of - recurrence rules. - - :param s: - Required, a string defining one or more recurrence rules. - - :param dtstart: - If given, used as the default recurrence start if not specified in the - rule string. - - :param cache: - If set ``True`` caching of results will be enabled, improving - performance of multiple queries considerably. - - :param unfold: - If set ``True`` indicates that a rule string is split over more - than one line and should be joined before processing. - - :param forceset: - If set ``True`` forces a :class:`dateutil.rrule.rruleset` to - be returned. - - :param compatible: - If set ``True`` forces ``unfold`` and ``forceset`` to be ``True``. - - :param ignoretz: - If set ``True``, time zones in parsed strings are ignored and a naive - :class:`datetime.datetime` object is returned. - - :param tzids: - If given, a callable or mapping used to retrieve a - :class:`datetime.tzinfo` from a string representation. - Defaults to :func:`dateutil.tz.gettz`. - - :param tzinfos: - Additional time zone names / aliases which may be present in a string - representation. See :func:`dateutil.parser.parse` for more - information. - - :return: - Returns a :class:`dateutil.rrule.rruleset` or - :class:`dateutil.rrule.rrule` - """ - - _freq_map = {"YEARLY": YEARLY, - "MONTHLY": MONTHLY, - "WEEKLY": WEEKLY, - "DAILY": DAILY, - "HOURLY": HOURLY, - "MINUTELY": MINUTELY, - "SECONDLY": SECONDLY} - - _weekday_map = {"MO": 0, "TU": 1, "WE": 2, "TH": 3, - "FR": 4, "SA": 5, "SU": 6} - - def _handle_int(self, rrkwargs, name, value, **kwargs): - rrkwargs[name.lower()] = int(value) - - def _handle_int_list(self, rrkwargs, name, value, **kwargs): - rrkwargs[name.lower()] = [int(x) for x in value.split(',')] - - _handle_INTERVAL = _handle_int - _handle_COUNT = _handle_int - _handle_BYSETPOS = _handle_int_list - _handle_BYMONTH = _handle_int_list - _handle_BYMONTHDAY = _handle_int_list - _handle_BYYEARDAY = _handle_int_list - _handle_BYEASTER = _handle_int_list - _handle_BYWEEKNO = _handle_int_list - _handle_BYHOUR = _handle_int_list - _handle_BYMINUTE = _handle_int_list - _handle_BYSECOND = _handle_int_list - - def _handle_FREQ(self, rrkwargs, name, value, **kwargs): - rrkwargs["freq"] = self._freq_map[value] - - def _handle_UNTIL(self, rrkwargs, name, value, **kwargs): - global parser - if not parser: - from dateutil import parser - try: - rrkwargs["until"] = parser.parse(value, - ignoretz=kwargs.get("ignoretz"), - tzinfos=kwargs.get("tzinfos")) - except ValueError: - raise ValueError("invalid until date") - - def _handle_WKST(self, rrkwargs, name, value, **kwargs): - rrkwargs["wkst"] = self._weekday_map[value] - - def _handle_BYWEEKDAY(self, rrkwargs, name, value, **kwargs): - """ - Two ways to specify this: +1MO or MO(+1) - """ - l = [] - for wday in value.split(','): - if '(' in wday: - # If it's of the form TH(+1), etc. - splt = wday.split('(') - w = splt[0] - n = int(splt[1][:-1]) - elif len(wday): - # If it's of the form +1MO - for i in range(len(wday)): - if wday[i] not in '+-0123456789': - break - n = wday[:i] or None - w = wday[i:] - if n: - n = int(n) - else: - raise ValueError("Invalid (empty) BYDAY specification.") - - l.append(weekdays[self._weekday_map[w]](n)) - rrkwargs["byweekday"] = l - - _handle_BYDAY = _handle_BYWEEKDAY - - def _parse_rfc_rrule(self, line, - dtstart=None, - cache=False, - ignoretz=False, - tzinfos=None): - if line.find(':') != -1: - name, value = line.split(':') - if name != "RRULE": - raise ValueError("unknown parameter name") - else: - value = line - rrkwargs = {} - for pair in value.split(';'): - name, value = pair.split('=') - name = name.upper() - value = value.upper() - try: - getattr(self, "_handle_"+name)(rrkwargs, name, value, - ignoretz=ignoretz, - tzinfos=tzinfos) - except AttributeError: - raise ValueError("unknown parameter '%s'" % name) - except (KeyError, ValueError): - raise ValueError("invalid '%s': %s" % (name, value)) - return rrule(dtstart=dtstart, cache=cache, **rrkwargs) - - def _parse_date_value(self, date_value, parms, rule_tzids, - ignoretz, tzids, tzinfos): - global parser - if not parser: - from dateutil import parser - - datevals = [] - value_found = False - TZID = None - - for parm in parms: - if parm.startswith("TZID="): - try: - tzkey = rule_tzids[parm.split('TZID=')[-1]] - except KeyError: - continue - if tzids is None: - from . import tz - tzlookup = tz.gettz - elif callable(tzids): - tzlookup = tzids - else: - tzlookup = getattr(tzids, 'get', None) - if tzlookup is None: - msg = ('tzids must be a callable, mapping, or None, ' - 'not %s' % tzids) - raise ValueError(msg) - - TZID = tzlookup(tzkey) - continue - - # RFC 5445 3.8.2.4: The VALUE parameter is optional, but may be found - # only once. - if parm not in {"VALUE=DATE-TIME", "VALUE=DATE"}: - raise ValueError("unsupported parm: " + parm) - else: - if value_found: - msg = ("Duplicate value parameter found in: " + parm) - raise ValueError(msg) - value_found = True - - for datestr in date_value.split(','): - date = parser.parse(datestr, ignoretz=ignoretz, tzinfos=tzinfos) - if TZID is not None: - if date.tzinfo is None: - date = date.replace(tzinfo=TZID) - else: - raise ValueError('DTSTART/EXDATE specifies multiple timezone') - datevals.append(date) - - return datevals - - def _parse_rfc(self, s, - dtstart=None, - cache=False, - unfold=False, - forceset=False, - compatible=False, - ignoretz=False, - tzids=None, - tzinfos=None): - global parser - if compatible: - forceset = True - unfold = True - - TZID_NAMES = dict(map( - lambda x: (x.upper(), x), - re.findall('TZID=(?P[^:]+):', s) - )) - s = s.upper() - if not s.strip(): - raise ValueError("empty string") - if unfold: - lines = s.splitlines() - i = 0 - while i < len(lines): - line = lines[i].rstrip() - if not line: - del lines[i] - elif i > 0 and line[0] == " ": - lines[i-1] += line[1:] - del lines[i] - else: - i += 1 - else: - lines = s.split() - if (not forceset and len(lines) == 1 and (s.find(':') == -1 or - s.startswith('RRULE:'))): - return self._parse_rfc_rrule(lines[0], cache=cache, - dtstart=dtstart, ignoretz=ignoretz, - tzinfos=tzinfos) - else: - rrulevals = [] - rdatevals = [] - exrulevals = [] - exdatevals = [] - for line in lines: - if not line: - continue - if line.find(':') == -1: - name = "RRULE" - value = line - else: - name, value = line.split(':', 1) - parms = name.split(';') - if not parms: - raise ValueError("empty property name") - name = parms[0] - parms = parms[1:] - if name == "RRULE": - for parm in parms: - raise ValueError("unsupported RRULE parm: "+parm) - rrulevals.append(value) - elif name == "RDATE": - for parm in parms: - if parm != "VALUE=DATE-TIME": - raise ValueError("unsupported RDATE parm: "+parm) - rdatevals.append(value) - elif name == "EXRULE": - for parm in parms: - raise ValueError("unsupported EXRULE parm: "+parm) - exrulevals.append(value) - elif name == "EXDATE": - exdatevals.extend( - self._parse_date_value(value, parms, - TZID_NAMES, ignoretz, - tzids, tzinfos) - ) - elif name == "DTSTART": - dtvals = self._parse_date_value(value, parms, TZID_NAMES, - ignoretz, tzids, tzinfos) - if len(dtvals) != 1: - raise ValueError("Multiple DTSTART values specified:" + - value) - dtstart = dtvals[0] - else: - raise ValueError("unsupported property: "+name) - if (forceset or len(rrulevals) > 1 or rdatevals - or exrulevals or exdatevals): - if not parser and (rdatevals or exdatevals): - from dateutil import parser - rset = rruleset(cache=cache) - for value in rrulevals: - rset.rrule(self._parse_rfc_rrule(value, dtstart=dtstart, - ignoretz=ignoretz, - tzinfos=tzinfos)) - for value in rdatevals: - for datestr in value.split(','): - rset.rdate(parser.parse(datestr, - ignoretz=ignoretz, - tzinfos=tzinfos)) - for value in exrulevals: - rset.exrule(self._parse_rfc_rrule(value, dtstart=dtstart, - ignoretz=ignoretz, - tzinfos=tzinfos)) - for value in exdatevals: - rset.exdate(value) - if compatible and dtstart: - rset.rdate(dtstart) - return rset - else: - return self._parse_rfc_rrule(rrulevals[0], - dtstart=dtstart, - cache=cache, - ignoretz=ignoretz, - tzinfos=tzinfos) - - def __call__(self, s, **kwargs): - return self._parse_rfc(s, **kwargs) - - -rrulestr = _rrulestr() - -# vim:ts=4:sw=4:et diff --git a/apps/bitwarden_event_logs/lib/dateutil/tz/__init__.py b/apps/bitwarden_event_logs/lib/dateutil/tz/__init__.py deleted file mode 100755 index af1352c4..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/tz/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- -from .tz import * -from .tz import __doc__ - -__all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange", - "tzstr", "tzical", "tzwin", "tzwinlocal", "gettz", - "enfold", "datetime_ambiguous", "datetime_exists", - "resolve_imaginary", "UTC", "DeprecatedTzFormatWarning"] - - -class DeprecatedTzFormatWarning(Warning): - """Warning raised when time zones are parsed from deprecated formats.""" diff --git a/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/__init__.cpython-39.pyc b/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/__init__.cpython-39.pyc deleted file mode 100755 index a9c558fd..00000000 Binary files a/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/__init__.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/_common.cpython-39.pyc b/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/_common.cpython-39.pyc deleted file mode 100755 index 5abf9974..00000000 Binary files a/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/_common.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/_factories.cpython-39.pyc b/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/_factories.cpython-39.pyc deleted file mode 100755 index 50ffd133..00000000 Binary files a/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/_factories.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/tz.cpython-39.pyc b/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/tz.cpython-39.pyc deleted file mode 100755 index 0de52a40..00000000 Binary files a/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/tz.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/win.cpython-39.pyc b/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/win.cpython-39.pyc deleted file mode 100755 index 6f6f9c2d..00000000 Binary files a/apps/bitwarden_event_logs/lib/dateutil/tz/__pycache__/win.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/dateutil/tz/_common.py b/apps/bitwarden_event_logs/lib/dateutil/tz/_common.py deleted file mode 100755 index e6ac1183..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/tz/_common.py +++ /dev/null @@ -1,419 +0,0 @@ -from six import PY2 - -from functools import wraps - -from datetime import datetime, timedelta, tzinfo - - -ZERO = timedelta(0) - -__all__ = ['tzname_in_python2', 'enfold'] - - -def tzname_in_python2(namefunc): - """Change unicode output into bytestrings in Python 2 - - tzname() API changed in Python 3. It used to return bytes, but was changed - to unicode strings - """ - if PY2: - @wraps(namefunc) - def adjust_encoding(*args, **kwargs): - name = namefunc(*args, **kwargs) - if name is not None: - name = name.encode() - - return name - - return adjust_encoding - else: - return namefunc - - -# The following is adapted from Alexander Belopolsky's tz library -# https://github.com/abalkin/tz -if hasattr(datetime, 'fold'): - # This is the pre-python 3.6 fold situation - def enfold(dt, fold=1): - """ - Provides a unified interface for assigning the ``fold`` attribute to - datetimes both before and after the implementation of PEP-495. - - :param fold: - The value for the ``fold`` attribute in the returned datetime. This - should be either 0 or 1. - - :return: - Returns an object for which ``getattr(dt, 'fold', 0)`` returns - ``fold`` for all versions of Python. In versions prior to - Python 3.6, this is a ``_DatetimeWithFold`` object, which is a - subclass of :py:class:`datetime.datetime` with the ``fold`` - attribute added, if ``fold`` is 1. - - .. versionadded:: 2.6.0 - """ - return dt.replace(fold=fold) - -else: - class _DatetimeWithFold(datetime): - """ - This is a class designed to provide a PEP 495-compliant interface for - Python versions before 3.6. It is used only for dates in a fold, so - the ``fold`` attribute is fixed at ``1``. - - .. versionadded:: 2.6.0 - """ - __slots__ = () - - def replace(self, *args, **kwargs): - """ - Return a datetime with the same attributes, except for those - attributes given new values by whichever keyword arguments are - specified. Note that tzinfo=None can be specified to create a naive - datetime from an aware datetime with no conversion of date and time - data. - - This is reimplemented in ``_DatetimeWithFold`` because pypy3 will - return a ``datetime.datetime`` even if ``fold`` is unchanged. - """ - argnames = ( - 'year', 'month', 'day', 'hour', 'minute', 'second', - 'microsecond', 'tzinfo' - ) - - for arg, argname in zip(args, argnames): - if argname in kwargs: - raise TypeError('Duplicate argument: {}'.format(argname)) - - kwargs[argname] = arg - - for argname in argnames: - if argname not in kwargs: - kwargs[argname] = getattr(self, argname) - - dt_class = self.__class__ if kwargs.get('fold', 1) else datetime - - return dt_class(**kwargs) - - @property - def fold(self): - return 1 - - def enfold(dt, fold=1): - """ - Provides a unified interface for assigning the ``fold`` attribute to - datetimes both before and after the implementation of PEP-495. - - :param fold: - The value for the ``fold`` attribute in the returned datetime. This - should be either 0 or 1. - - :return: - Returns an object for which ``getattr(dt, 'fold', 0)`` returns - ``fold`` for all versions of Python. In versions prior to - Python 3.6, this is a ``_DatetimeWithFold`` object, which is a - subclass of :py:class:`datetime.datetime` with the ``fold`` - attribute added, if ``fold`` is 1. - - .. versionadded:: 2.6.0 - """ - if getattr(dt, 'fold', 0) == fold: - return dt - - args = dt.timetuple()[:6] - args += (dt.microsecond, dt.tzinfo) - - if fold: - return _DatetimeWithFold(*args) - else: - return datetime(*args) - - -def _validate_fromutc_inputs(f): - """ - The CPython version of ``fromutc`` checks that the input is a ``datetime`` - object and that ``self`` is attached as its ``tzinfo``. - """ - @wraps(f) - def fromutc(self, dt): - if not isinstance(dt, datetime): - raise TypeError("fromutc() requires a datetime argument") - if dt.tzinfo is not self: - raise ValueError("dt.tzinfo is not self") - - return f(self, dt) - - return fromutc - - -class _tzinfo(tzinfo): - """ - Base class for all ``dateutil`` ``tzinfo`` objects. - """ - - def is_ambiguous(self, dt): - """ - Whether or not the "wall time" of a given datetime is ambiguous in this - zone. - - :param dt: - A :py:class:`datetime.datetime`, naive or time zone aware. - - - :return: - Returns ``True`` if ambiguous, ``False`` otherwise. - - .. versionadded:: 2.6.0 - """ - - dt = dt.replace(tzinfo=self) - - wall_0 = enfold(dt, fold=0) - wall_1 = enfold(dt, fold=1) - - same_offset = wall_0.utcoffset() == wall_1.utcoffset() - same_dt = wall_0.replace(tzinfo=None) == wall_1.replace(tzinfo=None) - - return same_dt and not same_offset - - def _fold_status(self, dt_utc, dt_wall): - """ - Determine the fold status of a "wall" datetime, given a representation - of the same datetime as a (naive) UTC datetime. This is calculated based - on the assumption that ``dt.utcoffset() - dt.dst()`` is constant for all - datetimes, and that this offset is the actual number of hours separating - ``dt_utc`` and ``dt_wall``. - - :param dt_utc: - Representation of the datetime as UTC - - :param dt_wall: - Representation of the datetime as "wall time". This parameter must - either have a `fold` attribute or have a fold-naive - :class:`datetime.tzinfo` attached, otherwise the calculation may - fail. - """ - if self.is_ambiguous(dt_wall): - delta_wall = dt_wall - dt_utc - _fold = int(delta_wall == (dt_utc.utcoffset() - dt_utc.dst())) - else: - _fold = 0 - - return _fold - - def _fold(self, dt): - return getattr(dt, 'fold', 0) - - def _fromutc(self, dt): - """ - Given a timezone-aware datetime in a given timezone, calculates a - timezone-aware datetime in a new timezone. - - Since this is the one time that we *know* we have an unambiguous - datetime object, we take this opportunity to determine whether the - datetime is ambiguous and in a "fold" state (e.g. if it's the first - occurrence, chronologically, of the ambiguous datetime). - - :param dt: - A timezone-aware :class:`datetime.datetime` object. - """ - - # Re-implement the algorithm from Python's datetime.py - dtoff = dt.utcoffset() - if dtoff is None: - raise ValueError("fromutc() requires a non-None utcoffset() " - "result") - - # The original datetime.py code assumes that `dst()` defaults to - # zero during ambiguous times. PEP 495 inverts this presumption, so - # for pre-PEP 495 versions of python, we need to tweak the algorithm. - dtdst = dt.dst() - if dtdst is None: - raise ValueError("fromutc() requires a non-None dst() result") - delta = dtoff - dtdst - - dt += delta - # Set fold=1 so we can default to being in the fold for - # ambiguous dates. - dtdst = enfold(dt, fold=1).dst() - if dtdst is None: - raise ValueError("fromutc(): dt.dst gave inconsistent " - "results; cannot convert") - return dt + dtdst - - @_validate_fromutc_inputs - def fromutc(self, dt): - """ - Given a timezone-aware datetime in a given timezone, calculates a - timezone-aware datetime in a new timezone. - - Since this is the one time that we *know* we have an unambiguous - datetime object, we take this opportunity to determine whether the - datetime is ambiguous and in a "fold" state (e.g. if it's the first - occurrence, chronologically, of the ambiguous datetime). - - :param dt: - A timezone-aware :class:`datetime.datetime` object. - """ - dt_wall = self._fromutc(dt) - - # Calculate the fold status given the two datetimes. - _fold = self._fold_status(dt, dt_wall) - - # Set the default fold value for ambiguous dates - return enfold(dt_wall, fold=_fold) - - -class tzrangebase(_tzinfo): - """ - This is an abstract base class for time zones represented by an annual - transition into and out of DST. Child classes should implement the following - methods: - - * ``__init__(self, *args, **kwargs)`` - * ``transitions(self, year)`` - this is expected to return a tuple of - datetimes representing the DST on and off transitions in standard - time. - - A fully initialized ``tzrangebase`` subclass should also provide the - following attributes: - * ``hasdst``: Boolean whether or not the zone uses DST. - * ``_dst_offset`` / ``_std_offset``: :class:`datetime.timedelta` objects - representing the respective UTC offsets. - * ``_dst_abbr`` / ``_std_abbr``: Strings representing the timezone short - abbreviations in DST and STD, respectively. - * ``_hasdst``: Whether or not the zone has DST. - - .. versionadded:: 2.6.0 - """ - def __init__(self): - raise NotImplementedError('tzrangebase is an abstract base class') - - def utcoffset(self, dt): - isdst = self._isdst(dt) - - if isdst is None: - return None - elif isdst: - return self._dst_offset - else: - return self._std_offset - - def dst(self, dt): - isdst = self._isdst(dt) - - if isdst is None: - return None - elif isdst: - return self._dst_base_offset - else: - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - if self._isdst(dt): - return self._dst_abbr - else: - return self._std_abbr - - def fromutc(self, dt): - """ Given a datetime in UTC, return local time """ - if not isinstance(dt, datetime): - raise TypeError("fromutc() requires a datetime argument") - - if dt.tzinfo is not self: - raise ValueError("dt.tzinfo is not self") - - # Get transitions - if there are none, fixed offset - transitions = self.transitions(dt.year) - if transitions is None: - return dt + self.utcoffset(dt) - - # Get the transition times in UTC - dston, dstoff = transitions - - dston -= self._std_offset - dstoff -= self._std_offset - - utc_transitions = (dston, dstoff) - dt_utc = dt.replace(tzinfo=None) - - isdst = self._naive_isdst(dt_utc, utc_transitions) - - if isdst: - dt_wall = dt + self._dst_offset - else: - dt_wall = dt + self._std_offset - - _fold = int(not isdst and self.is_ambiguous(dt_wall)) - - return enfold(dt_wall, fold=_fold) - - def is_ambiguous(self, dt): - """ - Whether or not the "wall time" of a given datetime is ambiguous in this - zone. - - :param dt: - A :py:class:`datetime.datetime`, naive or time zone aware. - - - :return: - Returns ``True`` if ambiguous, ``False`` otherwise. - - .. versionadded:: 2.6.0 - """ - if not self.hasdst: - return False - - start, end = self.transitions(dt.year) - - dt = dt.replace(tzinfo=None) - return (end <= dt < end + self._dst_base_offset) - - def _isdst(self, dt): - if not self.hasdst: - return False - elif dt is None: - return None - - transitions = self.transitions(dt.year) - - if transitions is None: - return False - - dt = dt.replace(tzinfo=None) - - isdst = self._naive_isdst(dt, transitions) - - # Handle ambiguous dates - if not isdst and self.is_ambiguous(dt): - return not self._fold(dt) - else: - return isdst - - def _naive_isdst(self, dt, transitions): - dston, dstoff = transitions - - dt = dt.replace(tzinfo=None) - - if dston < dstoff: - isdst = dston <= dt < dstoff - else: - isdst = not dstoff <= dt < dston - - return isdst - - @property - def _dst_base_offset(self): - return self._dst_offset - self._std_offset - - __hash__ = None - - def __ne__(self, other): - return not (self == other) - - def __repr__(self): - return "%s(...)" % self.__class__.__name__ - - __reduce__ = object.__reduce__ diff --git a/apps/bitwarden_event_logs/lib/dateutil/tz/_factories.py b/apps/bitwarden_event_logs/lib/dateutil/tz/_factories.py deleted file mode 100755 index f8a65891..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/tz/_factories.py +++ /dev/null @@ -1,80 +0,0 @@ -from datetime import timedelta -import weakref -from collections import OrderedDict - -from six.moves import _thread - - -class _TzSingleton(type): - def __init__(cls, *args, **kwargs): - cls.__instance = None - super(_TzSingleton, cls).__init__(*args, **kwargs) - - def __call__(cls): - if cls.__instance is None: - cls.__instance = super(_TzSingleton, cls).__call__() - return cls.__instance - - -class _TzFactory(type): - def instance(cls, *args, **kwargs): - """Alternate constructor that returns a fresh instance""" - return type.__call__(cls, *args, **kwargs) - - -class _TzOffsetFactory(_TzFactory): - def __init__(cls, *args, **kwargs): - cls.__instances = weakref.WeakValueDictionary() - cls.__strong_cache = OrderedDict() - cls.__strong_cache_size = 8 - - cls._cache_lock = _thread.allocate_lock() - - def __call__(cls, name, offset): - if isinstance(offset, timedelta): - key = (name, offset.total_seconds()) - else: - key = (name, offset) - - instance = cls.__instances.get(key, None) - if instance is None: - instance = cls.__instances.setdefault(key, - cls.instance(name, offset)) - - # This lock may not be necessary in Python 3. See GH issue #901 - with cls._cache_lock: - cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) - - # Remove an item if the strong cache is overpopulated - if len(cls.__strong_cache) > cls.__strong_cache_size: - cls.__strong_cache.popitem(last=False) - - return instance - - -class _TzStrFactory(_TzFactory): - def __init__(cls, *args, **kwargs): - cls.__instances = weakref.WeakValueDictionary() - cls.__strong_cache = OrderedDict() - cls.__strong_cache_size = 8 - - cls.__cache_lock = _thread.allocate_lock() - - def __call__(cls, s, posix_offset=False): - key = (s, posix_offset) - instance = cls.__instances.get(key, None) - - if instance is None: - instance = cls.__instances.setdefault(key, - cls.instance(s, posix_offset)) - - # This lock may not be necessary in Python 3. See GH issue #901 - with cls.__cache_lock: - cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) - - # Remove an item if the strong cache is overpopulated - if len(cls.__strong_cache) > cls.__strong_cache_size: - cls.__strong_cache.popitem(last=False) - - return instance - diff --git a/apps/bitwarden_event_logs/lib/dateutil/tz/tz.py b/apps/bitwarden_event_logs/lib/dateutil/tz/tz.py deleted file mode 100755 index 61759144..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/tz/tz.py +++ /dev/null @@ -1,1849 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module offers timezone implementations subclassing the abstract -:py:class:`datetime.tzinfo` type. There are classes to handle tzfile format -files (usually are in :file:`/etc/localtime`, :file:`/usr/share/zoneinfo`, -etc), TZ environment string (in all known formats), given ranges (with help -from relative deltas), local machine timezone, fixed offset timezone, and UTC -timezone. -""" -import datetime -import struct -import time -import sys -import os -import bisect -import weakref -from collections import OrderedDict - -import six -from six import string_types -from six.moves import _thread -from ._common import tzname_in_python2, _tzinfo -from ._common import tzrangebase, enfold -from ._common import _validate_fromutc_inputs - -from ._factories import _TzSingleton, _TzOffsetFactory -from ._factories import _TzStrFactory -try: - from .win import tzwin, tzwinlocal -except ImportError: - tzwin = tzwinlocal = None - -# For warning about rounding tzinfo -from warnings import warn - -ZERO = datetime.timedelta(0) -EPOCH = datetime.datetime(1970, 1, 1, 0, 0) -EPOCHORDINAL = EPOCH.toordinal() - - -@six.add_metaclass(_TzSingleton) -class tzutc(datetime.tzinfo): - """ - This is a tzinfo object that represents the UTC time zone. - - **Examples:** - - .. doctest:: - - >>> from datetime import * - >>> from dateutil.tz import * - - >>> datetime.now() - datetime.datetime(2003, 9, 27, 9, 40, 1, 521290) - - >>> datetime.now(tzutc()) - datetime.datetime(2003, 9, 27, 12, 40, 12, 156379, tzinfo=tzutc()) - - >>> datetime.now(tzutc()).tzname() - 'UTC' - - .. versionchanged:: 2.7.0 - ``tzutc()`` is now a singleton, so the result of ``tzutc()`` will - always return the same object. - - .. doctest:: - - >>> from dateutil.tz import tzutc, UTC - >>> tzutc() is tzutc() - True - >>> tzutc() is UTC - True - """ - def utcoffset(self, dt): - return ZERO - - def dst(self, dt): - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - return "UTC" - - def is_ambiguous(self, dt): - """ - Whether or not the "wall time" of a given datetime is ambiguous in this - zone. - - :param dt: - A :py:class:`datetime.datetime`, naive or time zone aware. - - - :return: - Returns ``True`` if ambiguous, ``False`` otherwise. - - .. versionadded:: 2.6.0 - """ - return False - - @_validate_fromutc_inputs - def fromutc(self, dt): - """ - Fast track version of fromutc() returns the original ``dt`` object for - any valid :py:class:`datetime.datetime` object. - """ - return dt - - def __eq__(self, other): - if not isinstance(other, (tzutc, tzoffset)): - return NotImplemented - - return (isinstance(other, tzutc) or - (isinstance(other, tzoffset) and other._offset == ZERO)) - - __hash__ = None - - def __ne__(self, other): - return not (self == other) - - def __repr__(self): - return "%s()" % self.__class__.__name__ - - __reduce__ = object.__reduce__ - - -#: Convenience constant providing a :class:`tzutc()` instance -#: -#: .. versionadded:: 2.7.0 -UTC = tzutc() - - -@six.add_metaclass(_TzOffsetFactory) -class tzoffset(datetime.tzinfo): - """ - A simple class for representing a fixed offset from UTC. - - :param name: - The timezone name, to be returned when ``tzname()`` is called. - :param offset: - The time zone offset in seconds, or (since version 2.6.0, represented - as a :py:class:`datetime.timedelta` object). - """ - def __init__(self, name, offset): - self._name = name - - try: - # Allow a timedelta - offset = offset.total_seconds() - except (TypeError, AttributeError): - pass - - self._offset = datetime.timedelta(seconds=_get_supported_offset(offset)) - - def utcoffset(self, dt): - return self._offset - - def dst(self, dt): - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - return self._name - - @_validate_fromutc_inputs - def fromutc(self, dt): - return dt + self._offset - - def is_ambiguous(self, dt): - """ - Whether or not the "wall time" of a given datetime is ambiguous in this - zone. - - :param dt: - A :py:class:`datetime.datetime`, naive or time zone aware. - :return: - Returns ``True`` if ambiguous, ``False`` otherwise. - - .. versionadded:: 2.6.0 - """ - return False - - def __eq__(self, other): - if not isinstance(other, tzoffset): - return NotImplemented - - return self._offset == other._offset - - __hash__ = None - - def __ne__(self, other): - return not (self == other) - - def __repr__(self): - return "%s(%s, %s)" % (self.__class__.__name__, - repr(self._name), - int(self._offset.total_seconds())) - - __reduce__ = object.__reduce__ - - -class tzlocal(_tzinfo): - """ - A :class:`tzinfo` subclass built around the ``time`` timezone functions. - """ - def __init__(self): - super(tzlocal, self).__init__() - - self._std_offset = datetime.timedelta(seconds=-time.timezone) - if time.daylight: - self._dst_offset = datetime.timedelta(seconds=-time.altzone) - else: - self._dst_offset = self._std_offset - - self._dst_saved = self._dst_offset - self._std_offset - self._hasdst = bool(self._dst_saved) - self._tznames = tuple(time.tzname) - - def utcoffset(self, dt): - if dt is None and self._hasdst: - return None - - if self._isdst(dt): - return self._dst_offset - else: - return self._std_offset - - def dst(self, dt): - if dt is None and self._hasdst: - return None - - if self._isdst(dt): - return self._dst_offset - self._std_offset - else: - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - return self._tznames[self._isdst(dt)] - - def is_ambiguous(self, dt): - """ - Whether or not the "wall time" of a given datetime is ambiguous in this - zone. - - :param dt: - A :py:class:`datetime.datetime`, naive or time zone aware. - - - :return: - Returns ``True`` if ambiguous, ``False`` otherwise. - - .. versionadded:: 2.6.0 - """ - naive_dst = self._naive_is_dst(dt) - return (not naive_dst and - (naive_dst != self._naive_is_dst(dt - self._dst_saved))) - - def _naive_is_dst(self, dt): - timestamp = _datetime_to_timestamp(dt) - return time.localtime(timestamp + time.timezone).tm_isdst - - def _isdst(self, dt, fold_naive=True): - # We can't use mktime here. It is unstable when deciding if - # the hour near to a change is DST or not. - # - # timestamp = time.mktime((dt.year, dt.month, dt.day, dt.hour, - # dt.minute, dt.second, dt.weekday(), 0, -1)) - # return time.localtime(timestamp).tm_isdst - # - # The code above yields the following result: - # - # >>> import tz, datetime - # >>> t = tz.tzlocal() - # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() - # 'BRDT' - # >>> datetime.datetime(2003,2,16,0,tzinfo=t).tzname() - # 'BRST' - # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() - # 'BRST' - # >>> datetime.datetime(2003,2,15,22,tzinfo=t).tzname() - # 'BRDT' - # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() - # 'BRDT' - # - # Here is a more stable implementation: - # - if not self._hasdst: - return False - - # Check for ambiguous times: - dstval = self._naive_is_dst(dt) - fold = getattr(dt, 'fold', None) - - if self.is_ambiguous(dt): - if fold is not None: - return not self._fold(dt) - else: - return True - - return dstval - - def __eq__(self, other): - if isinstance(other, tzlocal): - return (self._std_offset == other._std_offset and - self._dst_offset == other._dst_offset) - elif isinstance(other, tzutc): - return (not self._hasdst and - self._tznames[0] in {'UTC', 'GMT'} and - self._std_offset == ZERO) - elif isinstance(other, tzoffset): - return (not self._hasdst and - self._tznames[0] == other._name and - self._std_offset == other._offset) - else: - return NotImplemented - - __hash__ = None - - def __ne__(self, other): - return not (self == other) - - def __repr__(self): - return "%s()" % self.__class__.__name__ - - __reduce__ = object.__reduce__ - - -class _ttinfo(object): - __slots__ = ["offset", "delta", "isdst", "abbr", - "isstd", "isgmt", "dstoffset"] - - def __init__(self): - for attr in self.__slots__: - setattr(self, attr, None) - - def __repr__(self): - l = [] - for attr in self.__slots__: - value = getattr(self, attr) - if value is not None: - l.append("%s=%s" % (attr, repr(value))) - return "%s(%s)" % (self.__class__.__name__, ", ".join(l)) - - def __eq__(self, other): - if not isinstance(other, _ttinfo): - return NotImplemented - - return (self.offset == other.offset and - self.delta == other.delta and - self.isdst == other.isdst and - self.abbr == other.abbr and - self.isstd == other.isstd and - self.isgmt == other.isgmt and - self.dstoffset == other.dstoffset) - - __hash__ = None - - def __ne__(self, other): - return not (self == other) - - def __getstate__(self): - state = {} - for name in self.__slots__: - state[name] = getattr(self, name, None) - return state - - def __setstate__(self, state): - for name in self.__slots__: - if name in state: - setattr(self, name, state[name]) - - -class _tzfile(object): - """ - Lightweight class for holding the relevant transition and time zone - information read from binary tzfiles. - """ - attrs = ['trans_list', 'trans_list_utc', 'trans_idx', 'ttinfo_list', - 'ttinfo_std', 'ttinfo_dst', 'ttinfo_before', 'ttinfo_first'] - - def __init__(self, **kwargs): - for attr in self.attrs: - setattr(self, attr, kwargs.get(attr, None)) - - -class tzfile(_tzinfo): - """ - This is a ``tzinfo`` subclass that allows one to use the ``tzfile(5)`` - format timezone files to extract current and historical zone information. - - :param fileobj: - This can be an opened file stream or a file name that the time zone - information can be read from. - - :param filename: - This is an optional parameter specifying the source of the time zone - information in the event that ``fileobj`` is a file object. If omitted - and ``fileobj`` is a file stream, this parameter will be set either to - ``fileobj``'s ``name`` attribute or to ``repr(fileobj)``. - - See `Sources for Time Zone and Daylight Saving Time Data - `_ for more information. - Time zone files can be compiled from the `IANA Time Zone database files - `_ with the `zic time zone compiler - `_ - - .. note:: - - Only construct a ``tzfile`` directly if you have a specific timezone - file on disk that you want to read into a Python ``tzinfo`` object. - If you want to get a ``tzfile`` representing a specific IANA zone, - (e.g. ``'America/New_York'``), you should call - :func:`dateutil.tz.gettz` with the zone identifier. - - - **Examples:** - - Using the US Eastern time zone as an example, we can see that a ``tzfile`` - provides time zone information for the standard Daylight Saving offsets: - - .. testsetup:: tzfile - - from dateutil.tz import gettz - from datetime import datetime - - .. doctest:: tzfile - - >>> NYC = gettz('America/New_York') - >>> NYC - tzfile('/usr/share/zoneinfo/America/New_York') - - >>> print(datetime(2016, 1, 3, tzinfo=NYC)) # EST - 2016-01-03 00:00:00-05:00 - - >>> print(datetime(2016, 7, 7, tzinfo=NYC)) # EDT - 2016-07-07 00:00:00-04:00 - - - The ``tzfile`` structure contains a fully history of the time zone, - so historical dates will also have the right offsets. For example, before - the adoption of the UTC standards, New York used local solar mean time: - - .. doctest:: tzfile - - >>> print(datetime(1901, 4, 12, tzinfo=NYC)) # LMT - 1901-04-12 00:00:00-04:56 - - And during World War II, New York was on "Eastern War Time", which was a - state of permanent daylight saving time: - - .. doctest:: tzfile - - >>> print(datetime(1944, 2, 7, tzinfo=NYC)) # EWT - 1944-02-07 00:00:00-04:00 - - """ - - def __init__(self, fileobj, filename=None): - super(tzfile, self).__init__() - - file_opened_here = False - if isinstance(fileobj, string_types): - self._filename = fileobj - fileobj = open(fileobj, 'rb') - file_opened_here = True - elif filename is not None: - self._filename = filename - elif hasattr(fileobj, "name"): - self._filename = fileobj.name - else: - self._filename = repr(fileobj) - - if fileobj is not None: - if not file_opened_here: - fileobj = _nullcontext(fileobj) - - with fileobj as file_stream: - tzobj = self._read_tzfile(file_stream) - - self._set_tzdata(tzobj) - - def _set_tzdata(self, tzobj): - """ Set the time zone data of this object from a _tzfile object """ - # Copy the relevant attributes over as private attributes - for attr in _tzfile.attrs: - setattr(self, '_' + attr, getattr(tzobj, attr)) - - def _read_tzfile(self, fileobj): - out = _tzfile() - - # From tzfile(5): - # - # The time zone information files used by tzset(3) - # begin with the magic characters "TZif" to identify - # them as time zone information files, followed by - # sixteen bytes reserved for future use, followed by - # six four-byte values of type long, written in a - # ``standard'' byte order (the high-order byte - # of the value is written first). - if fileobj.read(4).decode() != "TZif": - raise ValueError("magic not found") - - fileobj.read(16) - - ( - # The number of UTC/local indicators stored in the file. - ttisgmtcnt, - - # The number of standard/wall indicators stored in the file. - ttisstdcnt, - - # The number of leap seconds for which data is - # stored in the file. - leapcnt, - - # The number of "transition times" for which data - # is stored in the file. - timecnt, - - # The number of "local time types" for which data - # is stored in the file (must not be zero). - typecnt, - - # The number of characters of "time zone - # abbreviation strings" stored in the file. - charcnt, - - ) = struct.unpack(">6l", fileobj.read(24)) - - # The above header is followed by tzh_timecnt four-byte - # values of type long, sorted in ascending order. - # These values are written in ``standard'' byte order. - # Each is used as a transition time (as returned by - # time(2)) at which the rules for computing local time - # change. - - if timecnt: - out.trans_list_utc = list(struct.unpack(">%dl" % timecnt, - fileobj.read(timecnt*4))) - else: - out.trans_list_utc = [] - - # Next come tzh_timecnt one-byte values of type unsigned - # char; each one tells which of the different types of - # ``local time'' types described in the file is associated - # with the same-indexed transition time. These values - # serve as indices into an array of ttinfo structures that - # appears next in the file. - - if timecnt: - out.trans_idx = struct.unpack(">%dB" % timecnt, - fileobj.read(timecnt)) - else: - out.trans_idx = [] - - # Each ttinfo structure is written as a four-byte value - # for tt_gmtoff of type long, in a standard byte - # order, followed by a one-byte value for tt_isdst - # and a one-byte value for tt_abbrind. In each - # structure, tt_gmtoff gives the number of - # seconds to be added to UTC, tt_isdst tells whether - # tm_isdst should be set by localtime(3), and - # tt_abbrind serves as an index into the array of - # time zone abbreviation characters that follow the - # ttinfo structure(s) in the file. - - ttinfo = [] - - for i in range(typecnt): - ttinfo.append(struct.unpack(">lbb", fileobj.read(6))) - - abbr = fileobj.read(charcnt).decode() - - # Then there are tzh_leapcnt pairs of four-byte - # values, written in standard byte order; the - # first value of each pair gives the time (as - # returned by time(2)) at which a leap second - # occurs; the second gives the total number of - # leap seconds to be applied after the given time. - # The pairs of values are sorted in ascending order - # by time. - - # Not used, for now (but seek for correct file position) - if leapcnt: - fileobj.seek(leapcnt * 8, os.SEEK_CUR) - - # Then there are tzh_ttisstdcnt standard/wall - # indicators, each stored as a one-byte value; - # they tell whether the transition times associated - # with local time types were specified as standard - # time or wall clock time, and are used when - # a time zone file is used in handling POSIX-style - # time zone environment variables. - - if ttisstdcnt: - isstd = struct.unpack(">%db" % ttisstdcnt, - fileobj.read(ttisstdcnt)) - - # Finally, there are tzh_ttisgmtcnt UTC/local - # indicators, each stored as a one-byte value; - # they tell whether the transition times associated - # with local time types were specified as UTC or - # local time, and are used when a time zone file - # is used in handling POSIX-style time zone envi- - # ronment variables. - - if ttisgmtcnt: - isgmt = struct.unpack(">%db" % ttisgmtcnt, - fileobj.read(ttisgmtcnt)) - - # Build ttinfo list - out.ttinfo_list = [] - for i in range(typecnt): - gmtoff, isdst, abbrind = ttinfo[i] - gmtoff = _get_supported_offset(gmtoff) - tti = _ttinfo() - tti.offset = gmtoff - tti.dstoffset = datetime.timedelta(0) - tti.delta = datetime.timedelta(seconds=gmtoff) - tti.isdst = isdst - tti.abbr = abbr[abbrind:abbr.find('\x00', abbrind)] - tti.isstd = (ttisstdcnt > i and isstd[i] != 0) - tti.isgmt = (ttisgmtcnt > i and isgmt[i] != 0) - out.ttinfo_list.append(tti) - - # Replace ttinfo indexes for ttinfo objects. - out.trans_idx = [out.ttinfo_list[idx] for idx in out.trans_idx] - - # Set standard, dst, and before ttinfos. before will be - # used when a given time is before any transitions, - # and will be set to the first non-dst ttinfo, or to - # the first dst, if all of them are dst. - out.ttinfo_std = None - out.ttinfo_dst = None - out.ttinfo_before = None - if out.ttinfo_list: - if not out.trans_list_utc: - out.ttinfo_std = out.ttinfo_first = out.ttinfo_list[0] - else: - for i in range(timecnt-1, -1, -1): - tti = out.trans_idx[i] - if not out.ttinfo_std and not tti.isdst: - out.ttinfo_std = tti - elif not out.ttinfo_dst and tti.isdst: - out.ttinfo_dst = tti - - if out.ttinfo_std and out.ttinfo_dst: - break - else: - if out.ttinfo_dst and not out.ttinfo_std: - out.ttinfo_std = out.ttinfo_dst - - for tti in out.ttinfo_list: - if not tti.isdst: - out.ttinfo_before = tti - break - else: - out.ttinfo_before = out.ttinfo_list[0] - - # Now fix transition times to become relative to wall time. - # - # I'm not sure about this. In my tests, the tz source file - # is setup to wall time, and in the binary file isstd and - # isgmt are off, so it should be in wall time. OTOH, it's - # always in gmt time. Let me know if you have comments - # about this. - lastdst = None - lastoffset = None - lastdstoffset = None - lastbaseoffset = None - out.trans_list = [] - - for i, tti in enumerate(out.trans_idx): - offset = tti.offset - dstoffset = 0 - - if lastdst is not None: - if tti.isdst: - if not lastdst: - dstoffset = offset - lastoffset - - if not dstoffset and lastdstoffset: - dstoffset = lastdstoffset - - tti.dstoffset = datetime.timedelta(seconds=dstoffset) - lastdstoffset = dstoffset - - # If a time zone changes its base offset during a DST transition, - # then you need to adjust by the previous base offset to get the - # transition time in local time. Otherwise you use the current - # base offset. Ideally, I would have some mathematical proof of - # why this is true, but I haven't really thought about it enough. - baseoffset = offset - dstoffset - adjustment = baseoffset - if (lastbaseoffset is not None and baseoffset != lastbaseoffset - and tti.isdst != lastdst): - # The base DST has changed - adjustment = lastbaseoffset - - lastdst = tti.isdst - lastoffset = offset - lastbaseoffset = baseoffset - - out.trans_list.append(out.trans_list_utc[i] + adjustment) - - out.trans_idx = tuple(out.trans_idx) - out.trans_list = tuple(out.trans_list) - out.trans_list_utc = tuple(out.trans_list_utc) - - return out - - def _find_last_transition(self, dt, in_utc=False): - # If there's no list, there are no transitions to find - if not self._trans_list: - return None - - timestamp = _datetime_to_timestamp(dt) - - # Find where the timestamp fits in the transition list - if the - # timestamp is a transition time, it's part of the "after" period. - trans_list = self._trans_list_utc if in_utc else self._trans_list - idx = bisect.bisect_right(trans_list, timestamp) - - # We want to know when the previous transition was, so subtract off 1 - return idx - 1 - - def _get_ttinfo(self, idx): - # For no list or after the last transition, default to _ttinfo_std - if idx is None or (idx + 1) >= len(self._trans_list): - return self._ttinfo_std - - # If there is a list and the time is before it, return _ttinfo_before - if idx < 0: - return self._ttinfo_before - - return self._trans_idx[idx] - - def _find_ttinfo(self, dt): - idx = self._resolve_ambiguous_time(dt) - - return self._get_ttinfo(idx) - - def fromutc(self, dt): - """ - The ``tzfile`` implementation of :py:func:`datetime.tzinfo.fromutc`. - - :param dt: - A :py:class:`datetime.datetime` object. - - :raises TypeError: - Raised if ``dt`` is not a :py:class:`datetime.datetime` object. - - :raises ValueError: - Raised if this is called with a ``dt`` which does not have this - ``tzinfo`` attached. - - :return: - Returns a :py:class:`datetime.datetime` object representing the - wall time in ``self``'s time zone. - """ - # These isinstance checks are in datetime.tzinfo, so we'll preserve - # them, even if we don't care about duck typing. - if not isinstance(dt, datetime.datetime): - raise TypeError("fromutc() requires a datetime argument") - - if dt.tzinfo is not self: - raise ValueError("dt.tzinfo is not self") - - # First treat UTC as wall time and get the transition we're in. - idx = self._find_last_transition(dt, in_utc=True) - tti = self._get_ttinfo(idx) - - dt_out = dt + datetime.timedelta(seconds=tti.offset) - - fold = self.is_ambiguous(dt_out, idx=idx) - - return enfold(dt_out, fold=int(fold)) - - def is_ambiguous(self, dt, idx=None): - """ - Whether or not the "wall time" of a given datetime is ambiguous in this - zone. - - :param dt: - A :py:class:`datetime.datetime`, naive or time zone aware. - - - :return: - Returns ``True`` if ambiguous, ``False`` otherwise. - - .. versionadded:: 2.6.0 - """ - if idx is None: - idx = self._find_last_transition(dt) - - # Calculate the difference in offsets from current to previous - timestamp = _datetime_to_timestamp(dt) - tti = self._get_ttinfo(idx) - - if idx is None or idx <= 0: - return False - - od = self._get_ttinfo(idx - 1).offset - tti.offset - tt = self._trans_list[idx] # Transition time - - return timestamp < tt + od - - def _resolve_ambiguous_time(self, dt): - idx = self._find_last_transition(dt) - - # If we have no transitions, return the index - _fold = self._fold(dt) - if idx is None or idx == 0: - return idx - - # If it's ambiguous and we're in a fold, shift to a different index. - idx_offset = int(not _fold and self.is_ambiguous(dt, idx)) - - return idx - idx_offset - - def utcoffset(self, dt): - if dt is None: - return None - - if not self._ttinfo_std: - return ZERO - - return self._find_ttinfo(dt).delta - - def dst(self, dt): - if dt is None: - return None - - if not self._ttinfo_dst: - return ZERO - - tti = self._find_ttinfo(dt) - - if not tti.isdst: - return ZERO - - # The documentation says that utcoffset()-dst() must - # be constant for every dt. - return tti.dstoffset - - @tzname_in_python2 - def tzname(self, dt): - if not self._ttinfo_std or dt is None: - return None - return self._find_ttinfo(dt).abbr - - def __eq__(self, other): - if not isinstance(other, tzfile): - return NotImplemented - return (self._trans_list == other._trans_list and - self._trans_idx == other._trans_idx and - self._ttinfo_list == other._ttinfo_list) - - __hash__ = None - - def __ne__(self, other): - return not (self == other) - - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, repr(self._filename)) - - def __reduce__(self): - return self.__reduce_ex__(None) - - def __reduce_ex__(self, protocol): - return (self.__class__, (None, self._filename), self.__dict__) - - -class tzrange(tzrangebase): - """ - The ``tzrange`` object is a time zone specified by a set of offsets and - abbreviations, equivalent to the way the ``TZ`` variable can be specified - in POSIX-like systems, but using Python delta objects to specify DST - start, end and offsets. - - :param stdabbr: - The abbreviation for standard time (e.g. ``'EST'``). - - :param stdoffset: - An integer or :class:`datetime.timedelta` object or equivalent - specifying the base offset from UTC. - - If unspecified, +00:00 is used. - - :param dstabbr: - The abbreviation for DST / "Summer" time (e.g. ``'EDT'``). - - If specified, with no other DST information, DST is assumed to occur - and the default behavior or ``dstoffset``, ``start`` and ``end`` is - used. If unspecified and no other DST information is specified, it - is assumed that this zone has no DST. - - If this is unspecified and other DST information is *is* specified, - DST occurs in the zone but the time zone abbreviation is left - unchanged. - - :param dstoffset: - A an integer or :class:`datetime.timedelta` object or equivalent - specifying the UTC offset during DST. If unspecified and any other DST - information is specified, it is assumed to be the STD offset +1 hour. - - :param start: - A :class:`relativedelta.relativedelta` object or equivalent specifying - the time and time of year that daylight savings time starts. To - specify, for example, that DST starts at 2AM on the 2nd Sunday in - March, pass: - - ``relativedelta(hours=2, month=3, day=1, weekday=SU(+2))`` - - If unspecified and any other DST information is specified, the default - value is 2 AM on the first Sunday in April. - - :param end: - A :class:`relativedelta.relativedelta` object or equivalent - representing the time and time of year that daylight savings time - ends, with the same specification method as in ``start``. One note is - that this should point to the first time in the *standard* zone, so if - a transition occurs at 2AM in the DST zone and the clocks are set back - 1 hour to 1AM, set the ``hours`` parameter to +1. - - - **Examples:** - - .. testsetup:: tzrange - - from dateutil.tz import tzrange, tzstr - - .. doctest:: tzrange - - >>> tzstr('EST5EDT') == tzrange("EST", -18000, "EDT") - True - - >>> from dateutil.relativedelta import * - >>> range1 = tzrange("EST", -18000, "EDT") - >>> range2 = tzrange("EST", -18000, "EDT", -14400, - ... relativedelta(hours=+2, month=4, day=1, - ... weekday=SU(+1)), - ... relativedelta(hours=+1, month=10, day=31, - ... weekday=SU(-1))) - >>> tzstr('EST5EDT') == range1 == range2 - True - - """ - def __init__(self, stdabbr, stdoffset=None, - dstabbr=None, dstoffset=None, - start=None, end=None): - - global relativedelta - from dateutil import relativedelta - - self._std_abbr = stdabbr - self._dst_abbr = dstabbr - - try: - stdoffset = stdoffset.total_seconds() - except (TypeError, AttributeError): - pass - - try: - dstoffset = dstoffset.total_seconds() - except (TypeError, AttributeError): - pass - - if stdoffset is not None: - self._std_offset = datetime.timedelta(seconds=stdoffset) - else: - self._std_offset = ZERO - - if dstoffset is not None: - self._dst_offset = datetime.timedelta(seconds=dstoffset) - elif dstabbr and stdoffset is not None: - self._dst_offset = self._std_offset + datetime.timedelta(hours=+1) - else: - self._dst_offset = ZERO - - if dstabbr and start is None: - self._start_delta = relativedelta.relativedelta( - hours=+2, month=4, day=1, weekday=relativedelta.SU(+1)) - else: - self._start_delta = start - - if dstabbr and end is None: - self._end_delta = relativedelta.relativedelta( - hours=+1, month=10, day=31, weekday=relativedelta.SU(-1)) - else: - self._end_delta = end - - self._dst_base_offset_ = self._dst_offset - self._std_offset - self.hasdst = bool(self._start_delta) - - def transitions(self, year): - """ - For a given year, get the DST on and off transition times, expressed - always on the standard time side. For zones with no transitions, this - function returns ``None``. - - :param year: - The year whose transitions you would like to query. - - :return: - Returns a :class:`tuple` of :class:`datetime.datetime` objects, - ``(dston, dstoff)`` for zones with an annual DST transition, or - ``None`` for fixed offset zones. - """ - if not self.hasdst: - return None - - base_year = datetime.datetime(year, 1, 1) - - start = base_year + self._start_delta - end = base_year + self._end_delta - - return (start, end) - - def __eq__(self, other): - if not isinstance(other, tzrange): - return NotImplemented - - return (self._std_abbr == other._std_abbr and - self._dst_abbr == other._dst_abbr and - self._std_offset == other._std_offset and - self._dst_offset == other._dst_offset and - self._start_delta == other._start_delta and - self._end_delta == other._end_delta) - - @property - def _dst_base_offset(self): - return self._dst_base_offset_ - - -@six.add_metaclass(_TzStrFactory) -class tzstr(tzrange): - """ - ``tzstr`` objects are time zone objects specified by a time-zone string as - it would be passed to a ``TZ`` variable on POSIX-style systems (see - the `GNU C Library: TZ Variable`_ for more details). - - There is one notable exception, which is that POSIX-style time zones use an - inverted offset format, so normally ``GMT+3`` would be parsed as an offset - 3 hours *behind* GMT. The ``tzstr`` time zone object will parse this as an - offset 3 hours *ahead* of GMT. If you would like to maintain the POSIX - behavior, pass a ``True`` value to ``posix_offset``. - - The :class:`tzrange` object provides the same functionality, but is - specified using :class:`relativedelta.relativedelta` objects. rather than - strings. - - :param s: - A time zone string in ``TZ`` variable format. This can be a - :class:`bytes` (2.x: :class:`str`), :class:`str` (2.x: - :class:`unicode`) or a stream emitting unicode characters - (e.g. :class:`StringIO`). - - :param posix_offset: - Optional. If set to ``True``, interpret strings such as ``GMT+3`` or - ``UTC+3`` as being 3 hours *behind* UTC rather than ahead, per the - POSIX standard. - - .. caution:: - - Prior to version 2.7.0, this function also supported time zones - in the format: - - * ``EST5EDT,4,0,6,7200,10,0,26,7200,3600`` - * ``EST5EDT,4,1,0,7200,10,-1,0,7200,3600`` - - This format is non-standard and has been deprecated; this function - will raise a :class:`DeprecatedTZFormatWarning` until - support is removed in a future version. - - .. _`GNU C Library: TZ Variable`: - https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html - """ - def __init__(self, s, posix_offset=False): - global parser - from dateutil.parser import _parser as parser - - self._s = s - - res = parser._parsetz(s) - if res is None or res.any_unused_tokens: - raise ValueError("unknown string format") - - # Here we break the compatibility with the TZ variable handling. - # GMT-3 actually *means* the timezone -3. - if res.stdabbr in ("GMT", "UTC") and not posix_offset: - res.stdoffset *= -1 - - # We must initialize it first, since _delta() needs - # _std_offset and _dst_offset set. Use False in start/end - # to avoid building it two times. - tzrange.__init__(self, res.stdabbr, res.stdoffset, - res.dstabbr, res.dstoffset, - start=False, end=False) - - if not res.dstabbr: - self._start_delta = None - self._end_delta = None - else: - self._start_delta = self._delta(res.start) - if self._start_delta: - self._end_delta = self._delta(res.end, isend=1) - - self.hasdst = bool(self._start_delta) - - def _delta(self, x, isend=0): - from dateutil import relativedelta - kwargs = {} - if x.month is not None: - kwargs["month"] = x.month - if x.weekday is not None: - kwargs["weekday"] = relativedelta.weekday(x.weekday, x.week) - if x.week > 0: - kwargs["day"] = 1 - else: - kwargs["day"] = 31 - elif x.day: - kwargs["day"] = x.day - elif x.yday is not None: - kwargs["yearday"] = x.yday - elif x.jyday is not None: - kwargs["nlyearday"] = x.jyday - if not kwargs: - # Default is to start on first sunday of april, and end - # on last sunday of october. - if not isend: - kwargs["month"] = 4 - kwargs["day"] = 1 - kwargs["weekday"] = relativedelta.SU(+1) - else: - kwargs["month"] = 10 - kwargs["day"] = 31 - kwargs["weekday"] = relativedelta.SU(-1) - if x.time is not None: - kwargs["seconds"] = x.time - else: - # Default is 2AM. - kwargs["seconds"] = 7200 - if isend: - # Convert to standard time, to follow the documented way - # of working with the extra hour. See the documentation - # of the tzinfo class. - delta = self._dst_offset - self._std_offset - kwargs["seconds"] -= delta.seconds + delta.days * 86400 - return relativedelta.relativedelta(**kwargs) - - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, repr(self._s)) - - -class _tzicalvtzcomp(object): - def __init__(self, tzoffsetfrom, tzoffsetto, isdst, - tzname=None, rrule=None): - self.tzoffsetfrom = datetime.timedelta(seconds=tzoffsetfrom) - self.tzoffsetto = datetime.timedelta(seconds=tzoffsetto) - self.tzoffsetdiff = self.tzoffsetto - self.tzoffsetfrom - self.isdst = isdst - self.tzname = tzname - self.rrule = rrule - - -class _tzicalvtz(_tzinfo): - def __init__(self, tzid, comps=[]): - super(_tzicalvtz, self).__init__() - - self._tzid = tzid - self._comps = comps - self._cachedate = [] - self._cachecomp = [] - self._cache_lock = _thread.allocate_lock() - - def _find_comp(self, dt): - if len(self._comps) == 1: - return self._comps[0] - - dt = dt.replace(tzinfo=None) - - try: - with self._cache_lock: - return self._cachecomp[self._cachedate.index( - (dt, self._fold(dt)))] - except ValueError: - pass - - lastcompdt = None - lastcomp = None - - for comp in self._comps: - compdt = self._find_compdt(comp, dt) - - if compdt and (not lastcompdt or lastcompdt < compdt): - lastcompdt = compdt - lastcomp = comp - - if not lastcomp: - # RFC says nothing about what to do when a given - # time is before the first onset date. We'll look for the - # first standard component, or the first component, if - # none is found. - for comp in self._comps: - if not comp.isdst: - lastcomp = comp - break - else: - lastcomp = comp[0] - - with self._cache_lock: - self._cachedate.insert(0, (dt, self._fold(dt))) - self._cachecomp.insert(0, lastcomp) - - if len(self._cachedate) > 10: - self._cachedate.pop() - self._cachecomp.pop() - - return lastcomp - - def _find_compdt(self, comp, dt): - if comp.tzoffsetdiff < ZERO and self._fold(dt): - dt -= comp.tzoffsetdiff - - compdt = comp.rrule.before(dt, inc=True) - - return compdt - - def utcoffset(self, dt): - if dt is None: - return None - - return self._find_comp(dt).tzoffsetto - - def dst(self, dt): - comp = self._find_comp(dt) - if comp.isdst: - return comp.tzoffsetdiff - else: - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - return self._find_comp(dt).tzname - - def __repr__(self): - return "" % repr(self._tzid) - - __reduce__ = object.__reduce__ - - -class tzical(object): - """ - This object is designed to parse an iCalendar-style ``VTIMEZONE`` structure - as set out in `RFC 5545`_ Section 4.6.5 into one or more `tzinfo` objects. - - :param `fileobj`: - A file or stream in iCalendar format, which should be UTF-8 encoded - with CRLF endings. - - .. _`RFC 5545`: https://tools.ietf.org/html/rfc5545 - """ - def __init__(self, fileobj): - global rrule - from dateutil import rrule - - if isinstance(fileobj, string_types): - self._s = fileobj - # ical should be encoded in UTF-8 with CRLF - fileobj = open(fileobj, 'r') - else: - self._s = getattr(fileobj, 'name', repr(fileobj)) - fileobj = _nullcontext(fileobj) - - self._vtz = {} - - with fileobj as fobj: - self._parse_rfc(fobj.read()) - - def keys(self): - """ - Retrieves the available time zones as a list. - """ - return list(self._vtz.keys()) - - def get(self, tzid=None): - """ - Retrieve a :py:class:`datetime.tzinfo` object by its ``tzid``. - - :param tzid: - If there is exactly one time zone available, omitting ``tzid`` - or passing :py:const:`None` value returns it. Otherwise a valid - key (which can be retrieved from :func:`keys`) is required. - - :raises ValueError: - Raised if ``tzid`` is not specified but there are either more - or fewer than 1 zone defined. - - :returns: - Returns either a :py:class:`datetime.tzinfo` object representing - the relevant time zone or :py:const:`None` if the ``tzid`` was - not found. - """ - if tzid is None: - if len(self._vtz) == 0: - raise ValueError("no timezones defined") - elif len(self._vtz) > 1: - raise ValueError("more than one timezone available") - tzid = next(iter(self._vtz)) - - return self._vtz.get(tzid) - - def _parse_offset(self, s): - s = s.strip() - if not s: - raise ValueError("empty offset") - if s[0] in ('+', '-'): - signal = (-1, +1)[s[0] == '+'] - s = s[1:] - else: - signal = +1 - if len(s) == 4: - return (int(s[:2]) * 3600 + int(s[2:]) * 60) * signal - elif len(s) == 6: - return (int(s[:2]) * 3600 + int(s[2:4]) * 60 + int(s[4:])) * signal - else: - raise ValueError("invalid offset: " + s) - - def _parse_rfc(self, s): - lines = s.splitlines() - if not lines: - raise ValueError("empty string") - - # Unfold - i = 0 - while i < len(lines): - line = lines[i].rstrip() - if not line: - del lines[i] - elif i > 0 and line[0] == " ": - lines[i-1] += line[1:] - del lines[i] - else: - i += 1 - - tzid = None - comps = [] - invtz = False - comptype = None - for line in lines: - if not line: - continue - name, value = line.split(':', 1) - parms = name.split(';') - if not parms: - raise ValueError("empty property name") - name = parms[0].upper() - parms = parms[1:] - if invtz: - if name == "BEGIN": - if value in ("STANDARD", "DAYLIGHT"): - # Process component - pass - else: - raise ValueError("unknown component: "+value) - comptype = value - founddtstart = False - tzoffsetfrom = None - tzoffsetto = None - rrulelines = [] - tzname = None - elif name == "END": - if value == "VTIMEZONE": - if comptype: - raise ValueError("component not closed: "+comptype) - if not tzid: - raise ValueError("mandatory TZID not found") - if not comps: - raise ValueError( - "at least one component is needed") - # Process vtimezone - self._vtz[tzid] = _tzicalvtz(tzid, comps) - invtz = False - elif value == comptype: - if not founddtstart: - raise ValueError("mandatory DTSTART not found") - if tzoffsetfrom is None: - raise ValueError( - "mandatory TZOFFSETFROM not found") - if tzoffsetto is None: - raise ValueError( - "mandatory TZOFFSETFROM not found") - # Process component - rr = None - if rrulelines: - rr = rrule.rrulestr("\n".join(rrulelines), - compatible=True, - ignoretz=True, - cache=True) - comp = _tzicalvtzcomp(tzoffsetfrom, tzoffsetto, - (comptype == "DAYLIGHT"), - tzname, rr) - comps.append(comp) - comptype = None - else: - raise ValueError("invalid component end: "+value) - elif comptype: - if name == "DTSTART": - # DTSTART in VTIMEZONE takes a subset of valid RRULE - # values under RFC 5545. - for parm in parms: - if parm != 'VALUE=DATE-TIME': - msg = ('Unsupported DTSTART param in ' + - 'VTIMEZONE: ' + parm) - raise ValueError(msg) - rrulelines.append(line) - founddtstart = True - elif name in ("RRULE", "RDATE", "EXRULE", "EXDATE"): - rrulelines.append(line) - elif name == "TZOFFSETFROM": - if parms: - raise ValueError( - "unsupported %s parm: %s " % (name, parms[0])) - tzoffsetfrom = self._parse_offset(value) - elif name == "TZOFFSETTO": - if parms: - raise ValueError( - "unsupported TZOFFSETTO parm: "+parms[0]) - tzoffsetto = self._parse_offset(value) - elif name == "TZNAME": - if parms: - raise ValueError( - "unsupported TZNAME parm: "+parms[0]) - tzname = value - elif name == "COMMENT": - pass - else: - raise ValueError("unsupported property: "+name) - else: - if name == "TZID": - if parms: - raise ValueError( - "unsupported TZID parm: "+parms[0]) - tzid = value - elif name in ("TZURL", "LAST-MODIFIED", "COMMENT"): - pass - else: - raise ValueError("unsupported property: "+name) - elif name == "BEGIN" and value == "VTIMEZONE": - tzid = None - comps = [] - invtz = True - - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, repr(self._s)) - - -if sys.platform != "win32": - TZFILES = ["/etc/localtime", "localtime"] - TZPATHS = ["/usr/share/zoneinfo", - "/usr/lib/zoneinfo", - "/usr/share/lib/zoneinfo", - "/etc/zoneinfo"] -else: - TZFILES = [] - TZPATHS = [] - - -def __get_gettz(): - tzlocal_classes = (tzlocal,) - if tzwinlocal is not None: - tzlocal_classes += (tzwinlocal,) - - class GettzFunc(object): - """ - Retrieve a time zone object from a string representation - - This function is intended to retrieve the :py:class:`tzinfo` subclass - that best represents the time zone that would be used if a POSIX - `TZ variable`_ were set to the same value. - - If no argument or an empty string is passed to ``gettz``, local time - is returned: - - .. code-block:: python3 - - >>> gettz() - tzfile('/etc/localtime') - - This function is also the preferred way to map IANA tz database keys - to :class:`tzfile` objects: - - .. code-block:: python3 - - >>> gettz('Pacific/Kiritimati') - tzfile('/usr/share/zoneinfo/Pacific/Kiritimati') - - On Windows, the standard is extended to include the Windows-specific - zone names provided by the operating system: - - .. code-block:: python3 - - >>> gettz('Egypt Standard Time') - tzwin('Egypt Standard Time') - - Passing a GNU ``TZ`` style string time zone specification returns a - :class:`tzstr` object: - - .. code-block:: python3 - - >>> gettz('AEST-10AEDT-11,M10.1.0/2,M4.1.0/3') - tzstr('AEST-10AEDT-11,M10.1.0/2,M4.1.0/3') - - :param name: - A time zone name (IANA, or, on Windows, Windows keys), location of - a ``tzfile(5)`` zoneinfo file or ``TZ`` variable style time zone - specifier. An empty string, no argument or ``None`` is interpreted - as local time. - - :return: - Returns an instance of one of ``dateutil``'s :py:class:`tzinfo` - subclasses. - - .. versionchanged:: 2.7.0 - - After version 2.7.0, any two calls to ``gettz`` using the same - input strings will return the same object: - - .. code-block:: python3 - - >>> tz.gettz('America/Chicago') is tz.gettz('America/Chicago') - True - - In addition to improving performance, this ensures that - `"same zone" semantics`_ are used for datetimes in the same zone. - - - .. _`TZ variable`: - https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html - - .. _`"same zone" semantics`: - https://blog.ganssle.io/articles/2018/02/aware-datetime-arithmetic.html - """ - def __init__(self): - - self.__instances = weakref.WeakValueDictionary() - self.__strong_cache_size = 8 - self.__strong_cache = OrderedDict() - self._cache_lock = _thread.allocate_lock() - - def __call__(self, name=None): - with self._cache_lock: - rv = self.__instances.get(name, None) - - if rv is None: - rv = self.nocache(name=name) - if not (name is None - or isinstance(rv, tzlocal_classes) - or rv is None): - # tzlocal is slightly more complicated than the other - # time zone providers because it depends on environment - # at construction time, so don't cache that. - # - # We also cannot store weak references to None, so we - # will also not store that. - self.__instances[name] = rv - else: - # No need for strong caching, return immediately - return rv - - self.__strong_cache[name] = self.__strong_cache.pop(name, rv) - - if len(self.__strong_cache) > self.__strong_cache_size: - self.__strong_cache.popitem(last=False) - - return rv - - def set_cache_size(self, size): - with self._cache_lock: - self.__strong_cache_size = size - while len(self.__strong_cache) > size: - self.__strong_cache.popitem(last=False) - - def cache_clear(self): - with self._cache_lock: - self.__instances = weakref.WeakValueDictionary() - self.__strong_cache.clear() - - @staticmethod - def nocache(name=None): - """A non-cached version of gettz""" - tz = None - if not name: - try: - name = os.environ["TZ"] - except KeyError: - pass - if name is None or name in ("", ":"): - for filepath in TZFILES: - if not os.path.isabs(filepath): - filename = filepath - for path in TZPATHS: - filepath = os.path.join(path, filename) - if os.path.isfile(filepath): - break - else: - continue - if os.path.isfile(filepath): - try: - tz = tzfile(filepath) - break - except (IOError, OSError, ValueError): - pass - else: - tz = tzlocal() - else: - try: - if name.startswith(":"): - name = name[1:] - except TypeError as e: - if isinstance(name, bytes): - new_msg = "gettz argument should be str, not bytes" - six.raise_from(TypeError(new_msg), e) - else: - raise - if os.path.isabs(name): - if os.path.isfile(name): - tz = tzfile(name) - else: - tz = None - else: - for path in TZPATHS: - filepath = os.path.join(path, name) - if not os.path.isfile(filepath): - filepath = filepath.replace(' ', '_') - if not os.path.isfile(filepath): - continue - try: - tz = tzfile(filepath) - break - except (IOError, OSError, ValueError): - pass - else: - tz = None - if tzwin is not None: - try: - tz = tzwin(name) - except (WindowsError, UnicodeEncodeError): - # UnicodeEncodeError is for Python 2.7 compat - tz = None - - if not tz: - from dateutil.zoneinfo import get_zonefile_instance - tz = get_zonefile_instance().get(name) - - if not tz: - for c in name: - # name is not a tzstr unless it has at least - # one offset. For short values of "name", an - # explicit for loop seems to be the fastest way - # To determine if a string contains a digit - if c in "0123456789": - try: - tz = tzstr(name) - except ValueError: - pass - break - else: - if name in ("GMT", "UTC"): - tz = UTC - elif name in time.tzname: - tz = tzlocal() - return tz - - return GettzFunc() - - -gettz = __get_gettz() -del __get_gettz - - -def datetime_exists(dt, tz=None): - """ - Given a datetime and a time zone, determine whether or not a given datetime - would fall in a gap. - - :param dt: - A :class:`datetime.datetime` (whose time zone will be ignored if ``tz`` - is provided.) - - :param tz: - A :class:`datetime.tzinfo` with support for the ``fold`` attribute. If - ``None`` or not provided, the datetime's own time zone will be used. - - :return: - Returns a boolean value whether or not the "wall time" exists in - ``tz``. - - .. versionadded:: 2.7.0 - """ - if tz is None: - if dt.tzinfo is None: - raise ValueError('Datetime is naive and no time zone provided.') - tz = dt.tzinfo - - dt = dt.replace(tzinfo=None) - - # This is essentially a test of whether or not the datetime can survive - # a round trip to UTC. - dt_rt = dt.replace(tzinfo=tz).astimezone(UTC).astimezone(tz) - dt_rt = dt_rt.replace(tzinfo=None) - - return dt == dt_rt - - -def datetime_ambiguous(dt, tz=None): - """ - Given a datetime and a time zone, determine whether or not a given datetime - is ambiguous (i.e if there are two times differentiated only by their DST - status). - - :param dt: - A :class:`datetime.datetime` (whose time zone will be ignored if ``tz`` - is provided.) - - :param tz: - A :class:`datetime.tzinfo` with support for the ``fold`` attribute. If - ``None`` or not provided, the datetime's own time zone will be used. - - :return: - Returns a boolean value whether or not the "wall time" is ambiguous in - ``tz``. - - .. versionadded:: 2.6.0 - """ - if tz is None: - if dt.tzinfo is None: - raise ValueError('Datetime is naive and no time zone provided.') - - tz = dt.tzinfo - - # If a time zone defines its own "is_ambiguous" function, we'll use that. - is_ambiguous_fn = getattr(tz, 'is_ambiguous', None) - if is_ambiguous_fn is not None: - try: - return tz.is_ambiguous(dt) - except Exception: - pass - - # If it doesn't come out and tell us it's ambiguous, we'll just check if - # the fold attribute has any effect on this particular date and time. - dt = dt.replace(tzinfo=tz) - wall_0 = enfold(dt, fold=0) - wall_1 = enfold(dt, fold=1) - - same_offset = wall_0.utcoffset() == wall_1.utcoffset() - same_dst = wall_0.dst() == wall_1.dst() - - return not (same_offset and same_dst) - - -def resolve_imaginary(dt): - """ - Given a datetime that may be imaginary, return an existing datetime. - - This function assumes that an imaginary datetime represents what the - wall time would be in a zone had the offset transition not occurred, so - it will always fall forward by the transition's change in offset. - - .. doctest:: - - >>> from dateutil import tz - >>> from datetime import datetime - >>> NYC = tz.gettz('America/New_York') - >>> print(tz.resolve_imaginary(datetime(2017, 3, 12, 2, 30, tzinfo=NYC))) - 2017-03-12 03:30:00-04:00 - - >>> KIR = tz.gettz('Pacific/Kiritimati') - >>> print(tz.resolve_imaginary(datetime(1995, 1, 1, 12, 30, tzinfo=KIR))) - 1995-01-02 12:30:00+14:00 - - As a note, :func:`datetime.astimezone` is guaranteed to produce a valid, - existing datetime, so a round-trip to and from UTC is sufficient to get - an extant datetime, however, this generally "falls back" to an earlier time - rather than falling forward to the STD side (though no guarantees are made - about this behavior). - - :param dt: - A :class:`datetime.datetime` which may or may not exist. - - :return: - Returns an existing :class:`datetime.datetime`. If ``dt`` was not - imaginary, the datetime returned is guaranteed to be the same object - passed to the function. - - .. versionadded:: 2.7.0 - """ - if dt.tzinfo is not None and not datetime_exists(dt): - - curr_offset = (dt + datetime.timedelta(hours=24)).utcoffset() - old_offset = (dt - datetime.timedelta(hours=24)).utcoffset() - - dt += curr_offset - old_offset - - return dt - - -def _datetime_to_timestamp(dt): - """ - Convert a :class:`datetime.datetime` object to an epoch timestamp in - seconds since January 1, 1970, ignoring the time zone. - """ - return (dt.replace(tzinfo=None) - EPOCH).total_seconds() - - -if sys.version_info >= (3, 6): - def _get_supported_offset(second_offset): - return second_offset -else: - def _get_supported_offset(second_offset): - # For python pre-3.6, round to full-minutes if that's not the case. - # Python's datetime doesn't accept sub-minute timezones. Check - # http://python.org/sf/1447945 or https://bugs.python.org/issue5288 - # for some information. - old_offset = second_offset - calculated_offset = 60 * ((second_offset + 30) // 60) - return calculated_offset - - -try: - # Python 3.7 feature - from contextlib import nullcontext as _nullcontext -except ImportError: - class _nullcontext(object): - """ - Class for wrapping contexts so that they are passed through in a - with statement. - """ - def __init__(self, context): - self.context = context - - def __enter__(self): - return self.context - - def __exit__(*args, **kwargs): - pass - -# vim:ts=4:sw=4:et diff --git a/apps/bitwarden_event_logs/lib/dateutil/tz/win.py b/apps/bitwarden_event_logs/lib/dateutil/tz/win.py deleted file mode 100755 index cde07ba7..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/tz/win.py +++ /dev/null @@ -1,370 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module provides an interface to the native time zone data on Windows, -including :py:class:`datetime.tzinfo` implementations. - -Attempting to import this module on a non-Windows platform will raise an -:py:obj:`ImportError`. -""" -# This code was originally contributed by Jeffrey Harris. -import datetime -import struct - -from six.moves import winreg -from six import text_type - -try: - import ctypes - from ctypes import wintypes -except ValueError: - # ValueError is raised on non-Windows systems for some horrible reason. - raise ImportError("Running tzwin on non-Windows system") - -from ._common import tzrangebase - -__all__ = ["tzwin", "tzwinlocal", "tzres"] - -ONEWEEK = datetime.timedelta(7) - -TZKEYNAMENT = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones" -TZKEYNAME9X = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Time Zones" -TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation" - - -def _settzkeyname(): - handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) - try: - winreg.OpenKey(handle, TZKEYNAMENT).Close() - TZKEYNAME = TZKEYNAMENT - except WindowsError: - TZKEYNAME = TZKEYNAME9X - handle.Close() - return TZKEYNAME - - -TZKEYNAME = _settzkeyname() - - -class tzres(object): - """ - Class for accessing ``tzres.dll``, which contains timezone name related - resources. - - .. versionadded:: 2.5.0 - """ - p_wchar = ctypes.POINTER(wintypes.WCHAR) # Pointer to a wide char - - def __init__(self, tzres_loc='tzres.dll'): - # Load the user32 DLL so we can load strings from tzres - user32 = ctypes.WinDLL('user32') - - # Specify the LoadStringW function - user32.LoadStringW.argtypes = (wintypes.HINSTANCE, - wintypes.UINT, - wintypes.LPWSTR, - ctypes.c_int) - - self.LoadStringW = user32.LoadStringW - self._tzres = ctypes.WinDLL(tzres_loc) - self.tzres_loc = tzres_loc - - def load_name(self, offset): - """ - Load a timezone name from a DLL offset (integer). - - >>> from dateutil.tzwin import tzres - >>> tzr = tzres() - >>> print(tzr.load_name(112)) - 'Eastern Standard Time' - - :param offset: - A positive integer value referring to a string from the tzres dll. - - .. note:: - - Offsets found in the registry are generally of the form - ``@tzres.dll,-114``. The offset in this case is 114, not -114. - - """ - resource = self.p_wchar() - lpBuffer = ctypes.cast(ctypes.byref(resource), wintypes.LPWSTR) - nchar = self.LoadStringW(self._tzres._handle, offset, lpBuffer, 0) - return resource[:nchar] - - def name_from_string(self, tzname_str): - """ - Parse strings as returned from the Windows registry into the time zone - name as defined in the registry. - - >>> from dateutil.tzwin import tzres - >>> tzr = tzres() - >>> print(tzr.name_from_string('@tzres.dll,-251')) - 'Dateline Daylight Time' - >>> print(tzr.name_from_string('Eastern Standard Time')) - 'Eastern Standard Time' - - :param tzname_str: - A timezone name string as returned from a Windows registry key. - - :return: - Returns the localized timezone string from tzres.dll if the string - is of the form `@tzres.dll,-offset`, else returns the input string. - """ - if not tzname_str.startswith('@'): - return tzname_str - - name_splt = tzname_str.split(',-') - try: - offset = int(name_splt[1]) - except: - raise ValueError("Malformed timezone string.") - - return self.load_name(offset) - - -class tzwinbase(tzrangebase): - """tzinfo class based on win32's timezones available in the registry.""" - def __init__(self): - raise NotImplementedError('tzwinbase is an abstract base class') - - def __eq__(self, other): - # Compare on all relevant dimensions, including name. - if not isinstance(other, tzwinbase): - return NotImplemented - - return (self._std_offset == other._std_offset and - self._dst_offset == other._dst_offset and - self._stddayofweek == other._stddayofweek and - self._dstdayofweek == other._dstdayofweek and - self._stdweeknumber == other._stdweeknumber and - self._dstweeknumber == other._dstweeknumber and - self._stdhour == other._stdhour and - self._dsthour == other._dsthour and - self._stdminute == other._stdminute and - self._dstminute == other._dstminute and - self._std_abbr == other._std_abbr and - self._dst_abbr == other._dst_abbr) - - @staticmethod - def list(): - """Return a list of all time zones known to the system.""" - with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: - with winreg.OpenKey(handle, TZKEYNAME) as tzkey: - result = [winreg.EnumKey(tzkey, i) - for i in range(winreg.QueryInfoKey(tzkey)[0])] - return result - - def display(self): - """ - Return the display name of the time zone. - """ - return self._display - - def transitions(self, year): - """ - For a given year, get the DST on and off transition times, expressed - always on the standard time side. For zones with no transitions, this - function returns ``None``. - - :param year: - The year whose transitions you would like to query. - - :return: - Returns a :class:`tuple` of :class:`datetime.datetime` objects, - ``(dston, dstoff)`` for zones with an annual DST transition, or - ``None`` for fixed offset zones. - """ - - if not self.hasdst: - return None - - dston = picknthweekday(year, self._dstmonth, self._dstdayofweek, - self._dsthour, self._dstminute, - self._dstweeknumber) - - dstoff = picknthweekday(year, self._stdmonth, self._stddayofweek, - self._stdhour, self._stdminute, - self._stdweeknumber) - - # Ambiguous dates default to the STD side - dstoff -= self._dst_base_offset - - return dston, dstoff - - def _get_hasdst(self): - return self._dstmonth != 0 - - @property - def _dst_base_offset(self): - return self._dst_base_offset_ - - -class tzwin(tzwinbase): - """ - Time zone object created from the zone info in the Windows registry - - These are similar to :py:class:`dateutil.tz.tzrange` objects in that - the time zone data is provided in the format of a single offset rule - for either 0 or 2 time zone transitions per year. - - :param: name - The name of a Windows time zone key, e.g. "Eastern Standard Time". - The full list of keys can be retrieved with :func:`tzwin.list`. - """ - - def __init__(self, name): - self._name = name - - with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: - tzkeyname = text_type("{kn}\\{name}").format(kn=TZKEYNAME, name=name) - with winreg.OpenKey(handle, tzkeyname) as tzkey: - keydict = valuestodict(tzkey) - - self._std_abbr = keydict["Std"] - self._dst_abbr = keydict["Dlt"] - - self._display = keydict["Display"] - - # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm - tup = struct.unpack("=3l16h", keydict["TZI"]) - stdoffset = -tup[0]-tup[1] # Bias + StandardBias * -1 - dstoffset = stdoffset-tup[2] # + DaylightBias * -1 - self._std_offset = datetime.timedelta(minutes=stdoffset) - self._dst_offset = datetime.timedelta(minutes=dstoffset) - - # for the meaning see the win32 TIME_ZONE_INFORMATION structure docs - # http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx - (self._stdmonth, - self._stddayofweek, # Sunday = 0 - self._stdweeknumber, # Last = 5 - self._stdhour, - self._stdminute) = tup[4:9] - - (self._dstmonth, - self._dstdayofweek, # Sunday = 0 - self._dstweeknumber, # Last = 5 - self._dsthour, - self._dstminute) = tup[12:17] - - self._dst_base_offset_ = self._dst_offset - self._std_offset - self.hasdst = self._get_hasdst() - - def __repr__(self): - return "tzwin(%s)" % repr(self._name) - - def __reduce__(self): - return (self.__class__, (self._name,)) - - -class tzwinlocal(tzwinbase): - """ - Class representing the local time zone information in the Windows registry - - While :class:`dateutil.tz.tzlocal` makes system calls (via the :mod:`time` - module) to retrieve time zone information, ``tzwinlocal`` retrieves the - rules directly from the Windows registry and creates an object like - :class:`dateutil.tz.tzwin`. - - Because Windows does not have an equivalent of :func:`time.tzset`, on - Windows, :class:`dateutil.tz.tzlocal` instances will always reflect the - time zone settings *at the time that the process was started*, meaning - changes to the machine's time zone settings during the run of a program - on Windows will **not** be reflected by :class:`dateutil.tz.tzlocal`. - Because ``tzwinlocal`` reads the registry directly, it is unaffected by - this issue. - """ - def __init__(self): - with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: - with winreg.OpenKey(handle, TZLOCALKEYNAME) as tzlocalkey: - keydict = valuestodict(tzlocalkey) - - self._std_abbr = keydict["StandardName"] - self._dst_abbr = keydict["DaylightName"] - - try: - tzkeyname = text_type('{kn}\\{sn}').format(kn=TZKEYNAME, - sn=self._std_abbr) - with winreg.OpenKey(handle, tzkeyname) as tzkey: - _keydict = valuestodict(tzkey) - self._display = _keydict["Display"] - except OSError: - self._display = None - - stdoffset = -keydict["Bias"]-keydict["StandardBias"] - dstoffset = stdoffset-keydict["DaylightBias"] - - self._std_offset = datetime.timedelta(minutes=stdoffset) - self._dst_offset = datetime.timedelta(minutes=dstoffset) - - # For reasons unclear, in this particular key, the day of week has been - # moved to the END of the SYSTEMTIME structure. - tup = struct.unpack("=8h", keydict["StandardStart"]) - - (self._stdmonth, - self._stdweeknumber, # Last = 5 - self._stdhour, - self._stdminute) = tup[1:5] - - self._stddayofweek = tup[7] - - tup = struct.unpack("=8h", keydict["DaylightStart"]) - - (self._dstmonth, - self._dstweeknumber, # Last = 5 - self._dsthour, - self._dstminute) = tup[1:5] - - self._dstdayofweek = tup[7] - - self._dst_base_offset_ = self._dst_offset - self._std_offset - self.hasdst = self._get_hasdst() - - def __repr__(self): - return "tzwinlocal()" - - def __str__(self): - # str will return the standard name, not the daylight name. - return "tzwinlocal(%s)" % repr(self._std_abbr) - - def __reduce__(self): - return (self.__class__, ()) - - -def picknthweekday(year, month, dayofweek, hour, minute, whichweek): - """ dayofweek == 0 means Sunday, whichweek 5 means last instance """ - first = datetime.datetime(year, month, 1, hour, minute) - - # This will work if dayofweek is ISO weekday (1-7) or Microsoft-style (0-6), - # Because 7 % 7 = 0 - weekdayone = first.replace(day=((dayofweek - first.isoweekday()) % 7) + 1) - wd = weekdayone + ((whichweek - 1) * ONEWEEK) - if (wd.month != month): - wd -= ONEWEEK - - return wd - - -def valuestodict(key): - """Convert a registry key's values to a dictionary.""" - dout = {} - size = winreg.QueryInfoKey(key)[1] - tz_res = None - - for i in range(size): - key_name, value, dtype = winreg.EnumValue(key, i) - if dtype == winreg.REG_DWORD or dtype == winreg.REG_DWORD_LITTLE_ENDIAN: - # If it's a DWORD (32-bit integer), it's stored as unsigned - convert - # that to a proper signed integer - if value & (1 << 31): - value = value - (1 << 32) - elif dtype == winreg.REG_SZ: - # If it's a reference to the tzres DLL, load the actual string - if value.startswith('@tzres'): - tz_res = tz_res or tzres() - value = tz_res.name_from_string(value) - - value = value.rstrip('\x00') # Remove trailing nulls - - dout[key_name] = value - - return dout diff --git a/apps/bitwarden_event_logs/lib/dateutil/tzwin.py b/apps/bitwarden_event_logs/lib/dateutil/tzwin.py deleted file mode 100755 index cebc673e..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/tzwin.py +++ /dev/null @@ -1,2 +0,0 @@ -# tzwin has moved to dateutil.tz.win -from .tz.win import * diff --git a/apps/bitwarden_event_logs/lib/dateutil/utils.py b/apps/bitwarden_event_logs/lib/dateutil/utils.py deleted file mode 100755 index dd2d245a..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/utils.py +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module offers general convenience and utility functions for dealing with -datetimes. - -.. versionadded:: 2.7.0 -""" -from __future__ import unicode_literals - -from datetime import datetime, time - - -def today(tzinfo=None): - """ - Returns a :py:class:`datetime` representing the current day at midnight - - :param tzinfo: - The time zone to attach (also used to determine the current day). - - :return: - A :py:class:`datetime.datetime` object representing the current day - at midnight. - """ - - dt = datetime.now(tzinfo) - return datetime.combine(dt.date(), time(0, tzinfo=tzinfo)) - - -def default_tzinfo(dt, tzinfo): - """ - Sets the ``tzinfo`` parameter on naive datetimes only - - This is useful for example when you are provided a datetime that may have - either an implicit or explicit time zone, such as when parsing a time zone - string. - - .. doctest:: - - >>> from dateutil.tz import tzoffset - >>> from dateutil.parser import parse - >>> from dateutil.utils import default_tzinfo - >>> dflt_tz = tzoffset("EST", -18000) - >>> print(default_tzinfo(parse('2014-01-01 12:30 UTC'), dflt_tz)) - 2014-01-01 12:30:00+00:00 - >>> print(default_tzinfo(parse('2014-01-01 12:30'), dflt_tz)) - 2014-01-01 12:30:00-05:00 - - :param dt: - The datetime on which to replace the time zone - - :param tzinfo: - The :py:class:`datetime.tzinfo` subclass instance to assign to - ``dt`` if (and only if) it is naive. - - :return: - Returns an aware :py:class:`datetime.datetime`. - """ - if dt.tzinfo is not None: - return dt - else: - return dt.replace(tzinfo=tzinfo) - - -def within_delta(dt1, dt2, delta): - """ - Useful for comparing two datetimes that may have a negligible difference - to be considered equal. - """ - delta = abs(delta) - difference = dt1 - dt2 - return -delta <= difference <= delta diff --git a/apps/bitwarden_event_logs/lib/dateutil/zoneinfo/__init__.py b/apps/bitwarden_event_logs/lib/dateutil/zoneinfo/__init__.py deleted file mode 100755 index 34f11ad6..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/zoneinfo/__init__.py +++ /dev/null @@ -1,167 +0,0 @@ -# -*- coding: utf-8 -*- -import warnings -import json - -from tarfile import TarFile -from pkgutil import get_data -from io import BytesIO - -from dateutil.tz import tzfile as _tzfile - -__all__ = ["get_zonefile_instance", "gettz", "gettz_db_metadata"] - -ZONEFILENAME = "dateutil-zoneinfo.tar.gz" -METADATA_FN = 'METADATA' - - -class tzfile(_tzfile): - def __reduce__(self): - return (gettz, (self._filename,)) - - -def getzoneinfofile_stream(): - try: - return BytesIO(get_data(__name__, ZONEFILENAME)) - except IOError as e: # TODO switch to FileNotFoundError? - warnings.warn("I/O error({0}): {1}".format(e.errno, e.strerror)) - return None - - -class ZoneInfoFile(object): - def __init__(self, zonefile_stream=None): - if zonefile_stream is not None: - with TarFile.open(fileobj=zonefile_stream) as tf: - self.zones = {zf.name: tzfile(tf.extractfile(zf), filename=zf.name) - for zf in tf.getmembers() - if zf.isfile() and zf.name != METADATA_FN} - # deal with links: They'll point to their parent object. Less - # waste of memory - links = {zl.name: self.zones[zl.linkname] - for zl in tf.getmembers() if - zl.islnk() or zl.issym()} - self.zones.update(links) - try: - metadata_json = tf.extractfile(tf.getmember(METADATA_FN)) - metadata_str = metadata_json.read().decode('UTF-8') - self.metadata = json.loads(metadata_str) - except KeyError: - # no metadata in tar file - self.metadata = None - else: - self.zones = {} - self.metadata = None - - def get(self, name, default=None): - """ - Wrapper for :func:`ZoneInfoFile.zones.get`. This is a convenience method - for retrieving zones from the zone dictionary. - - :param name: - The name of the zone to retrieve. (Generally IANA zone names) - - :param default: - The value to return in the event of a missing key. - - .. versionadded:: 2.6.0 - - """ - return self.zones.get(name, default) - - -# The current API has gettz as a module function, although in fact it taps into -# a stateful class. So as a workaround for now, without changing the API, we -# will create a new "global" class instance the first time a user requests a -# timezone. Ugly, but adheres to the api. -# -# TODO: Remove after deprecation period. -_CLASS_ZONE_INSTANCE = [] - - -def get_zonefile_instance(new_instance=False): - """ - This is a convenience function which provides a :class:`ZoneInfoFile` - instance using the data provided by the ``dateutil`` package. By default, it - caches a single instance of the ZoneInfoFile object and returns that. - - :param new_instance: - If ``True``, a new instance of :class:`ZoneInfoFile` is instantiated and - used as the cached instance for the next call. Otherwise, new instances - are created only as necessary. - - :return: - Returns a :class:`ZoneInfoFile` object. - - .. versionadded:: 2.6 - """ - if new_instance: - zif = None - else: - zif = getattr(get_zonefile_instance, '_cached_instance', None) - - if zif is None: - zif = ZoneInfoFile(getzoneinfofile_stream()) - - get_zonefile_instance._cached_instance = zif - - return zif - - -def gettz(name): - """ - This retrieves a time zone from the local zoneinfo tarball that is packaged - with dateutil. - - :param name: - An IANA-style time zone name, as found in the zoneinfo file. - - :return: - Returns a :class:`dateutil.tz.tzfile` time zone object. - - .. warning:: - It is generally inadvisable to use this function, and it is only - provided for API compatibility with earlier versions. This is *not* - equivalent to ``dateutil.tz.gettz()``, which selects an appropriate - time zone based on the inputs, favoring system zoneinfo. This is ONLY - for accessing the dateutil-specific zoneinfo (which may be out of - date compared to the system zoneinfo). - - .. deprecated:: 2.6 - If you need to use a specific zoneinfofile over the system zoneinfo, - instantiate a :class:`dateutil.zoneinfo.ZoneInfoFile` object and call - :func:`dateutil.zoneinfo.ZoneInfoFile.get(name)` instead. - - Use :func:`get_zonefile_instance` to retrieve an instance of the - dateutil-provided zoneinfo. - """ - warnings.warn("zoneinfo.gettz() will be removed in future versions, " - "to use the dateutil-provided zoneinfo files, instantiate a " - "ZoneInfoFile object and use ZoneInfoFile.zones.get() " - "instead. See the documentation for details.", - DeprecationWarning) - - if len(_CLASS_ZONE_INSTANCE) == 0: - _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream())) - return _CLASS_ZONE_INSTANCE[0].zones.get(name) - - -def gettz_db_metadata(): - """ Get the zonefile metadata - - See `zonefile_metadata`_ - - :returns: - A dictionary with the database metadata - - .. deprecated:: 2.6 - See deprecation warning in :func:`zoneinfo.gettz`. To get metadata, - query the attribute ``zoneinfo.ZoneInfoFile.metadata``. - """ - warnings.warn("zoneinfo.gettz_db_metadata() will be removed in future " - "versions, to use the dateutil-provided zoneinfo files, " - "ZoneInfoFile object and query the 'metadata' attribute " - "instead. See the documentation for details.", - DeprecationWarning) - - if len(_CLASS_ZONE_INSTANCE) == 0: - _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream())) - return _CLASS_ZONE_INSTANCE[0].metadata diff --git a/apps/bitwarden_event_logs/lib/dateutil/zoneinfo/rebuild.py b/apps/bitwarden_event_logs/lib/dateutil/zoneinfo/rebuild.py deleted file mode 100755 index 684c6586..00000000 --- a/apps/bitwarden_event_logs/lib/dateutil/zoneinfo/rebuild.py +++ /dev/null @@ -1,75 +0,0 @@ -import logging -import os -import tempfile -import shutil -import json -from subprocess import check_call, check_output -from tarfile import TarFile - -from dateutil.zoneinfo import METADATA_FN, ZONEFILENAME - - -def rebuild(filename, tag=None, format="gz", zonegroups=[], metadata=None): - """Rebuild the internal timezone info in dateutil/zoneinfo/zoneinfo*tar* - - filename is the timezone tarball from ``ftp.iana.org/tz``. - - """ - tmpdir = tempfile.mkdtemp() - zonedir = os.path.join(tmpdir, "zoneinfo") - moduledir = os.path.dirname(__file__) - try: - with TarFile.open(filename) as tf: - for name in zonegroups: - tf.extract(name, tmpdir) - filepaths = [os.path.join(tmpdir, n) for n in zonegroups] - - _run_zic(zonedir, filepaths) - - # write metadata file - with open(os.path.join(zonedir, METADATA_FN), 'w') as f: - json.dump(metadata, f, indent=4, sort_keys=True) - target = os.path.join(moduledir, ZONEFILENAME) - with TarFile.open(target, "w:%s" % format) as tf: - for entry in os.listdir(zonedir): - entrypath = os.path.join(zonedir, entry) - tf.add(entrypath, entry) - finally: - shutil.rmtree(tmpdir) - - -def _run_zic(zonedir, filepaths): - """Calls the ``zic`` compiler in a compatible way to get a "fat" binary. - - Recent versions of ``zic`` default to ``-b slim``, while older versions - don't even have the ``-b`` option (but default to "fat" binaries). The - current version of dateutil does not support Version 2+ TZif files, which - causes problems when used in conjunction with "slim" binaries, so this - function is used to ensure that we always get a "fat" binary. - """ - - try: - help_text = check_output(["zic", "--help"]) - except OSError as e: - _print_on_nosuchfile(e) - raise - - if b"-b " in help_text: - bloat_args = ["-b", "fat"] - else: - bloat_args = [] - - check_call(["zic"] + bloat_args + ["-d", zonedir] + filepaths) - - -def _print_on_nosuchfile(e): - """Print helpful troubleshooting message - - e is an exception raised by subprocess.check_call() - - """ - if e.errno == 2: - logging.error( - "Could not find zic. Perhaps you need to install " - "libc-bin or some other package that provides it, " - "or it's not in your PATH?") diff --git a/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/INSTALLER deleted file mode 100755 index a1b589e3..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/LICENSE b/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/LICENSE deleted file mode 100755 index 311690c6..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/LICENSE +++ /dev/null @@ -1,49 +0,0 @@ -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF -hereby grants Licensee a nonexclusive, royalty-free, world-wide -license to reproduce, analyze, test, perform and/or display publicly, -prepare derivative works, distribute, and otherwise use Python -alone or in any derivative version, provided, however, that PSF's -License Agreement and PSF's notice of copyright, i.e., "Copyright (c) -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Python Software Foundation; -All Rights Reserved" are retained in Python alone or in any derivative -version prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - diff --git a/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/METADATA b/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/METADATA deleted file mode 100755 index f916e891..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/METADATA +++ /dev/null @@ -1,978 +0,0 @@ -Metadata-Version: 2.1 -Name: defusedxml -Version: 0.7.1 -Summary: XML bomb protection for Python stdlib modules -Home-page: https://github.com/tiran/defusedxml -Author: Christian Heimes -Author-email: christian@python.org -Maintainer: Christian Heimes -Maintainer-email: christian@python.org -License: PSFL -Download-URL: https://pypi.python.org/pypi/defusedxml -Keywords: xml bomb DoS -Platform: all -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: Python Software Foundation License -Classifier: Natural Language :: English -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Topic :: Text Processing :: Markup :: XML -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* - -=================================================== -defusedxml -- defusing XML bombs and other exploits -=================================================== - -.. image:: https://img.shields.io/pypi/v/defusedxml.svg - :target: https://pypi.org/project/defusedxml/ - :alt: Latest Version - -.. image:: https://img.shields.io/pypi/pyversions/defusedxml.svg - :target: https://pypi.org/project/defusedxml/ - :alt: Supported Python versions - -.. image:: https://travis-ci.org/tiran/defusedxml.svg?branch=master - :target: https://travis-ci.org/tiran/defusedxml - :alt: Travis CI - -.. image:: https://codecov.io/github/tiran/defusedxml/coverage.svg?branch=master - :target: https://codecov.io/github/tiran/defusedxml?branch=master - :alt: codecov - -.. image:: https://img.shields.io/pypi/dm/defusedxml.svg - :target: https://pypistats.org/packages/defusedxml - :alt: PyPI downloads - -.. image:: https://img.shields.io/badge/code%20style-black-000000.svg - :target: https://github.com/psf/black - :alt: Code style: black - -.. - - "It's just XML, what could probably go wrong?" - -Christian Heimes - -Synopsis -======== - -The results of an attack on a vulnerable XML library can be fairly dramatic. -With just a few hundred **Bytes** of XML data an attacker can occupy several -**Gigabytes** of memory within **seconds**. An attacker can also keep -CPUs busy for a long time with a small to medium size request. Under some -circumstances it is even possible to access local files on your -server, to circumvent a firewall, or to abuse services to rebound attacks to -third parties. - -The attacks use and abuse less common features of XML and its parsers. The -majority of developers are unacquainted with features such as processing -instructions and entity expansions that XML inherited from SGML. At best -they know about ```` from experience with HTML but they are not -aware that a document type definition (DTD) can generate an HTTP request -or load a file from the file system. - -None of the issues is new. They have been known for a long time. Billion -laughs was first reported in 2003. Nevertheless some XML libraries and -applications are still vulnerable and even heavy users of XML are -surprised by these features. It's hard to say whom to blame for the -situation. It's too short sighted to shift all blame on XML parsers and -XML libraries for using insecure default settings. After all they -properly implement XML specifications. Application developers must not rely -that a library is always configured for security and potential harmful data -by default. - - -.. contents:: Table of Contents - :depth: 2 - - -Attack vectors -============== - -billion laughs / exponential entity expansion ---------------------------------------------- - -The `Billion Laughs`_ attack -- also known as exponential entity expansion -- -uses multiple levels of nested entities. The original example uses 9 levels -of 10 expansions in each level to expand the string ``lol`` to a string of -3 * 10 :sup:`9` bytes, hence the name "billion laughs". The resulting string -occupies 3 GB (2.79 GiB) of memory; intermediate strings require additional -memory. Because most parsers don't cache the intermediate step for every -expansion it is repeated over and over again. It increases the CPU load even -more. - -An XML document of just a few hundred bytes can disrupt all services on a -machine within seconds. - -Example XML:: - - - - - - ]> - &d; - - -quadratic blowup entity expansion ---------------------------------- - -A quadratic blowup attack is similar to a `Billion Laughs`_ attack; it abuses -entity expansion, too. Instead of nested entities it repeats one large entity -with a couple of thousand chars over and over again. The attack isn't as -efficient as the exponential case but it avoids triggering countermeasures of -parsers against heavily nested entities. Some parsers limit the depth and -breadth of a single entity but not the total amount of expanded text -throughout an entire XML document. - -A medium-sized XML document with a couple of hundred kilobytes can require a -couple of hundred MB to several GB of memory. When the attack is combined -with some level of nested expansion an attacker is able to achieve a higher -ratio of success. - -:: - - - ]> - &a;&a;&a;... repeat - - -external entity expansion (remote) ----------------------------------- - -Entity declarations can contain more than just text for replacement. They can -also point to external resources by public identifiers or system identifiers. -System identifiers are standard URIs. When the URI is a URL (e.g. a -``http://`` locator) some parsers download the resource from the remote -location and embed them into the XML document verbatim. - -Simple example of a parsed external entity:: - - - ]> - - -The case of parsed external entities works only for valid XML content. The -XML standard also supports unparsed external entities with a -``NData declaration``. - -External entity expansion opens the door to plenty of exploits. An attacker -can abuse a vulnerable XML library and application to rebound and forward -network requests with the IP address of the server. It highly depends -on the parser and the application what kind of exploit is possible. For -example: - -* An attacker can circumvent firewalls and gain access to restricted - resources as all the requests are made from an internal and trustworthy - IP address, not from the outside. -* An attacker can abuse a service to attack, spy on or DoS your servers but - also third party services. The attack is disguised with the IP address of - the server and the attacker is able to utilize the high bandwidth of a big - machine. -* An attacker can exhaust additional resources on the machine, e.g. with - requests to a service that doesn't respond or responds with very large - files. -* An attacker may gain knowledge, when, how often and from which IP address - an XML document is accessed. -* An attacker could send mail from inside your network if the URL handler - supports ``smtp://`` URIs. - - -external entity expansion (local file) --------------------------------------- - -External entities with references to local files are a sub-case of external -entity expansion. It's listed as an extra attack because it deserves extra -attention. Some XML libraries such as lxml disable network access by default -but still allow entity expansion with local file access by default. Local -files are either referenced with a ``file://`` URL or by a file path (either -relative or absolute). - -An attacker may be able to access and download all files that can be read by -the application process. This may include critical configuration files, too. - -:: - - - ]> - - - -DTD retrieval -------------- - -This case is similar to external entity expansion, too. Some XML libraries -like Python's xml.dom.pulldom retrieve document type definitions from remote -or local locations. Several attack scenarios from the external entity case -apply to this issue as well. - -:: - - - - - - text - - - -Python XML Libraries -==================== - -.. csv-table:: vulnerabilities and features - :header: "kind", "sax", "etree", "minidom", "pulldom", "xmlrpc", "lxml", "genshi" - :widths: 24, 7, 8, 8, 7, 8, 8, 8 - :stub-columns: 0 - - "billion laughs", "**True**", "**True**", "**True**", "**True**", "**True**", "False (1)", "False (5)" - "quadratic blowup", "**True**", "**True**", "**True**", "**True**", "**True**", "**True**", "False (5)" - "external entity expansion (remote)", "**True**", "False (3)", "False (4)", "**True**", "false", "False (1)", "False (5)" - "external entity expansion (local file)", "**True**", "False (3)", "False (4)", "**True**", "false", "**True**", "False (5)" - "DTD retrieval", "**True**", "False", "False", "**True**", "false", "False (1)", "False" - "gzip bomb", "False", "False", "False", "False", "**True**", "**partly** (2)", "False" - "xpath support (7)", "False", "False", "False", "False", "False", "**True**", "False" - "xsl(t) support (7)", "False", "False", "False", "False", "False", "**True**", "False" - "xinclude support (7)", "False", "**True** (6)", "False", "False", "False", "**True** (6)", "**True**" - "C library", "expat", "expat", "expat", "expat", "expat", "libxml2", "expat" - -1. Lxml is protected against billion laughs attacks and doesn't do network - lookups by default. -2. libxml2 and lxml are not directly vulnerable to gzip decompression bombs - but they don't protect you against them either. -3. xml.etree doesn't expand entities and raises a ParserError when an entity - occurs. -4. minidom doesn't expand entities and simply returns the unexpanded entity - verbatim. -5. genshi.input of genshi 0.6 doesn't support entity expansion and raises a - ParserError when an entity occurs. -6. Library has (limited) XInclude support but requires an additional step to - process inclusion. -7. These are features but they may introduce exploitable holes, see - `Other things to consider`_ - - -Settings in standard library ----------------------------- - - -xml.sax.handler Features -........................ - -feature_external_ges (http://xml.org/sax/features/external-general-entities) - disables external entity expansion - -feature_external_pes (http://xml.org/sax/features/external-parameter-entities) - the option is ignored and doesn't modify any functionality - -DOM xml.dom.xmlbuilder.Options -.............................. - -external_parameter_entities - ignored - -external_general_entities - ignored - -external_dtd_subset - ignored - -entities - unsure - - -defusedxml -========== - -The `defusedxml package`_ (`defusedxml on PyPI`_) -contains several Python-only workarounds and fixes -for denial of service and other vulnerabilities in Python's XML libraries. -In order to benefit from the protection you just have to import and use the -listed functions / classes from the right defusedxml module instead of the -original module. Merely `defusedxml.xmlrpc`_ is implemented as monkey patch. - -Instead of:: - - >>> from xml.etree.ElementTree import parse - >>> et = parse(xmlfile) - -alter code to:: - - >>> from defusedxml.ElementTree import parse - >>> et = parse(xmlfile) - -Additionally the package has an **untested** function to monkey patch -all stdlib modules with ``defusedxml.defuse_stdlib()``. - -All functions and parser classes accept three additional keyword arguments. -They return either the same objects as the original functions or compatible -subclasses. - -forbid_dtd (default: False) - disallow XML with a ```` processing instruction and raise a - *DTDForbidden* exception when a DTD processing instruction is found. - -forbid_entities (default: True) - disallow XML with ```` declarations inside the DTD and raise an - *EntitiesForbidden* exception when an entity is declared. - -forbid_external (default: True) - disallow any access to remote or local resources in external entities - or DTD and raising an *ExternalReferenceForbidden* exception when a DTD - or entity references an external resource. - - -defusedxml (package) --------------------- - -DefusedXmlException, DTDForbidden, EntitiesForbidden, -ExternalReferenceForbidden, NotSupportedError - -defuse_stdlib() (*experimental*) - - -defusedxml.cElementTree ------------------------ - -**NOTE** ``defusedxml.cElementTree`` is deprecated and will be removed in a -future release. Import from ``defusedxml.ElementTree`` instead. - -parse(), iterparse(), fromstring(), XMLParser - - -defusedxml.ElementTree ------------------------ - -parse(), iterparse(), fromstring(), XMLParser - - -defusedxml.expatreader ----------------------- - -create_parser(), DefusedExpatParser - - -defusedxml.sax --------------- - -parse(), parseString(), make_parser() - - -defusedxml.expatbuilder ------------------------ - -parse(), parseString(), DefusedExpatBuilder, DefusedExpatBuilderNS - - -defusedxml.minidom ------------------- - -parse(), parseString() - - -defusedxml.pulldom ------------------- - -parse(), parseString() - - -defusedxml.xmlrpc ------------------ - -The fix is implemented as monkey patch for the stdlib's xmlrpc package (3.x) -or xmlrpclib module (2.x). The function `monkey_patch()` enables the fixes, -`unmonkey_patch()` removes the patch and puts the code in its former state. - -The monkey patch protects against XML related attacks as well as -decompression bombs and excessively large requests or responses. The default -setting is 30 MB for requests, responses and gzip decompression. You can -modify the default by changing the module variable `MAX_DATA`. A value of -`-1` disables the limit. - - -defusedxml.lxml ---------------- - -**DEPRECATED** The module is deprecated and will be removed in a future -release. - -The module acts as an *example* how you could protect code that uses -lxml.etree. It implements a custom Element class that filters out -Entity instances, a custom parser factory and a thread local storage for -parser instances. It also has a check_docinfo() function which inspects -a tree for internal or external DTDs and entity declarations. In order to -check for entities lxml > 3.0 is required. - -parse(), fromstring() -RestrictedElement, GlobalParserTLS, getDefaultParser(), check_docinfo() - - -defusedexpat -============ - -The `defusedexpat package`_ (`defusedexpat on PyPI`_) -comes with binary extensions and a -`modified expat`_ library instead of the standard `expat parser`_. It's -basically a stand-alone version of the patches for Python's standard -library C extensions. - -Modifications in expat ----------------------- - -new definitions:: - - XML_BOMB_PROTECTION - XML_DEFAULT_MAX_ENTITY_INDIRECTIONS - XML_DEFAULT_MAX_ENTITY_EXPANSIONS - XML_DEFAULT_RESET_DTD - -new XML_FeatureEnum members:: - - XML_FEATURE_MAX_ENTITY_INDIRECTIONS - XML_FEATURE_MAX_ENTITY_EXPANSIONS - XML_FEATURE_IGNORE_DTD - -new XML_Error members:: - - XML_ERROR_ENTITY_INDIRECTIONS - XML_ERROR_ENTITY_EXPANSION - -new API functions:: - - int XML_GetFeature(XML_Parser parser, - enum XML_FeatureEnum feature, - long *value); - int XML_SetFeature(XML_Parser parser, - enum XML_FeatureEnum feature, - long value); - int XML_GetFeatureDefault(enum XML_FeatureEnum feature, - long *value); - int XML_SetFeatureDefault(enum XML_FeatureEnum feature, - long value); - -XML_FEATURE_MAX_ENTITY_INDIRECTIONS - Limit the amount of indirections that are allowed to occur during the - expansion of a nested entity. A counter starts when an entity reference - is encountered. It resets after the entity is fully expanded. The limit - protects the parser against exponential entity expansion attacks (aka - billion laughs attack). When the limit is exceeded the parser stops and - fails with `XML_ERROR_ENTITY_INDIRECTIONS`. - A value of 0 disables the protection. - - Supported range - 0 .. UINT_MAX - Default - 40 - -XML_FEATURE_MAX_ENTITY_EXPANSIONS - Limit the total length of all entity expansions throughout the entire - document. The lengths of all entities are accumulated in a parser variable. - The setting protects against quadratic blowup attacks (lots of expansions - of a large entity declaration). When the sum of all entities exceeds - the limit, the parser stops and fails with `XML_ERROR_ENTITY_EXPANSION`. - A value of 0 disables the protection. - - Supported range - 0 .. UINT_MAX - Default - 8 MiB - -XML_FEATURE_RESET_DTD - Reset all DTD information after the block has been parsed. When - the flag is set (default: false) all DTD information after the - endDoctypeDeclHandler has been called. The flag can be set inside the - endDoctypeDeclHandler. Without DTD information any entity reference in - the document body leads to `XML_ERROR_UNDEFINED_ENTITY`. - - Supported range - 0, 1 - Default - 0 - - -How to avoid XML vulnerabilities -================================ - -Best practices --------------- - -* Don't allow DTDs -* Don't expand entities -* Don't resolve externals -* Limit parse depth -* Limit total input size -* Limit parse time -* Favor a SAX or iterparse-like parser for potential large data -* Validate and properly quote arguments to XSL transformations and - XPath queries -* Don't use XPath expression from untrusted sources -* Don't apply XSL transformations that come untrusted sources - -(based on Brad Hill's `Attacking XML Security`_) - - -Other things to consider -======================== - -XML, XML parsers and processing libraries have more features and possible -issue that could lead to DoS vulnerabilities or security exploits in -applications. I have compiled an incomplete list of theoretical issues that -need further research and more attention. The list is deliberately pessimistic -and a bit paranoid, too. It contains things that might go wrong under daffy -circumstances. - - -attribute blowup / hash collision attack ----------------------------------------- - -XML parsers may use an algorithm with quadratic runtime O(n :sup:`2`) to -handle attributes and namespaces. If it uses hash tables (dictionaries) to -store attributes and namespaces the implementation may be vulnerable to -hash collision attacks, thus reducing the performance to O(n :sup:`2`) again. -In either case an attacker is able to forge a denial of service attack with -an XML document that contains thousands upon thousands of attributes in -a single node. - -I haven't researched yet if expat, pyexpat or libxml2 are vulnerable. - - -decompression bomb ------------------- - -The issue of decompression bombs (aka `ZIP bomb`_) apply to all XML libraries -that can parse compressed XML stream like gzipped HTTP streams or LZMA-ed -files. For an attacker it can reduce the amount of transmitted data by three -magnitudes or more. Gzip is able to compress 1 GiB zeros to roughly 1 MB, -lzma is even better:: - - $ dd if=/dev/zero bs=1M count=1024 | gzip > zeros.gz - $ dd if=/dev/zero bs=1M count=1024 | lzma -z > zeros.xy - $ ls -sh zeros.* - 1020K zeros.gz - 148K zeros.xy - -None of Python's standard XML libraries decompress streams except for -``xmlrpclib``. The module is vulnerable -to decompression bombs. - -lxml can load and process compressed data through libxml2 transparently. -libxml2 can handle even very large blobs of compressed data efficiently -without using too much memory. But it doesn't protect applications from -decompression bombs. A carefully written SAX or iterparse-like approach can -be safe. - - -Processing Instruction ----------------------- - -`PI`_'s like:: - - - -may impose more threats for XML processing. It depends if and how a -processor handles processing instructions. The issue of URL retrieval with -network or local file access apply to processing instructions, too. - - -Other DTD features ------------------- - -`DTD`_ has more features like ````. I haven't researched how -these features may be a security threat. - - -XPath ------ - -XPath statements may introduce DoS vulnerabilities. Code should never execute -queries from untrusted sources. An attacker may also be able to create an XML -document that makes certain XPath queries costly or resource hungry. - - -XPath injection attacks ------------------------ - -XPath injeciton attacks pretty much work like SQL injection attacks. -Arguments to XPath queries must be quoted and validated properly, especially -when they are taken from the user. The page `Avoid the dangers of XPath injection`_ -list some ramifications of XPath injections. - -Python's standard library doesn't have XPath support. Lxml supports -parameterized XPath queries which does proper quoting. You just have to use -its xpath() method correctly:: - - # DON'T - >>> tree.xpath("/tag[@id='%s']" % value) - - # instead do - >>> tree.xpath("/tag[@id=$tagid]", tagid=name) - - -XInclude --------- - -`XML Inclusion`_ is another way to load and include external files:: - - - - - -This feature should be disabled when XML files from an untrusted source are -processed. Some Python XML libraries and libxml2 support XInclude but don't -have an option to sandbox inclusion and limit it to allowed directories. - - -XMLSchema location ------------------- - -A validating XML parser may download schema files from the information in a -``xsi:schemaLocation`` attribute. - -:: - - - - - -XSL Transformation ------------------- - -You should keep in mind that XSLT is a Turing complete language. Never -process XSLT code from unknown or untrusted source! XSLT processors may -allow you to interact with external resources in ways you can't even imagine. -Some processors even support extensions that allow read/write access to file -system, access to JRE objects or scripting with Jython. - -Example from `Attacking XML Security`_ for Xalan-J:: - - - - - - - - - - - -Related CVEs -============ - -CVE-2013-1664 - Unrestricted entity expansion induces DoS vulnerabilities in Python XML - libraries (XML bomb) - -CVE-2013-1665 - External entity expansion in Python XML libraries inflicts potential - security flaws and DoS vulnerabilities - - -Other languages / frameworks -============================= - -Several other programming languages and frameworks are vulnerable as well. A -couple of them are affected by the fact that libxml2 up to 2.9.0 has no -protection against quadratic blowup attacks. Most of them have potential -dangerous default settings for entity expansion and external entities, too. - -Perl ----- - -Perl's XML::Simple is vulnerable to quadratic entity expansion and external -entity expansion (both local and remote). - - -Ruby ----- - -Ruby's REXML document parser is vulnerable to entity expansion attacks -(both quadratic and exponential) but it doesn't do external entity -expansion by default. In order to counteract entity expansion you have to -disable the feature:: - - REXML::Document.entity_expansion_limit = 0 - -libxml-ruby and hpricot don't expand entities in their default configuration. - - -PHP ---- - -PHP's SimpleXML API is vulnerable to quadratic entity expansion and loads -entities from local and remote resources. The option ``LIBXML_NONET`` disables -network access but still allows local file access. ``LIBXML_NOENT`` seems to -have no effect on entity expansion in PHP 5.4.6. - - -C# / .NET / Mono ----------------- - -Information in `XML DoS and Defenses (MSDN)`_ suggest that .NET is -vulnerable with its default settings. The article contains code snippets -how to create a secure XML reader:: - - XmlReaderSettings settings = new XmlReaderSettings(); - settings.ProhibitDtd = false; - settings.MaxCharactersFromEntities = 1024; - settings.XmlResolver = null; - XmlReader reader = XmlReader.Create(stream, settings); - - -Java ----- - -Untested. The documentation of Xerces and its `Xerces SecurityMananger`_ -sounds like Xerces is also vulnerable to billion laugh attacks with its -default settings. It also does entity resolving when an -``org.xml.sax.EntityResolver`` is configured. I'm not yet sure about the -default setting here. - -Java specialists suggest to have a custom builder factory:: - - DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); - builderFactory.setXIncludeAware(False); - builderFactory.setExpandEntityReferences(False); - builderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, True); - # either - builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", True); - # or if you need DTDs - builderFactory.setFeature("http://xml.org/sax/features/external-general-entities", False); - builderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", False); - builderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", False); - builderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", False); - - -TODO -==== - -* DOM: Use xml.dom.xmlbuilder options for entity handling -* SAX: take feature_external_ges and feature_external_pes (?) into account -* test experimental monkey patching of stdlib modules -* improve documentation - - -License -======= - -Copyright (c) 2013-2017 by Christian Heimes - -Licensed to PSF under a Contributor Agreement. - -See https://www.python.org/psf/license for licensing details. - - -Acknowledgements -================ - -Brett Cannon (Python Core developer) - review and code cleanup - -Antoine Pitrou (Python Core developer) - code review - -Aaron Patterson, Ben Murphy and Michael Koziarski (Ruby community) - Many thanks to Aaron, Ben and Michael from the Ruby community for their - report and assistance. - -Thierry Carrez (OpenStack) - Many thanks to Thierry for his report to the Python Security Response - Team on behalf of the OpenStack security team. - -Carl Meyer (Django) - Many thanks to Carl for his report to PSRT on behalf of the Django security - team. - -Daniel Veillard (libxml2) - Many thanks to Daniel for his insight and assistance with libxml2. - -semantics GmbH (https://www.semantics.de/) - Many thanks to my employer semantics for letting me work on the issue - during working hours as part of semantics's open source initiative. - - -References -========== - -* `XML DoS and Defenses (MSDN)`_ -* `Billion Laughs`_ on Wikipedia -* `ZIP bomb`_ on Wikipedia -* `Configure SAX parsers for secure processing`_ -* `Testing for XML Injection`_ - -.. _defusedxml package: https://github.com/tiran/defusedxml -.. _defusedxml on PyPI: https://pypi.python.org/pypi/defusedxml -.. _defusedexpat package: https://github.com/tiran/defusedexpat -.. _defusedexpat on PyPI: https://pypi.python.org/pypi/defusedexpat -.. _modified expat: https://github.com/tiran/expat -.. _expat parser: http://expat.sourceforge.net/ -.. _Attacking XML Security: https://www.isecpartners.com/media/12976/iSEC-HILL-Attacking-XML-Security-bh07.pdf -.. _Billion Laughs: https://en.wikipedia.org/wiki/Billion_laughs -.. _XML DoS and Defenses (MSDN): https://msdn.microsoft.com/en-us/magazine/ee335713.aspx -.. _ZIP bomb: https://en.wikipedia.org/wiki/Zip_bomb -.. _DTD: https://en.wikipedia.org/wiki/Document_Type_Definition -.. _PI: https://en.wikipedia.org/wiki/Processing_Instruction -.. _Avoid the dangers of XPath injection: http://www.ibm.com/developerworks/xml/library/x-xpathinjection/index.html -.. _Configure SAX parsers for secure processing: http://www.ibm.com/developerworks/xml/library/x-tipcfsx/index.html -.. _Testing for XML Injection: https://www.owasp.org/index.php/Testing_for_XML_Injection_(OWASP-DV-008) -.. _Xerces SecurityMananger: https://xerces.apache.org/xerces2-j/javadocs/xerces2/org/apache/xerces/util/SecurityManager.html -.. _XML Inclusion: https://www.w3.org/TR/xinclude/#include_element - -Changelog -========= - -defusedxml 0.7.1 ---------------------- - -*Release date: 08-Mar-2021* - -- Fix regression ``defusedxml.ElementTree.ParseError`` (#63) - The ``ParseError`` exception is now the same class object as - ``xml.etree.ElementTree.ParseError`` again. - - -defusedxml 0.7.0 ----------------- - -*Release date: 4-Mar-2021* - -- No changes - - -defusedxml 0.7.0rc2 -------------------- - -*Release date: 12-Jan-2021* - -- Re-add and deprecate ``defusedxml.cElementTree`` -- Use GitHub Actions instead of TravisCI -- Restore ``ElementTree`` attribute of ``xml.etree`` module after patching - -defusedxml 0.7.0rc1 -------------------- - -*Release date: 04-May-2020* - -- Add support for Python 3.9 -- ``defusedxml.cElementTree`` is not available with Python 3.9. -- Python 2 is deprecate. Support for Python 2 will be removed in 0.8.0. - - -defusedxml 0.6.0 ----------------- - -*Release date: 17-Apr-2019* - -- Increase test coverage. -- Add badges to README. - - -defusedxml 0.6.0rc1 -------------------- - -*Release date: 14-Apr-2019* - -- Test on Python 3.7 stable and 3.8-dev -- Drop support for Python 3.4 -- No longer pass *html* argument to XMLParse. It has been deprecated and - ignored for a long time. The DefusedXMLParser still takes a html argument. - A deprecation warning is issued when the argument is False and a TypeError - when it's True. -- defusedxml now fails early when pyexpat stdlib module is not available or - broken. -- defusedxml.ElementTree.__all__ now lists ParseError as public attribute. -- The defusedxml.ElementTree and defusedxml.cElementTree modules had a typo - and used XMLParse instead of XMLParser as an alias for DefusedXMLParser. - Both the old and fixed name are now available. - - -defusedxml 0.5.0 ----------------- - -*Release date: 07-Feb-2017* - -- No changes - - -defusedxml 0.5.0.rc1 --------------------- - -*Release date: 28-Jan-2017* - -- Add compatibility with Python 3.6 -- Drop support for Python 2.6, 3.1, 3.2, 3.3 -- Fix lxml tests (XMLSyntaxError: Detected an entity reference loop) - - -defusedxml 0.4.1 ----------------- - -*Release date: 28-Mar-2013* - -- Add more demo exploits, e.g. python_external.py and Xalan XSLT demos. -- Improved documentation. - - -defusedxml 0.4 --------------- - -*Release date: 25-Feb-2013* - -- As per http://seclists.org/oss-sec/2013/q1/340 please REJECT - CVE-2013-0278, CVE-2013-0279 and CVE-2013-0280 and use CVE-2013-1664, - CVE-2013-1665 for OpenStack/etc. -- Add missing parser_list argument to sax.make_parser(). The argument is - ignored, though. (thanks to Florian Apolloner) -- Add demo exploit for external entity attack on Python's SAX parser, XML-RPC - and WebDAV. - - -defusedxml 0.3 --------------- - -*Release date: 19-Feb-2013* - -- Improve documentation - - -defusedxml 0.2 --------------- - -*Release date: 15-Feb-2013* - -- Rename ExternalEntitiesForbidden to ExternalReferenceForbidden -- Rename defusedxml.lxml.check_dtd() to check_docinfo() -- Unify argument names in callbacks -- Add arguments and formatted representation to exceptions -- Add forbid_external argument to all functions and classes -- More tests -- LOTS of documentation -- Add example code for other languages (Ruby, Perl, PHP) and parsers (Genshi) -- Add protection against XML and gzip attacks to xmlrpclib - -defusedxml 0.1 --------------- - -*Release date: 08-Feb-2013* - -- Initial and internal release for PSRT review - - diff --git a/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/RECORD b/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/RECORD deleted file mode 100755 index 6c3d73e3..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/RECORD +++ /dev/null @@ -1,18 +0,0 @@ -defusedxml-0.7.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -defusedxml-0.7.1.dist-info/LICENSE,sha256=uAzp2oxCofkQeWJ_u-K_JyEK4Qig_-Xwd9WwjgdsJMg,2409 -defusedxml-0.7.1.dist-info/METADATA,sha256=Np0872SHDa-En7pxHLjQWn7-PI2asPdjrcNAef43i7E,32518 -defusedxml-0.7.1.dist-info/RECORD,, -defusedxml-0.7.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -defusedxml-0.7.1.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 -defusedxml-0.7.1.dist-info/top_level.txt,sha256=QGHa90F50pVKhWSFlERI0jtSKtqDiGyfeZX7dQNZAAw,11 -defusedxml/ElementTree.py,sha256=GLSqpCz58oXGPGyzf_HylsPS9_dcGVP5SN4dK7yvyPw,4640 -defusedxml/__init__.py,sha256=RczeaVJG64p2Fgy1jlCzbuRdchEPnEaCBrxgk8JJ_pM,1444 -defusedxml/cElementTree.py,sha256=PpaKMh3rU29sY8amAK4fzHQKl8gcAYD0h1LCoW62Rtk,1449 -defusedxml/common.py,sha256=3d26jNW4fNXzgjWhvUfs83Afiz5EVxFDupQbugkSMZc,4036 -defusedxml/expatbuilder.py,sha256=b4Q05vsBMJ5StkiTFf4my2rGGo1gZyEl_hC5MeFTOAA,3732 -defusedxml/expatreader.py,sha256=KOpSrwkSvj5SGOY9pTXOM26Dnz00rsJt33WueVvzpvc,2196 -defusedxml/lxml.py,sha256=HW-LFKdrfMRzHdi0Vcucq4-n8yz7v_OQwEQWFg1JQYA,4940 -defusedxml/minidom.py,sha256=3QcgygVwJqcWDQ3IZ2iol8zsH4cx3BRX70SPcd0bG2g,1884 -defusedxml/pulldom.py,sha256=DYj2D2lc7xoxZ38gfzujXmdznd8ovzDqGFXqyXbtxjk,1170 -defusedxml/sax.py,sha256=-SF08Msc2mWEYAMw62pJ5FMwWccOctFSnQwDLYLLlVE,1477 -defusedxml/xmlrpc.py,sha256=7rZQey3tqXcc1hrrM3RprOICU6fiFny9B9l4nmTioxA,5364 diff --git a/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/REQUESTED deleted file mode 100755 index e69de29b..00000000 diff --git a/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/WHEEL deleted file mode 100755 index ef99c6cf..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml-0.7.1.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.34.2) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/apps/bitwarden_event_logs/lib/defusedxml/ElementTree.py b/apps/bitwarden_event_logs/lib/defusedxml/ElementTree.py deleted file mode 100755 index 5ba765f1..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml/ElementTree.py +++ /dev/null @@ -1,154 +0,0 @@ -# defusedxml -# -# Copyright (c) 2013 by Christian Heimes -# Licensed to PSF under a Contributor Agreement. -# See https://www.python.org/psf/license for licensing details. -"""Defused xml.etree.ElementTree facade -""" -from __future__ import print_function, absolute_import - -import sys -import warnings -from xml.etree.ElementTree import ParseError -from xml.etree.ElementTree import TreeBuilder as _TreeBuilder -from xml.etree.ElementTree import parse as _parse -from xml.etree.ElementTree import tostring - -from .common import PY3 - -if PY3: - import importlib -else: - from xml.etree.ElementTree import XMLParser as _XMLParser - from xml.etree.ElementTree import iterparse as _iterparse - - -from .common import ( - DTDForbidden, - EntitiesForbidden, - ExternalReferenceForbidden, - _generate_etree_functions, -) - -__origin__ = "xml.etree.ElementTree" - - -def _get_py3_cls(): - """Python 3.3 hides the pure Python code but defusedxml requires it. - - The code is based on test.support.import_fresh_module(). - """ - pymodname = "xml.etree.ElementTree" - cmodname = "_elementtree" - - pymod = sys.modules.pop(pymodname, None) - cmod = sys.modules.pop(cmodname, None) - - sys.modules[cmodname] = None - try: - pure_pymod = importlib.import_module(pymodname) - finally: - # restore module - sys.modules[pymodname] = pymod - if cmod is not None: - sys.modules[cmodname] = cmod - else: - sys.modules.pop(cmodname, None) - # restore attribute on original package - etree_pkg = sys.modules["xml.etree"] - if pymod is not None: - etree_pkg.ElementTree = pymod - elif hasattr(etree_pkg, "ElementTree"): - del etree_pkg.ElementTree - - _XMLParser = pure_pymod.XMLParser - _iterparse = pure_pymod.iterparse - # patch pure module to use ParseError from C extension - pure_pymod.ParseError = ParseError - - return _XMLParser, _iterparse - - -if PY3: - _XMLParser, _iterparse = _get_py3_cls() - - -_sentinel = object() - - -class DefusedXMLParser(_XMLParser): - def __init__( - self, - html=_sentinel, - target=None, - encoding=None, - forbid_dtd=False, - forbid_entities=True, - forbid_external=True, - ): - # Python 2.x old style class - _XMLParser.__init__(self, target=target, encoding=encoding) - if html is not _sentinel: - # the 'html' argument has been deprecated and ignored in all - # supported versions of Python. Python 3.8 finally removed it. - if html: - raise TypeError("'html=True' is no longer supported.") - else: - warnings.warn( - "'html' keyword argument is no longer supported. Pass " - "in arguments as keyword arguments.", - category=DeprecationWarning, - ) - - self.forbid_dtd = forbid_dtd - self.forbid_entities = forbid_entities - self.forbid_external = forbid_external - if PY3: - parser = self.parser - else: - parser = self._parser - if self.forbid_dtd: - parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl - if self.forbid_entities: - parser.EntityDeclHandler = self.defused_entity_decl - parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl - if self.forbid_external: - parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler - - def defused_start_doctype_decl(self, name, sysid, pubid, has_internal_subset): - raise DTDForbidden(name, sysid, pubid) - - def defused_entity_decl( - self, name, is_parameter_entity, value, base, sysid, pubid, notation_name - ): - raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name) - - def defused_unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): - # expat 1.2 - raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name) # pragma: no cover - - def defused_external_entity_ref_handler(self, context, base, sysid, pubid): - raise ExternalReferenceForbidden(context, base, sysid, pubid) - - -# aliases -# XMLParse is a typo, keep it for backwards compatibility -XMLTreeBuilder = XMLParse = XMLParser = DefusedXMLParser - -parse, iterparse, fromstring = _generate_etree_functions( - DefusedXMLParser, _TreeBuilder, _parse, _iterparse -) -XML = fromstring - - -__all__ = [ - "ParseError", - "XML", - "XMLParse", - "XMLParser", - "XMLTreeBuilder", - "fromstring", - "iterparse", - "parse", - "tostring", -] diff --git a/apps/bitwarden_event_logs/lib/defusedxml/__init__.py b/apps/bitwarden_event_logs/lib/defusedxml/__init__.py deleted file mode 100755 index 4b5a2300..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml/__init__.py +++ /dev/null @@ -1,67 +0,0 @@ -# defusedxml -# -# Copyright (c) 2013 by Christian Heimes -# Licensed to PSF under a Contributor Agreement. -# See https://www.python.org/psf/license for licensing details. -"""Defuse XML bomb denial of service vulnerabilities -""" -from __future__ import print_function, absolute_import - -import warnings - -from .common import ( - DefusedXmlException, - DTDForbidden, - EntitiesForbidden, - ExternalReferenceForbidden, - NotSupportedError, - _apply_defusing, -) - - -def defuse_stdlib(): - """Monkey patch and defuse all stdlib packages - - :warning: The monkey patch is an EXPERIMETNAL feature. - """ - defused = {} - - with warnings.catch_warnings(): - from . import cElementTree - from . import ElementTree - from . import minidom - from . import pulldom - from . import sax - from . import expatbuilder - from . import expatreader - from . import xmlrpc - - xmlrpc.monkey_patch() - defused[xmlrpc] = None - - defused_mods = [ - cElementTree, - ElementTree, - minidom, - pulldom, - sax, - expatbuilder, - expatreader, - ] - - for defused_mod in defused_mods: - stdlib_mod = _apply_defusing(defused_mod) - defused[defused_mod] = stdlib_mod - - return defused - - -__version__ = "0.7.1" - -__all__ = [ - "DefusedXmlException", - "DTDForbidden", - "EntitiesForbidden", - "ExternalReferenceForbidden", - "NotSupportedError", -] diff --git a/apps/bitwarden_event_logs/lib/defusedxml/cElementTree.py b/apps/bitwarden_event_logs/lib/defusedxml/cElementTree.py deleted file mode 100755 index 84670c68..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml/cElementTree.py +++ /dev/null @@ -1,62 +0,0 @@ -# defusedxml -# -# Copyright (c) 2013 by Christian Heimes -# Licensed to PSF under a Contributor Agreement. -# See https://www.python.org/psf/license for licensing details. -"""Defused xml.etree.cElementTree -""" -from __future__ import absolute_import - -import warnings - -from .common import _generate_etree_functions - -from xml.etree.cElementTree import TreeBuilder as _TreeBuilder -from xml.etree.cElementTree import parse as _parse -from xml.etree.cElementTree import tostring - -# iterparse from ElementTree! -from xml.etree.ElementTree import iterparse as _iterparse - -# This module is an alias for ElementTree just like xml.etree.cElementTree -from .ElementTree import ( - XML, - XMLParse, - XMLParser, - XMLTreeBuilder, - fromstring, - iterparse, - parse, - tostring, - DefusedXMLParser, - ParseError, -) - -__origin__ = "xml.etree.cElementTree" - - -warnings.warn( - "defusedxml.cElementTree is deprecated, import from defusedxml.ElementTree instead.", - category=DeprecationWarning, - stacklevel=2, -) - -# XMLParse is a typo, keep it for backwards compatibility -XMLTreeBuilder = XMLParse = XMLParser = DefusedXMLParser - -parse, iterparse, fromstring = _generate_etree_functions( - DefusedXMLParser, _TreeBuilder, _parse, _iterparse -) -XML = fromstring - -__all__ = [ - "ParseError", - "XML", - "XMLParse", - "XMLParser", - "XMLTreeBuilder", - "fromstring", - "iterparse", - "parse", - "tostring", -] diff --git a/apps/bitwarden_event_logs/lib/defusedxml/common.py b/apps/bitwarden_event_logs/lib/defusedxml/common.py deleted file mode 100755 index 5ceda1fb..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml/common.py +++ /dev/null @@ -1,129 +0,0 @@ -# defusedxml -# -# Copyright (c) 2013 by Christian Heimes -# Licensed to PSF under a Contributor Agreement. -# See https://www.python.org/psf/license for licensing details. -"""Common constants, exceptions and helpe functions -""" -import sys -import xml.parsers.expat - -PY3 = sys.version_info[0] == 3 - -# Fail early when pyexpat is not installed correctly -if not hasattr(xml.parsers.expat, "ParserCreate"): - raise ImportError("pyexpat") # pragma: no cover - - -class DefusedXmlException(ValueError): - """Base exception""" - - def __repr__(self): - return str(self) - - -class DTDForbidden(DefusedXmlException): - """Document type definition is forbidden""" - - def __init__(self, name, sysid, pubid): - super(DTDForbidden, self).__init__() - self.name = name - self.sysid = sysid - self.pubid = pubid - - def __str__(self): - tpl = "DTDForbidden(name='{}', system_id={!r}, public_id={!r})" - return tpl.format(self.name, self.sysid, self.pubid) - - -class EntitiesForbidden(DefusedXmlException): - """Entity definition is forbidden""" - - def __init__(self, name, value, base, sysid, pubid, notation_name): - super(EntitiesForbidden, self).__init__() - self.name = name - self.value = value - self.base = base - self.sysid = sysid - self.pubid = pubid - self.notation_name = notation_name - - def __str__(self): - tpl = "EntitiesForbidden(name='{}', system_id={!r}, public_id={!r})" - return tpl.format(self.name, self.sysid, self.pubid) - - -class ExternalReferenceForbidden(DefusedXmlException): - """Resolving an external reference is forbidden""" - - def __init__(self, context, base, sysid, pubid): - super(ExternalReferenceForbidden, self).__init__() - self.context = context - self.base = base - self.sysid = sysid - self.pubid = pubid - - def __str__(self): - tpl = "ExternalReferenceForbidden(system_id='{}', public_id={})" - return tpl.format(self.sysid, self.pubid) - - -class NotSupportedError(DefusedXmlException): - """The operation is not supported""" - - -def _apply_defusing(defused_mod): - assert defused_mod is sys.modules[defused_mod.__name__] - stdlib_name = defused_mod.__origin__ - __import__(stdlib_name, {}, {}, ["*"]) - stdlib_mod = sys.modules[stdlib_name] - stdlib_names = set(dir(stdlib_mod)) - for name, obj in vars(defused_mod).items(): - if name.startswith("_") or name not in stdlib_names: - continue - setattr(stdlib_mod, name, obj) - return stdlib_mod - - -def _generate_etree_functions(DefusedXMLParser, _TreeBuilder, _parse, _iterparse): - """Factory for functions needed by etree, dependent on whether - cElementTree or ElementTree is used.""" - - def parse(source, parser=None, forbid_dtd=False, forbid_entities=True, forbid_external=True): - if parser is None: - parser = DefusedXMLParser( - target=_TreeBuilder(), - forbid_dtd=forbid_dtd, - forbid_entities=forbid_entities, - forbid_external=forbid_external, - ) - return _parse(source, parser) - - def iterparse( - source, - events=None, - parser=None, - forbid_dtd=False, - forbid_entities=True, - forbid_external=True, - ): - if parser is None: - parser = DefusedXMLParser( - target=_TreeBuilder(), - forbid_dtd=forbid_dtd, - forbid_entities=forbid_entities, - forbid_external=forbid_external, - ) - return _iterparse(source, events, parser) - - def fromstring(text, forbid_dtd=False, forbid_entities=True, forbid_external=True): - parser = DefusedXMLParser( - target=_TreeBuilder(), - forbid_dtd=forbid_dtd, - forbid_entities=forbid_entities, - forbid_external=forbid_external, - ) - parser.feed(text) - return parser.close() - - return parse, iterparse, fromstring diff --git a/apps/bitwarden_event_logs/lib/defusedxml/expatbuilder.py b/apps/bitwarden_event_logs/lib/defusedxml/expatbuilder.py deleted file mode 100755 index 7bfc57e4..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml/expatbuilder.py +++ /dev/null @@ -1,107 +0,0 @@ -# defusedxml -# -# Copyright (c) 2013 by Christian Heimes -# Licensed to PSF under a Contributor Agreement. -# See https://www.python.org/psf/license for licensing details. -"""Defused xml.dom.expatbuilder -""" -from __future__ import print_function, absolute_import - -from xml.dom.expatbuilder import ExpatBuilder as _ExpatBuilder -from xml.dom.expatbuilder import Namespaces as _Namespaces - -from .common import DTDForbidden, EntitiesForbidden, ExternalReferenceForbidden - -__origin__ = "xml.dom.expatbuilder" - - -class DefusedExpatBuilder(_ExpatBuilder): - """Defused document builder""" - - def __init__( - self, options=None, forbid_dtd=False, forbid_entities=True, forbid_external=True - ): - _ExpatBuilder.__init__(self, options) - self.forbid_dtd = forbid_dtd - self.forbid_entities = forbid_entities - self.forbid_external = forbid_external - - def defused_start_doctype_decl(self, name, sysid, pubid, has_internal_subset): - raise DTDForbidden(name, sysid, pubid) - - def defused_entity_decl( - self, name, is_parameter_entity, value, base, sysid, pubid, notation_name - ): - raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name) - - def defused_unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): - # expat 1.2 - raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name) # pragma: no cover - - def defused_external_entity_ref_handler(self, context, base, sysid, pubid): - raise ExternalReferenceForbidden(context, base, sysid, pubid) - - def install(self, parser): - _ExpatBuilder.install(self, parser) - - if self.forbid_dtd: - parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl - if self.forbid_entities: - # if self._options.entities: - parser.EntityDeclHandler = self.defused_entity_decl - parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl - if self.forbid_external: - parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler - - -class DefusedExpatBuilderNS(_Namespaces, DefusedExpatBuilder): - """Defused document builder that supports namespaces.""" - - def install(self, parser): - DefusedExpatBuilder.install(self, parser) - if self._options.namespace_declarations: - parser.StartNamespaceDeclHandler = self.start_namespace_decl_handler - - def reset(self): - DefusedExpatBuilder.reset(self) - self._initNamespaces() - - -def parse(file, namespaces=True, forbid_dtd=False, forbid_entities=True, forbid_external=True): - """Parse a document, returning the resulting Document node. - - 'file' may be either a file name or an open file object. - """ - if namespaces: - build_builder = DefusedExpatBuilderNS - else: - build_builder = DefusedExpatBuilder - builder = build_builder( - forbid_dtd=forbid_dtd, forbid_entities=forbid_entities, forbid_external=forbid_external - ) - - if isinstance(file, str): - fp = open(file, "rb") - try: - result = builder.parseFile(fp) - finally: - fp.close() - else: - result = builder.parseFile(file) - return result - - -def parseString( - string, namespaces=True, forbid_dtd=False, forbid_entities=True, forbid_external=True -): - """Parse a document from a string, returning the resulting - Document node. - """ - if namespaces: - build_builder = DefusedExpatBuilderNS - else: - build_builder = DefusedExpatBuilder - builder = build_builder( - forbid_dtd=forbid_dtd, forbid_entities=forbid_entities, forbid_external=forbid_external - ) - return builder.parseString(string) diff --git a/apps/bitwarden_event_logs/lib/defusedxml/expatreader.py b/apps/bitwarden_event_logs/lib/defusedxml/expatreader.py deleted file mode 100755 index 890e1d16..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml/expatreader.py +++ /dev/null @@ -1,61 +0,0 @@ -# defusedxml -# -# Copyright (c) 2013 by Christian Heimes -# Licensed to PSF under a Contributor Agreement. -# See https://www.python.org/psf/license for licensing details. -"""Defused xml.sax.expatreader -""" -from __future__ import print_function, absolute_import - -from xml.sax.expatreader import ExpatParser as _ExpatParser - -from .common import DTDForbidden, EntitiesForbidden, ExternalReferenceForbidden - -__origin__ = "xml.sax.expatreader" - - -class DefusedExpatParser(_ExpatParser): - """Defused SAX driver for the pyexpat C module.""" - - def __init__( - self, - namespaceHandling=0, - bufsize=2 ** 16 - 20, - forbid_dtd=False, - forbid_entities=True, - forbid_external=True, - ): - _ExpatParser.__init__(self, namespaceHandling, bufsize) - self.forbid_dtd = forbid_dtd - self.forbid_entities = forbid_entities - self.forbid_external = forbid_external - - def defused_start_doctype_decl(self, name, sysid, pubid, has_internal_subset): - raise DTDForbidden(name, sysid, pubid) - - def defused_entity_decl( - self, name, is_parameter_entity, value, base, sysid, pubid, notation_name - ): - raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name) - - def defused_unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): - # expat 1.2 - raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name) # pragma: no cover - - def defused_external_entity_ref_handler(self, context, base, sysid, pubid): - raise ExternalReferenceForbidden(context, base, sysid, pubid) - - def reset(self): - _ExpatParser.reset(self) - parser = self._parser - if self.forbid_dtd: - parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl - if self.forbid_entities: - parser.EntityDeclHandler = self.defused_entity_decl - parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl - if self.forbid_external: - parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler - - -def create_parser(*args, **kwargs): - return DefusedExpatParser(*args, **kwargs) diff --git a/apps/bitwarden_event_logs/lib/defusedxml/lxml.py b/apps/bitwarden_event_logs/lib/defusedxml/lxml.py deleted file mode 100755 index 99d5be93..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml/lxml.py +++ /dev/null @@ -1,153 +0,0 @@ -# defusedxml -# -# Copyright (c) 2013 by Christian Heimes -# Licensed to PSF under a Contributor Agreement. -# See https://www.python.org/psf/license for licensing details. -"""DEPRECATED Example code for lxml.etree protection - -The code has NO protection against decompression bombs. -""" -from __future__ import print_function, absolute_import - -import threading -import warnings - -from lxml import etree as _etree - -from .common import DTDForbidden, EntitiesForbidden, NotSupportedError - -LXML3 = _etree.LXML_VERSION[0] >= 3 - -__origin__ = "lxml.etree" - -tostring = _etree.tostring - - -warnings.warn( - "defusedxml.lxml is no longer supported and will be removed in a future release.", - category=DeprecationWarning, - stacklevel=2, -) - - -class RestrictedElement(_etree.ElementBase): - """A restricted Element class that filters out instances of some classes""" - - __slots__ = () - # blacklist = (etree._Entity, etree._ProcessingInstruction, etree._Comment) - blacklist = _etree._Entity - - def _filter(self, iterator): - blacklist = self.blacklist - for child in iterator: - if isinstance(child, blacklist): - continue - yield child - - def __iter__(self): - iterator = super(RestrictedElement, self).__iter__() - return self._filter(iterator) - - def iterchildren(self, tag=None, reversed=False): - iterator = super(RestrictedElement, self).iterchildren(tag=tag, reversed=reversed) - return self._filter(iterator) - - def iter(self, tag=None, *tags): - iterator = super(RestrictedElement, self).iter(tag=tag, *tags) - return self._filter(iterator) - - def iterdescendants(self, tag=None, *tags): - iterator = super(RestrictedElement, self).iterdescendants(tag=tag, *tags) - return self._filter(iterator) - - def itersiblings(self, tag=None, preceding=False): - iterator = super(RestrictedElement, self).itersiblings(tag=tag, preceding=preceding) - return self._filter(iterator) - - def getchildren(self): - iterator = super(RestrictedElement, self).__iter__() - return list(self._filter(iterator)) - - def getiterator(self, tag=None): - iterator = super(RestrictedElement, self).getiterator(tag) - return self._filter(iterator) - - -class GlobalParserTLS(threading.local): - """Thread local context for custom parser instances""" - - parser_config = { - "resolve_entities": False, - # 'remove_comments': True, - # 'remove_pis': True, - } - - element_class = RestrictedElement - - def createDefaultParser(self): - parser = _etree.XMLParser(**self.parser_config) - element_class = self.element_class - if self.element_class is not None: - lookup = _etree.ElementDefaultClassLookup(element=element_class) - parser.set_element_class_lookup(lookup) - return parser - - def setDefaultParser(self, parser): - self._default_parser = parser - - def getDefaultParser(self): - parser = getattr(self, "_default_parser", None) - if parser is None: - parser = self.createDefaultParser() - self.setDefaultParser(parser) - return parser - - -_parser_tls = GlobalParserTLS() -getDefaultParser = _parser_tls.getDefaultParser - - -def check_docinfo(elementtree, forbid_dtd=False, forbid_entities=True): - """Check docinfo of an element tree for DTD and entity declarations - - The check for entity declarations needs lxml 3 or newer. lxml 2.x does - not support dtd.iterentities(). - """ - docinfo = elementtree.docinfo - if docinfo.doctype: - if forbid_dtd: - raise DTDForbidden(docinfo.doctype, docinfo.system_url, docinfo.public_id) - if forbid_entities and not LXML3: - # lxml < 3 has no iterentities() - raise NotSupportedError("Unable to check for entity declarations " "in lxml 2.x") - - if forbid_entities: - for dtd in docinfo.internalDTD, docinfo.externalDTD: - if dtd is None: - continue - for entity in dtd.iterentities(): - raise EntitiesForbidden(entity.name, entity.content, None, None, None, None) - - -def parse(source, parser=None, base_url=None, forbid_dtd=False, forbid_entities=True): - if parser is None: - parser = getDefaultParser() - elementtree = _etree.parse(source, parser, base_url=base_url) - check_docinfo(elementtree, forbid_dtd, forbid_entities) - return elementtree - - -def fromstring(text, parser=None, base_url=None, forbid_dtd=False, forbid_entities=True): - if parser is None: - parser = getDefaultParser() - rootelement = _etree.fromstring(text, parser, base_url=base_url) - elementtree = rootelement.getroottree() - check_docinfo(elementtree, forbid_dtd, forbid_entities) - return rootelement - - -XML = fromstring - - -def iterparse(*args, **kwargs): - raise NotSupportedError("defused lxml.etree.iterparse not available") diff --git a/apps/bitwarden_event_logs/lib/defusedxml/minidom.py b/apps/bitwarden_event_logs/lib/defusedxml/minidom.py deleted file mode 100755 index 78033b6c..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml/minidom.py +++ /dev/null @@ -1,63 +0,0 @@ -# defusedxml -# -# Copyright (c) 2013 by Christian Heimes -# Licensed to PSF under a Contributor Agreement. -# See https://www.python.org/psf/license for licensing details. -"""Defused xml.dom.minidom -""" -from __future__ import print_function, absolute_import - -from xml.dom.minidom import _do_pulldom_parse -from . import expatbuilder as _expatbuilder -from . import pulldom as _pulldom - -__origin__ = "xml.dom.minidom" - - -def parse( - file, parser=None, bufsize=None, forbid_dtd=False, forbid_entities=True, forbid_external=True -): - """Parse a file into a DOM by filename or file object.""" - if parser is None and not bufsize: - return _expatbuilder.parse( - file, - forbid_dtd=forbid_dtd, - forbid_entities=forbid_entities, - forbid_external=forbid_external, - ) - else: - return _do_pulldom_parse( - _pulldom.parse, - (file,), - { - "parser": parser, - "bufsize": bufsize, - "forbid_dtd": forbid_dtd, - "forbid_entities": forbid_entities, - "forbid_external": forbid_external, - }, - ) - - -def parseString( - string, parser=None, forbid_dtd=False, forbid_entities=True, forbid_external=True -): - """Parse a file into a DOM from a string.""" - if parser is None: - return _expatbuilder.parseString( - string, - forbid_dtd=forbid_dtd, - forbid_entities=forbid_entities, - forbid_external=forbid_external, - ) - else: - return _do_pulldom_parse( - _pulldom.parseString, - (string,), - { - "parser": parser, - "forbid_dtd": forbid_dtd, - "forbid_entities": forbid_entities, - "forbid_external": forbid_external, - }, - ) diff --git a/apps/bitwarden_event_logs/lib/defusedxml/pulldom.py b/apps/bitwarden_event_logs/lib/defusedxml/pulldom.py deleted file mode 100755 index e3b10a46..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml/pulldom.py +++ /dev/null @@ -1,41 +0,0 @@ -# defusedxml -# -# Copyright (c) 2013 by Christian Heimes -# Licensed to PSF under a Contributor Agreement. -# See https://www.python.org/psf/license for licensing details. -"""Defused xml.dom.pulldom -""" -from __future__ import print_function, absolute_import - -from xml.dom.pulldom import parse as _parse -from xml.dom.pulldom import parseString as _parseString -from .sax import make_parser - -__origin__ = "xml.dom.pulldom" - - -def parse( - stream_or_string, - parser=None, - bufsize=None, - forbid_dtd=False, - forbid_entities=True, - forbid_external=True, -): - if parser is None: - parser = make_parser() - parser.forbid_dtd = forbid_dtd - parser.forbid_entities = forbid_entities - parser.forbid_external = forbid_external - return _parse(stream_or_string, parser, bufsize) - - -def parseString( - string, parser=None, forbid_dtd=False, forbid_entities=True, forbid_external=True -): - if parser is None: - parser = make_parser() - parser.forbid_dtd = forbid_dtd - parser.forbid_entities = forbid_entities - parser.forbid_external = forbid_external - return _parseString(string, parser) diff --git a/apps/bitwarden_event_logs/lib/defusedxml/sax.py b/apps/bitwarden_event_logs/lib/defusedxml/sax.py deleted file mode 100755 index b2786f74..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml/sax.py +++ /dev/null @@ -1,60 +0,0 @@ -# defusedxml -# -# Copyright (c) 2013 by Christian Heimes -# Licensed to PSF under a Contributor Agreement. -# See https://www.python.org/psf/license for licensing details. -"""Defused xml.sax -""" -from __future__ import print_function, absolute_import - -from xml.sax import InputSource as _InputSource -from xml.sax import ErrorHandler as _ErrorHandler - -from . import expatreader - -__origin__ = "xml.sax" - - -def parse( - source, - handler, - errorHandler=_ErrorHandler(), - forbid_dtd=False, - forbid_entities=True, - forbid_external=True, -): - parser = make_parser() - parser.setContentHandler(handler) - parser.setErrorHandler(errorHandler) - parser.forbid_dtd = forbid_dtd - parser.forbid_entities = forbid_entities - parser.forbid_external = forbid_external - parser.parse(source) - - -def parseString( - string, - handler, - errorHandler=_ErrorHandler(), - forbid_dtd=False, - forbid_entities=True, - forbid_external=True, -): - from io import BytesIO - - if errorHandler is None: - errorHandler = _ErrorHandler() - parser = make_parser() - parser.setContentHandler(handler) - parser.setErrorHandler(errorHandler) - parser.forbid_dtd = forbid_dtd - parser.forbid_entities = forbid_entities - parser.forbid_external = forbid_external - - inpsrc = _InputSource() - inpsrc.setByteStream(BytesIO(string)) - parser.parse(inpsrc) - - -def make_parser(parser_list=[]): - return expatreader.create_parser() diff --git a/apps/bitwarden_event_logs/lib/defusedxml/xmlrpc.py b/apps/bitwarden_event_logs/lib/defusedxml/xmlrpc.py deleted file mode 100755 index fbc674da..00000000 --- a/apps/bitwarden_event_logs/lib/defusedxml/xmlrpc.py +++ /dev/null @@ -1,153 +0,0 @@ -# defusedxml -# -# Copyright (c) 2013 by Christian Heimes -# Licensed to PSF under a Contributor Agreement. -# See https://www.python.org/psf/license for licensing details. -"""Defused xmlrpclib - -Also defuses gzip bomb -""" -from __future__ import print_function, absolute_import - -import io - -from .common import DTDForbidden, EntitiesForbidden, ExternalReferenceForbidden, PY3 - -if PY3: - __origin__ = "xmlrpc.client" - from xmlrpc.client import ExpatParser - from xmlrpc import client as xmlrpc_client - from xmlrpc import server as xmlrpc_server - from xmlrpc.client import gzip_decode as _orig_gzip_decode - from xmlrpc.client import GzipDecodedResponse as _OrigGzipDecodedResponse -else: - __origin__ = "xmlrpclib" - from xmlrpclib import ExpatParser - import xmlrpclib as xmlrpc_client - - xmlrpc_server = None - from xmlrpclib import gzip_decode as _orig_gzip_decode - from xmlrpclib import GzipDecodedResponse as _OrigGzipDecodedResponse - -try: - import gzip -except ImportError: # pragma: no cover - gzip = None - - -# Limit maximum request size to prevent resource exhaustion DoS -# Also used to limit maximum amount of gzip decoded data in order to prevent -# decompression bombs -# A value of -1 or smaller disables the limit -MAX_DATA = 30 * 1024 * 1024 # 30 MB - - -def defused_gzip_decode(data, limit=None): - """gzip encoded data -> unencoded data - - Decode data using the gzip content encoding as described in RFC 1952 - """ - if not gzip: # pragma: no cover - raise NotImplementedError - if limit is None: - limit = MAX_DATA - f = io.BytesIO(data) - gzf = gzip.GzipFile(mode="rb", fileobj=f) - try: - if limit < 0: # no limit - decoded = gzf.read() - else: - decoded = gzf.read(limit + 1) - except IOError: # pragma: no cover - raise ValueError("invalid data") - f.close() - gzf.close() - if limit >= 0 and len(decoded) > limit: - raise ValueError("max gzipped payload length exceeded") - return decoded - - -class DefusedGzipDecodedResponse(gzip.GzipFile if gzip else object): - """a file-like object to decode a response encoded with the gzip - method, as described in RFC 1952. - """ - - def __init__(self, response, limit=None): - # response doesn't support tell() and read(), required by - # GzipFile - if not gzip: # pragma: no cover - raise NotImplementedError - self.limit = limit = limit if limit is not None else MAX_DATA - if limit < 0: # no limit - data = response.read() - self.readlength = None - else: - data = response.read(limit + 1) - self.readlength = 0 - if limit >= 0 and len(data) > limit: - raise ValueError("max payload length exceeded") - self.stringio = io.BytesIO(data) - gzip.GzipFile.__init__(self, mode="rb", fileobj=self.stringio) - - def read(self, n): - if self.limit >= 0: - left = self.limit - self.readlength - n = min(n, left + 1) - data = gzip.GzipFile.read(self, n) - self.readlength += len(data) - if self.readlength > self.limit: - raise ValueError("max payload length exceeded") - return data - else: - return gzip.GzipFile.read(self, n) - - def close(self): - gzip.GzipFile.close(self) - self.stringio.close() - - -class DefusedExpatParser(ExpatParser): - def __init__(self, target, forbid_dtd=False, forbid_entities=True, forbid_external=True): - ExpatParser.__init__(self, target) - self.forbid_dtd = forbid_dtd - self.forbid_entities = forbid_entities - self.forbid_external = forbid_external - parser = self._parser - if self.forbid_dtd: - parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl - if self.forbid_entities: - parser.EntityDeclHandler = self.defused_entity_decl - parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl - if self.forbid_external: - parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler - - def defused_start_doctype_decl(self, name, sysid, pubid, has_internal_subset): - raise DTDForbidden(name, sysid, pubid) - - def defused_entity_decl( - self, name, is_parameter_entity, value, base, sysid, pubid, notation_name - ): - raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name) - - def defused_unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): - # expat 1.2 - raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name) # pragma: no cover - - def defused_external_entity_ref_handler(self, context, base, sysid, pubid): - raise ExternalReferenceForbidden(context, base, sysid, pubid) - - -def monkey_patch(): - xmlrpc_client.FastParser = DefusedExpatParser - xmlrpc_client.GzipDecodedResponse = DefusedGzipDecodedResponse - xmlrpc_client.gzip_decode = defused_gzip_decode - if xmlrpc_server: - xmlrpc_server.gzip_decode = defused_gzip_decode - - -def unmonkey_patch(): - xmlrpc_client.FastParser = None - xmlrpc_client.GzipDecodedResponse = _OrigGzipDecodedResponse - xmlrpc_client.gzip_decode = _orig_gzip_decode - if xmlrpc_server: - xmlrpc_server.gzip_decode = _orig_gzip_decode diff --git a/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/INSTALLER deleted file mode 100755 index a1b589e3..00000000 --- a/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/LICENSE b/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/LICENSE deleted file mode 100755 index 8dada3ed..00000000 --- a/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/METADATA b/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/METADATA deleted file mode 100755 index 1d44ff8c..00000000 --- a/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/METADATA +++ /dev/null @@ -1,114 +0,0 @@ -Metadata-Version: 2.1 -Name: deprecation -Version: 2.1.0 -Summary: A library to handle automated deprecations -Home-page: http://deprecation.readthedocs.io/ -Author: Brian Curtin -Author-email: brian@python.org -Maintainer: Brian Curtin -Maintainer-email: brian@python.org -License: Apache 2 -Project-URL: Documentation, http://deprecation.readthedocs.io/en/latest/ -Project-URL: Source, https://github.com/briancurtin/deprecation -Project-URL: Bug Tracker, https://github.com/briancurtin/deprecation/issues -Keywords: deprecation -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: License :: OSI Approved :: Apache Software License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Requires-Dist: packaging - -deprecation -=========== - -.. image:: https://readthedocs.org/projects/deprecation/badge/?version=latest - :target: http://deprecation.readthedocs.io/en/latest/ - :alt: Documentation Status - -.. image:: https://travis-ci.org/briancurtin/deprecation.svg?branch=master - :target: https://travis-ci.org/briancurtin/deprecation - -.. image:: https://codecov.io/gh/briancurtin/deprecation/branch/master/graph/badge.svg - :target: https://codecov.io/gh/briancurtin/deprecation - -The ``deprecation`` library provides a ``deprecated`` decorator and a -``fail_if_not_removed`` decorator for your tests. Together, the two -enable the automation of several things: - -1. The docstring of a deprecated method gets the deprecation details - appended to the end of it. If you generate your API docs direct - from your source, you don't need to worry about writing your own - notification. You also don't need to worry about forgetting to - write it. It's done for you. -2. Rather than having code live on forever because you only deprecated - it but never actually moved on from it, you can have your tests - tell you when it's time to remove the code. The ``@deprecated`` - decorator can be told when it's time to entirely remove the code, - which causes ``@fail_if_not_removed`` to raise an ``AssertionError``, - causing either your unittest or py.test tests to fail. - -See http://deprecation.readthedocs.io/ for the full documentation. - -Installation -============ - - :: - - pip install deprecation - -Usage -===== - - :: - - import deprecation - - @deprecation.deprecated(deprecated_in="1.0", removed_in="2.0", - current_version=__version__, - details="Use the bar function instead") - def foo(): - """Do some stuff""" - return 1 - -...but doesn't Python ignore ``DeprecationWarning``? -==================================================== - -Yes, by default since 2.7—and for good reason [#]_ —and this works fine -with that. - -1. It often makes sense for you to run your tests with a ``-W`` flag or - the ``PYTHONWARNINGS`` environment variable so you catch warnings - in development and handle them appropriately. The warnings raised by - this library show up there, as they're subclasses of the built-in - ``DeprecationWarning``. See the `Command Line - `_ - and `Environment Variable - `_ - documentation for more details. -2. Even if you don't enable those things, the behavior of this library - remains the same. The docstrings will still be updated and the tests - will still fail when they need to. You'll get the benefits regardless - of what Python cares about ``DeprecationWarning``. - ----- - -.. [#] Exposing application users to ``DeprecationWarning``\s that are - emitted by lower-level code needlessly involves end-users in - "how things are done." It often leads to users raising issues - about warnings they're presented, which on one hand is done - rightfully so, as it's been presented to them as some sort of - issue to resolve. However, at the same time, the warning could - be well known and planned for. From either side, loud - ``DeprecationWarning``\s can be seen as noise that isn't - necessary outside of development. - - diff --git a/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/RECORD b/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/RECORD deleted file mode 100755 index 6865e23f..00000000 --- a/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/RECORD +++ /dev/null @@ -1,8 +0,0 @@ -deprecation-2.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -deprecation-2.1.0.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357 -deprecation-2.1.0.dist-info/METADATA,sha256=AmlhU86t_lQQh858jSMZMZpoYM6gfnnLSKKe5DgGU88,4604 -deprecation-2.1.0.dist-info/RECORD,, -deprecation-2.1.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -deprecation-2.1.0.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 -deprecation-2.1.0.dist-info/top_level.txt,sha256=ztDh9pLraFksBgQ6iXWE_OnukoBC6_jkPQ4Y6p7771o,12 -deprecation.py,sha256=Z8qPVC-janAf7Ppoc1wYTiTWvGSdSjErOV1jDhnHN0Y,12895 diff --git a/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/REQUESTED deleted file mode 100755 index e69de29b..00000000 diff --git a/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/WHEEL deleted file mode 100755 index ef99c6cf..00000000 --- a/apps/bitwarden_event_logs/lib/deprecation-2.1.0.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.34.2) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/apps/bitwarden_event_logs/lib/deprecation.py b/apps/bitwarden_event_logs/lib/deprecation.py deleted file mode 100755 index 0217b589..00000000 --- a/apps/bitwarden_event_logs/lib/deprecation.py +++ /dev/null @@ -1,290 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -import collections -import functools -import textwrap -import warnings - -from packaging import version -from datetime import date - -__version__ = "2.1.0" - -# This is mostly here so automodule docs are ordered more ideally. -__all__ = ["deprecated", "message_location", "fail_if_not_removed", - "DeprecatedWarning", "UnsupportedWarning"] - -#: Location where the details are added to a deprecated docstring -#: -#: When set to ``"bottom"``, the details are appended to the end. -#: When set to ``"top"``, the details are inserted between the -#: summary line and docstring contents. -message_location = "bottom" - - -class DeprecatedWarning(DeprecationWarning): - """A warning class for deprecated methods - - This is a specialization of the built-in :class:`DeprecationWarning`, - adding parameters that allow us to get information into the __str__ - that ends up being sent through the :mod:`warnings` system. - The attributes aren't able to be retrieved after the warning gets - raised and passed through the system as only the class--not the - instance--and message are what gets preserved. - - :param function: The function being deprecated. - :param deprecated_in: The version that ``function`` is deprecated in - :param removed_in: The version or :class:`datetime.date` specifying - when ``function`` gets removed. - :param details: Optional details about the deprecation. Most often - this will include directions on what to use instead - of the now deprecated code. - """ - - def __init__(self, function, deprecated_in, removed_in, details=""): - # NOTE: The docstring only works for this class if it appears up - # near the class name, not here inside __init__. I think it has - # to do with being an exception class. - self.function = function - self.deprecated_in = deprecated_in - self.removed_in = removed_in - self.details = details - super(DeprecatedWarning, self).__init__(function, deprecated_in, - removed_in, details) - - def __str__(self): - # Use a defaultdict to give us the empty string - # when a part isn't included. - parts = collections.defaultdict(str) - parts["function"] = self.function - - if self.deprecated_in: - parts["deprecated"] = " as of %s" % self.deprecated_in - if self.removed_in: - parts["removed"] = " and will be removed {} {}".format("on" if isinstance(self.removed_in, date) else "in", - self.removed_in) - if any([self.deprecated_in, self.removed_in, self.details]): - parts["period"] = "." - if self.details: - parts["details"] = " %s" % self.details - - return ("%(function)s is deprecated%(deprecated)s%(removed)s" - "%(period)s%(details)s" % (parts)) - - -class UnsupportedWarning(DeprecatedWarning): - """A warning class for methods to be removed - - This is a subclass of :class:`~deprecation.DeprecatedWarning` and is used - to output a proper message about a function being unsupported. - Additionally, the :func:`~deprecation.fail_if_not_removed` decorator - will handle this warning and cause any tests to fail if the system - under test uses code that raises this warning. - """ - - def __str__(self): - parts = collections.defaultdict(str) - parts["function"] = self.function - parts["removed"] = self.removed_in - - if self.details: - parts["details"] = " %s" % self.details - - return ("%(function)s is unsupported as of %(removed)s." - "%(details)s" % (parts)) - - -def deprecated(deprecated_in=None, removed_in=None, current_version=None, - details=""): - """Decorate a function to signify its deprecation - - This function wraps a method that will soon be removed and does two things: - * The docstring of the method will be modified to include a notice - about deprecation, e.g., "Deprecated since 0.9.11. Use foo instead." - * Raises a :class:`~deprecation.DeprecatedWarning` - via the :mod:`warnings` module, which is a subclass of the built-in - :class:`DeprecationWarning`. Note that built-in - :class:`DeprecationWarning`s are ignored by default, so for users - to be informed of said warnings they will need to enable them--see - the :mod:`warnings` module documentation for more details. - - :param deprecated_in: The version at which the decorated method is - considered deprecated. This will usually be the - next version to be released when the decorator is - added. The default is **None**, which effectively - means immediate deprecation. If this is not - specified, then the `removed_in` and - `current_version` arguments are ignored. - :param removed_in: The version or :class:`datetime.date` when the decorated - method will be removed. The default is **None**, - specifying that the function is not currently planned - to be removed. - Note: This parameter cannot be set to a value if - `deprecated_in=None`. - :param current_version: The source of version information for the - currently running code. This will usually be - a `__version__` attribute on your library. - The default is `None`. - When `current_version=None` the automation to - determine if the wrapped function is actually - in a period of deprecation or time for removal - does not work, causing a - :class:`~deprecation.DeprecatedWarning` - to be raised in all cases. - :param details: Extra details to be added to the method docstring and - warning. For example, the details may point users to - a replacement method, such as "Use the foo_bar - method instead". By default there are no details. - """ - # You can't just jump to removal. It's weird, unfair, and also makes - # building up the docstring weird. - if deprecated_in is None and removed_in is not None: - raise TypeError("Cannot set removed_in to a value " - "without also setting deprecated_in") - - # Only warn when it's appropriate. There may be cases when it makes sense - # to add this decorator before a formal deprecation period begins. - # In CPython, PendingDeprecatedWarning gets used in that period, - # so perhaps mimick that at some point. - is_deprecated = False - is_unsupported = False - - # StrictVersion won't take a None or a "", so make whatever goes to it - # is at least *something*. Compare versions only if removed_in is not - # of type datetime.date - if isinstance(removed_in, date): - if date.today() >= removed_in: - is_unsupported = True - else: - is_deprecated = True - elif current_version: - current_version = version.parse(current_version) - - if (removed_in - and current_version >= version.parse(removed_in)): - is_unsupported = True - elif (deprecated_in - and current_version >= version.parse(deprecated_in)): - is_deprecated = True - else: - # If we can't actually calculate that we're in a period of - # deprecation...well, they used the decorator, so it's deprecated. - # This will cover the case of someone just using - # @deprecated("1.0") without the other advantages. - is_deprecated = True - - should_warn = any([is_deprecated, is_unsupported]) - - def _function_wrapper(function): - if should_warn: - # Everything *should* have a docstring, but just in case... - existing_docstring = function.__doc__ or "" - - # The various parts of this decorator being optional makes for - # a number of ways the deprecation notice could go. The following - # makes for a nicely constructed sentence with or without any - # of the parts. - - # If removed_in is a date, use "removed on" - # If removed_in is a version, use "removed in" - parts = { - "deprecated_in": - " %s" % deprecated_in if deprecated_in else "", - "removed_in": - "\n This will be removed {} {}.".format("on" if isinstance(removed_in, date) else "in", - removed_in) if removed_in else "", - "details": - " %s" % details if details else ""} - - deprecation_note = (".. deprecated::{deprecated_in}" - "{removed_in}{details}".format(**parts)) - - # default location for insertion of deprecation note - loc = 1 - - # split docstring at first occurrence of newline - string_list = existing_docstring.split("\n", 1) - - if len(string_list) > 1: - # With a multi-line docstring, when we modify - # existing_docstring to add our deprecation_note, - # if we're not careful we'll interfere with the - # indentation levels of the contents below the - # first line, or as PEP 257 calls it, the summary - # line. Since the summary line can start on the - # same line as the """, dedenting the whole thing - # won't help. Split the summary and contents up, - # dedent the contents independently, then join - # summary, dedent'ed contents, and our - # deprecation_note. - - # in-place dedent docstring content - string_list[1] = textwrap.dedent(string_list[1]) - - # we need another newline - string_list.insert(loc, "\n") - - # change the message_location if we add to end of docstring - # do this always if not "top" - if message_location != "top": - loc = 3 - - # insert deprecation note and dual newline - string_list.insert(loc, deprecation_note) - string_list.insert(loc, "\n\n") - - function.__doc__ = "".join(string_list) - - @functools.wraps(function) - def _inner(*args, **kwargs): - if should_warn: - if is_unsupported: - cls = UnsupportedWarning - else: - cls = DeprecatedWarning - - the_warning = cls(function.__name__, deprecated_in, - removed_in, details) - warnings.warn(the_warning, category=DeprecationWarning, - stacklevel=2) - - return function(*args, **kwargs) - return _inner - return _function_wrapper - - -def fail_if_not_removed(method): - """Decorate a test method to track removal of deprecated code - - This decorator catches :class:`~deprecation.UnsupportedWarning` - warnings that occur during testing and causes unittests to fail, - making it easier to keep track of when code should be removed. - - :raises: :class:`AssertionError` if an - :class:`~deprecation.UnsupportedWarning` - is raised while running the test method. - """ - # NOTE(briancurtin): Unless this is named test_inner, nose won't work - # properly. See Issue #32. - @functools.wraps(method) - def test_inner(*args, **kwargs): - with warnings.catch_warnings(record=True) as caught_warnings: - warnings.simplefilter("always") - rv = method(*args, **kwargs) - - for warning in caught_warnings: - if warning.category == UnsupportedWarning: - raise AssertionError( - ("%s uses a function that should be removed: %s" % - (method, str(warning.message)))) - return rv - return test_inner diff --git a/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/INSTALLER deleted file mode 100755 index a1b589e3..00000000 --- a/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/METADATA b/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/METADATA deleted file mode 100755 index 7a4a4b7a..00000000 --- a/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/METADATA +++ /dev/null @@ -1,209 +0,0 @@ -Metadata-Version: 2.4 -Name: idna -Version: 3.11 -Summary: Internationalized Domain Names in Applications (IDNA) -Author-email: Kim Davies -Requires-Python: >=3.8 -Description-Content-Type: text/x-rst -License-Expression: BSD-3-Clause -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: System Administrators -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3.13 -Classifier: Programming Language :: Python :: 3.14 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Internet :: Name Service (DNS) -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Utilities -License-File: LICENSE.md -Requires-Dist: ruff >= 0.6.2 ; extra == "all" -Requires-Dist: mypy >= 1.11.2 ; extra == "all" -Requires-Dist: pytest >= 8.3.2 ; extra == "all" -Requires-Dist: flake8 >= 7.1.1 ; extra == "all" -Project-URL: Changelog, https://github.com/kjd/idna/blob/master/HISTORY.rst -Project-URL: Issue tracker, https://github.com/kjd/idna/issues -Project-URL: Source, https://github.com/kjd/idna -Provides-Extra: all - -Internationalized Domain Names in Applications (IDNA) -===================================================== - -Support for `Internationalized Domain Names in -Applications (IDNA) `_ -and `Unicode IDNA Compatibility Processing -`_. - -The latest versions of these standards supplied here provide -more comprehensive language coverage and reduce the potential of -allowing domains with known security vulnerabilities. This library -is a suitable replacement for the “encodings.idna” -module that comes with the Python standard library, but which -only supports an older superseded IDNA specification from 2003. - -Basic functions are simply executed: - -.. code-block:: pycon - - >>> import idna - >>> idna.encode('ドメイン.テスト') - b'xn--eckwd4c7c.xn--zckzah' - >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah')) - ドメイン.テスト - - -Installation ------------- - -This package is available for installation from PyPI via the -typical mechanisms, such as: - -.. code-block:: bash - - $ python3 -m pip install idna - - -Usage ------ - -For typical usage, the ``encode`` and ``decode`` functions will take a -domain name argument and perform a conversion to ASCII compatible encoding -(known as A-labels), or to Unicode strings (known as U-labels) -respectively. - -.. code-block:: pycon - - >>> import idna - >>> idna.encode('ドメイン.テスト') - b'xn--eckwd4c7c.xn--zckzah' - >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah')) - ドメイン.テスト - -Conversions can be applied at a per-label basis using the ``ulabel`` or -``alabel`` functions if necessary: - -.. code-block:: pycon - - >>> idna.alabel('测试') - b'xn--0zwm56d' - - -Compatibility Mapping (UTS #46) -+++++++++++++++++++++++++++++++ - -This library provides support for `Unicode IDNA Compatibility -Processing `_ which normalizes input from -different potential ways a user may input a domain prior to performing the IDNA -conversion operations. This functionality, known as a -`mapping `_, is considered by the -specification to be a local user-interface issue distinct from IDNA -conversion functionality. - -For example, “Königsgäßchen” is not a permissible label as *LATIN -CAPITAL LETTER K* is not allowed (nor are capital letters in general). -UTS 46 will convert this into lower case prior to applying the IDNA -conversion. - -.. code-block:: pycon - - >>> import idna - >>> idna.encode('Königsgäßchen') - ... - idna.core.InvalidCodepoint: Codepoint U+004B at position 1 of 'Königsgäßchen' not allowed - >>> idna.encode('Königsgäßchen', uts46=True) - b'xn--knigsgchen-b4a3dun' - >>> print(idna.decode('xn--knigsgchen-b4a3dun')) - königsgäßchen - - -Exceptions ----------- - -All errors raised during the conversion following the specification -should raise an exception derived from the ``idna.IDNAError`` base -class. - -More specific exceptions that may be generated as ``idna.IDNABidiError`` -when the error reflects an illegal combination of left-to-right and -right-to-left characters in a label; ``idna.InvalidCodepoint`` when -a specific codepoint is an illegal character in an IDN label (i.e. -INVALID); and ``idna.InvalidCodepointContext`` when the codepoint is -illegal based on its position in the string (i.e. it is CONTEXTO or CONTEXTJ -but the contextual requirements are not satisfied.) - -Building and Diagnostics ------------------------- - -The IDNA and UTS 46 functionality relies upon pre-calculated lookup -tables for performance. These tables are derived from computing against -eligibility criteria in the respective standards using the command-line -script ``tools/idna-data``. - -This tool will fetch relevant codepoint data from the Unicode repository -and perform the required calculations to identify eligibility. There are -three main modes: - -* ``idna-data make-libdata``. Generates ``idnadata.py`` and - ``uts46data.py``, the pre-calculated lookup tables used for IDNA and - UTS 46 conversions. Implementers who wish to track this library against - a different Unicode version may use this tool to manually generate a - different version of the ``idnadata.py`` and ``uts46data.py`` files. - -* ``idna-data make-table``. Generate a table of the IDNA disposition - (e.g. PVALID, CONTEXTJ, CONTEXTO) in the format found in Appendix - B.1 of RFC 5892 and the pre-computed tables published by `IANA - `_. - -* ``idna-data U+0061``. Prints debugging output on the various - properties associated with an individual Unicode codepoint (in this - case, U+0061), that are used to assess the IDNA and UTS 46 status of a - codepoint. This is helpful in debugging or analysis. - -The tool accepts a number of arguments, described using ``idna-data --h``. Most notably, the ``--version`` argument allows the specification -of the version of Unicode to be used in computing the table data. For -example, ``idna-data --version 9.0.0 make-libdata`` will generate -library data against Unicode 9.0.0. - - -Additional Notes ----------------- - -* **Packages**. The latest tagged release version is published in the - `Python Package Index `_. - -* **Version support**. This library supports Python 3.8 and higher. - As this library serves as a low-level toolkit for a variety of - applications, many of which strive for broad compatibility with older - Python versions, there is no rush to remove older interpreter support. - Support for older versions are likely to be removed from new releases - as automated tests can no longer easily be run, i.e. once the Python - version is officially end-of-life. - -* **Testing**. The library has a test suite based on each rule of the - IDNA specification, as well as tests that are provided as part of the - Unicode Technical Standard 46, `Unicode IDNA Compatibility Processing - `_. - -* **Emoji**. It is an occasional request to support emoji domains in - this library. Encoding of symbols like emoji is expressly prohibited by - the technical standard IDNA 2008 and emoji domains are broadly phased - out across the domain industry due to associated security risks. For - now, applications that need to support these non-compliant labels - may wish to consider trying the encode/decode operation in this library - first, and then falling back to using `encodings.idna`. See `the Github - project `_ for more discussion. - -* **Transitional processing**. Unicode 16.0.0 removed transitional - processing so the `transitional` argument for the encode() method - no longer has any effect and will be removed at a later date. - diff --git a/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/RECORD b/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/RECORD deleted file mode 100755 index 151b8df6..00000000 --- a/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/RECORD +++ /dev/null @@ -1,15 +0,0 @@ -idna-3.11.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -idna-3.11.dist-info/METADATA,sha256=fCwSww9SuiN8TIHllFSASUQCW55hAs8dzKnr9RaEEbA,8378 -idna-3.11.dist-info/RECORD,, -idna-3.11.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -idna-3.11.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 -idna-3.11.dist-info/licenses/LICENSE.md,sha256=t6M2q_OwThgOwGXN0W5wXQeeHMehT5EKpukYfza5zYc,1541 -idna/__init__.py,sha256=MPqNDLZbXqGaNdXxAFhiqFPKEQXju2jNQhCey6-5eJM,868 -idna/codec.py,sha256=M2SGWN7cs_6B32QmKTyTN6xQGZeYQgQ2wiX3_DR6loE,3438 -idna/compat.py,sha256=RzLy6QQCdl9784aFhb2EX9EKGCJjg0P3PilGdeXXcx8,316 -idna/core.py,sha256=P26_XVycuMTZ1R2mNK1ZREVzM5mvTzdabBXfyZVU1Lc,13246 -idna/idnadata.py,sha256=SG8jhaGE53iiD6B49pt2pwTv_UvClciWE-N54oR2p4U,79623 -idna/intranges.py,sha256=amUtkdhYcQG8Zr-CoMM_kVRacxkivC1WgxN1b63KKdU,1898 -idna/package_data.py,sha256=_CUavOxobnbyNG2FLyHoN8QHP3QM9W1tKuw7eq9QwBk,21 -idna/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -idna/uts46data.py,sha256=H9J35VkD0F9L9mKOqjeNGd2A-Va6FlPoz6Jz4K7h-ps,243725 diff --git a/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/REQUESTED deleted file mode 100755 index e69de29b..00000000 diff --git a/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/WHEEL deleted file mode 100755 index d8b9936d..00000000 --- a/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: flit 3.12.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/licenses/LICENSE.md b/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/licenses/LICENSE.md deleted file mode 100755 index 256ba90c..00000000 --- a/apps/bitwarden_event_logs/lib/idna-3.11.dist-info/licenses/LICENSE.md +++ /dev/null @@ -1,31 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2013-2025, Kim Davies and contributors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/apps/bitwarden_event_logs/lib/idna/__init__.py b/apps/bitwarden_event_logs/lib/idna/__init__.py deleted file mode 100755 index cfdc030a..00000000 --- a/apps/bitwarden_event_logs/lib/idna/__init__.py +++ /dev/null @@ -1,45 +0,0 @@ -from .core import ( - IDNABidiError, - IDNAError, - InvalidCodepoint, - InvalidCodepointContext, - alabel, - check_bidi, - check_hyphen_ok, - check_initial_combiner, - check_label, - check_nfc, - decode, - encode, - ulabel, - uts46_remap, - valid_contextj, - valid_contexto, - valid_label_length, - valid_string_length, -) -from .intranges import intranges_contain -from .package_data import __version__ - -__all__ = [ - "__version__", - "IDNABidiError", - "IDNAError", - "InvalidCodepoint", - "InvalidCodepointContext", - "alabel", - "check_bidi", - "check_hyphen_ok", - "check_initial_combiner", - "check_label", - "check_nfc", - "decode", - "encode", - "intranges_contain", - "ulabel", - "uts46_remap", - "valid_contextj", - "valid_contexto", - "valid_label_length", - "valid_string_length", -] diff --git a/apps/bitwarden_event_logs/lib/idna/__pycache__/__init__.cpython-39.pyc b/apps/bitwarden_event_logs/lib/idna/__pycache__/__init__.cpython-39.pyc deleted file mode 100755 index d3b7fcc0..00000000 Binary files a/apps/bitwarden_event_logs/lib/idna/__pycache__/__init__.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/idna/__pycache__/core.cpython-39.pyc b/apps/bitwarden_event_logs/lib/idna/__pycache__/core.cpython-39.pyc deleted file mode 100755 index 127106ac..00000000 Binary files a/apps/bitwarden_event_logs/lib/idna/__pycache__/core.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/idna/__pycache__/idnadata.cpython-39.pyc b/apps/bitwarden_event_logs/lib/idna/__pycache__/idnadata.cpython-39.pyc deleted file mode 100755 index f8c193be..00000000 Binary files a/apps/bitwarden_event_logs/lib/idna/__pycache__/idnadata.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/idna/__pycache__/intranges.cpython-39.pyc b/apps/bitwarden_event_logs/lib/idna/__pycache__/intranges.cpython-39.pyc deleted file mode 100755 index 002e7284..00000000 Binary files a/apps/bitwarden_event_logs/lib/idna/__pycache__/intranges.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/idna/__pycache__/package_data.cpython-39.pyc b/apps/bitwarden_event_logs/lib/idna/__pycache__/package_data.cpython-39.pyc deleted file mode 100755 index 2486b180..00000000 Binary files a/apps/bitwarden_event_logs/lib/idna/__pycache__/package_data.cpython-39.pyc and /dev/null differ diff --git a/apps/bitwarden_event_logs/lib/idna/codec.py b/apps/bitwarden_event_logs/lib/idna/codec.py deleted file mode 100755 index cbc2e4ff..00000000 --- a/apps/bitwarden_event_logs/lib/idna/codec.py +++ /dev/null @@ -1,122 +0,0 @@ -import codecs -import re -from typing import Any, Optional, Tuple - -from .core import IDNAError, alabel, decode, encode, ulabel - -_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]") - - -class Codec(codecs.Codec): - def encode(self, data: str, errors: str = "strict") -> Tuple[bytes, int]: - if errors != "strict": - raise IDNAError('Unsupported error handling "{}"'.format(errors)) - - if not data: - return b"", 0 - - return encode(data), len(data) - - def decode(self, data: bytes, errors: str = "strict") -> Tuple[str, int]: - if errors != "strict": - raise IDNAError('Unsupported error handling "{}"'.format(errors)) - - if not data: - return "", 0 - - return decode(data), len(data) - - -class IncrementalEncoder(codecs.BufferedIncrementalEncoder): - def _buffer_encode(self, data: str, errors: str, final: bool) -> Tuple[bytes, int]: - if errors != "strict": - raise IDNAError('Unsupported error handling "{}"'.format(errors)) - - if not data: - return b"", 0 - - labels = _unicode_dots_re.split(data) - trailing_dot = b"" - if labels: - if not labels[-1]: - trailing_dot = b"." - del labels[-1] - elif not final: - # Keep potentially unfinished label until the next call - del labels[-1] - if labels: - trailing_dot = b"." - - result = [] - size = 0 - for label in labels: - result.append(alabel(label)) - if size: - size += 1 - size += len(label) - - # Join with U+002E - result_bytes = b".".join(result) + trailing_dot - size += len(trailing_dot) - return result_bytes, size - - -class IncrementalDecoder(codecs.BufferedIncrementalDecoder): - def _buffer_decode(self, data: Any, errors: str, final: bool) -> Tuple[str, int]: - if errors != "strict": - raise IDNAError('Unsupported error handling "{}"'.format(errors)) - - if not data: - return ("", 0) - - if not isinstance(data, str): - data = str(data, "ascii") - - labels = _unicode_dots_re.split(data) - trailing_dot = "" - if labels: - if not labels[-1]: - trailing_dot = "." - del labels[-1] - elif not final: - # Keep potentially unfinished label until the next call - del labels[-1] - if labels: - trailing_dot = "." - - result = [] - size = 0 - for label in labels: - result.append(ulabel(label)) - if size: - size += 1 - size += len(label) - - result_str = ".".join(result) + trailing_dot - size += len(trailing_dot) - return (result_str, size) - - -class StreamWriter(Codec, codecs.StreamWriter): - pass - - -class StreamReader(Codec, codecs.StreamReader): - pass - - -def search_function(name: str) -> Optional[codecs.CodecInfo]: - if name != "idna2008": - return None - return codecs.CodecInfo( - name=name, - encode=Codec().encode, - decode=Codec().decode, # type: ignore - incrementalencoder=IncrementalEncoder, - incrementaldecoder=IncrementalDecoder, - streamwriter=StreamWriter, - streamreader=StreamReader, - ) - - -codecs.register(search_function) diff --git a/apps/bitwarden_event_logs/lib/idna/compat.py b/apps/bitwarden_event_logs/lib/idna/compat.py deleted file mode 100755 index 1df9f2a7..00000000 --- a/apps/bitwarden_event_logs/lib/idna/compat.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Any, Union - -from .core import decode, encode - - -def ToASCII(label: str) -> bytes: - return encode(label) - - -def ToUnicode(label: Union[bytes, bytearray]) -> str: - return decode(label) - - -def nameprep(s: Any) -> None: - raise NotImplementedError("IDNA 2008 does not utilise nameprep protocol") diff --git a/apps/bitwarden_event_logs/lib/idna/core.py b/apps/bitwarden_event_logs/lib/idna/core.py deleted file mode 100755 index 8177bf7a..00000000 --- a/apps/bitwarden_event_logs/lib/idna/core.py +++ /dev/null @@ -1,437 +0,0 @@ -import bisect -import re -import unicodedata -from typing import Optional, Union - -from . import idnadata -from .intranges import intranges_contain - -_virama_combining_class = 9 -_alabel_prefix = b"xn--" -_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]") - - -class IDNAError(UnicodeError): - """Base exception for all IDNA-encoding related problems""" - - pass - - -class IDNABidiError(IDNAError): - """Exception when bidirectional requirements are not satisfied""" - - pass - - -class InvalidCodepoint(IDNAError): - """Exception when a disallowed or unallocated codepoint is used""" - - pass - - -class InvalidCodepointContext(IDNAError): - """Exception when the codepoint is not valid in the context it is used""" - - pass - - -def _combining_class(cp: int) -> int: - v = unicodedata.combining(chr(cp)) - if v == 0: - if not unicodedata.name(chr(cp)): - raise ValueError("Unknown character in unicodedata") - return v - - -def _is_script(cp: str, script: str) -> bool: - return intranges_contain(ord(cp), idnadata.scripts[script]) - - -def _punycode(s: str) -> bytes: - return s.encode("punycode") - - -def _unot(s: int) -> str: - return "U+{:04X}".format(s) - - -def valid_label_length(label: Union[bytes, str]) -> bool: - if len(label) > 63: - return False - return True - - -def valid_string_length(label: Union[bytes, str], trailing_dot: bool) -> bool: - if len(label) > (254 if trailing_dot else 253): - return False - return True - - -def check_bidi(label: str, check_ltr: bool = False) -> bool: - # Bidi rules should only be applied if string contains RTL characters - bidi_label = False - for idx, cp in enumerate(label, 1): - direction = unicodedata.bidirectional(cp) - if direction == "": - # String likely comes from a newer version of Unicode - raise IDNABidiError("Unknown directionality in label {} at position {}".format(repr(label), idx)) - if direction in ["R", "AL", "AN"]: - bidi_label = True - if not bidi_label and not check_ltr: - return True - - # Bidi rule 1 - direction = unicodedata.bidirectional(label[0]) - if direction in ["R", "AL"]: - rtl = True - elif direction == "L": - rtl = False - else: - raise IDNABidiError("First codepoint in label {} must be directionality L, R or AL".format(repr(label))) - - valid_ending = False - number_type: Optional[str] = None - for idx, cp in enumerate(label, 1): - direction = unicodedata.bidirectional(cp) - - if rtl: - # Bidi rule 2 - if direction not in [ - "R", - "AL", - "AN", - "EN", - "ES", - "CS", - "ET", - "ON", - "BN", - "NSM", - ]: - raise IDNABidiError("Invalid direction for codepoint at position {} in a right-to-left label".format(idx)) - # Bidi rule 3 - if direction in ["R", "AL", "EN", "AN"]: - valid_ending = True - elif direction != "NSM": - valid_ending = False - # Bidi rule 4 - if direction in ["AN", "EN"]: - if not number_type: - number_type = direction - else: - if number_type != direction: - raise IDNABidiError("Can not mix numeral types in a right-to-left label") - else: - # Bidi rule 5 - if direction not in ["L", "EN", "ES", "CS", "ET", "ON", "BN", "NSM"]: - raise IDNABidiError("Invalid direction for codepoint at position {} in a left-to-right label".format(idx)) - # Bidi rule 6 - if direction in ["L", "EN"]: - valid_ending = True - elif direction != "NSM": - valid_ending = False - - if not valid_ending: - raise IDNABidiError("Label ends with illegal codepoint directionality") - - return True - - -def check_initial_combiner(label: str) -> bool: - if unicodedata.category(label[0])[0] == "M": - raise IDNAError("Label begins with an illegal combining character") - return True - - -def check_hyphen_ok(label: str) -> bool: - if label[2:4] == "--": - raise IDNAError("Label has disallowed hyphens in 3rd and 4th position") - if label[0] == "-" or label[-1] == "-": - raise IDNAError("Label must not start or end with a hyphen") - return True - - -def check_nfc(label: str) -> None: - if unicodedata.normalize("NFC", label) != label: - raise IDNAError("Label must be in Normalization Form C") - - -def valid_contextj(label: str, pos: int) -> bool: - cp_value = ord(label[pos]) - - if cp_value == 0x200C: - if pos > 0: - if _combining_class(ord(label[pos - 1])) == _virama_combining_class: - return True - - ok = False - for i in range(pos - 1, -1, -1): - joining_type = idnadata.joining_types.get(ord(label[i])) - if joining_type == ord("T"): - continue - elif joining_type in [ord("L"), ord("D")]: - ok = True - break - else: - break - - if not ok: - return False - - ok = False - for i in range(pos + 1, len(label)): - joining_type = idnadata.joining_types.get(ord(label[i])) - if joining_type == ord("T"): - continue - elif joining_type in [ord("R"), ord("D")]: - ok = True - break - else: - break - return ok - - if cp_value == 0x200D: - if pos > 0: - if _combining_class(ord(label[pos - 1])) == _virama_combining_class: - return True - return False - - else: - return False - - -def valid_contexto(label: str, pos: int, exception: bool = False) -> bool: - cp_value = ord(label[pos]) - - if cp_value == 0x00B7: - if 0 < pos < len(label) - 1: - if ord(label[pos - 1]) == 0x006C and ord(label[pos + 1]) == 0x006C: - return True - return False - - elif cp_value == 0x0375: - if pos < len(label) - 1 and len(label) > 1: - return _is_script(label[pos + 1], "Greek") - return False - - elif cp_value == 0x05F3 or cp_value == 0x05F4: - if pos > 0: - return _is_script(label[pos - 1], "Hebrew") - return False - - elif cp_value == 0x30FB: - for cp in label: - if cp == "\u30fb": - continue - if _is_script(cp, "Hiragana") or _is_script(cp, "Katakana") or _is_script(cp, "Han"): - return True - return False - - elif 0x660 <= cp_value <= 0x669: - for cp in label: - if 0x6F0 <= ord(cp) <= 0x06F9: - return False - return True - - elif 0x6F0 <= cp_value <= 0x6F9: - for cp in label: - if 0x660 <= ord(cp) <= 0x0669: - return False - return True - - return False - - -def check_label(label: Union[str, bytes, bytearray]) -> None: - if isinstance(label, (bytes, bytearray)): - label = label.decode("utf-8") - if len(label) == 0: - raise IDNAError("Empty Label") - - check_nfc(label) - check_hyphen_ok(label) - check_initial_combiner(label) - - for pos, cp in enumerate(label): - cp_value = ord(cp) - if intranges_contain(cp_value, idnadata.codepoint_classes["PVALID"]): - continue - elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTJ"]): - try: - if not valid_contextj(label, pos): - raise InvalidCodepointContext( - "Joiner {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label)) - ) - except ValueError: - raise IDNAError( - "Unknown codepoint adjacent to joiner {} at position {} in {}".format( - _unot(cp_value), pos + 1, repr(label) - ) - ) - elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTO"]): - if not valid_contexto(label, pos): - raise InvalidCodepointContext( - "Codepoint {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label)) - ) - else: - raise InvalidCodepoint( - "Codepoint {} at position {} of {} not allowed".format(_unot(cp_value), pos + 1, repr(label)) - ) - - check_bidi(label) - - -def alabel(label: str) -> bytes: - try: - label_bytes = label.encode("ascii") - ulabel(label_bytes) - if not valid_label_length(label_bytes): - raise IDNAError("Label too long") - return label_bytes - except UnicodeEncodeError: - pass - - check_label(label) - label_bytes = _alabel_prefix + _punycode(label) - - if not valid_label_length(label_bytes): - raise IDNAError("Label too long") - - return label_bytes - - -def ulabel(label: Union[str, bytes, bytearray]) -> str: - if not isinstance(label, (bytes, bytearray)): - try: - label_bytes = label.encode("ascii") - except UnicodeEncodeError: - check_label(label) - return label - else: - label_bytes = bytes(label) - - label_bytes = label_bytes.lower() - if label_bytes.startswith(_alabel_prefix): - label_bytes = label_bytes[len(_alabel_prefix) :] - if not label_bytes: - raise IDNAError("Malformed A-label, no Punycode eligible content found") - if label_bytes.decode("ascii")[-1] == "-": - raise IDNAError("A-label must not end with a hyphen") - else: - check_label(label_bytes) - return label_bytes.decode("ascii") - - try: - label = label_bytes.decode("punycode") - except UnicodeError: - raise IDNAError("Invalid A-label") - check_label(label) - return label - - -def uts46_remap(domain: str, std3_rules: bool = True, transitional: bool = False) -> str: - """Re-map the characters in the string according to UTS46 processing.""" - from .uts46data import uts46data - - output = "" - - for pos, char in enumerate(domain): - code_point = ord(char) - try: - uts46row = uts46data[code_point if code_point < 256 else bisect.bisect_left(uts46data, (code_point, "Z")) - 1] - status = uts46row[1] - replacement: Optional[str] = None - if len(uts46row) == 3: - replacement = uts46row[2] - if ( - status == "V" - or (status == "D" and not transitional) - or (status == "3" and not std3_rules and replacement is None) - ): - output += char - elif replacement is not None and ( - status == "M" or (status == "3" and not std3_rules) or (status == "D" and transitional) - ): - output += replacement - elif status != "I": - raise IndexError() - except IndexError: - raise InvalidCodepoint( - "Codepoint {} not allowed at position {} in {}".format(_unot(code_point), pos + 1, repr(domain)) - ) - - return unicodedata.normalize("NFC", output) - - -def encode( - s: Union[str, bytes, bytearray], - strict: bool = False, - uts46: bool = False, - std3_rules: bool = False, - transitional: bool = False, -) -> bytes: - if not isinstance(s, str): - try: - s = str(s, "ascii") - except UnicodeDecodeError: - raise IDNAError("should pass a unicode string to the function rather than a byte string.") - if uts46: - s = uts46_remap(s, std3_rules, transitional) - trailing_dot = False - result = [] - if strict: - labels = s.split(".") - else: - labels = _unicode_dots_re.split(s) - if not labels or labels == [""]: - raise IDNAError("Empty domain") - if labels[-1] == "": - del labels[-1] - trailing_dot = True - for label in labels: - s = alabel(label) - if s: - result.append(s) - else: - raise IDNAError("Empty label") - if trailing_dot: - result.append(b"") - s = b".".join(result) - if not valid_string_length(s, trailing_dot): - raise IDNAError("Domain too long") - return s - - -def decode( - s: Union[str, bytes, bytearray], - strict: bool = False, - uts46: bool = False, - std3_rules: bool = False, -) -> str: - try: - if not isinstance(s, str): - s = str(s, "ascii") - except UnicodeDecodeError: - raise IDNAError("Invalid ASCII in A-label") - if uts46: - s = uts46_remap(s, std3_rules, False) - trailing_dot = False - result = [] - if not strict: - labels = _unicode_dots_re.split(s) - else: - labels = s.split(".") - if not labels or labels == [""]: - raise IDNAError("Empty domain") - if not labels[-1]: - del labels[-1] - trailing_dot = True - for label in labels: - s = ulabel(label) - if s: - result.append(s) - else: - raise IDNAError("Empty label") - if trailing_dot: - result.append("") - return ".".join(result) diff --git a/apps/bitwarden_event_logs/lib/idna/idnadata.py b/apps/bitwarden_event_logs/lib/idna/idnadata.py deleted file mode 100755 index ded47cae..00000000 --- a/apps/bitwarden_event_logs/lib/idna/idnadata.py +++ /dev/null @@ -1,4309 +0,0 @@ -# This file is automatically generated by tools/idna-data - -__version__ = "16.0.0" - -scripts = { - "Greek": ( - 0x37000000374, - 0x37500000378, - 0x37A0000037E, - 0x37F00000380, - 0x38400000385, - 0x38600000387, - 0x3880000038B, - 0x38C0000038D, - 0x38E000003A2, - 0x3A3000003E2, - 0x3F000000400, - 0x1D2600001D2B, - 0x1D5D00001D62, - 0x1D6600001D6B, - 0x1DBF00001DC0, - 0x1F0000001F16, - 0x1F1800001F1E, - 0x1F2000001F46, - 0x1F4800001F4E, - 0x1F5000001F58, - 0x1F5900001F5A, - 0x1F5B00001F5C, - 0x1F5D00001F5E, - 0x1F5F00001F7E, - 0x1F8000001FB5, - 0x1FB600001FC5, - 0x1FC600001FD4, - 0x1FD600001FDC, - 0x1FDD00001FF0, - 0x1FF200001FF5, - 0x1FF600001FFF, - 0x212600002127, - 0xAB650000AB66, - 0x101400001018F, - 0x101A0000101A1, - 0x1D2000001D246, - ), - "Han": ( - 0x2E8000002E9A, - 0x2E9B00002EF4, - 0x2F0000002FD6, - 0x300500003006, - 0x300700003008, - 0x30210000302A, - 0x30380000303C, - 0x340000004DC0, - 0x4E000000A000, - 0xF9000000FA6E, - 0xFA700000FADA, - 0x16FE200016FE4, - 0x16FF000016FF2, - 0x200000002A6E0, - 0x2A7000002B73A, - 0x2B7400002B81E, - 0x2B8200002CEA2, - 0x2CEB00002EBE1, - 0x2EBF00002EE5E, - 0x2F8000002FA1E, - 0x300000003134B, - 0x31350000323B0, - ), - "Hebrew": ( - 0x591000005C8, - 0x5D0000005EB, - 0x5EF000005F5, - 0xFB1D0000FB37, - 0xFB380000FB3D, - 0xFB3E0000FB3F, - 0xFB400000FB42, - 0xFB430000FB45, - 0xFB460000FB50, - ), - "Hiragana": ( - 0x304100003097, - 0x309D000030A0, - 0x1B0010001B120, - 0x1B1320001B133, - 0x1B1500001B153, - 0x1F2000001F201, - ), - "Katakana": ( - 0x30A1000030FB, - 0x30FD00003100, - 0x31F000003200, - 0x32D0000032FF, - 0x330000003358, - 0xFF660000FF70, - 0xFF710000FF9E, - 0x1AFF00001AFF4, - 0x1AFF50001AFFC, - 0x1AFFD0001AFFF, - 0x1B0000001B001, - 0x1B1200001B123, - 0x1B1550001B156, - 0x1B1640001B168, - ), -} -joining_types = { - 0xAD: 84, - 0x300: 84, - 0x301: 84, - 0x302: 84, - 0x303: 84, - 0x304: 84, - 0x305: 84, - 0x306: 84, - 0x307: 84, - 0x308: 84, - 0x309: 84, - 0x30A: 84, - 0x30B: 84, - 0x30C: 84, - 0x30D: 84, - 0x30E: 84, - 0x30F: 84, - 0x310: 84, - 0x311: 84, - 0x312: 84, - 0x313: 84, - 0x314: 84, - 0x315: 84, - 0x316: 84, - 0x317: 84, - 0x318: 84, - 0x319: 84, - 0x31A: 84, - 0x31B: 84, - 0x31C: 84, - 0x31D: 84, - 0x31E: 84, - 0x31F: 84, - 0x320: 84, - 0x321: 84, - 0x322: 84, - 0x323: 84, - 0x324: 84, - 0x325: 84, - 0x326: 84, - 0x327: 84, - 0x328: 84, - 0x329: 84, - 0x32A: 84, - 0x32B: 84, - 0x32C: 84, - 0x32D: 84, - 0x32E: 84, - 0x32F: 84, - 0x330: 84, - 0x331: 84, - 0x332: 84, - 0x333: 84, - 0x334: 84, - 0x335: 84, - 0x336: 84, - 0x337: 84, - 0x338: 84, - 0x339: 84, - 0x33A: 84, - 0x33B: 84, - 0x33C: 84, - 0x33D: 84, - 0x33E: 84, - 0x33F: 84, - 0x340: 84, - 0x341: 84, - 0x342: 84, - 0x343: 84, - 0x344: 84, - 0x345: 84, - 0x346: 84, - 0x347: 84, - 0x348: 84, - 0x349: 84, - 0x34A: 84, - 0x34B: 84, - 0x34C: 84, - 0x34D: 84, - 0x34E: 84, - 0x34F: 84, - 0x350: 84, - 0x351: 84, - 0x352: 84, - 0x353: 84, - 0x354: 84, - 0x355: 84, - 0x356: 84, - 0x357: 84, - 0x358: 84, - 0x359: 84, - 0x35A: 84, - 0x35B: 84, - 0x35C: 84, - 0x35D: 84, - 0x35E: 84, - 0x35F: 84, - 0x360: 84, - 0x361: 84, - 0x362: 84, - 0x363: 84, - 0x364: 84, - 0x365: 84, - 0x366: 84, - 0x367: 84, - 0x368: 84, - 0x369: 84, - 0x36A: 84, - 0x36B: 84, - 0x36C: 84, - 0x36D: 84, - 0x36E: 84, - 0x36F: 84, - 0x483: 84, - 0x484: 84, - 0x485: 84, - 0x486: 84, - 0x487: 84, - 0x488: 84, - 0x489: 84, - 0x591: 84, - 0x592: 84, - 0x593: 84, - 0x594: 84, - 0x595: 84, - 0x596: 84, - 0x597: 84, - 0x598: 84, - 0x599: 84, - 0x59A: 84, - 0x59B: 84, - 0x59C: 84, - 0x59D: 84, - 0x59E: 84, - 0x59F: 84, - 0x5A0: 84, - 0x5A1: 84, - 0x5A2: 84, - 0x5A3: 84, - 0x5A4: 84, - 0x5A5: 84, - 0x5A6: 84, - 0x5A7: 84, - 0x5A8: 84, - 0x5A9: 84, - 0x5AA: 84, - 0x5AB: 84, - 0x5AC: 84, - 0x5AD: 84, - 0x5AE: 84, - 0x5AF: 84, - 0x5B0: 84, - 0x5B1: 84, - 0x5B2: 84, - 0x5B3: 84, - 0x5B4: 84, - 0x5B5: 84, - 0x5B6: 84, - 0x5B7: 84, - 0x5B8: 84, - 0x5B9: 84, - 0x5BA: 84, - 0x5BB: 84, - 0x5BC: 84, - 0x5BD: 84, - 0x5BF: 84, - 0x5C1: 84, - 0x5C2: 84, - 0x5C4: 84, - 0x5C5: 84, - 0x5C7: 84, - 0x610: 84, - 0x611: 84, - 0x612: 84, - 0x613: 84, - 0x614: 84, - 0x615: 84, - 0x616: 84, - 0x617: 84, - 0x618: 84, - 0x619: 84, - 0x61A: 84, - 0x61C: 84, - 0x620: 68, - 0x622: 82, - 0x623: 82, - 0x624: 82, - 0x625: 82, - 0x626: 68, - 0x627: 82, - 0x628: 68, - 0x629: 82, - 0x62A: 68, - 0x62B: 68, - 0x62C: 68, - 0x62D: 68, - 0x62E: 68, - 0x62F: 82, - 0x630: 82, - 0x631: 82, - 0x632: 82, - 0x633: 68, - 0x634: 68, - 0x635: 68, - 0x636: 68, - 0x637: 68, - 0x638: 68, - 0x639: 68, - 0x63A: 68, - 0x63B: 68, - 0x63C: 68, - 0x63D: 68, - 0x63E: 68, - 0x63F: 68, - 0x640: 67, - 0x641: 68, - 0x642: 68, - 0x643: 68, - 0x644: 68, - 0x645: 68, - 0x646: 68, - 0x647: 68, - 0x648: 82, - 0x649: 68, - 0x64A: 68, - 0x64B: 84, - 0x64C: 84, - 0x64D: 84, - 0x64E: 84, - 0x64F: 84, - 0x650: 84, - 0x651: 84, - 0x652: 84, - 0x653: 84, - 0x654: 84, - 0x655: 84, - 0x656: 84, - 0x657: 84, - 0x658: 84, - 0x659: 84, - 0x65A: 84, - 0x65B: 84, - 0x65C: 84, - 0x65D: 84, - 0x65E: 84, - 0x65F: 84, - 0x66E: 68, - 0x66F: 68, - 0x670: 84, - 0x671: 82, - 0x672: 82, - 0x673: 82, - 0x675: 82, - 0x676: 82, - 0x677: 82, - 0x678: 68, - 0x679: 68, - 0x67A: 68, - 0x67B: 68, - 0x67C: 68, - 0x67D: 68, - 0x67E: 68, - 0x67F: 68, - 0x680: 68, - 0x681: 68, - 0x682: 68, - 0x683: 68, - 0x684: 68, - 0x685: 68, - 0x686: 68, - 0x687: 68, - 0x688: 82, - 0x689: 82, - 0x68A: 82, - 0x68B: 82, - 0x68C: 82, - 0x68D: 82, - 0x68E: 82, - 0x68F: 82, - 0x690: 82, - 0x691: 82, - 0x692: 82, - 0x693: 82, - 0x694: 82, - 0x695: 82, - 0x696: 82, - 0x697: 82, - 0x698: 82, - 0x699: 82, - 0x69A: 68, - 0x69B: 68, - 0x69C: 68, - 0x69D: 68, - 0x69E: 68, - 0x69F: 68, - 0x6A0: 68, - 0x6A1: 68, - 0x6A2: 68, - 0x6A3: 68, - 0x6A4: 68, - 0x6A5: 68, - 0x6A6: 68, - 0x6A7: 68, - 0x6A8: 68, - 0x6A9: 68, - 0x6AA: 68, - 0x6AB: 68, - 0x6AC: 68, - 0x6AD: 68, - 0x6AE: 68, - 0x6AF: 68, - 0x6B0: 68, - 0x6B1: 68, - 0x6B2: 68, - 0x6B3: 68, - 0x6B4: 68, - 0x6B5: 68, - 0x6B6: 68, - 0x6B7: 68, - 0x6B8: 68, - 0x6B9: 68, - 0x6BA: 68, - 0x6BB: 68, - 0x6BC: 68, - 0x6BD: 68, - 0x6BE: 68, - 0x6BF: 68, - 0x6C0: 82, - 0x6C1: 68, - 0x6C2: 68, - 0x6C3: 82, - 0x6C4: 82, - 0x6C5: 82, - 0x6C6: 82, - 0x6C7: 82, - 0x6C8: 82, - 0x6C9: 82, - 0x6CA: 82, - 0x6CB: 82, - 0x6CC: 68, - 0x6CD: 82, - 0x6CE: 68, - 0x6CF: 82, - 0x6D0: 68, - 0x6D1: 68, - 0x6D2: 82, - 0x6D3: 82, - 0x6D5: 82, - 0x6D6: 84, - 0x6D7: 84, - 0x6D8: 84, - 0x6D9: 84, - 0x6DA: 84, - 0x6DB: 84, - 0x6DC: 84, - 0x6DF: 84, - 0x6E0: 84, - 0x6E1: 84, - 0x6E2: 84, - 0x6E3: 84, - 0x6E4: 84, - 0x6E7: 84, - 0x6E8: 84, - 0x6EA: 84, - 0x6EB: 84, - 0x6EC: 84, - 0x6ED: 84, - 0x6EE: 82, - 0x6EF: 82, - 0x6FA: 68, - 0x6FB: 68, - 0x6FC: 68, - 0x6FF: 68, - 0x70F: 84, - 0x710: 82, - 0x711: 84, - 0x712: 68, - 0x713: 68, - 0x714: 68, - 0x715: 82, - 0x716: 82, - 0x717: 82, - 0x718: 82, - 0x719: 82, - 0x71A: 68, - 0x71B: 68, - 0x71C: 68, - 0x71D: 68, - 0x71E: 82, - 0x71F: 68, - 0x720: 68, - 0x721: 68, - 0x722: 68, - 0x723: 68, - 0x724: 68, - 0x725: 68, - 0x726: 68, - 0x727: 68, - 0x728: 82, - 0x729: 68, - 0x72A: 82, - 0x72B: 68, - 0x72C: 82, - 0x72D: 68, - 0x72E: 68, - 0x72F: 82, - 0x730: 84, - 0x731: 84, - 0x732: 84, - 0x733: 84, - 0x734: 84, - 0x735: 84, - 0x736: 84, - 0x737: 84, - 0x738: 84, - 0x739: 84, - 0x73A: 84, - 0x73B: 84, - 0x73C: 84, - 0x73D: 84, - 0x73E: 84, - 0x73F: 84, - 0x740: 84, - 0x741: 84, - 0x742: 84, - 0x743: 84, - 0x744: 84, - 0x745: 84, - 0x746: 84, - 0x747: 84, - 0x748: 84, - 0x749: 84, - 0x74A: 84, - 0x74D: 82, - 0x74E: 68, - 0x74F: 68, - 0x750: 68, - 0x751: 68, - 0x752: 68, - 0x753: 68, - 0x754: 68, - 0x755: 68, - 0x756: 68, - 0x757: 68, - 0x758: 68, - 0x759: 82, - 0x75A: 82, - 0x75B: 82, - 0x75C: 68, - 0x75D: 68, - 0x75E: 68, - 0x75F: 68, - 0x760: 68, - 0x761: 68, - 0x762: 68, - 0x763: 68, - 0x764: 68, - 0x765: 68, - 0x766: 68, - 0x767: 68, - 0x768: 68, - 0x769: 68, - 0x76A: 68, - 0x76B: 82, - 0x76C: 82, - 0x76D: 68, - 0x76E: 68, - 0x76F: 68, - 0x770: 68, - 0x771: 82, - 0x772: 68, - 0x773: 82, - 0x774: 82, - 0x775: 68, - 0x776: 68, - 0x777: 68, - 0x778: 82, - 0x779: 82, - 0x77A: 68, - 0x77B: 68, - 0x77C: 68, - 0x77D: 68, - 0x77E: 68, - 0x77F: 68, - 0x7A6: 84, - 0x7A7: 84, - 0x7A8: 84, - 0x7A9: 84, - 0x7AA: 84, - 0x7AB: 84, - 0x7AC: 84, - 0x7AD: 84, - 0x7AE: 84, - 0x7AF: 84, - 0x7B0: 84, - 0x7CA: 68, - 0x7CB: 68, - 0x7CC: 68, - 0x7CD: 68, - 0x7CE: 68, - 0x7CF: 68, - 0x7D0: 68, - 0x7D1: 68, - 0x7D2: 68, - 0x7D3: 68, - 0x7D4: 68, - 0x7D5: 68, - 0x7D6: 68, - 0x7D7: 68, - 0x7D8: 68, - 0x7D9: 68, - 0x7DA: 68, - 0x7DB: 68, - 0x7DC: 68, - 0x7DD: 68, - 0x7DE: 68, - 0x7DF: 68, - 0x7E0: 68, - 0x7E1: 68, - 0x7E2: 68, - 0x7E3: 68, - 0x7E4: 68, - 0x7E5: 68, - 0x7E6: 68, - 0x7E7: 68, - 0x7E8: 68, - 0x7E9: 68, - 0x7EA: 68, - 0x7EB: 84, - 0x7EC: 84, - 0x7ED: 84, - 0x7EE: 84, - 0x7EF: 84, - 0x7F0: 84, - 0x7F1: 84, - 0x7F2: 84, - 0x7F3: 84, - 0x7FA: 67, - 0x7FD: 84, - 0x816: 84, - 0x817: 84, - 0x818: 84, - 0x819: 84, - 0x81B: 84, - 0x81C: 84, - 0x81D: 84, - 0x81E: 84, - 0x81F: 84, - 0x820: 84, - 0x821: 84, - 0x822: 84, - 0x823: 84, - 0x825: 84, - 0x826: 84, - 0x827: 84, - 0x829: 84, - 0x82A: 84, - 0x82B: 84, - 0x82C: 84, - 0x82D: 84, - 0x840: 82, - 0x841: 68, - 0x842: 68, - 0x843: 68, - 0x844: 68, - 0x845: 68, - 0x846: 82, - 0x847: 82, - 0x848: 68, - 0x849: 82, - 0x84A: 68, - 0x84B: 68, - 0x84C: 68, - 0x84D: 68, - 0x84E: 68, - 0x84F: 68, - 0x850: 68, - 0x851: 68, - 0x852: 68, - 0x853: 68, - 0x854: 82, - 0x855: 68, - 0x856: 82, - 0x857: 82, - 0x858: 82, - 0x859: 84, - 0x85A: 84, - 0x85B: 84, - 0x860: 68, - 0x862: 68, - 0x863: 68, - 0x864: 68, - 0x865: 68, - 0x867: 82, - 0x868: 68, - 0x869: 82, - 0x86A: 82, - 0x870: 82, - 0x871: 82, - 0x872: 82, - 0x873: 82, - 0x874: 82, - 0x875: 82, - 0x876: 82, - 0x877: 82, - 0x878: 82, - 0x879: 82, - 0x87A: 82, - 0x87B: 82, - 0x87C: 82, - 0x87D: 82, - 0x87E: 82, - 0x87F: 82, - 0x880: 82, - 0x881: 82, - 0x882: 82, - 0x883: 67, - 0x884: 67, - 0x885: 67, - 0x886: 68, - 0x889: 68, - 0x88A: 68, - 0x88B: 68, - 0x88C: 68, - 0x88D: 68, - 0x88E: 82, - 0x897: 84, - 0x898: 84, - 0x899: 84, - 0x89A: 84, - 0x89B: 84, - 0x89C: 84, - 0x89D: 84, - 0x89E: 84, - 0x89F: 84, - 0x8A0: 68, - 0x8A1: 68, - 0x8A2: 68, - 0x8A3: 68, - 0x8A4: 68, - 0x8A5: 68, - 0x8A6: 68, - 0x8A7: 68, - 0x8A8: 68, - 0x8A9: 68, - 0x8AA: 82, - 0x8AB: 82, - 0x8AC: 82, - 0x8AE: 82, - 0x8AF: 68, - 0x8B0: 68, - 0x8B1: 82, - 0x8B2: 82, - 0x8B3: 68, - 0x8B4: 68, - 0x8B5: 68, - 0x8B6: 68, - 0x8B7: 68, - 0x8B8: 68, - 0x8B9: 82, - 0x8BA: 68, - 0x8BB: 68, - 0x8BC: 68, - 0x8BD: 68, - 0x8BE: 68, - 0x8BF: 68, - 0x8C0: 68, - 0x8C1: 68, - 0x8C2: 68, - 0x8C3: 68, - 0x8C4: 68, - 0x8C5: 68, - 0x8C6: 68, - 0x8C7: 68, - 0x8C8: 68, - 0x8CA: 84, - 0x8CB: 84, - 0x8CC: 84, - 0x8CD: 84, - 0x8CE: 84, - 0x8CF: 84, - 0x8D0: 84, - 0x8D1: 84, - 0x8D2: 84, - 0x8D3: 84, - 0x8D4: 84, - 0x8D5: 84, - 0x8D6: 84, - 0x8D7: 84, - 0x8D8: 84, - 0x8D9: 84, - 0x8DA: 84, - 0x8DB: 84, - 0x8DC: 84, - 0x8DD: 84, - 0x8DE: 84, - 0x8DF: 84, - 0x8E0: 84, - 0x8E1: 84, - 0x8E3: 84, - 0x8E4: 84, - 0x8E5: 84, - 0x8E6: 84, - 0x8E7: 84, - 0x8E8: 84, - 0x8E9: 84, - 0x8EA: 84, - 0x8EB: 84, - 0x8EC: 84, - 0x8ED: 84, - 0x8EE: 84, - 0x8EF: 84, - 0x8F0: 84, - 0x8F1: 84, - 0x8F2: 84, - 0x8F3: 84, - 0x8F4: 84, - 0x8F5: 84, - 0x8F6: 84, - 0x8F7: 84, - 0x8F8: 84, - 0x8F9: 84, - 0x8FA: 84, - 0x8FB: 84, - 0x8FC: 84, - 0x8FD: 84, - 0x8FE: 84, - 0x8FF: 84, - 0x900: 84, - 0x901: 84, - 0x902: 84, - 0x93A: 84, - 0x93C: 84, - 0x941: 84, - 0x942: 84, - 0x943: 84, - 0x944: 84, - 0x945: 84, - 0x946: 84, - 0x947: 84, - 0x948: 84, - 0x94D: 84, - 0x951: 84, - 0x952: 84, - 0x953: 84, - 0x954: 84, - 0x955: 84, - 0x956: 84, - 0x957: 84, - 0x962: 84, - 0x963: 84, - 0x981: 84, - 0x9BC: 84, - 0x9C1: 84, - 0x9C2: 84, - 0x9C3: 84, - 0x9C4: 84, - 0x9CD: 84, - 0x9E2: 84, - 0x9E3: 84, - 0x9FE: 84, - 0xA01: 84, - 0xA02: 84, - 0xA3C: 84, - 0xA41: 84, - 0xA42: 84, - 0xA47: 84, - 0xA48: 84, - 0xA4B: 84, - 0xA4C: 84, - 0xA4D: 84, - 0xA51: 84, - 0xA70: 84, - 0xA71: 84, - 0xA75: 84, - 0xA81: 84, - 0xA82: 84, - 0xABC: 84, - 0xAC1: 84, - 0xAC2: 84, - 0xAC3: 84, - 0xAC4: 84, - 0xAC5: 84, - 0xAC7: 84, - 0xAC8: 84, - 0xACD: 84, - 0xAE2: 84, - 0xAE3: 84, - 0xAFA: 84, - 0xAFB: 84, - 0xAFC: 84, - 0xAFD: 84, - 0xAFE: 84, - 0xAFF: 84, - 0xB01: 84, - 0xB3C: 84, - 0xB3F: 84, - 0xB41: 84, - 0xB42: 84, - 0xB43: 84, - 0xB44: 84, - 0xB4D: 84, - 0xB55: 84, - 0xB56: 84, - 0xB62: 84, - 0xB63: 84, - 0xB82: 84, - 0xBC0: 84, - 0xBCD: 84, - 0xC00: 84, - 0xC04: 84, - 0xC3C: 84, - 0xC3E: 84, - 0xC3F: 84, - 0xC40: 84, - 0xC46: 84, - 0xC47: 84, - 0xC48: 84, - 0xC4A: 84, - 0xC4B: 84, - 0xC4C: 84, - 0xC4D: 84, - 0xC55: 84, - 0xC56: 84, - 0xC62: 84, - 0xC63: 84, - 0xC81: 84, - 0xCBC: 84, - 0xCBF: 84, - 0xCC6: 84, - 0xCCC: 84, - 0xCCD: 84, - 0xCE2: 84, - 0xCE3: 84, - 0xD00: 84, - 0xD01: 84, - 0xD3B: 84, - 0xD3C: 84, - 0xD41: 84, - 0xD42: 84, - 0xD43: 84, - 0xD44: 84, - 0xD4D: 84, - 0xD62: 84, - 0xD63: 84, - 0xD81: 84, - 0xDCA: 84, - 0xDD2: 84, - 0xDD3: 84, - 0xDD4: 84, - 0xDD6: 84, - 0xE31: 84, - 0xE34: 84, - 0xE35: 84, - 0xE36: 84, - 0xE37: 84, - 0xE38: 84, - 0xE39: 84, - 0xE3A: 84, - 0xE47: 84, - 0xE48: 84, - 0xE49: 84, - 0xE4A: 84, - 0xE4B: 84, - 0xE4C: 84, - 0xE4D: 84, - 0xE4E: 84, - 0xEB1: 84, - 0xEB4: 84, - 0xEB5: 84, - 0xEB6: 84, - 0xEB7: 84, - 0xEB8: 84, - 0xEB9: 84, - 0xEBA: 84, - 0xEBB: 84, - 0xEBC: 84, - 0xEC8: 84, - 0xEC9: 84, - 0xECA: 84, - 0xECB: 84, - 0xECC: 84, - 0xECD: 84, - 0xECE: 84, - 0xF18: 84, - 0xF19: 84, - 0xF35: 84, - 0xF37: 84, - 0xF39: 84, - 0xF71: 84, - 0xF72: 84, - 0xF73: 84, - 0xF74: 84, - 0xF75: 84, - 0xF76: 84, - 0xF77: 84, - 0xF78: 84, - 0xF79: 84, - 0xF7A: 84, - 0xF7B: 84, - 0xF7C: 84, - 0xF7D: 84, - 0xF7E: 84, - 0xF80: 84, - 0xF81: 84, - 0xF82: 84, - 0xF83: 84, - 0xF84: 84, - 0xF86: 84, - 0xF87: 84, - 0xF8D: 84, - 0xF8E: 84, - 0xF8F: 84, - 0xF90: 84, - 0xF91: 84, - 0xF92: 84, - 0xF93: 84, - 0xF94: 84, - 0xF95: 84, - 0xF96: 84, - 0xF97: 84, - 0xF99: 84, - 0xF9A: 84, - 0xF9B: 84, - 0xF9C: 84, - 0xF9D: 84, - 0xF9E: 84, - 0xF9F: 84, - 0xFA0: 84, - 0xFA1: 84, - 0xFA2: 84, - 0xFA3: 84, - 0xFA4: 84, - 0xFA5: 84, - 0xFA6: 84, - 0xFA7: 84, - 0xFA8: 84, - 0xFA9: 84, - 0xFAA: 84, - 0xFAB: 84, - 0xFAC: 84, - 0xFAD: 84, - 0xFAE: 84, - 0xFAF: 84, - 0xFB0: 84, - 0xFB1: 84, - 0xFB2: 84, - 0xFB3: 84, - 0xFB4: 84, - 0xFB5: 84, - 0xFB6: 84, - 0xFB7: 84, - 0xFB8: 84, - 0xFB9: 84, - 0xFBA: 84, - 0xFBB: 84, - 0xFBC: 84, - 0xFC6: 84, - 0x102D: 84, - 0x102E: 84, - 0x102F: 84, - 0x1030: 84, - 0x1032: 84, - 0x1033: 84, - 0x1034: 84, - 0x1035: 84, - 0x1036: 84, - 0x1037: 84, - 0x1039: 84, - 0x103A: 84, - 0x103D: 84, - 0x103E: 84, - 0x1058: 84, - 0x1059: 84, - 0x105E: 84, - 0x105F: 84, - 0x1060: 84, - 0x1071: 84, - 0x1072: 84, - 0x1073: 84, - 0x1074: 84, - 0x1082: 84, - 0x1085: 84, - 0x1086: 84, - 0x108D: 84, - 0x109D: 84, - 0x135D: 84, - 0x135E: 84, - 0x135F: 84, - 0x1712: 84, - 0x1713: 84, - 0x1714: 84, - 0x1732: 84, - 0x1733: 84, - 0x1752: 84, - 0x1753: 84, - 0x1772: 84, - 0x1773: 84, - 0x17B4: 84, - 0x17B5: 84, - 0x17B7: 84, - 0x17B8: 84, - 0x17B9: 84, - 0x17BA: 84, - 0x17BB: 84, - 0x17BC: 84, - 0x17BD: 84, - 0x17C6: 84, - 0x17C9: 84, - 0x17CA: 84, - 0x17CB: 84, - 0x17CC: 84, - 0x17CD: 84, - 0x17CE: 84, - 0x17CF: 84, - 0x17D0: 84, - 0x17D1: 84, - 0x17D2: 84, - 0x17D3: 84, - 0x17DD: 84, - 0x1807: 68, - 0x180A: 67, - 0x180B: 84, - 0x180C: 84, - 0x180D: 84, - 0x180F: 84, - 0x1820: 68, - 0x1821: 68, - 0x1822: 68, - 0x1823: 68, - 0x1824: 68, - 0x1825: 68, - 0x1826: 68, - 0x1827: 68, - 0x1828: 68, - 0x1829: 68, - 0x182A: 68, - 0x182B: 68, - 0x182C: 68, - 0x182D: 68, - 0x182E: 68, - 0x182F: 68, - 0x1830: 68, - 0x1831: 68, - 0x1832: 68, - 0x1833: 68, - 0x1834: 68, - 0x1835: 68, - 0x1836: 68, - 0x1837: 68, - 0x1838: 68, - 0x1839: 68, - 0x183A: 68, - 0x183B: 68, - 0x183C: 68, - 0x183D: 68, - 0x183E: 68, - 0x183F: 68, - 0x1840: 68, - 0x1841: 68, - 0x1842: 68, - 0x1843: 68, - 0x1844: 68, - 0x1845: 68, - 0x1846: 68, - 0x1847: 68, - 0x1848: 68, - 0x1849: 68, - 0x184A: 68, - 0x184B: 68, - 0x184C: 68, - 0x184D: 68, - 0x184E: 68, - 0x184F: 68, - 0x1850: 68, - 0x1851: 68, - 0x1852: 68, - 0x1853: 68, - 0x1854: 68, - 0x1855: 68, - 0x1856: 68, - 0x1857: 68, - 0x1858: 68, - 0x1859: 68, - 0x185A: 68, - 0x185B: 68, - 0x185C: 68, - 0x185D: 68, - 0x185E: 68, - 0x185F: 68, - 0x1860: 68, - 0x1861: 68, - 0x1862: 68, - 0x1863: 68, - 0x1864: 68, - 0x1865: 68, - 0x1866: 68, - 0x1867: 68, - 0x1868: 68, - 0x1869: 68, - 0x186A: 68, - 0x186B: 68, - 0x186C: 68, - 0x186D: 68, - 0x186E: 68, - 0x186F: 68, - 0x1870: 68, - 0x1871: 68, - 0x1872: 68, - 0x1873: 68, - 0x1874: 68, - 0x1875: 68, - 0x1876: 68, - 0x1877: 68, - 0x1878: 68, - 0x1885: 84, - 0x1886: 84, - 0x1887: 68, - 0x1888: 68, - 0x1889: 68, - 0x188A: 68, - 0x188B: 68, - 0x188C: 68, - 0x188D: 68, - 0x188E: 68, - 0x188F: 68, - 0x1890: 68, - 0x1891: 68, - 0x1892: 68, - 0x1893: 68, - 0x1894: 68, - 0x1895: 68, - 0x1896: 68, - 0x1897: 68, - 0x1898: 68, - 0x1899: 68, - 0x189A: 68, - 0x189B: 68, - 0x189C: 68, - 0x189D: 68, - 0x189E: 68, - 0x189F: 68, - 0x18A0: 68, - 0x18A1: 68, - 0x18A2: 68, - 0x18A3: 68, - 0x18A4: 68, - 0x18A5: 68, - 0x18A6: 68, - 0x18A7: 68, - 0x18A8: 68, - 0x18A9: 84, - 0x18AA: 68, - 0x1920: 84, - 0x1921: 84, - 0x1922: 84, - 0x1927: 84, - 0x1928: 84, - 0x1932: 84, - 0x1939: 84, - 0x193A: 84, - 0x193B: 84, - 0x1A17: 84, - 0x1A18: 84, - 0x1A1B: 84, - 0x1A56: 84, - 0x1A58: 84, - 0x1A59: 84, - 0x1A5A: 84, - 0x1A5B: 84, - 0x1A5C: 84, - 0x1A5D: 84, - 0x1A5E: 84, - 0x1A60: 84, - 0x1A62: 84, - 0x1A65: 84, - 0x1A66: 84, - 0x1A67: 84, - 0x1A68: 84, - 0x1A69: 84, - 0x1A6A: 84, - 0x1A6B: 84, - 0x1A6C: 84, - 0x1A73: 84, - 0x1A74: 84, - 0x1A75: 84, - 0x1A76: 84, - 0x1A77: 84, - 0x1A78: 84, - 0x1A79: 84, - 0x1A7A: 84, - 0x1A7B: 84, - 0x1A7C: 84, - 0x1A7F: 84, - 0x1AB0: 84, - 0x1AB1: 84, - 0x1AB2: 84, - 0x1AB3: 84, - 0x1AB4: 84, - 0x1AB5: 84, - 0x1AB6: 84, - 0x1AB7: 84, - 0x1AB8: 84, - 0x1AB9: 84, - 0x1ABA: 84, - 0x1ABB: 84, - 0x1ABC: 84, - 0x1ABD: 84, - 0x1ABE: 84, - 0x1ABF: 84, - 0x1AC0: 84, - 0x1AC1: 84, - 0x1AC2: 84, - 0x1AC3: 84, - 0x1AC4: 84, - 0x1AC5: 84, - 0x1AC6: 84, - 0x1AC7: 84, - 0x1AC8: 84, - 0x1AC9: 84, - 0x1ACA: 84, - 0x1ACB: 84, - 0x1ACC: 84, - 0x1ACD: 84, - 0x1ACE: 84, - 0x1B00: 84, - 0x1B01: 84, - 0x1B02: 84, - 0x1B03: 84, - 0x1B34: 84, - 0x1B36: 84, - 0x1B37: 84, - 0x1B38: 84, - 0x1B39: 84, - 0x1B3A: 84, - 0x1B3C: 84, - 0x1B42: 84, - 0x1B6B: 84, - 0x1B6C: 84, - 0x1B6D: 84, - 0x1B6E: 84, - 0x1B6F: 84, - 0x1B70: 84, - 0x1B71: 84, - 0x1B72: 84, - 0x1B73: 84, - 0x1B80: 84, - 0x1B81: 84, - 0x1BA2: 84, - 0x1BA3: 84, - 0x1BA4: 84, - 0x1BA5: 84, - 0x1BA8: 84, - 0x1BA9: 84, - 0x1BAB: 84, - 0x1BAC: 84, - 0x1BAD: 84, - 0x1BE6: 84, - 0x1BE8: 84, - 0x1BE9: 84, - 0x1BED: 84, - 0x1BEF: 84, - 0x1BF0: 84, - 0x1BF1: 84, - 0x1C2C: 84, - 0x1C2D: 84, - 0x1C2E: 84, - 0x1C2F: 84, - 0x1C30: 84, - 0x1C31: 84, - 0x1C32: 84, - 0x1C33: 84, - 0x1C36: 84, - 0x1C37: 84, - 0x1CD0: 84, - 0x1CD1: 84, - 0x1CD2: 84, - 0x1CD4: 84, - 0x1CD5: 84, - 0x1CD6: 84, - 0x1CD7: 84, - 0x1CD8: 84, - 0x1CD9: 84, - 0x1CDA: 84, - 0x1CDB: 84, - 0x1CDC: 84, - 0x1CDD: 84, - 0x1CDE: 84, - 0x1CDF: 84, - 0x1CE0: 84, - 0x1CE2: 84, - 0x1CE3: 84, - 0x1CE4: 84, - 0x1CE5: 84, - 0x1CE6: 84, - 0x1CE7: 84, - 0x1CE8: 84, - 0x1CED: 84, - 0x1CF4: 84, - 0x1CF8: 84, - 0x1CF9: 84, - 0x1DC0: 84, - 0x1DC1: 84, - 0x1DC2: 84, - 0x1DC3: 84, - 0x1DC4: 84, - 0x1DC5: 84, - 0x1DC6: 84, - 0x1DC7: 84, - 0x1DC8: 84, - 0x1DC9: 84, - 0x1DCA: 84, - 0x1DCB: 84, - 0x1DCC: 84, - 0x1DCD: 84, - 0x1DCE: 84, - 0x1DCF: 84, - 0x1DD0: 84, - 0x1DD1: 84, - 0x1DD2: 84, - 0x1DD3: 84, - 0x1DD4: 84, - 0x1DD5: 84, - 0x1DD6: 84, - 0x1DD7: 84, - 0x1DD8: 84, - 0x1DD9: 84, - 0x1DDA: 84, - 0x1DDB: 84, - 0x1DDC: 84, - 0x1DDD: 84, - 0x1DDE: 84, - 0x1DDF: 84, - 0x1DE0: 84, - 0x1DE1: 84, - 0x1DE2: 84, - 0x1DE3: 84, - 0x1DE4: 84, - 0x1DE5: 84, - 0x1DE6: 84, - 0x1DE7: 84, - 0x1DE8: 84, - 0x1DE9: 84, - 0x1DEA: 84, - 0x1DEB: 84, - 0x1DEC: 84, - 0x1DED: 84, - 0x1DEE: 84, - 0x1DEF: 84, - 0x1DF0: 84, - 0x1DF1: 84, - 0x1DF2: 84, - 0x1DF3: 84, - 0x1DF4: 84, - 0x1DF5: 84, - 0x1DF6: 84, - 0x1DF7: 84, - 0x1DF8: 84, - 0x1DF9: 84, - 0x1DFA: 84, - 0x1DFB: 84, - 0x1DFC: 84, - 0x1DFD: 84, - 0x1DFE: 84, - 0x1DFF: 84, - 0x200B: 84, - 0x200D: 67, - 0x200E: 84, - 0x200F: 84, - 0x202A: 84, - 0x202B: 84, - 0x202C: 84, - 0x202D: 84, - 0x202E: 84, - 0x2060: 84, - 0x2061: 84, - 0x2062: 84, - 0x2063: 84, - 0x2064: 84, - 0x206A: 84, - 0x206B: 84, - 0x206C: 84, - 0x206D: 84, - 0x206E: 84, - 0x206F: 84, - 0x20D0: 84, - 0x20D1: 84, - 0x20D2: 84, - 0x20D3: 84, - 0x20D4: 84, - 0x20D5: 84, - 0x20D6: 84, - 0x20D7: 84, - 0x20D8: 84, - 0x20D9: 84, - 0x20DA: 84, - 0x20DB: 84, - 0x20DC: 84, - 0x20DD: 84, - 0x20DE: 84, - 0x20DF: 84, - 0x20E0: 84, - 0x20E1: 84, - 0x20E2: 84, - 0x20E3: 84, - 0x20E4: 84, - 0x20E5: 84, - 0x20E6: 84, - 0x20E7: 84, - 0x20E8: 84, - 0x20E9: 84, - 0x20EA: 84, - 0x20EB: 84, - 0x20EC: 84, - 0x20ED: 84, - 0x20EE: 84, - 0x20EF: 84, - 0x20F0: 84, - 0x2CEF: 84, - 0x2CF0: 84, - 0x2CF1: 84, - 0x2D7F: 84, - 0x2DE0: 84, - 0x2DE1: 84, - 0x2DE2: 84, - 0x2DE3: 84, - 0x2DE4: 84, - 0x2DE5: 84, - 0x2DE6: 84, - 0x2DE7: 84, - 0x2DE8: 84, - 0x2DE9: 84, - 0x2DEA: 84, - 0x2DEB: 84, - 0x2DEC: 84, - 0x2DED: 84, - 0x2DEE: 84, - 0x2DEF: 84, - 0x2DF0: 84, - 0x2DF1: 84, - 0x2DF2: 84, - 0x2DF3: 84, - 0x2DF4: 84, - 0x2DF5: 84, - 0x2DF6: 84, - 0x2DF7: 84, - 0x2DF8: 84, - 0x2DF9: 84, - 0x2DFA: 84, - 0x2DFB: 84, - 0x2DFC: 84, - 0x2DFD: 84, - 0x2DFE: 84, - 0x2DFF: 84, - 0x302A: 84, - 0x302B: 84, - 0x302C: 84, - 0x302D: 84, - 0x3099: 84, - 0x309A: 84, - 0xA66F: 84, - 0xA670: 84, - 0xA671: 84, - 0xA672: 84, - 0xA674: 84, - 0xA675: 84, - 0xA676: 84, - 0xA677: 84, - 0xA678: 84, - 0xA679: 84, - 0xA67A: 84, - 0xA67B: 84, - 0xA67C: 84, - 0xA67D: 84, - 0xA69E: 84, - 0xA69F: 84, - 0xA6F0: 84, - 0xA6F1: 84, - 0xA802: 84, - 0xA806: 84, - 0xA80B: 84, - 0xA825: 84, - 0xA826: 84, - 0xA82C: 84, - 0xA840: 68, - 0xA841: 68, - 0xA842: 68, - 0xA843: 68, - 0xA844: 68, - 0xA845: 68, - 0xA846: 68, - 0xA847: 68, - 0xA848: 68, - 0xA849: 68, - 0xA84A: 68, - 0xA84B: 68, - 0xA84C: 68, - 0xA84D: 68, - 0xA84E: 68, - 0xA84F: 68, - 0xA850: 68, - 0xA851: 68, - 0xA852: 68, - 0xA853: 68, - 0xA854: 68, - 0xA855: 68, - 0xA856: 68, - 0xA857: 68, - 0xA858: 68, - 0xA859: 68, - 0xA85A: 68, - 0xA85B: 68, - 0xA85C: 68, - 0xA85D: 68, - 0xA85E: 68, - 0xA85F: 68, - 0xA860: 68, - 0xA861: 68, - 0xA862: 68, - 0xA863: 68, - 0xA864: 68, - 0xA865: 68, - 0xA866: 68, - 0xA867: 68, - 0xA868: 68, - 0xA869: 68, - 0xA86A: 68, - 0xA86B: 68, - 0xA86C: 68, - 0xA86D: 68, - 0xA86E: 68, - 0xA86F: 68, - 0xA870: 68, - 0xA871: 68, - 0xA872: 76, - 0xA8C4: 84, - 0xA8C5: 84, - 0xA8E0: 84, - 0xA8E1: 84, - 0xA8E2: 84, - 0xA8E3: 84, - 0xA8E4: 84, - 0xA8E5: 84, - 0xA8E6: 84, - 0xA8E7: 84, - 0xA8E8: 84, - 0xA8E9: 84, - 0xA8EA: 84, - 0xA8EB: 84, - 0xA8EC: 84, - 0xA8ED: 84, - 0xA8EE: 84, - 0xA8EF: 84, - 0xA8F0: 84, - 0xA8F1: 84, - 0xA8FF: 84, - 0xA926: 84, - 0xA927: 84, - 0xA928: 84, - 0xA929: 84, - 0xA92A: 84, - 0xA92B: 84, - 0xA92C: 84, - 0xA92D: 84, - 0xA947: 84, - 0xA948: 84, - 0xA949: 84, - 0xA94A: 84, - 0xA94B: 84, - 0xA94C: 84, - 0xA94D: 84, - 0xA94E: 84, - 0xA94F: 84, - 0xA950: 84, - 0xA951: 84, - 0xA980: 84, - 0xA981: 84, - 0xA982: 84, - 0xA9B3: 84, - 0xA9B6: 84, - 0xA9B7: 84, - 0xA9B8: 84, - 0xA9B9: 84, - 0xA9BC: 84, - 0xA9BD: 84, - 0xA9E5: 84, - 0xAA29: 84, - 0xAA2A: 84, - 0xAA2B: 84, - 0xAA2C: 84, - 0xAA2D: 84, - 0xAA2E: 84, - 0xAA31: 84, - 0xAA32: 84, - 0xAA35: 84, - 0xAA36: 84, - 0xAA43: 84, - 0xAA4C: 84, - 0xAA7C: 84, - 0xAAB0: 84, - 0xAAB2: 84, - 0xAAB3: 84, - 0xAAB4: 84, - 0xAAB7: 84, - 0xAAB8: 84, - 0xAABE: 84, - 0xAABF: 84, - 0xAAC1: 84, - 0xAAEC: 84, - 0xAAED: 84, - 0xAAF6: 84, - 0xABE5: 84, - 0xABE8: 84, - 0xABED: 84, - 0xFB1E: 84, - 0xFE00: 84, - 0xFE01: 84, - 0xFE02: 84, - 0xFE03: 84, - 0xFE04: 84, - 0xFE05: 84, - 0xFE06: 84, - 0xFE07: 84, - 0xFE08: 84, - 0xFE09: 84, - 0xFE0A: 84, - 0xFE0B: 84, - 0xFE0C: 84, - 0xFE0D: 84, - 0xFE0E: 84, - 0xFE0F: 84, - 0xFE20: 84, - 0xFE21: 84, - 0xFE22: 84, - 0xFE23: 84, - 0xFE24: 84, - 0xFE25: 84, - 0xFE26: 84, - 0xFE27: 84, - 0xFE28: 84, - 0xFE29: 84, - 0xFE2A: 84, - 0xFE2B: 84, - 0xFE2C: 84, - 0xFE2D: 84, - 0xFE2E: 84, - 0xFE2F: 84, - 0xFEFF: 84, - 0xFFF9: 84, - 0xFFFA: 84, - 0xFFFB: 84, - 0x101FD: 84, - 0x102E0: 84, - 0x10376: 84, - 0x10377: 84, - 0x10378: 84, - 0x10379: 84, - 0x1037A: 84, - 0x10A01: 84, - 0x10A02: 84, - 0x10A03: 84, - 0x10A05: 84, - 0x10A06: 84, - 0x10A0C: 84, - 0x10A0D: 84, - 0x10A0E: 84, - 0x10A0F: 84, - 0x10A38: 84, - 0x10A39: 84, - 0x10A3A: 84, - 0x10A3F: 84, - 0x10AC0: 68, - 0x10AC1: 68, - 0x10AC2: 68, - 0x10AC3: 68, - 0x10AC4: 68, - 0x10AC5: 82, - 0x10AC7: 82, - 0x10AC9: 82, - 0x10ACA: 82, - 0x10ACD: 76, - 0x10ACE: 82, - 0x10ACF: 82, - 0x10AD0: 82, - 0x10AD1: 82, - 0x10AD2: 82, - 0x10AD3: 68, - 0x10AD4: 68, - 0x10AD5: 68, - 0x10AD6: 68, - 0x10AD7: 76, - 0x10AD8: 68, - 0x10AD9: 68, - 0x10ADA: 68, - 0x10ADB: 68, - 0x10ADC: 68, - 0x10ADD: 82, - 0x10ADE: 68, - 0x10ADF: 68, - 0x10AE0: 68, - 0x10AE1: 82, - 0x10AE4: 82, - 0x10AE5: 84, - 0x10AE6: 84, - 0x10AEB: 68, - 0x10AEC: 68, - 0x10AED: 68, - 0x10AEE: 68, - 0x10AEF: 82, - 0x10B80: 68, - 0x10B81: 82, - 0x10B82: 68, - 0x10B83: 82, - 0x10B84: 82, - 0x10B85: 82, - 0x10B86: 68, - 0x10B87: 68, - 0x10B88: 68, - 0x10B89: 82, - 0x10B8A: 68, - 0x10B8B: 68, - 0x10B8C: 82, - 0x10B8D: 68, - 0x10B8E: 82, - 0x10B8F: 82, - 0x10B90: 68, - 0x10B91: 82, - 0x10BA9: 82, - 0x10BAA: 82, - 0x10BAB: 82, - 0x10BAC: 82, - 0x10BAD: 68, - 0x10BAE: 68, - 0x10D00: 76, - 0x10D01: 68, - 0x10D02: 68, - 0x10D03: 68, - 0x10D04: 68, - 0x10D05: 68, - 0x10D06: 68, - 0x10D07: 68, - 0x10D08: 68, - 0x10D09: 68, - 0x10D0A: 68, - 0x10D0B: 68, - 0x10D0C: 68, - 0x10D0D: 68, - 0x10D0E: 68, - 0x10D0F: 68, - 0x10D10: 68, - 0x10D11: 68, - 0x10D12: 68, - 0x10D13: 68, - 0x10D14: 68, - 0x10D15: 68, - 0x10D16: 68, - 0x10D17: 68, - 0x10D18: 68, - 0x10D19: 68, - 0x10D1A: 68, - 0x10D1B: 68, - 0x10D1C: 68, - 0x10D1D: 68, - 0x10D1E: 68, - 0x10D1F: 68, - 0x10D20: 68, - 0x10D21: 68, - 0x10D22: 82, - 0x10D23: 68, - 0x10D24: 84, - 0x10D25: 84, - 0x10D26: 84, - 0x10D27: 84, - 0x10D69: 84, - 0x10D6A: 84, - 0x10D6B: 84, - 0x10D6C: 84, - 0x10D6D: 84, - 0x10EAB: 84, - 0x10EAC: 84, - 0x10EC2: 82, - 0x10EC3: 68, - 0x10EC4: 68, - 0x10EFC: 84, - 0x10EFD: 84, - 0x10EFE: 84, - 0x10EFF: 84, - 0x10F30: 68, - 0x10F31: 68, - 0x10F32: 68, - 0x10F33: 82, - 0x10F34: 68, - 0x10F35: 68, - 0x10F36: 68, - 0x10F37: 68, - 0x10F38: 68, - 0x10F39: 68, - 0x10F3A: 68, - 0x10F3B: 68, - 0x10F3C: 68, - 0x10F3D: 68, - 0x10F3E: 68, - 0x10F3F: 68, - 0x10F40: 68, - 0x10F41: 68, - 0x10F42: 68, - 0x10F43: 68, - 0x10F44: 68, - 0x10F46: 84, - 0x10F47: 84, - 0x10F48: 84, - 0x10F49: 84, - 0x10F4A: 84, - 0x10F4B: 84, - 0x10F4C: 84, - 0x10F4D: 84, - 0x10F4E: 84, - 0x10F4F: 84, - 0x10F50: 84, - 0x10F51: 68, - 0x10F52: 68, - 0x10F53: 68, - 0x10F54: 82, - 0x10F70: 68, - 0x10F71: 68, - 0x10F72: 68, - 0x10F73: 68, - 0x10F74: 82, - 0x10F75: 82, - 0x10F76: 68, - 0x10F77: 68, - 0x10F78: 68, - 0x10F79: 68, - 0x10F7A: 68, - 0x10F7B: 68, - 0x10F7C: 68, - 0x10F7D: 68, - 0x10F7E: 68, - 0x10F7F: 68, - 0x10F80: 68, - 0x10F81: 68, - 0x10F82: 84, - 0x10F83: 84, - 0x10F84: 84, - 0x10F85: 84, - 0x10FB0: 68, - 0x10FB2: 68, - 0x10FB3: 68, - 0x10FB4: 82, - 0x10FB5: 82, - 0x10FB6: 82, - 0x10FB8: 68, - 0x10FB9: 82, - 0x10FBA: 82, - 0x10FBB: 68, - 0x10FBC: 68, - 0x10FBD: 82, - 0x10FBE: 68, - 0x10FBF: 68, - 0x10FC1: 68, - 0x10FC2: 82, - 0x10FC3: 82, - 0x10FC4: 68, - 0x10FC9: 82, - 0x10FCA: 68, - 0x10FCB: 76, - 0x11001: 84, - 0x11038: 84, - 0x11039: 84, - 0x1103A: 84, - 0x1103B: 84, - 0x1103C: 84, - 0x1103D: 84, - 0x1103E: 84, - 0x1103F: 84, - 0x11040: 84, - 0x11041: 84, - 0x11042: 84, - 0x11043: 84, - 0x11044: 84, - 0x11045: 84, - 0x11046: 84, - 0x11070: 84, - 0x11073: 84, - 0x11074: 84, - 0x1107F: 84, - 0x11080: 84, - 0x11081: 84, - 0x110B3: 84, - 0x110B4: 84, - 0x110B5: 84, - 0x110B6: 84, - 0x110B9: 84, - 0x110BA: 84, - 0x110C2: 84, - 0x11100: 84, - 0x11101: 84, - 0x11102: 84, - 0x11127: 84, - 0x11128: 84, - 0x11129: 84, - 0x1112A: 84, - 0x1112B: 84, - 0x1112D: 84, - 0x1112E: 84, - 0x1112F: 84, - 0x11130: 84, - 0x11131: 84, - 0x11132: 84, - 0x11133: 84, - 0x11134: 84, - 0x11173: 84, - 0x11180: 84, - 0x11181: 84, - 0x111B6: 84, - 0x111B7: 84, - 0x111B8: 84, - 0x111B9: 84, - 0x111BA: 84, - 0x111BB: 84, - 0x111BC: 84, - 0x111BD: 84, - 0x111BE: 84, - 0x111C9: 84, - 0x111CA: 84, - 0x111CB: 84, - 0x111CC: 84, - 0x111CF: 84, - 0x1122F: 84, - 0x11230: 84, - 0x11231: 84, - 0x11234: 84, - 0x11236: 84, - 0x11237: 84, - 0x1123E: 84, - 0x11241: 84, - 0x112DF: 84, - 0x112E3: 84, - 0x112E4: 84, - 0x112E5: 84, - 0x112E6: 84, - 0x112E7: 84, - 0x112E8: 84, - 0x112E9: 84, - 0x112EA: 84, - 0x11300: 84, - 0x11301: 84, - 0x1133B: 84, - 0x1133C: 84, - 0x11340: 84, - 0x11366: 84, - 0x11367: 84, - 0x11368: 84, - 0x11369: 84, - 0x1136A: 84, - 0x1136B: 84, - 0x1136C: 84, - 0x11370: 84, - 0x11371: 84, - 0x11372: 84, - 0x11373: 84, - 0x11374: 84, - 0x113BB: 84, - 0x113BC: 84, - 0x113BD: 84, - 0x113BE: 84, - 0x113BF: 84, - 0x113C0: 84, - 0x113CE: 84, - 0x113D0: 84, - 0x113D2: 84, - 0x113E1: 84, - 0x113E2: 84, - 0x11438: 84, - 0x11439: 84, - 0x1143A: 84, - 0x1143B: 84, - 0x1143C: 84, - 0x1143D: 84, - 0x1143E: 84, - 0x1143F: 84, - 0x11442: 84, - 0x11443: 84, - 0x11444: 84, - 0x11446: 84, - 0x1145E: 84, - 0x114B3: 84, - 0x114B4: 84, - 0x114B5: 84, - 0x114B6: 84, - 0x114B7: 84, - 0x114B8: 84, - 0x114BA: 84, - 0x114BF: 84, - 0x114C0: 84, - 0x114C2: 84, - 0x114C3: 84, - 0x115B2: 84, - 0x115B3: 84, - 0x115B4: 84, - 0x115B5: 84, - 0x115BC: 84, - 0x115BD: 84, - 0x115BF: 84, - 0x115C0: 84, - 0x115DC: 84, - 0x115DD: 84, - 0x11633: 84, - 0x11634: 84, - 0x11635: 84, - 0x11636: 84, - 0x11637: 84, - 0x11638: 84, - 0x11639: 84, - 0x1163A: 84, - 0x1163D: 84, - 0x1163F: 84, - 0x11640: 84, - 0x116AB: 84, - 0x116AD: 84, - 0x116B0: 84, - 0x116B1: 84, - 0x116B2: 84, - 0x116B3: 84, - 0x116B4: 84, - 0x116B5: 84, - 0x116B7: 84, - 0x1171D: 84, - 0x1171F: 84, - 0x11722: 84, - 0x11723: 84, - 0x11724: 84, - 0x11725: 84, - 0x11727: 84, - 0x11728: 84, - 0x11729: 84, - 0x1172A: 84, - 0x1172B: 84, - 0x1182F: 84, - 0x11830: 84, - 0x11831: 84, - 0x11832: 84, - 0x11833: 84, - 0x11834: 84, - 0x11835: 84, - 0x11836: 84, - 0x11837: 84, - 0x11839: 84, - 0x1183A: 84, - 0x1193B: 84, - 0x1193C: 84, - 0x1193E: 84, - 0x11943: 84, - 0x119D4: 84, - 0x119D5: 84, - 0x119D6: 84, - 0x119D7: 84, - 0x119DA: 84, - 0x119DB: 84, - 0x119E0: 84, - 0x11A01: 84, - 0x11A02: 84, - 0x11A03: 84, - 0x11A04: 84, - 0x11A05: 84, - 0x11A06: 84, - 0x11A07: 84, - 0x11A08: 84, - 0x11A09: 84, - 0x11A0A: 84, - 0x11A33: 84, - 0x11A34: 84, - 0x11A35: 84, - 0x11A36: 84, - 0x11A37: 84, - 0x11A38: 84, - 0x11A3B: 84, - 0x11A3C: 84, - 0x11A3D: 84, - 0x11A3E: 84, - 0x11A47: 84, - 0x11A51: 84, - 0x11A52: 84, - 0x11A53: 84, - 0x11A54: 84, - 0x11A55: 84, - 0x11A56: 84, - 0x11A59: 84, - 0x11A5A: 84, - 0x11A5B: 84, - 0x11A8A: 84, - 0x11A8B: 84, - 0x11A8C: 84, - 0x11A8D: 84, - 0x11A8E: 84, - 0x11A8F: 84, - 0x11A90: 84, - 0x11A91: 84, - 0x11A92: 84, - 0x11A93: 84, - 0x11A94: 84, - 0x11A95: 84, - 0x11A96: 84, - 0x11A98: 84, - 0x11A99: 84, - 0x11C30: 84, - 0x11C31: 84, - 0x11C32: 84, - 0x11C33: 84, - 0x11C34: 84, - 0x11C35: 84, - 0x11C36: 84, - 0x11C38: 84, - 0x11C39: 84, - 0x11C3A: 84, - 0x11C3B: 84, - 0x11C3C: 84, - 0x11C3D: 84, - 0x11C3F: 84, - 0x11C92: 84, - 0x11C93: 84, - 0x11C94: 84, - 0x11C95: 84, - 0x11C96: 84, - 0x11C97: 84, - 0x11C98: 84, - 0x11C99: 84, - 0x11C9A: 84, - 0x11C9B: 84, - 0x11C9C: 84, - 0x11C9D: 84, - 0x11C9E: 84, - 0x11C9F: 84, - 0x11CA0: 84, - 0x11CA1: 84, - 0x11CA2: 84, - 0x11CA3: 84, - 0x11CA4: 84, - 0x11CA5: 84, - 0x11CA6: 84, - 0x11CA7: 84, - 0x11CAA: 84, - 0x11CAB: 84, - 0x11CAC: 84, - 0x11CAD: 84, - 0x11CAE: 84, - 0x11CAF: 84, - 0x11CB0: 84, - 0x11CB2: 84, - 0x11CB3: 84, - 0x11CB5: 84, - 0x11CB6: 84, - 0x11D31: 84, - 0x11D32: 84, - 0x11D33: 84, - 0x11D34: 84, - 0x11D35: 84, - 0x11D36: 84, - 0x11D3A: 84, - 0x11D3C: 84, - 0x11D3D: 84, - 0x11D3F: 84, - 0x11D40: 84, - 0x11D41: 84, - 0x11D42: 84, - 0x11D43: 84, - 0x11D44: 84, - 0x11D45: 84, - 0x11D47: 84, - 0x11D90: 84, - 0x11D91: 84, - 0x11D95: 84, - 0x11D97: 84, - 0x11EF3: 84, - 0x11EF4: 84, - 0x11F00: 84, - 0x11F01: 84, - 0x11F36: 84, - 0x11F37: 84, - 0x11F38: 84, - 0x11F39: 84, - 0x11F3A: 84, - 0x11F40: 84, - 0x11F42: 84, - 0x11F5A: 84, - 0x13430: 84, - 0x13431: 84, - 0x13432: 84, - 0x13433: 84, - 0x13434: 84, - 0x13435: 84, - 0x13436: 84, - 0x13437: 84, - 0x13438: 84, - 0x13439: 84, - 0x1343A: 84, - 0x1343B: 84, - 0x1343C: 84, - 0x1343D: 84, - 0x1343E: 84, - 0x1343F: 84, - 0x13440: 84, - 0x13447: 84, - 0x13448: 84, - 0x13449: 84, - 0x1344A: 84, - 0x1344B: 84, - 0x1344C: 84, - 0x1344D: 84, - 0x1344E: 84, - 0x1344F: 84, - 0x13450: 84, - 0x13451: 84, - 0x13452: 84, - 0x13453: 84, - 0x13454: 84, - 0x13455: 84, - 0x1611E: 84, - 0x1611F: 84, - 0x16120: 84, - 0x16121: 84, - 0x16122: 84, - 0x16123: 84, - 0x16124: 84, - 0x16125: 84, - 0x16126: 84, - 0x16127: 84, - 0x16128: 84, - 0x16129: 84, - 0x1612D: 84, - 0x1612E: 84, - 0x1612F: 84, - 0x16AF0: 84, - 0x16AF1: 84, - 0x16AF2: 84, - 0x16AF3: 84, - 0x16AF4: 84, - 0x16B30: 84, - 0x16B31: 84, - 0x16B32: 84, - 0x16B33: 84, - 0x16B34: 84, - 0x16B35: 84, - 0x16B36: 84, - 0x16F4F: 84, - 0x16F8F: 84, - 0x16F90: 84, - 0x16F91: 84, - 0x16F92: 84, - 0x16FE4: 84, - 0x1BC9D: 84, - 0x1BC9E: 84, - 0x1BCA0: 84, - 0x1BCA1: 84, - 0x1BCA2: 84, - 0x1BCA3: 84, - 0x1CF00: 84, - 0x1CF01: 84, - 0x1CF02: 84, - 0x1CF03: 84, - 0x1CF04: 84, - 0x1CF05: 84, - 0x1CF06: 84, - 0x1CF07: 84, - 0x1CF08: 84, - 0x1CF09: 84, - 0x1CF0A: 84, - 0x1CF0B: 84, - 0x1CF0C: 84, - 0x1CF0D: 84, - 0x1CF0E: 84, - 0x1CF0F: 84, - 0x1CF10: 84, - 0x1CF11: 84, - 0x1CF12: 84, - 0x1CF13: 84, - 0x1CF14: 84, - 0x1CF15: 84, - 0x1CF16: 84, - 0x1CF17: 84, - 0x1CF18: 84, - 0x1CF19: 84, - 0x1CF1A: 84, - 0x1CF1B: 84, - 0x1CF1C: 84, - 0x1CF1D: 84, - 0x1CF1E: 84, - 0x1CF1F: 84, - 0x1CF20: 84, - 0x1CF21: 84, - 0x1CF22: 84, - 0x1CF23: 84, - 0x1CF24: 84, - 0x1CF25: 84, - 0x1CF26: 84, - 0x1CF27: 84, - 0x1CF28: 84, - 0x1CF29: 84, - 0x1CF2A: 84, - 0x1CF2B: 84, - 0x1CF2C: 84, - 0x1CF2D: 84, - 0x1CF30: 84, - 0x1CF31: 84, - 0x1CF32: 84, - 0x1CF33: 84, - 0x1CF34: 84, - 0x1CF35: 84, - 0x1CF36: 84, - 0x1CF37: 84, - 0x1CF38: 84, - 0x1CF39: 84, - 0x1CF3A: 84, - 0x1CF3B: 84, - 0x1CF3C: 84, - 0x1CF3D: 84, - 0x1CF3E: 84, - 0x1CF3F: 84, - 0x1CF40: 84, - 0x1CF41: 84, - 0x1CF42: 84, - 0x1CF43: 84, - 0x1CF44: 84, - 0x1CF45: 84, - 0x1CF46: 84, - 0x1D167: 84, - 0x1D168: 84, - 0x1D169: 84, - 0x1D173: 84, - 0x1D174: 84, - 0x1D175: 84, - 0x1D176: 84, - 0x1D177: 84, - 0x1D178: 84, - 0x1D179: 84, - 0x1D17A: 84, - 0x1D17B: 84, - 0x1D17C: 84, - 0x1D17D: 84, - 0x1D17E: 84, - 0x1D17F: 84, - 0x1D180: 84, - 0x1D181: 84, - 0x1D182: 84, - 0x1D185: 84, - 0x1D186: 84, - 0x1D187: 84, - 0x1D188: 84, - 0x1D189: 84, - 0x1D18A: 84, - 0x1D18B: 84, - 0x1D1AA: 84, - 0x1D1AB: 84, - 0x1D1AC: 84, - 0x1D1AD: 84, - 0x1D242: 84, - 0x1D243: 84, - 0x1D244: 84, - 0x1DA00: 84, - 0x1DA01: 84, - 0x1DA02: 84, - 0x1DA03: 84, - 0x1DA04: 84, - 0x1DA05: 84, - 0x1DA06: 84, - 0x1DA07: 84, - 0x1DA08: 84, - 0x1DA09: 84, - 0x1DA0A: 84, - 0x1DA0B: 84, - 0x1DA0C: 84, - 0x1DA0D: 84, - 0x1DA0E: 84, - 0x1DA0F: 84, - 0x1DA10: 84, - 0x1DA11: 84, - 0x1DA12: 84, - 0x1DA13: 84, - 0x1DA14: 84, - 0x1DA15: 84, - 0x1DA16: 84, - 0x1DA17: 84, - 0x1DA18: 84, - 0x1DA19: 84, - 0x1DA1A: 84, - 0x1DA1B: 84, - 0x1DA1C: 84, - 0x1DA1D: 84, - 0x1DA1E: 84, - 0x1DA1F: 84, - 0x1DA20: 84, - 0x1DA21: 84, - 0x1DA22: 84, - 0x1DA23: 84, - 0x1DA24: 84, - 0x1DA25: 84, - 0x1DA26: 84, - 0x1DA27: 84, - 0x1DA28: 84, - 0x1DA29: 84, - 0x1DA2A: 84, - 0x1DA2B: 84, - 0x1DA2C: 84, - 0x1DA2D: 84, - 0x1DA2E: 84, - 0x1DA2F: 84, - 0x1DA30: 84, - 0x1DA31: 84, - 0x1DA32: 84, - 0x1DA33: 84, - 0x1DA34: 84, - 0x1DA35: 84, - 0x1DA36: 84, - 0x1DA3B: 84, - 0x1DA3C: 84, - 0x1DA3D: 84, - 0x1DA3E: 84, - 0x1DA3F: 84, - 0x1DA40: 84, - 0x1DA41: 84, - 0x1DA42: 84, - 0x1DA43: 84, - 0x1DA44: 84, - 0x1DA45: 84, - 0x1DA46: 84, - 0x1DA47: 84, - 0x1DA48: 84, - 0x1DA49: 84, - 0x1DA4A: 84, - 0x1DA4B: 84, - 0x1DA4C: 84, - 0x1DA4D: 84, - 0x1DA4E: 84, - 0x1DA4F: 84, - 0x1DA50: 84, - 0x1DA51: 84, - 0x1DA52: 84, - 0x1DA53: 84, - 0x1DA54: 84, - 0x1DA55: 84, - 0x1DA56: 84, - 0x1DA57: 84, - 0x1DA58: 84, - 0x1DA59: 84, - 0x1DA5A: 84, - 0x1DA5B: 84, - 0x1DA5C: 84, - 0x1DA5D: 84, - 0x1DA5E: 84, - 0x1DA5F: 84, - 0x1DA60: 84, - 0x1DA61: 84, - 0x1DA62: 84, - 0x1DA63: 84, - 0x1DA64: 84, - 0x1DA65: 84, - 0x1DA66: 84, - 0x1DA67: 84, - 0x1DA68: 84, - 0x1DA69: 84, - 0x1DA6A: 84, - 0x1DA6B: 84, - 0x1DA6C: 84, - 0x1DA75: 84, - 0x1DA84: 84, - 0x1DA9B: 84, - 0x1DA9C: 84, - 0x1DA9D: 84, - 0x1DA9E: 84, - 0x1DA9F: 84, - 0x1DAA1: 84, - 0x1DAA2: 84, - 0x1DAA3: 84, - 0x1DAA4: 84, - 0x1DAA5: 84, - 0x1DAA6: 84, - 0x1DAA7: 84, - 0x1DAA8: 84, - 0x1DAA9: 84, - 0x1DAAA: 84, - 0x1DAAB: 84, - 0x1DAAC: 84, - 0x1DAAD: 84, - 0x1DAAE: 84, - 0x1DAAF: 84, - 0x1E000: 84, - 0x1E001: 84, - 0x1E002: 84, - 0x1E003: 84, - 0x1E004: 84, - 0x1E005: 84, - 0x1E006: 84, - 0x1E008: 84, - 0x1E009: 84, - 0x1E00A: 84, - 0x1E00B: 84, - 0x1E00C: 84, - 0x1E00D: 84, - 0x1E00E: 84, - 0x1E00F: 84, - 0x1E010: 84, - 0x1E011: 84, - 0x1E012: 84, - 0x1E013: 84, - 0x1E014: 84, - 0x1E015: 84, - 0x1E016: 84, - 0x1E017: 84, - 0x1E018: 84, - 0x1E01B: 84, - 0x1E01C: 84, - 0x1E01D: 84, - 0x1E01E: 84, - 0x1E01F: 84, - 0x1E020: 84, - 0x1E021: 84, - 0x1E023: 84, - 0x1E024: 84, - 0x1E026: 84, - 0x1E027: 84, - 0x1E028: 84, - 0x1E029: 84, - 0x1E02A: 84, - 0x1E08F: 84, - 0x1E130: 84, - 0x1E131: 84, - 0x1E132: 84, - 0x1E133: 84, - 0x1E134: 84, - 0x1E135: 84, - 0x1E136: 84, - 0x1E2AE: 84, - 0x1E2EC: 84, - 0x1E2ED: 84, - 0x1E2EE: 84, - 0x1E2EF: 84, - 0x1E4EC: 84, - 0x1E4ED: 84, - 0x1E4EE: 84, - 0x1E4EF: 84, - 0x1E5EE: 84, - 0x1E5EF: 84, - 0x1E8D0: 84, - 0x1E8D1: 84, - 0x1E8D2: 84, - 0x1E8D3: 84, - 0x1E8D4: 84, - 0x1E8D5: 84, - 0x1E8D6: 84, - 0x1E900: 68, - 0x1E901: 68, - 0x1E902: 68, - 0x1E903: 68, - 0x1E904: 68, - 0x1E905: 68, - 0x1E906: 68, - 0x1E907: 68, - 0x1E908: 68, - 0x1E909: 68, - 0x1E90A: 68, - 0x1E90B: 68, - 0x1E90C: 68, - 0x1E90D: 68, - 0x1E90E: 68, - 0x1E90F: 68, - 0x1E910: 68, - 0x1E911: 68, - 0x1E912: 68, - 0x1E913: 68, - 0x1E914: 68, - 0x1E915: 68, - 0x1E916: 68, - 0x1E917: 68, - 0x1E918: 68, - 0x1E919: 68, - 0x1E91A: 68, - 0x1E91B: 68, - 0x1E91C: 68, - 0x1E91D: 68, - 0x1E91E: 68, - 0x1E91F: 68, - 0x1E920: 68, - 0x1E921: 68, - 0x1E922: 68, - 0x1E923: 68, - 0x1E924: 68, - 0x1E925: 68, - 0x1E926: 68, - 0x1E927: 68, - 0x1E928: 68, - 0x1E929: 68, - 0x1E92A: 68, - 0x1E92B: 68, - 0x1E92C: 68, - 0x1E92D: 68, - 0x1E92E: 68, - 0x1E92F: 68, - 0x1E930: 68, - 0x1E931: 68, - 0x1E932: 68, - 0x1E933: 68, - 0x1E934: 68, - 0x1E935: 68, - 0x1E936: 68, - 0x1E937: 68, - 0x1E938: 68, - 0x1E939: 68, - 0x1E93A: 68, - 0x1E93B: 68, - 0x1E93C: 68, - 0x1E93D: 68, - 0x1E93E: 68, - 0x1E93F: 68, - 0x1E940: 68, - 0x1E941: 68, - 0x1E942: 68, - 0x1E943: 68, - 0x1E944: 84, - 0x1E945: 84, - 0x1E946: 84, - 0x1E947: 84, - 0x1E948: 84, - 0x1E949: 84, - 0x1E94A: 84, - 0x1E94B: 84, - 0xE0001: 84, - 0xE0020: 84, - 0xE0021: 84, - 0xE0022: 84, - 0xE0023: 84, - 0xE0024: 84, - 0xE0025: 84, - 0xE0026: 84, - 0xE0027: 84, - 0xE0028: 84, - 0xE0029: 84, - 0xE002A: 84, - 0xE002B: 84, - 0xE002C: 84, - 0xE002D: 84, - 0xE002E: 84, - 0xE002F: 84, - 0xE0030: 84, - 0xE0031: 84, - 0xE0032: 84, - 0xE0033: 84, - 0xE0034: 84, - 0xE0035: 84, - 0xE0036: 84, - 0xE0037: 84, - 0xE0038: 84, - 0xE0039: 84, - 0xE003A: 84, - 0xE003B: 84, - 0xE003C: 84, - 0xE003D: 84, - 0xE003E: 84, - 0xE003F: 84, - 0xE0040: 84, - 0xE0041: 84, - 0xE0042: 84, - 0xE0043: 84, - 0xE0044: 84, - 0xE0045: 84, - 0xE0046: 84, - 0xE0047: 84, - 0xE0048: 84, - 0xE0049: 84, - 0xE004A: 84, - 0xE004B: 84, - 0xE004C: 84, - 0xE004D: 84, - 0xE004E: 84, - 0xE004F: 84, - 0xE0050: 84, - 0xE0051: 84, - 0xE0052: 84, - 0xE0053: 84, - 0xE0054: 84, - 0xE0055: 84, - 0xE0056: 84, - 0xE0057: 84, - 0xE0058: 84, - 0xE0059: 84, - 0xE005A: 84, - 0xE005B: 84, - 0xE005C: 84, - 0xE005D: 84, - 0xE005E: 84, - 0xE005F: 84, - 0xE0060: 84, - 0xE0061: 84, - 0xE0062: 84, - 0xE0063: 84, - 0xE0064: 84, - 0xE0065: 84, - 0xE0066: 84, - 0xE0067: 84, - 0xE0068: 84, - 0xE0069: 84, - 0xE006A: 84, - 0xE006B: 84, - 0xE006C: 84, - 0xE006D: 84, - 0xE006E: 84, - 0xE006F: 84, - 0xE0070: 84, - 0xE0071: 84, - 0xE0072: 84, - 0xE0073: 84, - 0xE0074: 84, - 0xE0075: 84, - 0xE0076: 84, - 0xE0077: 84, - 0xE0078: 84, - 0xE0079: 84, - 0xE007A: 84, - 0xE007B: 84, - 0xE007C: 84, - 0xE007D: 84, - 0xE007E: 84, - 0xE007F: 84, - 0xE0100: 84, - 0xE0101: 84, - 0xE0102: 84, - 0xE0103: 84, - 0xE0104: 84, - 0xE0105: 84, - 0xE0106: 84, - 0xE0107: 84, - 0xE0108: 84, - 0xE0109: 84, - 0xE010A: 84, - 0xE010B: 84, - 0xE010C: 84, - 0xE010D: 84, - 0xE010E: 84, - 0xE010F: 84, - 0xE0110: 84, - 0xE0111: 84, - 0xE0112: 84, - 0xE0113: 84, - 0xE0114: 84, - 0xE0115: 84, - 0xE0116: 84, - 0xE0117: 84, - 0xE0118: 84, - 0xE0119: 84, - 0xE011A: 84, - 0xE011B: 84, - 0xE011C: 84, - 0xE011D: 84, - 0xE011E: 84, - 0xE011F: 84, - 0xE0120: 84, - 0xE0121: 84, - 0xE0122: 84, - 0xE0123: 84, - 0xE0124: 84, - 0xE0125: 84, - 0xE0126: 84, - 0xE0127: 84, - 0xE0128: 84, - 0xE0129: 84, - 0xE012A: 84, - 0xE012B: 84, - 0xE012C: 84, - 0xE012D: 84, - 0xE012E: 84, - 0xE012F: 84, - 0xE0130: 84, - 0xE0131: 84, - 0xE0132: 84, - 0xE0133: 84, - 0xE0134: 84, - 0xE0135: 84, - 0xE0136: 84, - 0xE0137: 84, - 0xE0138: 84, - 0xE0139: 84, - 0xE013A: 84, - 0xE013B: 84, - 0xE013C: 84, - 0xE013D: 84, - 0xE013E: 84, - 0xE013F: 84, - 0xE0140: 84, - 0xE0141: 84, - 0xE0142: 84, - 0xE0143: 84, - 0xE0144: 84, - 0xE0145: 84, - 0xE0146: 84, - 0xE0147: 84, - 0xE0148: 84, - 0xE0149: 84, - 0xE014A: 84, - 0xE014B: 84, - 0xE014C: 84, - 0xE014D: 84, - 0xE014E: 84, - 0xE014F: 84, - 0xE0150: 84, - 0xE0151: 84, - 0xE0152: 84, - 0xE0153: 84, - 0xE0154: 84, - 0xE0155: 84, - 0xE0156: 84, - 0xE0157: 84, - 0xE0158: 84, - 0xE0159: 84, - 0xE015A: 84, - 0xE015B: 84, - 0xE015C: 84, - 0xE015D: 84, - 0xE015E: 84, - 0xE015F: 84, - 0xE0160: 84, - 0xE0161: 84, - 0xE0162: 84, - 0xE0163: 84, - 0xE0164: 84, - 0xE0165: 84, - 0xE0166: 84, - 0xE0167: 84, - 0xE0168: 84, - 0xE0169: 84, - 0xE016A: 84, - 0xE016B: 84, - 0xE016C: 84, - 0xE016D: 84, - 0xE016E: 84, - 0xE016F: 84, - 0xE0170: 84, - 0xE0171: 84, - 0xE0172: 84, - 0xE0173: 84, - 0xE0174: 84, - 0xE0175: 84, - 0xE0176: 84, - 0xE0177: 84, - 0xE0178: 84, - 0xE0179: 84, - 0xE017A: 84, - 0xE017B: 84, - 0xE017C: 84, - 0xE017D: 84, - 0xE017E: 84, - 0xE017F: 84, - 0xE0180: 84, - 0xE0181: 84, - 0xE0182: 84, - 0xE0183: 84, - 0xE0184: 84, - 0xE0185: 84, - 0xE0186: 84, - 0xE0187: 84, - 0xE0188: 84, - 0xE0189: 84, - 0xE018A: 84, - 0xE018B: 84, - 0xE018C: 84, - 0xE018D: 84, - 0xE018E: 84, - 0xE018F: 84, - 0xE0190: 84, - 0xE0191: 84, - 0xE0192: 84, - 0xE0193: 84, - 0xE0194: 84, - 0xE0195: 84, - 0xE0196: 84, - 0xE0197: 84, - 0xE0198: 84, - 0xE0199: 84, - 0xE019A: 84, - 0xE019B: 84, - 0xE019C: 84, - 0xE019D: 84, - 0xE019E: 84, - 0xE019F: 84, - 0xE01A0: 84, - 0xE01A1: 84, - 0xE01A2: 84, - 0xE01A3: 84, - 0xE01A4: 84, - 0xE01A5: 84, - 0xE01A6: 84, - 0xE01A7: 84, - 0xE01A8: 84, - 0xE01A9: 84, - 0xE01AA: 84, - 0xE01AB: 84, - 0xE01AC: 84, - 0xE01AD: 84, - 0xE01AE: 84, - 0xE01AF: 84, - 0xE01B0: 84, - 0xE01B1: 84, - 0xE01B2: 84, - 0xE01B3: 84, - 0xE01B4: 84, - 0xE01B5: 84, - 0xE01B6: 84, - 0xE01B7: 84, - 0xE01B8: 84, - 0xE01B9: 84, - 0xE01BA: 84, - 0xE01BB: 84, - 0xE01BC: 84, - 0xE01BD: 84, - 0xE01BE: 84, - 0xE01BF: 84, - 0xE01C0: 84, - 0xE01C1: 84, - 0xE01C2: 84, - 0xE01C3: 84, - 0xE01C4: 84, - 0xE01C5: 84, - 0xE01C6: 84, - 0xE01C7: 84, - 0xE01C8: 84, - 0xE01C9: 84, - 0xE01CA: 84, - 0xE01CB: 84, - 0xE01CC: 84, - 0xE01CD: 84, - 0xE01CE: 84, - 0xE01CF: 84, - 0xE01D0: 84, - 0xE01D1: 84, - 0xE01D2: 84, - 0xE01D3: 84, - 0xE01D4: 84, - 0xE01D5: 84, - 0xE01D6: 84, - 0xE01D7: 84, - 0xE01D8: 84, - 0xE01D9: 84, - 0xE01DA: 84, - 0xE01DB: 84, - 0xE01DC: 84, - 0xE01DD: 84, - 0xE01DE: 84, - 0xE01DF: 84, - 0xE01E0: 84, - 0xE01E1: 84, - 0xE01E2: 84, - 0xE01E3: 84, - 0xE01E4: 84, - 0xE01E5: 84, - 0xE01E6: 84, - 0xE01E7: 84, - 0xE01E8: 84, - 0xE01E9: 84, - 0xE01EA: 84, - 0xE01EB: 84, - 0xE01EC: 84, - 0xE01ED: 84, - 0xE01EE: 84, - 0xE01EF: 84, -} -codepoint_classes = { - "PVALID": ( - 0x2D0000002E, - 0x300000003A, - 0x610000007B, - 0xDF000000F7, - 0xF800000100, - 0x10100000102, - 0x10300000104, - 0x10500000106, - 0x10700000108, - 0x1090000010A, - 0x10B0000010C, - 0x10D0000010E, - 0x10F00000110, - 0x11100000112, - 0x11300000114, - 0x11500000116, - 0x11700000118, - 0x1190000011A, - 0x11B0000011C, - 0x11D0000011E, - 0x11F00000120, - 0x12100000122, - 0x12300000124, - 0x12500000126, - 0x12700000128, - 0x1290000012A, - 0x12B0000012C, - 0x12D0000012E, - 0x12F00000130, - 0x13100000132, - 0x13500000136, - 0x13700000139, - 0x13A0000013B, - 0x13C0000013D, - 0x13E0000013F, - 0x14200000143, - 0x14400000145, - 0x14600000147, - 0x14800000149, - 0x14B0000014C, - 0x14D0000014E, - 0x14F00000150, - 0x15100000152, - 0x15300000154, - 0x15500000156, - 0x15700000158, - 0x1590000015A, - 0x15B0000015C, - 0x15D0000015E, - 0x15F00000160, - 0x16100000162, - 0x16300000164, - 0x16500000166, - 0x16700000168, - 0x1690000016A, - 0x16B0000016C, - 0x16D0000016E, - 0x16F00000170, - 0x17100000172, - 0x17300000174, - 0x17500000176, - 0x17700000178, - 0x17A0000017B, - 0x17C0000017D, - 0x17E0000017F, - 0x18000000181, - 0x18300000184, - 0x18500000186, - 0x18800000189, - 0x18C0000018E, - 0x19200000193, - 0x19500000196, - 0x1990000019C, - 0x19E0000019F, - 0x1A1000001A2, - 0x1A3000001A4, - 0x1A5000001A6, - 0x1A8000001A9, - 0x1AA000001AC, - 0x1AD000001AE, - 0x1B0000001B1, - 0x1B4000001B5, - 0x1B6000001B7, - 0x1B9000001BC, - 0x1BD000001C4, - 0x1CE000001CF, - 0x1D0000001D1, - 0x1D2000001D3, - 0x1D4000001D5, - 0x1D6000001D7, - 0x1D8000001D9, - 0x1DA000001DB, - 0x1DC000001DE, - 0x1DF000001E0, - 0x1E1000001E2, - 0x1E3000001E4, - 0x1E5000001E6, - 0x1E7000001E8, - 0x1E9000001EA, - 0x1EB000001EC, - 0x1ED000001EE, - 0x1EF000001F1, - 0x1F5000001F6, - 0x1F9000001FA, - 0x1FB000001FC, - 0x1FD000001FE, - 0x1FF00000200, - 0x20100000202, - 0x20300000204, - 0x20500000206, - 0x20700000208, - 0x2090000020A, - 0x20B0000020C, - 0x20D0000020E, - 0x20F00000210, - 0x21100000212, - 0x21300000214, - 0x21500000216, - 0x21700000218, - 0x2190000021A, - 0x21B0000021C, - 0x21D0000021E, - 0x21F00000220, - 0x22100000222, - 0x22300000224, - 0x22500000226, - 0x22700000228, - 0x2290000022A, - 0x22B0000022C, - 0x22D0000022E, - 0x22F00000230, - 0x23100000232, - 0x2330000023A, - 0x23C0000023D, - 0x23F00000241, - 0x24200000243, - 0x24700000248, - 0x2490000024A, - 0x24B0000024C, - 0x24D0000024E, - 0x24F000002B0, - 0x2B9000002C2, - 0x2C6000002D2, - 0x2EC000002ED, - 0x2EE000002EF, - 0x30000000340, - 0x34200000343, - 0x3460000034F, - 0x35000000370, - 0x37100000372, - 0x37300000374, - 0x37700000378, - 0x37B0000037E, - 0x39000000391, - 0x3AC000003CF, - 0x3D7000003D8, - 0x3D9000003DA, - 0x3DB000003DC, - 0x3DD000003DE, - 0x3DF000003E0, - 0x3E1000003E2, - 0x3E3000003E4, - 0x3E5000003E6, - 0x3E7000003E8, - 0x3E9000003EA, - 0x3EB000003EC, - 0x3ED000003EE, - 0x3EF000003F0, - 0x3F3000003F4, - 0x3F8000003F9, - 0x3FB000003FD, - 0x43000000460, - 0x46100000462, - 0x46300000464, - 0x46500000466, - 0x46700000468, - 0x4690000046A, - 0x46B0000046C, - 0x46D0000046E, - 0x46F00000470, - 0x47100000472, - 0x47300000474, - 0x47500000476, - 0x47700000478, - 0x4790000047A, - 0x47B0000047C, - 0x47D0000047E, - 0x47F00000480, - 0x48100000482, - 0x48300000488, - 0x48B0000048C, - 0x48D0000048E, - 0x48F00000490, - 0x49100000492, - 0x49300000494, - 0x49500000496, - 0x49700000498, - 0x4990000049A, - 0x49B0000049C, - 0x49D0000049E, - 0x49F000004A0, - 0x4A1000004A2, - 0x4A3000004A4, - 0x4A5000004A6, - 0x4A7000004A8, - 0x4A9000004AA, - 0x4AB000004AC, - 0x4AD000004AE, - 0x4AF000004B0, - 0x4B1000004B2, - 0x4B3000004B4, - 0x4B5000004B6, - 0x4B7000004B8, - 0x4B9000004BA, - 0x4BB000004BC, - 0x4BD000004BE, - 0x4BF000004C0, - 0x4C2000004C3, - 0x4C4000004C5, - 0x4C6000004C7, - 0x4C8000004C9, - 0x4CA000004CB, - 0x4CC000004CD, - 0x4CE000004D0, - 0x4D1000004D2, - 0x4D3000004D4, - 0x4D5000004D6, - 0x4D7000004D8, - 0x4D9000004DA, - 0x4DB000004DC, - 0x4DD000004DE, - 0x4DF000004E0, - 0x4E1000004E2, - 0x4E3000004E4, - 0x4E5000004E6, - 0x4E7000004E8, - 0x4E9000004EA, - 0x4EB000004EC, - 0x4ED000004EE, - 0x4EF000004F0, - 0x4F1000004F2, - 0x4F3000004F4, - 0x4F5000004F6, - 0x4F7000004F8, - 0x4F9000004FA, - 0x4FB000004FC, - 0x4FD000004FE, - 0x4FF00000500, - 0x50100000502, - 0x50300000504, - 0x50500000506, - 0x50700000508, - 0x5090000050A, - 0x50B0000050C, - 0x50D0000050E, - 0x50F00000510, - 0x51100000512, - 0x51300000514, - 0x51500000516, - 0x51700000518, - 0x5190000051A, - 0x51B0000051C, - 0x51D0000051E, - 0x51F00000520, - 0x52100000522, - 0x52300000524, - 0x52500000526, - 0x52700000528, - 0x5290000052A, - 0x52B0000052C, - 0x52D0000052E, - 0x52F00000530, - 0x5590000055A, - 0x56000000587, - 0x58800000589, - 0x591000005BE, - 0x5BF000005C0, - 0x5C1000005C3, - 0x5C4000005C6, - 0x5C7000005C8, - 0x5D0000005EB, - 0x5EF000005F3, - 0x6100000061B, - 0x62000000640, - 0x64100000660, - 0x66E00000675, - 0x679000006D4, - 0x6D5000006DD, - 0x6DF000006E9, - 0x6EA000006F0, - 0x6FA00000700, - 0x7100000074B, - 0x74D000007B2, - 0x7C0000007F6, - 0x7FD000007FE, - 0x8000000082E, - 0x8400000085C, - 0x8600000086B, - 0x87000000888, - 0x8890000088F, - 0x897000008E2, - 0x8E300000958, - 0x96000000964, - 0x96600000970, - 0x97100000984, - 0x9850000098D, - 0x98F00000991, - 0x993000009A9, - 0x9AA000009B1, - 0x9B2000009B3, - 0x9B6000009BA, - 0x9BC000009C5, - 0x9C7000009C9, - 0x9CB000009CF, - 0x9D7000009D8, - 0x9E0000009E4, - 0x9E6000009F2, - 0x9FC000009FD, - 0x9FE000009FF, - 0xA0100000A04, - 0xA0500000A0B, - 0xA0F00000A11, - 0xA1300000A29, - 0xA2A00000A31, - 0xA3200000A33, - 0xA3500000A36, - 0xA3800000A3A, - 0xA3C00000A3D, - 0xA3E00000A43, - 0xA4700000A49, - 0xA4B00000A4E, - 0xA5100000A52, - 0xA5C00000A5D, - 0xA6600000A76, - 0xA8100000A84, - 0xA8500000A8E, - 0xA8F00000A92, - 0xA9300000AA9, - 0xAAA00000AB1, - 0xAB200000AB4, - 0xAB500000ABA, - 0xABC00000AC6, - 0xAC700000ACA, - 0xACB00000ACE, - 0xAD000000AD1, - 0xAE000000AE4, - 0xAE600000AF0, - 0xAF900000B00, - 0xB0100000B04, - 0xB0500000B0D, - 0xB0F00000B11, - 0xB1300000B29, - 0xB2A00000B31, - 0xB3200000B34, - 0xB3500000B3A, - 0xB3C00000B45, - 0xB4700000B49, - 0xB4B00000B4E, - 0xB5500000B58, - 0xB5F00000B64, - 0xB6600000B70, - 0xB7100000B72, - 0xB8200000B84, - 0xB8500000B8B, - 0xB8E00000B91, - 0xB9200000B96, - 0xB9900000B9B, - 0xB9C00000B9D, - 0xB9E00000BA0, - 0xBA300000BA5, - 0xBA800000BAB, - 0xBAE00000BBA, - 0xBBE00000BC3, - 0xBC600000BC9, - 0xBCA00000BCE, - 0xBD000000BD1, - 0xBD700000BD8, - 0xBE600000BF0, - 0xC0000000C0D, - 0xC0E00000C11, - 0xC1200000C29, - 0xC2A00000C3A, - 0xC3C00000C45, - 0xC4600000C49, - 0xC4A00000C4E, - 0xC5500000C57, - 0xC5800000C5B, - 0xC5D00000C5E, - 0xC6000000C64, - 0xC6600000C70, - 0xC8000000C84, - 0xC8500000C8D, - 0xC8E00000C91, - 0xC9200000CA9, - 0xCAA00000CB4, - 0xCB500000CBA, - 0xCBC00000CC5, - 0xCC600000CC9, - 0xCCA00000CCE, - 0xCD500000CD7, - 0xCDD00000CDF, - 0xCE000000CE4, - 0xCE600000CF0, - 0xCF100000CF4, - 0xD0000000D0D, - 0xD0E00000D11, - 0xD1200000D45, - 0xD4600000D49, - 0xD4A00000D4F, - 0xD5400000D58, - 0xD5F00000D64, - 0xD6600000D70, - 0xD7A00000D80, - 0xD8100000D84, - 0xD8500000D97, - 0xD9A00000DB2, - 0xDB300000DBC, - 0xDBD00000DBE, - 0xDC000000DC7, - 0xDCA00000DCB, - 0xDCF00000DD5, - 0xDD600000DD7, - 0xDD800000DE0, - 0xDE600000DF0, - 0xDF200000DF4, - 0xE0100000E33, - 0xE3400000E3B, - 0xE4000000E4F, - 0xE5000000E5A, - 0xE8100000E83, - 0xE8400000E85, - 0xE8600000E8B, - 0xE8C00000EA4, - 0xEA500000EA6, - 0xEA700000EB3, - 0xEB400000EBE, - 0xEC000000EC5, - 0xEC600000EC7, - 0xEC800000ECF, - 0xED000000EDA, - 0xEDE00000EE0, - 0xF0000000F01, - 0xF0B00000F0C, - 0xF1800000F1A, - 0xF2000000F2A, - 0xF3500000F36, - 0xF3700000F38, - 0xF3900000F3A, - 0xF3E00000F43, - 0xF4400000F48, - 0xF4900000F4D, - 0xF4E00000F52, - 0xF5300000F57, - 0xF5800000F5C, - 0xF5D00000F69, - 0xF6A00000F6D, - 0xF7100000F73, - 0xF7400000F75, - 0xF7A00000F81, - 0xF8200000F85, - 0xF8600000F93, - 0xF9400000F98, - 0xF9900000F9D, - 0xF9E00000FA2, - 0xFA300000FA7, - 0xFA800000FAC, - 0xFAD00000FB9, - 0xFBA00000FBD, - 0xFC600000FC7, - 0x10000000104A, - 0x10500000109E, - 0x10D0000010FB, - 0x10FD00001100, - 0x120000001249, - 0x124A0000124E, - 0x125000001257, - 0x125800001259, - 0x125A0000125E, - 0x126000001289, - 0x128A0000128E, - 0x1290000012B1, - 0x12B2000012B6, - 0x12B8000012BF, - 0x12C0000012C1, - 0x12C2000012C6, - 0x12C8000012D7, - 0x12D800001311, - 0x131200001316, - 0x13180000135B, - 0x135D00001360, - 0x138000001390, - 0x13A0000013F6, - 0x14010000166D, - 0x166F00001680, - 0x16810000169B, - 0x16A0000016EB, - 0x16F1000016F9, - 0x170000001716, - 0x171F00001735, - 0x174000001754, - 0x17600000176D, - 0x176E00001771, - 0x177200001774, - 0x1780000017B4, - 0x17B6000017D4, - 0x17D7000017D8, - 0x17DC000017DE, - 0x17E0000017EA, - 0x18100000181A, - 0x182000001879, - 0x1880000018AB, - 0x18B0000018F6, - 0x19000000191F, - 0x19200000192C, - 0x19300000193C, - 0x19460000196E, - 0x197000001975, - 0x1980000019AC, - 0x19B0000019CA, - 0x19D0000019DA, - 0x1A0000001A1C, - 0x1A2000001A5F, - 0x1A6000001A7D, - 0x1A7F00001A8A, - 0x1A9000001A9A, - 0x1AA700001AA8, - 0x1AB000001ABE, - 0x1ABF00001ACF, - 0x1B0000001B4D, - 0x1B5000001B5A, - 0x1B6B00001B74, - 0x1B8000001BF4, - 0x1C0000001C38, - 0x1C4000001C4A, - 0x1C4D00001C7E, - 0x1C8A00001C8B, - 0x1CD000001CD3, - 0x1CD400001CFB, - 0x1D0000001D2C, - 0x1D2F00001D30, - 0x1D3B00001D3C, - 0x1D4E00001D4F, - 0x1D6B00001D78, - 0x1D7900001D9B, - 0x1DC000001E00, - 0x1E0100001E02, - 0x1E0300001E04, - 0x1E0500001E06, - 0x1E0700001E08, - 0x1E0900001E0A, - 0x1E0B00001E0C, - 0x1E0D00001E0E, - 0x1E0F00001E10, - 0x1E1100001E12, - 0x1E1300001E14, - 0x1E1500001E16, - 0x1E1700001E18, - 0x1E1900001E1A, - 0x1E1B00001E1C, - 0x1E1D00001E1E, - 0x1E1F00001E20, - 0x1E2100001E22, - 0x1E2300001E24, - 0x1E2500001E26, - 0x1E2700001E28, - 0x1E2900001E2A, - 0x1E2B00001E2C, - 0x1E2D00001E2E, - 0x1E2F00001E30, - 0x1E3100001E32, - 0x1E3300001E34, - 0x1E3500001E36, - 0x1E3700001E38, - 0x1E3900001E3A, - 0x1E3B00001E3C, - 0x1E3D00001E3E, - 0x1E3F00001E40, - 0x1E4100001E42, - 0x1E4300001E44, - 0x1E4500001E46, - 0x1E4700001E48, - 0x1E4900001E4A, - 0x1E4B00001E4C, - 0x1E4D00001E4E, - 0x1E4F00001E50, - 0x1E5100001E52, - 0x1E5300001E54, - 0x1E5500001E56, - 0x1E5700001E58, - 0x1E5900001E5A, - 0x1E5B00001E5C, - 0x1E5D00001E5E, - 0x1E5F00001E60, - 0x1E6100001E62, - 0x1E6300001E64, - 0x1E6500001E66, - 0x1E6700001E68, - 0x1E6900001E6A, - 0x1E6B00001E6C, - 0x1E6D00001E6E, - 0x1E6F00001E70, - 0x1E7100001E72, - 0x1E7300001E74, - 0x1E7500001E76, - 0x1E7700001E78, - 0x1E7900001E7A, - 0x1E7B00001E7C, - 0x1E7D00001E7E, - 0x1E7F00001E80, - 0x1E8100001E82, - 0x1E8300001E84, - 0x1E8500001E86, - 0x1E8700001E88, - 0x1E8900001E8A, - 0x1E8B00001E8C, - 0x1E8D00001E8E, - 0x1E8F00001E90, - 0x1E9100001E92, - 0x1E9300001E94, - 0x1E9500001E9A, - 0x1E9C00001E9E, - 0x1E9F00001EA0, - 0x1EA100001EA2, - 0x1EA300001EA4, - 0x1EA500001EA6, - 0x1EA700001EA8, - 0x1EA900001EAA, - 0x1EAB00001EAC, - 0x1EAD00001EAE, - 0x1EAF00001EB0, - 0x1EB100001EB2, - 0x1EB300001EB4, - 0x1EB500001EB6, - 0x1EB700001EB8, - 0x1EB900001EBA, - 0x1EBB00001EBC, - 0x1EBD00001EBE, - 0x1EBF00001EC0, - 0x1EC100001EC2, - 0x1EC300001EC4, - 0x1EC500001EC6, - 0x1EC700001EC8, - 0x1EC900001ECA, - 0x1ECB00001ECC, - 0x1ECD00001ECE, - 0x1ECF00001ED0, - 0x1ED100001ED2, - 0x1ED300001ED4, - 0x1ED500001ED6, - 0x1ED700001ED8, - 0x1ED900001EDA, - 0x1EDB00001EDC, - 0x1EDD00001EDE, - 0x1EDF00001EE0, - 0x1EE100001EE2, - 0x1EE300001EE4, - 0x1EE500001EE6, - 0x1EE700001EE8, - 0x1EE900001EEA, - 0x1EEB00001EEC, - 0x1EED00001EEE, - 0x1EEF00001EF0, - 0x1EF100001EF2, - 0x1EF300001EF4, - 0x1EF500001EF6, - 0x1EF700001EF8, - 0x1EF900001EFA, - 0x1EFB00001EFC, - 0x1EFD00001EFE, - 0x1EFF00001F08, - 0x1F1000001F16, - 0x1F2000001F28, - 0x1F3000001F38, - 0x1F4000001F46, - 0x1F5000001F58, - 0x1F6000001F68, - 0x1F7000001F71, - 0x1F7200001F73, - 0x1F7400001F75, - 0x1F7600001F77, - 0x1F7800001F79, - 0x1F7A00001F7B, - 0x1F7C00001F7D, - 0x1FB000001FB2, - 0x1FB600001FB7, - 0x1FC600001FC7, - 0x1FD000001FD3, - 0x1FD600001FD8, - 0x1FE000001FE3, - 0x1FE400001FE8, - 0x1FF600001FF7, - 0x214E0000214F, - 0x218400002185, - 0x2C3000002C60, - 0x2C6100002C62, - 0x2C6500002C67, - 0x2C6800002C69, - 0x2C6A00002C6B, - 0x2C6C00002C6D, - 0x2C7100002C72, - 0x2C7300002C75, - 0x2C7600002C7C, - 0x2C8100002C82, - 0x2C8300002C84, - 0x2C8500002C86, - 0x2C8700002C88, - 0x2C8900002C8A, - 0x2C8B00002C8C, - 0x2C8D00002C8E, - 0x2C8F00002C90, - 0x2C9100002C92, - 0x2C9300002C94, - 0x2C9500002C96, - 0x2C9700002C98, - 0x2C9900002C9A, - 0x2C9B00002C9C, - 0x2C9D00002C9E, - 0x2C9F00002CA0, - 0x2CA100002CA2, - 0x2CA300002CA4, - 0x2CA500002CA6, - 0x2CA700002CA8, - 0x2CA900002CAA, - 0x2CAB00002CAC, - 0x2CAD00002CAE, - 0x2CAF00002CB0, - 0x2CB100002CB2, - 0x2CB300002CB4, - 0x2CB500002CB6, - 0x2CB700002CB8, - 0x2CB900002CBA, - 0x2CBB00002CBC, - 0x2CBD00002CBE, - 0x2CBF00002CC0, - 0x2CC100002CC2, - 0x2CC300002CC4, - 0x2CC500002CC6, - 0x2CC700002CC8, - 0x2CC900002CCA, - 0x2CCB00002CCC, - 0x2CCD00002CCE, - 0x2CCF00002CD0, - 0x2CD100002CD2, - 0x2CD300002CD4, - 0x2CD500002CD6, - 0x2CD700002CD8, - 0x2CD900002CDA, - 0x2CDB00002CDC, - 0x2CDD00002CDE, - 0x2CDF00002CE0, - 0x2CE100002CE2, - 0x2CE300002CE5, - 0x2CEC00002CED, - 0x2CEE00002CF2, - 0x2CF300002CF4, - 0x2D0000002D26, - 0x2D2700002D28, - 0x2D2D00002D2E, - 0x2D3000002D68, - 0x2D7F00002D97, - 0x2DA000002DA7, - 0x2DA800002DAF, - 0x2DB000002DB7, - 0x2DB800002DBF, - 0x2DC000002DC7, - 0x2DC800002DCF, - 0x2DD000002DD7, - 0x2DD800002DDF, - 0x2DE000002E00, - 0x2E2F00002E30, - 0x300500003008, - 0x302A0000302E, - 0x303C0000303D, - 0x304100003097, - 0x30990000309B, - 0x309D0000309F, - 0x30A1000030FB, - 0x30FC000030FF, - 0x310500003130, - 0x31A0000031C0, - 0x31F000003200, - 0x340000004DC0, - 0x4E000000A48D, - 0xA4D00000A4FE, - 0xA5000000A60D, - 0xA6100000A62C, - 0xA6410000A642, - 0xA6430000A644, - 0xA6450000A646, - 0xA6470000A648, - 0xA6490000A64A, - 0xA64B0000A64C, - 0xA64D0000A64E, - 0xA64F0000A650, - 0xA6510000A652, - 0xA6530000A654, - 0xA6550000A656, - 0xA6570000A658, - 0xA6590000A65A, - 0xA65B0000A65C, - 0xA65D0000A65E, - 0xA65F0000A660, - 0xA6610000A662, - 0xA6630000A664, - 0xA6650000A666, - 0xA6670000A668, - 0xA6690000A66A, - 0xA66B0000A66C, - 0xA66D0000A670, - 0xA6740000A67E, - 0xA67F0000A680, - 0xA6810000A682, - 0xA6830000A684, - 0xA6850000A686, - 0xA6870000A688, - 0xA6890000A68A, - 0xA68B0000A68C, - 0xA68D0000A68E, - 0xA68F0000A690, - 0xA6910000A692, - 0xA6930000A694, - 0xA6950000A696, - 0xA6970000A698, - 0xA6990000A69A, - 0xA69B0000A69C, - 0xA69E0000A6E6, - 0xA6F00000A6F2, - 0xA7170000A720, - 0xA7230000A724, - 0xA7250000A726, - 0xA7270000A728, - 0xA7290000A72A, - 0xA72B0000A72C, - 0xA72D0000A72E, - 0xA72F0000A732, - 0xA7330000A734, - 0xA7350000A736, - 0xA7370000A738, - 0xA7390000A73A, - 0xA73B0000A73C, - 0xA73D0000A73E, - 0xA73F0000A740, - 0xA7410000A742, - 0xA7430000A744, - 0xA7450000A746, - 0xA7470000A748, - 0xA7490000A74A, - 0xA74B0000A74C, - 0xA74D0000A74E, - 0xA74F0000A750, - 0xA7510000A752, - 0xA7530000A754, - 0xA7550000A756, - 0xA7570000A758, - 0xA7590000A75A, - 0xA75B0000A75C, - 0xA75D0000A75E, - 0xA75F0000A760, - 0xA7610000A762, - 0xA7630000A764, - 0xA7650000A766, - 0xA7670000A768, - 0xA7690000A76A, - 0xA76B0000A76C, - 0xA76D0000A76E, - 0xA76F0000A770, - 0xA7710000A779, - 0xA77A0000A77B, - 0xA77C0000A77D, - 0xA77F0000A780, - 0xA7810000A782, - 0xA7830000A784, - 0xA7850000A786, - 0xA7870000A789, - 0xA78C0000A78D, - 0xA78E0000A790, - 0xA7910000A792, - 0xA7930000A796, - 0xA7970000A798, - 0xA7990000A79A, - 0xA79B0000A79C, - 0xA79D0000A79E, - 0xA79F0000A7A0, - 0xA7A10000A7A2, - 0xA7A30000A7A4, - 0xA7A50000A7A6, - 0xA7A70000A7A8, - 0xA7A90000A7AA, - 0xA7AF0000A7B0, - 0xA7B50000A7B6, - 0xA7B70000A7B8, - 0xA7B90000A7BA, - 0xA7BB0000A7BC, - 0xA7BD0000A7BE, - 0xA7BF0000A7C0, - 0xA7C10000A7C2, - 0xA7C30000A7C4, - 0xA7C80000A7C9, - 0xA7CA0000A7CB, - 0xA7CD0000A7CE, - 0xA7D10000A7D2, - 0xA7D30000A7D4, - 0xA7D50000A7D6, - 0xA7D70000A7D8, - 0xA7D90000A7DA, - 0xA7DB0000A7DC, - 0xA7F60000A7F8, - 0xA7FA0000A828, - 0xA82C0000A82D, - 0xA8400000A874, - 0xA8800000A8C6, - 0xA8D00000A8DA, - 0xA8E00000A8F8, - 0xA8FB0000A8FC, - 0xA8FD0000A92E, - 0xA9300000A954, - 0xA9800000A9C1, - 0xA9CF0000A9DA, - 0xA9E00000A9FF, - 0xAA000000AA37, - 0xAA400000AA4E, - 0xAA500000AA5A, - 0xAA600000AA77, - 0xAA7A0000AAC3, - 0xAADB0000AADE, - 0xAAE00000AAF0, - 0xAAF20000AAF7, - 0xAB010000AB07, - 0xAB090000AB0F, - 0xAB110000AB17, - 0xAB200000AB27, - 0xAB280000AB2F, - 0xAB300000AB5B, - 0xAB600000AB69, - 0xABC00000ABEB, - 0xABEC0000ABEE, - 0xABF00000ABFA, - 0xAC000000D7A4, - 0xFA0E0000FA10, - 0xFA110000FA12, - 0xFA130000FA15, - 0xFA1F0000FA20, - 0xFA210000FA22, - 0xFA230000FA25, - 0xFA270000FA2A, - 0xFB1E0000FB1F, - 0xFE200000FE30, - 0xFE730000FE74, - 0x100000001000C, - 0x1000D00010027, - 0x100280001003B, - 0x1003C0001003E, - 0x1003F0001004E, - 0x100500001005E, - 0x10080000100FB, - 0x101FD000101FE, - 0x102800001029D, - 0x102A0000102D1, - 0x102E0000102E1, - 0x1030000010320, - 0x1032D00010341, - 0x103420001034A, - 0x103500001037B, - 0x103800001039E, - 0x103A0000103C4, - 0x103C8000103D0, - 0x104280001049E, - 0x104A0000104AA, - 0x104D8000104FC, - 0x1050000010528, - 0x1053000010564, - 0x10597000105A2, - 0x105A3000105B2, - 0x105B3000105BA, - 0x105BB000105BD, - 0x105C0000105F4, - 0x1060000010737, - 0x1074000010756, - 0x1076000010768, - 0x1078000010781, - 0x1080000010806, - 0x1080800010809, - 0x1080A00010836, - 0x1083700010839, - 0x1083C0001083D, - 0x1083F00010856, - 0x1086000010877, - 0x108800001089F, - 0x108E0000108F3, - 0x108F4000108F6, - 0x1090000010916, - 0x109200001093A, - 0x10980000109B8, - 0x109BE000109C0, - 0x10A0000010A04, - 0x10A0500010A07, - 0x10A0C00010A14, - 0x10A1500010A18, - 0x10A1900010A36, - 0x10A3800010A3B, - 0x10A3F00010A40, - 0x10A6000010A7D, - 0x10A8000010A9D, - 0x10AC000010AC8, - 0x10AC900010AE7, - 0x10B0000010B36, - 0x10B4000010B56, - 0x10B6000010B73, - 0x10B8000010B92, - 0x10C0000010C49, - 0x10CC000010CF3, - 0x10D0000010D28, - 0x10D3000010D3A, - 0x10D4000010D50, - 0x10D6900010D6E, - 0x10D6F00010D86, - 0x10E8000010EAA, - 0x10EAB00010EAD, - 0x10EB000010EB2, - 0x10EC200010EC5, - 0x10EFC00010F1D, - 0x10F2700010F28, - 0x10F3000010F51, - 0x10F7000010F86, - 0x10FB000010FC5, - 0x10FE000010FF7, - 0x1100000011047, - 0x1106600011076, - 0x1107F000110BB, - 0x110C2000110C3, - 0x110D0000110E9, - 0x110F0000110FA, - 0x1110000011135, - 0x1113600011140, - 0x1114400011148, - 0x1115000011174, - 0x1117600011177, - 0x11180000111C5, - 0x111C9000111CD, - 0x111CE000111DB, - 0x111DC000111DD, - 0x1120000011212, - 0x1121300011238, - 0x1123E00011242, - 0x1128000011287, - 0x1128800011289, - 0x1128A0001128E, - 0x1128F0001129E, - 0x1129F000112A9, - 0x112B0000112EB, - 0x112F0000112FA, - 0x1130000011304, - 0x113050001130D, - 0x1130F00011311, - 0x1131300011329, - 0x1132A00011331, - 0x1133200011334, - 0x113350001133A, - 0x1133B00011345, - 0x1134700011349, - 0x1134B0001134E, - 0x1135000011351, - 0x1135700011358, - 0x1135D00011364, - 0x113660001136D, - 0x1137000011375, - 0x113800001138A, - 0x1138B0001138C, - 0x1138E0001138F, - 0x11390000113B6, - 0x113B7000113C1, - 0x113C2000113C3, - 0x113C5000113C6, - 0x113C7000113CB, - 0x113CC000113D4, - 0x113E1000113E3, - 0x114000001144B, - 0x114500001145A, - 0x1145E00011462, - 0x11480000114C6, - 0x114C7000114C8, - 0x114D0000114DA, - 0x11580000115B6, - 0x115B8000115C1, - 0x115D8000115DE, - 0x1160000011641, - 0x1164400011645, - 0x116500001165A, - 0x11680000116B9, - 0x116C0000116CA, - 0x116D0000116E4, - 0x117000001171B, - 0x1171D0001172C, - 0x117300001173A, - 0x1174000011747, - 0x118000001183B, - 0x118C0000118EA, - 0x118FF00011907, - 0x119090001190A, - 0x1190C00011914, - 0x1191500011917, - 0x1191800011936, - 0x1193700011939, - 0x1193B00011944, - 0x119500001195A, - 0x119A0000119A8, - 0x119AA000119D8, - 0x119DA000119E2, - 0x119E3000119E5, - 0x11A0000011A3F, - 0x11A4700011A48, - 0x11A5000011A9A, - 0x11A9D00011A9E, - 0x11AB000011AF9, - 0x11BC000011BE1, - 0x11BF000011BFA, - 0x11C0000011C09, - 0x11C0A00011C37, - 0x11C3800011C41, - 0x11C5000011C5A, - 0x11C7200011C90, - 0x11C9200011CA8, - 0x11CA900011CB7, - 0x11D0000011D07, - 0x11D0800011D0A, - 0x11D0B00011D37, - 0x11D3A00011D3B, - 0x11D3C00011D3E, - 0x11D3F00011D48, - 0x11D5000011D5A, - 0x11D6000011D66, - 0x11D6700011D69, - 0x11D6A00011D8F, - 0x11D9000011D92, - 0x11D9300011D99, - 0x11DA000011DAA, - 0x11EE000011EF7, - 0x11F0000011F11, - 0x11F1200011F3B, - 0x11F3E00011F43, - 0x11F5000011F5B, - 0x11FB000011FB1, - 0x120000001239A, - 0x1248000012544, - 0x12F9000012FF1, - 0x1300000013430, - 0x1344000013456, - 0x13460000143FB, - 0x1440000014647, - 0x161000001613A, - 0x1680000016A39, - 0x16A4000016A5F, - 0x16A6000016A6A, - 0x16A7000016ABF, - 0x16AC000016ACA, - 0x16AD000016AEE, - 0x16AF000016AF5, - 0x16B0000016B37, - 0x16B4000016B44, - 0x16B5000016B5A, - 0x16B6300016B78, - 0x16B7D00016B90, - 0x16D4000016D6D, - 0x16D7000016D7A, - 0x16E6000016E80, - 0x16F0000016F4B, - 0x16F4F00016F88, - 0x16F8F00016FA0, - 0x16FE000016FE2, - 0x16FE300016FE5, - 0x16FF000016FF2, - 0x17000000187F8, - 0x1880000018CD6, - 0x18CFF00018D09, - 0x1AFF00001AFF4, - 0x1AFF50001AFFC, - 0x1AFFD0001AFFF, - 0x1B0000001B123, - 0x1B1320001B133, - 0x1B1500001B153, - 0x1B1550001B156, - 0x1B1640001B168, - 0x1B1700001B2FC, - 0x1BC000001BC6B, - 0x1BC700001BC7D, - 0x1BC800001BC89, - 0x1BC900001BC9A, - 0x1BC9D0001BC9F, - 0x1CCF00001CCFA, - 0x1CF000001CF2E, - 0x1CF300001CF47, - 0x1DA000001DA37, - 0x1DA3B0001DA6D, - 0x1DA750001DA76, - 0x1DA840001DA85, - 0x1DA9B0001DAA0, - 0x1DAA10001DAB0, - 0x1DF000001DF1F, - 0x1DF250001DF2B, - 0x1E0000001E007, - 0x1E0080001E019, - 0x1E01B0001E022, - 0x1E0230001E025, - 0x1E0260001E02B, - 0x1E08F0001E090, - 0x1E1000001E12D, - 0x1E1300001E13E, - 0x1E1400001E14A, - 0x1E14E0001E14F, - 0x1E2900001E2AF, - 0x1E2C00001E2FA, - 0x1E4D00001E4FA, - 0x1E5D00001E5FB, - 0x1E7E00001E7E7, - 0x1E7E80001E7EC, - 0x1E7ED0001E7EF, - 0x1E7F00001E7FF, - 0x1E8000001E8C5, - 0x1E8D00001E8D7, - 0x1E9220001E94C, - 0x1E9500001E95A, - 0x200000002A6E0, - 0x2A7000002B73A, - 0x2B7400002B81E, - 0x2B8200002CEA2, - 0x2CEB00002EBE1, - 0x2EBF00002EE5E, - 0x300000003134B, - 0x31350000323B0, - ), - "CONTEXTJ": (0x200C0000200E,), - "CONTEXTO": ( - 0xB7000000B8, - 0x37500000376, - 0x5F3000005F5, - 0x6600000066A, - 0x6F0000006FA, - 0x30FB000030FC, - ), -} diff --git a/apps/bitwarden_event_logs/lib/idna/intranges.py b/apps/bitwarden_event_logs/lib/idna/intranges.py deleted file mode 100755 index 7bfaa8d8..00000000 --- a/apps/bitwarden_event_logs/lib/idna/intranges.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Given a list of integers, made up of (hopefully) a small number of long runs -of consecutive integers, compute a representation of the form -((start1, end1), (start2, end2) ...). Then answer the question "was x present -in the original list?" in time O(log(# runs)). -""" - -import bisect -from typing import List, Tuple - - -def intranges_from_list(list_: List[int]) -> Tuple[int, ...]: - """Represent a list of integers as a sequence of ranges: - ((start_0, end_0), (start_1, end_1), ...), such that the original - integers are exactly those x such that start_i <= x < end_i for some i. - - Ranges are encoded as single integers (start << 32 | end), not as tuples. - """ - - sorted_list = sorted(list_) - ranges = [] - last_write = -1 - for i in range(len(sorted_list)): - if i + 1 < len(sorted_list): - if sorted_list[i] == sorted_list[i + 1] - 1: - continue - current_range = sorted_list[last_write + 1 : i + 1] - ranges.append(_encode_range(current_range[0], current_range[-1] + 1)) - last_write = i - - return tuple(ranges) - - -def _encode_range(start: int, end: int) -> int: - return (start << 32) | end - - -def _decode_range(r: int) -> Tuple[int, int]: - return (r >> 32), (r & ((1 << 32) - 1)) - - -def intranges_contain(int_: int, ranges: Tuple[int, ...]) -> bool: - """Determine if `int_` falls into one of the ranges in `ranges`.""" - tuple_ = _encode_range(int_, 0) - pos = bisect.bisect_left(ranges, tuple_) - # we could be immediately ahead of a tuple (start, end) - # with start < int_ <= end - if pos > 0: - left, right = _decode_range(ranges[pos - 1]) - if left <= int_ < right: - return True - # or we could be immediately behind a tuple (int_, end) - if pos < len(ranges): - left, _ = _decode_range(ranges[pos]) - if left == int_: - return True - return False diff --git a/apps/bitwarden_event_logs/lib/idna/package_data.py b/apps/bitwarden_event_logs/lib/idna/package_data.py deleted file mode 100755 index 7272c8d9..00000000 --- a/apps/bitwarden_event_logs/lib/idna/package_data.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "3.11" diff --git a/apps/bitwarden_event_logs/lib/idna/py.typed b/apps/bitwarden_event_logs/lib/idna/py.typed deleted file mode 100755 index e69de29b..00000000 diff --git a/apps/bitwarden_event_logs/lib/idna/uts46data.py b/apps/bitwarden_event_logs/lib/idna/uts46data.py deleted file mode 100755 index 4610b71d..00000000 --- a/apps/bitwarden_event_logs/lib/idna/uts46data.py +++ /dev/null @@ -1,8841 +0,0 @@ -# This file is automatically generated by tools/idna-data -# vim: set fileencoding=utf-8 : - -from typing import List, Tuple, Union - -"""IDNA Mapping Table from UTS46.""" - - -__version__ = "16.0.0" - - -def _seg_0() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x0, "V"), - (0x1, "V"), - (0x2, "V"), - (0x3, "V"), - (0x4, "V"), - (0x5, "V"), - (0x6, "V"), - (0x7, "V"), - (0x8, "V"), - (0x9, "V"), - (0xA, "V"), - (0xB, "V"), - (0xC, "V"), - (0xD, "V"), - (0xE, "V"), - (0xF, "V"), - (0x10, "V"), - (0x11, "V"), - (0x12, "V"), - (0x13, "V"), - (0x14, "V"), - (0x15, "V"), - (0x16, "V"), - (0x17, "V"), - (0x18, "V"), - (0x19, "V"), - (0x1A, "V"), - (0x1B, "V"), - (0x1C, "V"), - (0x1D, "V"), - (0x1E, "V"), - (0x1F, "V"), - (0x20, "V"), - (0x21, "V"), - (0x22, "V"), - (0x23, "V"), - (0x24, "V"), - (0x25, "V"), - (0x26, "V"), - (0x27, "V"), - (0x28, "V"), - (0x29, "V"), - (0x2A, "V"), - (0x2B, "V"), - (0x2C, "V"), - (0x2D, "V"), - (0x2E, "V"), - (0x2F, "V"), - (0x30, "V"), - (0x31, "V"), - (0x32, "V"), - (0x33, "V"), - (0x34, "V"), - (0x35, "V"), - (0x36, "V"), - (0x37, "V"), - (0x38, "V"), - (0x39, "V"), - (0x3A, "V"), - (0x3B, "V"), - (0x3C, "V"), - (0x3D, "V"), - (0x3E, "V"), - (0x3F, "V"), - (0x40, "V"), - (0x41, "M", "a"), - (0x42, "M", "b"), - (0x43, "M", "c"), - (0x44, "M", "d"), - (0x45, "M", "e"), - (0x46, "M", "f"), - (0x47, "M", "g"), - (0x48, "M", "h"), - (0x49, "M", "i"), - (0x4A, "M", "j"), - (0x4B, "M", "k"), - (0x4C, "M", "l"), - (0x4D, "M", "m"), - (0x4E, "M", "n"), - (0x4F, "M", "o"), - (0x50, "M", "p"), - (0x51, "M", "q"), - (0x52, "M", "r"), - (0x53, "M", "s"), - (0x54, "M", "t"), - (0x55, "M", "u"), - (0x56, "M", "v"), - (0x57, "M", "w"), - (0x58, "M", "x"), - (0x59, "M", "y"), - (0x5A, "M", "z"), - (0x5B, "V"), - (0x5C, "V"), - (0x5D, "V"), - (0x5E, "V"), - (0x5F, "V"), - (0x60, "V"), - (0x61, "V"), - (0x62, "V"), - (0x63, "V"), - ] - - -def _seg_1() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x64, "V"), - (0x65, "V"), - (0x66, "V"), - (0x67, "V"), - (0x68, "V"), - (0x69, "V"), - (0x6A, "V"), - (0x6B, "V"), - (0x6C, "V"), - (0x6D, "V"), - (0x6E, "V"), - (0x6F, "V"), - (0x70, "V"), - (0x71, "V"), - (0x72, "V"), - (0x73, "V"), - (0x74, "V"), - (0x75, "V"), - (0x76, "V"), - (0x77, "V"), - (0x78, "V"), - (0x79, "V"), - (0x7A, "V"), - (0x7B, "V"), - (0x7C, "V"), - (0x7D, "V"), - (0x7E, "V"), - (0x7F, "V"), - (0x80, "X"), - (0x81, "X"), - (0x82, "X"), - (0x83, "X"), - (0x84, "X"), - (0x85, "X"), - (0x86, "X"), - (0x87, "X"), - (0x88, "X"), - (0x89, "X"), - (0x8A, "X"), - (0x8B, "X"), - (0x8C, "X"), - (0x8D, "X"), - (0x8E, "X"), - (0x8F, "X"), - (0x90, "X"), - (0x91, "X"), - (0x92, "X"), - (0x93, "X"), - (0x94, "X"), - (0x95, "X"), - (0x96, "X"), - (0x97, "X"), - (0x98, "X"), - (0x99, "X"), - (0x9A, "X"), - (0x9B, "X"), - (0x9C, "X"), - (0x9D, "X"), - (0x9E, "X"), - (0x9F, "X"), - (0xA0, "M", " "), - (0xA1, "V"), - (0xA2, "V"), - (0xA3, "V"), - (0xA4, "V"), - (0xA5, "V"), - (0xA6, "V"), - (0xA7, "V"), - (0xA8, "M", " ̈"), - (0xA9, "V"), - (0xAA, "M", "a"), - (0xAB, "V"), - (0xAC, "V"), - (0xAD, "I"), - (0xAE, "V"), - (0xAF, "M", " ̄"), - (0xB0, "V"), - (0xB1, "V"), - (0xB2, "M", "2"), - (0xB3, "M", "3"), - (0xB4, "M", " ́"), - (0xB5, "M", "μ"), - (0xB6, "V"), - (0xB7, "V"), - (0xB8, "M", " ̧"), - (0xB9, "M", "1"), - (0xBA, "M", "o"), - (0xBB, "V"), - (0xBC, "M", "1⁄4"), - (0xBD, "M", "1⁄2"), - (0xBE, "M", "3⁄4"), - (0xBF, "V"), - (0xC0, "M", "à"), - (0xC1, "M", "á"), - (0xC2, "M", "â"), - (0xC3, "M", "ã"), - (0xC4, "M", "ä"), - (0xC5, "M", "å"), - (0xC6, "M", "æ"), - (0xC7, "M", "ç"), - ] - - -def _seg_2() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xC8, "M", "è"), - (0xC9, "M", "é"), - (0xCA, "M", "ê"), - (0xCB, "M", "ë"), - (0xCC, "M", "ì"), - (0xCD, "M", "í"), - (0xCE, "M", "î"), - (0xCF, "M", "ï"), - (0xD0, "M", "ð"), - (0xD1, "M", "ñ"), - (0xD2, "M", "ò"), - (0xD3, "M", "ó"), - (0xD4, "M", "ô"), - (0xD5, "M", "õ"), - (0xD6, "M", "ö"), - (0xD7, "V"), - (0xD8, "M", "ø"), - (0xD9, "M", "ù"), - (0xDA, "M", "ú"), - (0xDB, "M", "û"), - (0xDC, "M", "ü"), - (0xDD, "M", "ý"), - (0xDE, "M", "þ"), - (0xDF, "D", "ss"), - (0xE0, "V"), - (0xE1, "V"), - (0xE2, "V"), - (0xE3, "V"), - (0xE4, "V"), - (0xE5, "V"), - (0xE6, "V"), - (0xE7, "V"), - (0xE8, "V"), - (0xE9, "V"), - (0xEA, "V"), - (0xEB, "V"), - (0xEC, "V"), - (0xED, "V"), - (0xEE, "V"), - (0xEF, "V"), - (0xF0, "V"), - (0xF1, "V"), - (0xF2, "V"), - (0xF3, "V"), - (0xF4, "V"), - (0xF5, "V"), - (0xF6, "V"), - (0xF7, "V"), - (0xF8, "V"), - (0xF9, "V"), - (0xFA, "V"), - (0xFB, "V"), - (0xFC, "V"), - (0xFD, "V"), - (0xFE, "V"), - (0xFF, "V"), - (0x100, "M", "ā"), - (0x101, "V"), - (0x102, "M", "ă"), - (0x103, "V"), - (0x104, "M", "ą"), - (0x105, "V"), - (0x106, "M", "ć"), - (0x107, "V"), - (0x108, "M", "ĉ"), - (0x109, "V"), - (0x10A, "M", "ċ"), - (0x10B, "V"), - (0x10C, "M", "č"), - (0x10D, "V"), - (0x10E, "M", "ď"), - (0x10F, "V"), - (0x110, "M", "đ"), - (0x111, "V"), - (0x112, "M", "ē"), - (0x113, "V"), - (0x114, "M", "ĕ"), - (0x115, "V"), - (0x116, "M", "ė"), - (0x117, "V"), - (0x118, "M", "ę"), - (0x119, "V"), - (0x11A, "M", "ě"), - (0x11B, "V"), - (0x11C, "M", "ĝ"), - (0x11D, "V"), - (0x11E, "M", "ğ"), - (0x11F, "V"), - (0x120, "M", "ġ"), - (0x121, "V"), - (0x122, "M", "ģ"), - (0x123, "V"), - (0x124, "M", "ĥ"), - (0x125, "V"), - (0x126, "M", "ħ"), - (0x127, "V"), - (0x128, "M", "ĩ"), - (0x129, "V"), - (0x12A, "M", "ī"), - (0x12B, "V"), - ] - - -def _seg_3() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x12C, "M", "ĭ"), - (0x12D, "V"), - (0x12E, "M", "į"), - (0x12F, "V"), - (0x130, "M", "i̇"), - (0x131, "V"), - (0x132, "M", "ij"), - (0x134, "M", "ĵ"), - (0x135, "V"), - (0x136, "M", "ķ"), - (0x137, "V"), - (0x139, "M", "ĺ"), - (0x13A, "V"), - (0x13B, "M", "ļ"), - (0x13C, "V"), - (0x13D, "M", "ľ"), - (0x13E, "V"), - (0x13F, "M", "l·"), - (0x141, "M", "ł"), - (0x142, "V"), - (0x143, "M", "ń"), - (0x144, "V"), - (0x145, "M", "ņ"), - (0x146, "V"), - (0x147, "M", "ň"), - (0x148, "V"), - (0x149, "M", "ʼn"), - (0x14A, "M", "ŋ"), - (0x14B, "V"), - (0x14C, "M", "ō"), - (0x14D, "V"), - (0x14E, "M", "ŏ"), - (0x14F, "V"), - (0x150, "M", "ő"), - (0x151, "V"), - (0x152, "M", "œ"), - (0x153, "V"), - (0x154, "M", "ŕ"), - (0x155, "V"), - (0x156, "M", "ŗ"), - (0x157, "V"), - (0x158, "M", "ř"), - (0x159, "V"), - (0x15A, "M", "ś"), - (0x15B, "V"), - (0x15C, "M", "ŝ"), - (0x15D, "V"), - (0x15E, "M", "ş"), - (0x15F, "V"), - (0x160, "M", "š"), - (0x161, "V"), - (0x162, "M", "ţ"), - (0x163, "V"), - (0x164, "M", "ť"), - (0x165, "V"), - (0x166, "M", "ŧ"), - (0x167, "V"), - (0x168, "M", "ũ"), - (0x169, "V"), - (0x16A, "M", "ū"), - (0x16B, "V"), - (0x16C, "M", "ŭ"), - (0x16D, "V"), - (0x16E, "M", "ů"), - (0x16F, "V"), - (0x170, "M", "ű"), - (0x171, "V"), - (0x172, "M", "ų"), - (0x173, "V"), - (0x174, "M", "ŵ"), - (0x175, "V"), - (0x176, "M", "ŷ"), - (0x177, "V"), - (0x178, "M", "ÿ"), - (0x179, "M", "ź"), - (0x17A, "V"), - (0x17B, "M", "ż"), - (0x17C, "V"), - (0x17D, "M", "ž"), - (0x17E, "V"), - (0x17F, "M", "s"), - (0x180, "V"), - (0x181, "M", "ɓ"), - (0x182, "M", "ƃ"), - (0x183, "V"), - (0x184, "M", "ƅ"), - (0x185, "V"), - (0x186, "M", "ɔ"), - (0x187, "M", "ƈ"), - (0x188, "V"), - (0x189, "M", "ɖ"), - (0x18A, "M", "ɗ"), - (0x18B, "M", "ƌ"), - (0x18C, "V"), - (0x18E, "M", "ǝ"), - (0x18F, "M", "ə"), - (0x190, "M", "ɛ"), - (0x191, "M", "ƒ"), - (0x192, "V"), - (0x193, "M", "ɠ"), - ] - - -def _seg_4() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x194, "M", "ɣ"), - (0x195, "V"), - (0x196, "M", "ɩ"), - (0x197, "M", "ɨ"), - (0x198, "M", "ƙ"), - (0x199, "V"), - (0x19C, "M", "ɯ"), - (0x19D, "M", "ɲ"), - (0x19E, "V"), - (0x19F, "M", "ɵ"), - (0x1A0, "M", "ơ"), - (0x1A1, "V"), - (0x1A2, "M", "ƣ"), - (0x1A3, "V"), - (0x1A4, "M", "ƥ"), - (0x1A5, "V"), - (0x1A6, "M", "ʀ"), - (0x1A7, "M", "ƨ"), - (0x1A8, "V"), - (0x1A9, "M", "ʃ"), - (0x1AA, "V"), - (0x1AC, "M", "ƭ"), - (0x1AD, "V"), - (0x1AE, "M", "ʈ"), - (0x1AF, "M", "ư"), - (0x1B0, "V"), - (0x1B1, "M", "ʊ"), - (0x1B2, "M", "ʋ"), - (0x1B3, "M", "ƴ"), - (0x1B4, "V"), - (0x1B5, "M", "ƶ"), - (0x1B6, "V"), - (0x1B7, "M", "ʒ"), - (0x1B8, "M", "ƹ"), - (0x1B9, "V"), - (0x1BC, "M", "ƽ"), - (0x1BD, "V"), - (0x1C4, "M", "dž"), - (0x1C7, "M", "lj"), - (0x1CA, "M", "nj"), - (0x1CD, "M", "ǎ"), - (0x1CE, "V"), - (0x1CF, "M", "ǐ"), - (0x1D0, "V"), - (0x1D1, "M", "ǒ"), - (0x1D2, "V"), - (0x1D3, "M", "ǔ"), - (0x1D4, "V"), - (0x1D5, "M", "ǖ"), - (0x1D6, "V"), - (0x1D7, "M", "ǘ"), - (0x1D8, "V"), - (0x1D9, "M", "ǚ"), - (0x1DA, "V"), - (0x1DB, "M", "ǜ"), - (0x1DC, "V"), - (0x1DE, "M", "ǟ"), - (0x1DF, "V"), - (0x1E0, "M", "ǡ"), - (0x1E1, "V"), - (0x1E2, "M", "ǣ"), - (0x1E3, "V"), - (0x1E4, "M", "ǥ"), - (0x1E5, "V"), - (0x1E6, "M", "ǧ"), - (0x1E7, "V"), - (0x1E8, "M", "ǩ"), - (0x1E9, "V"), - (0x1EA, "M", "ǫ"), - (0x1EB, "V"), - (0x1EC, "M", "ǭ"), - (0x1ED, "V"), - (0x1EE, "M", "ǯ"), - (0x1EF, "V"), - (0x1F1, "M", "dz"), - (0x1F4, "M", "ǵ"), - (0x1F5, "V"), - (0x1F6, "M", "ƕ"), - (0x1F7, "M", "ƿ"), - (0x1F8, "M", "ǹ"), - (0x1F9, "V"), - (0x1FA, "M", "ǻ"), - (0x1FB, "V"), - (0x1FC, "M", "ǽ"), - (0x1FD, "V"), - (0x1FE, "M", "ǿ"), - (0x1FF, "V"), - (0x200, "M", "ȁ"), - (0x201, "V"), - (0x202, "M", "ȃ"), - (0x203, "V"), - (0x204, "M", "ȅ"), - (0x205, "V"), - (0x206, "M", "ȇ"), - (0x207, "V"), - (0x208, "M", "ȉ"), - (0x209, "V"), - (0x20A, "M", "ȋ"), - (0x20B, "V"), - (0x20C, "M", "ȍ"), - ] - - -def _seg_5() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x20D, "V"), - (0x20E, "M", "ȏ"), - (0x20F, "V"), - (0x210, "M", "ȑ"), - (0x211, "V"), - (0x212, "M", "ȓ"), - (0x213, "V"), - (0x214, "M", "ȕ"), - (0x215, "V"), - (0x216, "M", "ȗ"), - (0x217, "V"), - (0x218, "M", "ș"), - (0x219, "V"), - (0x21A, "M", "ț"), - (0x21B, "V"), - (0x21C, "M", "ȝ"), - (0x21D, "V"), - (0x21E, "M", "ȟ"), - (0x21F, "V"), - (0x220, "M", "ƞ"), - (0x221, "V"), - (0x222, "M", "ȣ"), - (0x223, "V"), - (0x224, "M", "ȥ"), - (0x225, "V"), - (0x226, "M", "ȧ"), - (0x227, "V"), - (0x228, "M", "ȩ"), - (0x229, "V"), - (0x22A, "M", "ȫ"), - (0x22B, "V"), - (0x22C, "M", "ȭ"), - (0x22D, "V"), - (0x22E, "M", "ȯ"), - (0x22F, "V"), - (0x230, "M", "ȱ"), - (0x231, "V"), - (0x232, "M", "ȳ"), - (0x233, "V"), - (0x23A, "M", "ⱥ"), - (0x23B, "M", "ȼ"), - (0x23C, "V"), - (0x23D, "M", "ƚ"), - (0x23E, "M", "ⱦ"), - (0x23F, "V"), - (0x241, "M", "ɂ"), - (0x242, "V"), - (0x243, "M", "ƀ"), - (0x244, "M", "ʉ"), - (0x245, "M", "ʌ"), - (0x246, "M", "ɇ"), - (0x247, "V"), - (0x248, "M", "ɉ"), - (0x249, "V"), - (0x24A, "M", "ɋ"), - (0x24B, "V"), - (0x24C, "M", "ɍ"), - (0x24D, "V"), - (0x24E, "M", "ɏ"), - (0x24F, "V"), - (0x2B0, "M", "h"), - (0x2B1, "M", "ɦ"), - (0x2B2, "M", "j"), - (0x2B3, "M", "r"), - (0x2B4, "M", "ɹ"), - (0x2B5, "M", "ɻ"), - (0x2B6, "M", "ʁ"), - (0x2B7, "M", "w"), - (0x2B8, "M", "y"), - (0x2B9, "V"), - (0x2D8, "M", " ̆"), - (0x2D9, "M", " ̇"), - (0x2DA, "M", " ̊"), - (0x2DB, "M", " ̨"), - (0x2DC, "M", " ̃"), - (0x2DD, "M", " ̋"), - (0x2DE, "V"), - (0x2E0, "M", "ɣ"), - (0x2E1, "M", "l"), - (0x2E2, "M", "s"), - (0x2E3, "M", "x"), - (0x2E4, "M", "ʕ"), - (0x2E5, "V"), - (0x340, "M", "̀"), - (0x341, "M", "́"), - (0x342, "V"), - (0x343, "M", "̓"), - (0x344, "M", "̈́"), - (0x345, "M", "ι"), - (0x346, "V"), - (0x34F, "I"), - (0x350, "V"), - (0x370, "M", "ͱ"), - (0x371, "V"), - (0x372, "M", "ͳ"), - (0x373, "V"), - (0x374, "M", "ʹ"), - (0x375, "V"), - (0x376, "M", "ͷ"), - (0x377, "V"), - ] - - -def _seg_6() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x378, "X"), - (0x37A, "M", " ι"), - (0x37B, "V"), - (0x37E, "M", ";"), - (0x37F, "M", "ϳ"), - (0x380, "X"), - (0x384, "M", " ́"), - (0x385, "M", " ̈́"), - (0x386, "M", "ά"), - (0x387, "M", "·"), - (0x388, "M", "έ"), - (0x389, "M", "ή"), - (0x38A, "M", "ί"), - (0x38B, "X"), - (0x38C, "M", "ό"), - (0x38D, "X"), - (0x38E, "M", "ύ"), - (0x38F, "M", "ώ"), - (0x390, "V"), - (0x391, "M", "α"), - (0x392, "M", "β"), - (0x393, "M", "γ"), - (0x394, "M", "δ"), - (0x395, "M", "ε"), - (0x396, "M", "ζ"), - (0x397, "M", "η"), - (0x398, "M", "θ"), - (0x399, "M", "ι"), - (0x39A, "M", "κ"), - (0x39B, "M", "λ"), - (0x39C, "M", "μ"), - (0x39D, "M", "ν"), - (0x39E, "M", "ξ"), - (0x39F, "M", "ο"), - (0x3A0, "M", "π"), - (0x3A1, "M", "ρ"), - (0x3A2, "X"), - (0x3A3, "M", "σ"), - (0x3A4, "M", "τ"), - (0x3A5, "M", "υ"), - (0x3A6, "M", "φ"), - (0x3A7, "M", "χ"), - (0x3A8, "M", "ψ"), - (0x3A9, "M", "ω"), - (0x3AA, "M", "ϊ"), - (0x3AB, "M", "ϋ"), - (0x3AC, "V"), - (0x3C2, "D", "σ"), - (0x3C3, "V"), - (0x3CF, "M", "ϗ"), - (0x3D0, "M", "β"), - (0x3D1, "M", "θ"), - (0x3D2, "M", "υ"), - (0x3D3, "M", "ύ"), - (0x3D4, "M", "ϋ"), - (0x3D5, "M", "φ"), - (0x3D6, "M", "π"), - (0x3D7, "V"), - (0x3D8, "M", "ϙ"), - (0x3D9, "V"), - (0x3DA, "M", "ϛ"), - (0x3DB, "V"), - (0x3DC, "M", "ϝ"), - (0x3DD, "V"), - (0x3DE, "M", "ϟ"), - (0x3DF, "V"), - (0x3E0, "M", "ϡ"), - (0x3E1, "V"), - (0x3E2, "M", "ϣ"), - (0x3E3, "V"), - (0x3E4, "M", "ϥ"), - (0x3E5, "V"), - (0x3E6, "M", "ϧ"), - (0x3E7, "V"), - (0x3E8, "M", "ϩ"), - (0x3E9, "V"), - (0x3EA, "M", "ϫ"), - (0x3EB, "V"), - (0x3EC, "M", "ϭ"), - (0x3ED, "V"), - (0x3EE, "M", "ϯ"), - (0x3EF, "V"), - (0x3F0, "M", "κ"), - (0x3F1, "M", "ρ"), - (0x3F2, "M", "σ"), - (0x3F3, "V"), - (0x3F4, "M", "θ"), - (0x3F5, "M", "ε"), - (0x3F6, "V"), - (0x3F7, "M", "ϸ"), - (0x3F8, "V"), - (0x3F9, "M", "σ"), - (0x3FA, "M", "ϻ"), - (0x3FB, "V"), - (0x3FD, "M", "ͻ"), - (0x3FE, "M", "ͼ"), - (0x3FF, "M", "ͽ"), - (0x400, "M", "ѐ"), - (0x401, "M", "ё"), - (0x402, "M", "ђ"), - ] - - -def _seg_7() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x403, "M", "ѓ"), - (0x404, "M", "є"), - (0x405, "M", "ѕ"), - (0x406, "M", "і"), - (0x407, "M", "ї"), - (0x408, "M", "ј"), - (0x409, "M", "љ"), - (0x40A, "M", "њ"), - (0x40B, "M", "ћ"), - (0x40C, "M", "ќ"), - (0x40D, "M", "ѝ"), - (0x40E, "M", "ў"), - (0x40F, "M", "џ"), - (0x410, "M", "а"), - (0x411, "M", "б"), - (0x412, "M", "в"), - (0x413, "M", "г"), - (0x414, "M", "д"), - (0x415, "M", "е"), - (0x416, "M", "ж"), - (0x417, "M", "з"), - (0x418, "M", "и"), - (0x419, "M", "й"), - (0x41A, "M", "к"), - (0x41B, "M", "л"), - (0x41C, "M", "м"), - (0x41D, "M", "н"), - (0x41E, "M", "о"), - (0x41F, "M", "п"), - (0x420, "M", "р"), - (0x421, "M", "с"), - (0x422, "M", "т"), - (0x423, "M", "у"), - (0x424, "M", "ф"), - (0x425, "M", "х"), - (0x426, "M", "ц"), - (0x427, "M", "ч"), - (0x428, "M", "ш"), - (0x429, "M", "щ"), - (0x42A, "M", "ъ"), - (0x42B, "M", "ы"), - (0x42C, "M", "ь"), - (0x42D, "M", "э"), - (0x42E, "M", "ю"), - (0x42F, "M", "я"), - (0x430, "V"), - (0x460, "M", "ѡ"), - (0x461, "V"), - (0x462, "M", "ѣ"), - (0x463, "V"), - (0x464, "M", "ѥ"), - (0x465, "V"), - (0x466, "M", "ѧ"), - (0x467, "V"), - (0x468, "M", "ѩ"), - (0x469, "V"), - (0x46A, "M", "ѫ"), - (0x46B, "V"), - (0x46C, "M", "ѭ"), - (0x46D, "V"), - (0x46E, "M", "ѯ"), - (0x46F, "V"), - (0x470, "M", "ѱ"), - (0x471, "V"), - (0x472, "M", "ѳ"), - (0x473, "V"), - (0x474, "M", "ѵ"), - (0x475, "V"), - (0x476, "M", "ѷ"), - (0x477, "V"), - (0x478, "M", "ѹ"), - (0x479, "V"), - (0x47A, "M", "ѻ"), - (0x47B, "V"), - (0x47C, "M", "ѽ"), - (0x47D, "V"), - (0x47E, "M", "ѿ"), - (0x47F, "V"), - (0x480, "M", "ҁ"), - (0x481, "V"), - (0x48A, "M", "ҋ"), - (0x48B, "V"), - (0x48C, "M", "ҍ"), - (0x48D, "V"), - (0x48E, "M", "ҏ"), - (0x48F, "V"), - (0x490, "M", "ґ"), - (0x491, "V"), - (0x492, "M", "ғ"), - (0x493, "V"), - (0x494, "M", "ҕ"), - (0x495, "V"), - (0x496, "M", "җ"), - (0x497, "V"), - (0x498, "M", "ҙ"), - (0x499, "V"), - (0x49A, "M", "қ"), - (0x49B, "V"), - (0x49C, "M", "ҝ"), - (0x49D, "V"), - ] - - -def _seg_8() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x49E, "M", "ҟ"), - (0x49F, "V"), - (0x4A0, "M", "ҡ"), - (0x4A1, "V"), - (0x4A2, "M", "ң"), - (0x4A3, "V"), - (0x4A4, "M", "ҥ"), - (0x4A5, "V"), - (0x4A6, "M", "ҧ"), - (0x4A7, "V"), - (0x4A8, "M", "ҩ"), - (0x4A9, "V"), - (0x4AA, "M", "ҫ"), - (0x4AB, "V"), - (0x4AC, "M", "ҭ"), - (0x4AD, "V"), - (0x4AE, "M", "ү"), - (0x4AF, "V"), - (0x4B0, "M", "ұ"), - (0x4B1, "V"), - (0x4B2, "M", "ҳ"), - (0x4B3, "V"), - (0x4B4, "M", "ҵ"), - (0x4B5, "V"), - (0x4B6, "M", "ҷ"), - (0x4B7, "V"), - (0x4B8, "M", "ҹ"), - (0x4B9, "V"), - (0x4BA, "M", "һ"), - (0x4BB, "V"), - (0x4BC, "M", "ҽ"), - (0x4BD, "V"), - (0x4BE, "M", "ҿ"), - (0x4BF, "V"), - (0x4C0, "M", "ӏ"), - (0x4C1, "M", "ӂ"), - (0x4C2, "V"), - (0x4C3, "M", "ӄ"), - (0x4C4, "V"), - (0x4C5, "M", "ӆ"), - (0x4C6, "V"), - (0x4C7, "M", "ӈ"), - (0x4C8, "V"), - (0x4C9, "M", "ӊ"), - (0x4CA, "V"), - (0x4CB, "M", "ӌ"), - (0x4CC, "V"), - (0x4CD, "M", "ӎ"), - (0x4CE, "V"), - (0x4D0, "M", "ӑ"), - (0x4D1, "V"), - (0x4D2, "M", "ӓ"), - (0x4D3, "V"), - (0x4D4, "M", "ӕ"), - (0x4D5, "V"), - (0x4D6, "M", "ӗ"), - (0x4D7, "V"), - (0x4D8, "M", "ә"), - (0x4D9, "V"), - (0x4DA, "M", "ӛ"), - (0x4DB, "V"), - (0x4DC, "M", "ӝ"), - (0x4DD, "V"), - (0x4DE, "M", "ӟ"), - (0x4DF, "V"), - (0x4E0, "M", "ӡ"), - (0x4E1, "V"), - (0x4E2, "M", "ӣ"), - (0x4E3, "V"), - (0x4E4, "M", "ӥ"), - (0x4E5, "V"), - (0x4E6, "M", "ӧ"), - (0x4E7, "V"), - (0x4E8, "M", "ө"), - (0x4E9, "V"), - (0x4EA, "M", "ӫ"), - (0x4EB, "V"), - (0x4EC, "M", "ӭ"), - (0x4ED, "V"), - (0x4EE, "M", "ӯ"), - (0x4EF, "V"), - (0x4F0, "M", "ӱ"), - (0x4F1, "V"), - (0x4F2, "M", "ӳ"), - (0x4F3, "V"), - (0x4F4, "M", "ӵ"), - (0x4F5, "V"), - (0x4F6, "M", "ӷ"), - (0x4F7, "V"), - (0x4F8, "M", "ӹ"), - (0x4F9, "V"), - (0x4FA, "M", "ӻ"), - (0x4FB, "V"), - (0x4FC, "M", "ӽ"), - (0x4FD, "V"), - (0x4FE, "M", "ӿ"), - (0x4FF, "V"), - (0x500, "M", "ԁ"), - (0x501, "V"), - (0x502, "M", "ԃ"), - ] - - -def _seg_9() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x503, "V"), - (0x504, "M", "ԅ"), - (0x505, "V"), - (0x506, "M", "ԇ"), - (0x507, "V"), - (0x508, "M", "ԉ"), - (0x509, "V"), - (0x50A, "M", "ԋ"), - (0x50B, "V"), - (0x50C, "M", "ԍ"), - (0x50D, "V"), - (0x50E, "M", "ԏ"), - (0x50F, "V"), - (0x510, "M", "ԑ"), - (0x511, "V"), - (0x512, "M", "ԓ"), - (0x513, "V"), - (0x514, "M", "ԕ"), - (0x515, "V"), - (0x516, "M", "ԗ"), - (0x517, "V"), - (0x518, "M", "ԙ"), - (0x519, "V"), - (0x51A, "M", "ԛ"), - (0x51B, "V"), - (0x51C, "M", "ԝ"), - (0x51D, "V"), - (0x51E, "M", "ԟ"), - (0x51F, "V"), - (0x520, "M", "ԡ"), - (0x521, "V"), - (0x522, "M", "ԣ"), - (0x523, "V"), - (0x524, "M", "ԥ"), - (0x525, "V"), - (0x526, "M", "ԧ"), - (0x527, "V"), - (0x528, "M", "ԩ"), - (0x529, "V"), - (0x52A, "M", "ԫ"), - (0x52B, "V"), - (0x52C, "M", "ԭ"), - (0x52D, "V"), - (0x52E, "M", "ԯ"), - (0x52F, "V"), - (0x530, "X"), - (0x531, "M", "ա"), - (0x532, "M", "բ"), - (0x533, "M", "գ"), - (0x534, "M", "դ"), - (0x535, "M", "ե"), - (0x536, "M", "զ"), - (0x537, "M", "է"), - (0x538, "M", "ը"), - (0x539, "M", "թ"), - (0x53A, "M", "ժ"), - (0x53B, "M", "ի"), - (0x53C, "M", "լ"), - (0x53D, "M", "խ"), - (0x53E, "M", "ծ"), - (0x53F, "M", "կ"), - (0x540, "M", "հ"), - (0x541, "M", "ձ"), - (0x542, "M", "ղ"), - (0x543, "M", "ճ"), - (0x544, "M", "մ"), - (0x545, "M", "յ"), - (0x546, "M", "ն"), - (0x547, "M", "շ"), - (0x548, "M", "ո"), - (0x549, "M", "չ"), - (0x54A, "M", "պ"), - (0x54B, "M", "ջ"), - (0x54C, "M", "ռ"), - (0x54D, "M", "ս"), - (0x54E, "M", "վ"), - (0x54F, "M", "տ"), - (0x550, "M", "ր"), - (0x551, "M", "ց"), - (0x552, "M", "ւ"), - (0x553, "M", "փ"), - (0x554, "M", "ք"), - (0x555, "M", "օ"), - (0x556, "M", "ֆ"), - (0x557, "X"), - (0x559, "V"), - (0x587, "M", "եւ"), - (0x588, "V"), - (0x58B, "X"), - (0x58D, "V"), - (0x590, "X"), - (0x591, "V"), - (0x5C8, "X"), - (0x5D0, "V"), - (0x5EB, "X"), - (0x5EF, "V"), - (0x5F5, "X"), - (0x606, "V"), - (0x61C, "X"), - (0x61D, "V"), - ] - - -def _seg_10() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x675, "M", "اٴ"), - (0x676, "M", "وٴ"), - (0x677, "M", "ۇٴ"), - (0x678, "M", "يٴ"), - (0x679, "V"), - (0x6DD, "X"), - (0x6DE, "V"), - (0x70E, "X"), - (0x710, "V"), - (0x74B, "X"), - (0x74D, "V"), - (0x7B2, "X"), - (0x7C0, "V"), - (0x7FB, "X"), - (0x7FD, "V"), - (0x82E, "X"), - (0x830, "V"), - (0x83F, "X"), - (0x840, "V"), - (0x85C, "X"), - (0x85E, "V"), - (0x85F, "X"), - (0x860, "V"), - (0x86B, "X"), - (0x870, "V"), - (0x88F, "X"), - (0x897, "V"), - (0x8E2, "X"), - (0x8E3, "V"), - (0x958, "M", "क़"), - (0x959, "M", "ख़"), - (0x95A, "M", "ग़"), - (0x95B, "M", "ज़"), - (0x95C, "M", "ड़"), - (0x95D, "M", "ढ़"), - (0x95E, "M", "फ़"), - (0x95F, "M", "य़"), - (0x960, "V"), - (0x984, "X"), - (0x985, "V"), - (0x98D, "X"), - (0x98F, "V"), - (0x991, "X"), - (0x993, "V"), - (0x9A9, "X"), - (0x9AA, "V"), - (0x9B1, "X"), - (0x9B2, "V"), - (0x9B3, "X"), - (0x9B6, "V"), - (0x9BA, "X"), - (0x9BC, "V"), - (0x9C5, "X"), - (0x9C7, "V"), - (0x9C9, "X"), - (0x9CB, "V"), - (0x9CF, "X"), - (0x9D7, "V"), - (0x9D8, "X"), - (0x9DC, "M", "ড়"), - (0x9DD, "M", "ঢ়"), - (0x9DE, "X"), - (0x9DF, "M", "য়"), - (0x9E0, "V"), - (0x9E4, "X"), - (0x9E6, "V"), - (0x9FF, "X"), - (0xA01, "V"), - (0xA04, "X"), - (0xA05, "V"), - (0xA0B, "X"), - (0xA0F, "V"), - (0xA11, "X"), - (0xA13, "V"), - (0xA29, "X"), - (0xA2A, "V"), - (0xA31, "X"), - (0xA32, "V"), - (0xA33, "M", "ਲ਼"), - (0xA34, "X"), - (0xA35, "V"), - (0xA36, "M", "ਸ਼"), - (0xA37, "X"), - (0xA38, "V"), - (0xA3A, "X"), - (0xA3C, "V"), - (0xA3D, "X"), - (0xA3E, "V"), - (0xA43, "X"), - (0xA47, "V"), - (0xA49, "X"), - (0xA4B, "V"), - (0xA4E, "X"), - (0xA51, "V"), - (0xA52, "X"), - (0xA59, "M", "ਖ਼"), - (0xA5A, "M", "ਗ਼"), - (0xA5B, "M", "ਜ਼"), - (0xA5C, "V"), - (0xA5D, "X"), - ] - - -def _seg_11() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xA5E, "M", "ਫ਼"), - (0xA5F, "X"), - (0xA66, "V"), - (0xA77, "X"), - (0xA81, "V"), - (0xA84, "X"), - (0xA85, "V"), - (0xA8E, "X"), - (0xA8F, "V"), - (0xA92, "X"), - (0xA93, "V"), - (0xAA9, "X"), - (0xAAA, "V"), - (0xAB1, "X"), - (0xAB2, "V"), - (0xAB4, "X"), - (0xAB5, "V"), - (0xABA, "X"), - (0xABC, "V"), - (0xAC6, "X"), - (0xAC7, "V"), - (0xACA, "X"), - (0xACB, "V"), - (0xACE, "X"), - (0xAD0, "V"), - (0xAD1, "X"), - (0xAE0, "V"), - (0xAE4, "X"), - (0xAE6, "V"), - (0xAF2, "X"), - (0xAF9, "V"), - (0xB00, "X"), - (0xB01, "V"), - (0xB04, "X"), - (0xB05, "V"), - (0xB0D, "X"), - (0xB0F, "V"), - (0xB11, "X"), - (0xB13, "V"), - (0xB29, "X"), - (0xB2A, "V"), - (0xB31, "X"), - (0xB32, "V"), - (0xB34, "X"), - (0xB35, "V"), - (0xB3A, "X"), - (0xB3C, "V"), - (0xB45, "X"), - (0xB47, "V"), - (0xB49, "X"), - (0xB4B, "V"), - (0xB4E, "X"), - (0xB55, "V"), - (0xB58, "X"), - (0xB5C, "M", "ଡ଼"), - (0xB5D, "M", "ଢ଼"), - (0xB5E, "X"), - (0xB5F, "V"), - (0xB64, "X"), - (0xB66, "V"), - (0xB78, "X"), - (0xB82, "V"), - (0xB84, "X"), - (0xB85, "V"), - (0xB8B, "X"), - (0xB8E, "V"), - (0xB91, "X"), - (0xB92, "V"), - (0xB96, "X"), - (0xB99, "V"), - (0xB9B, "X"), - (0xB9C, "V"), - (0xB9D, "X"), - (0xB9E, "V"), - (0xBA0, "X"), - (0xBA3, "V"), - (0xBA5, "X"), - (0xBA8, "V"), - (0xBAB, "X"), - (0xBAE, "V"), - (0xBBA, "X"), - (0xBBE, "V"), - (0xBC3, "X"), - (0xBC6, "V"), - (0xBC9, "X"), - (0xBCA, "V"), - (0xBCE, "X"), - (0xBD0, "V"), - (0xBD1, "X"), - (0xBD7, "V"), - (0xBD8, "X"), - (0xBE6, "V"), - (0xBFB, "X"), - (0xC00, "V"), - (0xC0D, "X"), - (0xC0E, "V"), - (0xC11, "X"), - (0xC12, "V"), - (0xC29, "X"), - (0xC2A, "V"), - ] - - -def _seg_12() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xC3A, "X"), - (0xC3C, "V"), - (0xC45, "X"), - (0xC46, "V"), - (0xC49, "X"), - (0xC4A, "V"), - (0xC4E, "X"), - (0xC55, "V"), - (0xC57, "X"), - (0xC58, "V"), - (0xC5B, "X"), - (0xC5D, "V"), - (0xC5E, "X"), - (0xC60, "V"), - (0xC64, "X"), - (0xC66, "V"), - (0xC70, "X"), - (0xC77, "V"), - (0xC8D, "X"), - (0xC8E, "V"), - (0xC91, "X"), - (0xC92, "V"), - (0xCA9, "X"), - (0xCAA, "V"), - (0xCB4, "X"), - (0xCB5, "V"), - (0xCBA, "X"), - (0xCBC, "V"), - (0xCC5, "X"), - (0xCC6, "V"), - (0xCC9, "X"), - (0xCCA, "V"), - (0xCCE, "X"), - (0xCD5, "V"), - (0xCD7, "X"), - (0xCDD, "V"), - (0xCDF, "X"), - (0xCE0, "V"), - (0xCE4, "X"), - (0xCE6, "V"), - (0xCF0, "X"), - (0xCF1, "V"), - (0xCF4, "X"), - (0xD00, "V"), - (0xD0D, "X"), - (0xD0E, "V"), - (0xD11, "X"), - (0xD12, "V"), - (0xD45, "X"), - (0xD46, "V"), - (0xD49, "X"), - (0xD4A, "V"), - (0xD50, "X"), - (0xD54, "V"), - (0xD64, "X"), - (0xD66, "V"), - (0xD80, "X"), - (0xD81, "V"), - (0xD84, "X"), - (0xD85, "V"), - (0xD97, "X"), - (0xD9A, "V"), - (0xDB2, "X"), - (0xDB3, "V"), - (0xDBC, "X"), - (0xDBD, "V"), - (0xDBE, "X"), - (0xDC0, "V"), - (0xDC7, "X"), - (0xDCA, "V"), - (0xDCB, "X"), - (0xDCF, "V"), - (0xDD5, "X"), - (0xDD6, "V"), - (0xDD7, "X"), - (0xDD8, "V"), - (0xDE0, "X"), - (0xDE6, "V"), - (0xDF0, "X"), - (0xDF2, "V"), - (0xDF5, "X"), - (0xE01, "V"), - (0xE33, "M", "ํา"), - (0xE34, "V"), - (0xE3B, "X"), - (0xE3F, "V"), - (0xE5C, "X"), - (0xE81, "V"), - (0xE83, "X"), - (0xE84, "V"), - (0xE85, "X"), - (0xE86, "V"), - (0xE8B, "X"), - (0xE8C, "V"), - (0xEA4, "X"), - (0xEA5, "V"), - (0xEA6, "X"), - (0xEA7, "V"), - (0xEB3, "M", "ໍາ"), - (0xEB4, "V"), - ] - - -def _seg_13() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xEBE, "X"), - (0xEC0, "V"), - (0xEC5, "X"), - (0xEC6, "V"), - (0xEC7, "X"), - (0xEC8, "V"), - (0xECF, "X"), - (0xED0, "V"), - (0xEDA, "X"), - (0xEDC, "M", "ຫນ"), - (0xEDD, "M", "ຫມ"), - (0xEDE, "V"), - (0xEE0, "X"), - (0xF00, "V"), - (0xF0C, "M", "་"), - (0xF0D, "V"), - (0xF43, "M", "གྷ"), - (0xF44, "V"), - (0xF48, "X"), - (0xF49, "V"), - (0xF4D, "M", "ཌྷ"), - (0xF4E, "V"), - (0xF52, "M", "དྷ"), - (0xF53, "V"), - (0xF57, "M", "བྷ"), - (0xF58, "V"), - (0xF5C, "M", "ཛྷ"), - (0xF5D, "V"), - (0xF69, "M", "ཀྵ"), - (0xF6A, "V"), - (0xF6D, "X"), - (0xF71, "V"), - (0xF73, "M", "ཱི"), - (0xF74, "V"), - (0xF75, "M", "ཱུ"), - (0xF76, "M", "ྲྀ"), - (0xF77, "M", "ྲཱྀ"), - (0xF78, "M", "ླྀ"), - (0xF79, "M", "ླཱྀ"), - (0xF7A, "V"), - (0xF81, "M", "ཱྀ"), - (0xF82, "V"), - (0xF93, "M", "ྒྷ"), - (0xF94, "V"), - (0xF98, "X"), - (0xF99, "V"), - (0xF9D, "M", "ྜྷ"), - (0xF9E, "V"), - (0xFA2, "M", "ྡྷ"), - (0xFA3, "V"), - (0xFA7, "M", "ྦྷ"), - (0xFA8, "V"), - (0xFAC, "M", "ྫྷ"), - (0xFAD, "V"), - (0xFB9, "M", "ྐྵ"), - (0xFBA, "V"), - (0xFBD, "X"), - (0xFBE, "V"), - (0xFCD, "X"), - (0xFCE, "V"), - (0xFDB, "X"), - (0x1000, "V"), - (0x10A0, "M", "ⴀ"), - (0x10A1, "M", "ⴁ"), - (0x10A2, "M", "ⴂ"), - (0x10A3, "M", "ⴃ"), - (0x10A4, "M", "ⴄ"), - (0x10A5, "M", "ⴅ"), - (0x10A6, "M", "ⴆ"), - (0x10A7, "M", "ⴇ"), - (0x10A8, "M", "ⴈ"), - (0x10A9, "M", "ⴉ"), - (0x10AA, "M", "ⴊ"), - (0x10AB, "M", "ⴋ"), - (0x10AC, "M", "ⴌ"), - (0x10AD, "M", "ⴍ"), - (0x10AE, "M", "ⴎ"), - (0x10AF, "M", "ⴏ"), - (0x10B0, "M", "ⴐ"), - (0x10B1, "M", "ⴑ"), - (0x10B2, "M", "ⴒ"), - (0x10B3, "M", "ⴓ"), - (0x10B4, "M", "ⴔ"), - (0x10B5, "M", "ⴕ"), - (0x10B6, "M", "ⴖ"), - (0x10B7, "M", "ⴗ"), - (0x10B8, "M", "ⴘ"), - (0x10B9, "M", "ⴙ"), - (0x10BA, "M", "ⴚ"), - (0x10BB, "M", "ⴛ"), - (0x10BC, "M", "ⴜ"), - (0x10BD, "M", "ⴝ"), - (0x10BE, "M", "ⴞ"), - (0x10BF, "M", "ⴟ"), - (0x10C0, "M", "ⴠ"), - (0x10C1, "M", "ⴡ"), - (0x10C2, "M", "ⴢ"), - (0x10C3, "M", "ⴣ"), - (0x10C4, "M", "ⴤ"), - (0x10C5, "M", "ⴥ"), - ] - - -def _seg_14() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x10C6, "X"), - (0x10C7, "M", "ⴧ"), - (0x10C8, "X"), - (0x10CD, "M", "ⴭ"), - (0x10CE, "X"), - (0x10D0, "V"), - (0x10FC, "M", "ნ"), - (0x10FD, "V"), - (0x115F, "I"), - (0x1161, "V"), - (0x1249, "X"), - (0x124A, "V"), - (0x124E, "X"), - (0x1250, "V"), - (0x1257, "X"), - (0x1258, "V"), - (0x1259, "X"), - (0x125A, "V"), - (0x125E, "X"), - (0x1260, "V"), - (0x1289, "X"), - (0x128A, "V"), - (0x128E, "X"), - (0x1290, "V"), - (0x12B1, "X"), - (0x12B2, "V"), - (0x12B6, "X"), - (0x12B8, "V"), - (0x12BF, "X"), - (0x12C0, "V"), - (0x12C1, "X"), - (0x12C2, "V"), - (0x12C6, "X"), - (0x12C8, "V"), - (0x12D7, "X"), - (0x12D8, "V"), - (0x1311, "X"), - (0x1312, "V"), - (0x1316, "X"), - (0x1318, "V"), - (0x135B, "X"), - (0x135D, "V"), - (0x137D, "X"), - (0x1380, "V"), - (0x139A, "X"), - (0x13A0, "V"), - (0x13F6, "X"), - (0x13F8, "M", "Ᏸ"), - (0x13F9, "M", "Ᏹ"), - (0x13FA, "M", "Ᏺ"), - (0x13FB, "M", "Ᏻ"), - (0x13FC, "M", "Ᏼ"), - (0x13FD, "M", "Ᏽ"), - (0x13FE, "X"), - (0x1400, "V"), - (0x1680, "X"), - (0x1681, "V"), - (0x169D, "X"), - (0x16A0, "V"), - (0x16F9, "X"), - (0x1700, "V"), - (0x1716, "X"), - (0x171F, "V"), - (0x1737, "X"), - (0x1740, "V"), - (0x1754, "X"), - (0x1760, "V"), - (0x176D, "X"), - (0x176E, "V"), - (0x1771, "X"), - (0x1772, "V"), - (0x1774, "X"), - (0x1780, "V"), - (0x17B4, "I"), - (0x17B6, "V"), - (0x17DE, "X"), - (0x17E0, "V"), - (0x17EA, "X"), - (0x17F0, "V"), - (0x17FA, "X"), - (0x1800, "V"), - (0x180B, "I"), - (0x1810, "V"), - (0x181A, "X"), - (0x1820, "V"), - (0x1879, "X"), - (0x1880, "V"), - (0x18AB, "X"), - (0x18B0, "V"), - (0x18F6, "X"), - (0x1900, "V"), - (0x191F, "X"), - (0x1920, "V"), - (0x192C, "X"), - (0x1930, "V"), - (0x193C, "X"), - (0x1940, "V"), - (0x1941, "X"), - (0x1944, "V"), - (0x196E, "X"), - ] - - -def _seg_15() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1970, "V"), - (0x1975, "X"), - (0x1980, "V"), - (0x19AC, "X"), - (0x19B0, "V"), - (0x19CA, "X"), - (0x19D0, "V"), - (0x19DB, "X"), - (0x19DE, "V"), - (0x1A1C, "X"), - (0x1A1E, "V"), - (0x1A5F, "X"), - (0x1A60, "V"), - (0x1A7D, "X"), - (0x1A7F, "V"), - (0x1A8A, "X"), - (0x1A90, "V"), - (0x1A9A, "X"), - (0x1AA0, "V"), - (0x1AAE, "X"), - (0x1AB0, "V"), - (0x1ACF, "X"), - (0x1B00, "V"), - (0x1B4D, "X"), - (0x1B4E, "V"), - (0x1BF4, "X"), - (0x1BFC, "V"), - (0x1C38, "X"), - (0x1C3B, "V"), - (0x1C4A, "X"), - (0x1C4D, "V"), - (0x1C80, "M", "в"), - (0x1C81, "M", "д"), - (0x1C82, "M", "о"), - (0x1C83, "M", "с"), - (0x1C84, "M", "т"), - (0x1C86, "M", "ъ"), - (0x1C87, "M", "ѣ"), - (0x1C88, "M", "ꙋ"), - (0x1C89, "M", "ᲊ"), - (0x1C8A, "V"), - (0x1C8B, "X"), - (0x1C90, "M", "ა"), - (0x1C91, "M", "ბ"), - (0x1C92, "M", "გ"), - (0x1C93, "M", "დ"), - (0x1C94, "M", "ე"), - (0x1C95, "M", "ვ"), - (0x1C96, "M", "ზ"), - (0x1C97, "M", "თ"), - (0x1C98, "M", "ი"), - (0x1C99, "M", "კ"), - (0x1C9A, "M", "ლ"), - (0x1C9B, "M", "მ"), - (0x1C9C, "M", "ნ"), - (0x1C9D, "M", "ო"), - (0x1C9E, "M", "პ"), - (0x1C9F, "M", "ჟ"), - (0x1CA0, "M", "რ"), - (0x1CA1, "M", "ს"), - (0x1CA2, "M", "ტ"), - (0x1CA3, "M", "უ"), - (0x1CA4, "M", "ფ"), - (0x1CA5, "M", "ქ"), - (0x1CA6, "M", "ღ"), - (0x1CA7, "M", "ყ"), - (0x1CA8, "M", "შ"), - (0x1CA9, "M", "ჩ"), - (0x1CAA, "M", "ც"), - (0x1CAB, "M", "ძ"), - (0x1CAC, "M", "წ"), - (0x1CAD, "M", "ჭ"), - (0x1CAE, "M", "ხ"), - (0x1CAF, "M", "ჯ"), - (0x1CB0, "M", "ჰ"), - (0x1CB1, "M", "ჱ"), - (0x1CB2, "M", "ჲ"), - (0x1CB3, "M", "ჳ"), - (0x1CB4, "M", "ჴ"), - (0x1CB5, "M", "ჵ"), - (0x1CB6, "M", "ჶ"), - (0x1CB7, "M", "ჷ"), - (0x1CB8, "M", "ჸ"), - (0x1CB9, "M", "ჹ"), - (0x1CBA, "M", "ჺ"), - (0x1CBB, "X"), - (0x1CBD, "M", "ჽ"), - (0x1CBE, "M", "ჾ"), - (0x1CBF, "M", "ჿ"), - (0x1CC0, "V"), - (0x1CC8, "X"), - (0x1CD0, "V"), - (0x1CFB, "X"), - (0x1D00, "V"), - (0x1D2C, "M", "a"), - (0x1D2D, "M", "æ"), - (0x1D2E, "M", "b"), - (0x1D2F, "V"), - (0x1D30, "M", "d"), - (0x1D31, "M", "e"), - ] - - -def _seg_16() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1D32, "M", "ǝ"), - (0x1D33, "M", "g"), - (0x1D34, "M", "h"), - (0x1D35, "M", "i"), - (0x1D36, "M", "j"), - (0x1D37, "M", "k"), - (0x1D38, "M", "l"), - (0x1D39, "M", "m"), - (0x1D3A, "M", "n"), - (0x1D3B, "V"), - (0x1D3C, "M", "o"), - (0x1D3D, "M", "ȣ"), - (0x1D3E, "M", "p"), - (0x1D3F, "M", "r"), - (0x1D40, "M", "t"), - (0x1D41, "M", "u"), - (0x1D42, "M", "w"), - (0x1D43, "M", "a"), - (0x1D44, "M", "ɐ"), - (0x1D45, "M", "ɑ"), - (0x1D46, "M", "ᴂ"), - (0x1D47, "M", "b"), - (0x1D48, "M", "d"), - (0x1D49, "M", "e"), - (0x1D4A, "M", "ə"), - (0x1D4B, "M", "ɛ"), - (0x1D4C, "M", "ɜ"), - (0x1D4D, "M", "g"), - (0x1D4E, "V"), - (0x1D4F, "M", "k"), - (0x1D50, "M", "m"), - (0x1D51, "M", "ŋ"), - (0x1D52, "M", "o"), - (0x1D53, "M", "ɔ"), - (0x1D54, "M", "ᴖ"), - (0x1D55, "M", "ᴗ"), - (0x1D56, "M", "p"), - (0x1D57, "M", "t"), - (0x1D58, "M", "u"), - (0x1D59, "M", "ᴝ"), - (0x1D5A, "M", "ɯ"), - (0x1D5B, "M", "v"), - (0x1D5C, "M", "ᴥ"), - (0x1D5D, "M", "β"), - (0x1D5E, "M", "γ"), - (0x1D5F, "M", "δ"), - (0x1D60, "M", "φ"), - (0x1D61, "M", "χ"), - (0x1D62, "M", "i"), - (0x1D63, "M", "r"), - (0x1D64, "M", "u"), - (0x1D65, "M", "v"), - (0x1D66, "M", "β"), - (0x1D67, "M", "γ"), - (0x1D68, "M", "ρ"), - (0x1D69, "M", "φ"), - (0x1D6A, "M", "χ"), - (0x1D6B, "V"), - (0x1D78, "M", "н"), - (0x1D79, "V"), - (0x1D9B, "M", "ɒ"), - (0x1D9C, "M", "c"), - (0x1D9D, "M", "ɕ"), - (0x1D9E, "M", "ð"), - (0x1D9F, "M", "ɜ"), - (0x1DA0, "M", "f"), - (0x1DA1, "M", "ɟ"), - (0x1DA2, "M", "ɡ"), - (0x1DA3, "M", "ɥ"), - (0x1DA4, "M", "ɨ"), - (0x1DA5, "M", "ɩ"), - (0x1DA6, "M", "ɪ"), - (0x1DA7, "M", "ᵻ"), - (0x1DA8, "M", "ʝ"), - (0x1DA9, "M", "ɭ"), - (0x1DAA, "M", "ᶅ"), - (0x1DAB, "M", "ʟ"), - (0x1DAC, "M", "ɱ"), - (0x1DAD, "M", "ɰ"), - (0x1DAE, "M", "ɲ"), - (0x1DAF, "M", "ɳ"), - (0x1DB0, "M", "ɴ"), - (0x1DB1, "M", "ɵ"), - (0x1DB2, "M", "ɸ"), - (0x1DB3, "M", "ʂ"), - (0x1DB4, "M", "ʃ"), - (0x1DB5, "M", "ƫ"), - (0x1DB6, "M", "ʉ"), - (0x1DB7, "M", "ʊ"), - (0x1DB8, "M", "ᴜ"), - (0x1DB9, "M", "ʋ"), - (0x1DBA, "M", "ʌ"), - (0x1DBB, "M", "z"), - (0x1DBC, "M", "ʐ"), - (0x1DBD, "M", "ʑ"), - (0x1DBE, "M", "ʒ"), - (0x1DBF, "M", "θ"), - (0x1DC0, "V"), - (0x1E00, "M", "ḁ"), - (0x1E01, "V"), - ] - - -def _seg_17() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1E02, "M", "ḃ"), - (0x1E03, "V"), - (0x1E04, "M", "ḅ"), - (0x1E05, "V"), - (0x1E06, "M", "ḇ"), - (0x1E07, "V"), - (0x1E08, "M", "ḉ"), - (0x1E09, "V"), - (0x1E0A, "M", "ḋ"), - (0x1E0B, "V"), - (0x1E0C, "M", "ḍ"), - (0x1E0D, "V"), - (0x1E0E, "M", "ḏ"), - (0x1E0F, "V"), - (0x1E10, "M", "ḑ"), - (0x1E11, "V"), - (0x1E12, "M", "ḓ"), - (0x1E13, "V"), - (0x1E14, "M", "ḕ"), - (0x1E15, "V"), - (0x1E16, "M", "ḗ"), - (0x1E17, "V"), - (0x1E18, "M", "ḙ"), - (0x1E19, "V"), - (0x1E1A, "M", "ḛ"), - (0x1E1B, "V"), - (0x1E1C, "M", "ḝ"), - (0x1E1D, "V"), - (0x1E1E, "M", "ḟ"), - (0x1E1F, "V"), - (0x1E20, "M", "ḡ"), - (0x1E21, "V"), - (0x1E22, "M", "ḣ"), - (0x1E23, "V"), - (0x1E24, "M", "ḥ"), - (0x1E25, "V"), - (0x1E26, "M", "ḧ"), - (0x1E27, "V"), - (0x1E28, "M", "ḩ"), - (0x1E29, "V"), - (0x1E2A, "M", "ḫ"), - (0x1E2B, "V"), - (0x1E2C, "M", "ḭ"), - (0x1E2D, "V"), - (0x1E2E, "M", "ḯ"), - (0x1E2F, "V"), - (0x1E30, "M", "ḱ"), - (0x1E31, "V"), - (0x1E32, "M", "ḳ"), - (0x1E33, "V"), - (0x1E34, "M", "ḵ"), - (0x1E35, "V"), - (0x1E36, "M", "ḷ"), - (0x1E37, "V"), - (0x1E38, "M", "ḹ"), - (0x1E39, "V"), - (0x1E3A, "M", "ḻ"), - (0x1E3B, "V"), - (0x1E3C, "M", "ḽ"), - (0x1E3D, "V"), - (0x1E3E, "M", "ḿ"), - (0x1E3F, "V"), - (0x1E40, "M", "ṁ"), - (0x1E41, "V"), - (0x1E42, "M", "ṃ"), - (0x1E43, "V"), - (0x1E44, "M", "ṅ"), - (0x1E45, "V"), - (0x1E46, "M", "ṇ"), - (0x1E47, "V"), - (0x1E48, "M", "ṉ"), - (0x1E49, "V"), - (0x1E4A, "M", "ṋ"), - (0x1E4B, "V"), - (0x1E4C, "M", "ṍ"), - (0x1E4D, "V"), - (0x1E4E, "M", "ṏ"), - (0x1E4F, "V"), - (0x1E50, "M", "ṑ"), - (0x1E51, "V"), - (0x1E52, "M", "ṓ"), - (0x1E53, "V"), - (0x1E54, "M", "ṕ"), - (0x1E55, "V"), - (0x1E56, "M", "ṗ"), - (0x1E57, "V"), - (0x1E58, "M", "ṙ"), - (0x1E59, "V"), - (0x1E5A, "M", "ṛ"), - (0x1E5B, "V"), - (0x1E5C, "M", "ṝ"), - (0x1E5D, "V"), - (0x1E5E, "M", "ṟ"), - (0x1E5F, "V"), - (0x1E60, "M", "ṡ"), - (0x1E61, "V"), - (0x1E62, "M", "ṣ"), - (0x1E63, "V"), - (0x1E64, "M", "ṥ"), - (0x1E65, "V"), - ] - - -def _seg_18() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1E66, "M", "ṧ"), - (0x1E67, "V"), - (0x1E68, "M", "ṩ"), - (0x1E69, "V"), - (0x1E6A, "M", "ṫ"), - (0x1E6B, "V"), - (0x1E6C, "M", "ṭ"), - (0x1E6D, "V"), - (0x1E6E, "M", "ṯ"), - (0x1E6F, "V"), - (0x1E70, "M", "ṱ"), - (0x1E71, "V"), - (0x1E72, "M", "ṳ"), - (0x1E73, "V"), - (0x1E74, "M", "ṵ"), - (0x1E75, "V"), - (0x1E76, "M", "ṷ"), - (0x1E77, "V"), - (0x1E78, "M", "ṹ"), - (0x1E79, "V"), - (0x1E7A, "M", "ṻ"), - (0x1E7B, "V"), - (0x1E7C, "M", "ṽ"), - (0x1E7D, "V"), - (0x1E7E, "M", "ṿ"), - (0x1E7F, "V"), - (0x1E80, "M", "ẁ"), - (0x1E81, "V"), - (0x1E82, "M", "ẃ"), - (0x1E83, "V"), - (0x1E84, "M", "ẅ"), - (0x1E85, "V"), - (0x1E86, "M", "ẇ"), - (0x1E87, "V"), - (0x1E88, "M", "ẉ"), - (0x1E89, "V"), - (0x1E8A, "M", "ẋ"), - (0x1E8B, "V"), - (0x1E8C, "M", "ẍ"), - (0x1E8D, "V"), - (0x1E8E, "M", "ẏ"), - (0x1E8F, "V"), - (0x1E90, "M", "ẑ"), - (0x1E91, "V"), - (0x1E92, "M", "ẓ"), - (0x1E93, "V"), - (0x1E94, "M", "ẕ"), - (0x1E95, "V"), - (0x1E9A, "M", "aʾ"), - (0x1E9B, "M", "ṡ"), - (0x1E9C, "V"), - (0x1E9E, "M", "ß"), - (0x1E9F, "V"), - (0x1EA0, "M", "ạ"), - (0x1EA1, "V"), - (0x1EA2, "M", "ả"), - (0x1EA3, "V"), - (0x1EA4, "M", "ấ"), - (0x1EA5, "V"), - (0x1EA6, "M", "ầ"), - (0x1EA7, "V"), - (0x1EA8, "M", "ẩ"), - (0x1EA9, "V"), - (0x1EAA, "M", "ẫ"), - (0x1EAB, "V"), - (0x1EAC, "M", "ậ"), - (0x1EAD, "V"), - (0x1EAE, "M", "ắ"), - (0x1EAF, "V"), - (0x1EB0, "M", "ằ"), - (0x1EB1, "V"), - (0x1EB2, "M", "ẳ"), - (0x1EB3, "V"), - (0x1EB4, "M", "ẵ"), - (0x1EB5, "V"), - (0x1EB6, "M", "ặ"), - (0x1EB7, "V"), - (0x1EB8, "M", "ẹ"), - (0x1EB9, "V"), - (0x1EBA, "M", "ẻ"), - (0x1EBB, "V"), - (0x1EBC, "M", "ẽ"), - (0x1EBD, "V"), - (0x1EBE, "M", "ế"), - (0x1EBF, "V"), - (0x1EC0, "M", "ề"), - (0x1EC1, "V"), - (0x1EC2, "M", "ể"), - (0x1EC3, "V"), - (0x1EC4, "M", "ễ"), - (0x1EC5, "V"), - (0x1EC6, "M", "ệ"), - (0x1EC7, "V"), - (0x1EC8, "M", "ỉ"), - (0x1EC9, "V"), - (0x1ECA, "M", "ị"), - (0x1ECB, "V"), - (0x1ECC, "M", "ọ"), - (0x1ECD, "V"), - (0x1ECE, "M", "ỏ"), - ] - - -def _seg_19() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1ECF, "V"), - (0x1ED0, "M", "ố"), - (0x1ED1, "V"), - (0x1ED2, "M", "ồ"), - (0x1ED3, "V"), - (0x1ED4, "M", "ổ"), - (0x1ED5, "V"), - (0x1ED6, "M", "ỗ"), - (0x1ED7, "V"), - (0x1ED8, "M", "ộ"), - (0x1ED9, "V"), - (0x1EDA, "M", "ớ"), - (0x1EDB, "V"), - (0x1EDC, "M", "ờ"), - (0x1EDD, "V"), - (0x1EDE, "M", "ở"), - (0x1EDF, "V"), - (0x1EE0, "M", "ỡ"), - (0x1EE1, "V"), - (0x1EE2, "M", "ợ"), - (0x1EE3, "V"), - (0x1EE4, "M", "ụ"), - (0x1EE5, "V"), - (0x1EE6, "M", "ủ"), - (0x1EE7, "V"), - (0x1EE8, "M", "ứ"), - (0x1EE9, "V"), - (0x1EEA, "M", "ừ"), - (0x1EEB, "V"), - (0x1EEC, "M", "ử"), - (0x1EED, "V"), - (0x1EEE, "M", "ữ"), - (0x1EEF, "V"), - (0x1EF0, "M", "ự"), - (0x1EF1, "V"), - (0x1EF2, "M", "ỳ"), - (0x1EF3, "V"), - (0x1EF4, "M", "ỵ"), - (0x1EF5, "V"), - (0x1EF6, "M", "ỷ"), - (0x1EF7, "V"), - (0x1EF8, "M", "ỹ"), - (0x1EF9, "V"), - (0x1EFA, "M", "ỻ"), - (0x1EFB, "V"), - (0x1EFC, "M", "ỽ"), - (0x1EFD, "V"), - (0x1EFE, "M", "ỿ"), - (0x1EFF, "V"), - (0x1F08, "M", "ἀ"), - (0x1F09, "M", "ἁ"), - (0x1F0A, "M", "ἂ"), - (0x1F0B, "M", "ἃ"), - (0x1F0C, "M", "ἄ"), - (0x1F0D, "M", "ἅ"), - (0x1F0E, "M", "ἆ"), - (0x1F0F, "M", "ἇ"), - (0x1F10, "V"), - (0x1F16, "X"), - (0x1F18, "M", "ἐ"), - (0x1F19, "M", "ἑ"), - (0x1F1A, "M", "ἒ"), - (0x1F1B, "M", "ἓ"), - (0x1F1C, "M", "ἔ"), - (0x1F1D, "M", "ἕ"), - (0x1F1E, "X"), - (0x1F20, "V"), - (0x1F28, "M", "ἠ"), - (0x1F29, "M", "ἡ"), - (0x1F2A, "M", "ἢ"), - (0x1F2B, "M", "ἣ"), - (0x1F2C, "M", "ἤ"), - (0x1F2D, "M", "ἥ"), - (0x1F2E, "M", "ἦ"), - (0x1F2F, "M", "ἧ"), - (0x1F30, "V"), - (0x1F38, "M", "ἰ"), - (0x1F39, "M", "ἱ"), - (0x1F3A, "M", "ἲ"), - (0x1F3B, "M", "ἳ"), - (0x1F3C, "M", "ἴ"), - (0x1F3D, "M", "ἵ"), - (0x1F3E, "M", "ἶ"), - (0x1F3F, "M", "ἷ"), - (0x1F40, "V"), - (0x1F46, "X"), - (0x1F48, "M", "ὀ"), - (0x1F49, "M", "ὁ"), - (0x1F4A, "M", "ὂ"), - (0x1F4B, "M", "ὃ"), - (0x1F4C, "M", "ὄ"), - (0x1F4D, "M", "ὅ"), - (0x1F4E, "X"), - (0x1F50, "V"), - (0x1F58, "X"), - (0x1F59, "M", "ὑ"), - (0x1F5A, "X"), - (0x1F5B, "M", "ὓ"), - (0x1F5C, "X"), - (0x1F5D, "M", "ὕ"), - ] - - -def _seg_20() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1F5E, "X"), - (0x1F5F, "M", "ὗ"), - (0x1F60, "V"), - (0x1F68, "M", "ὠ"), - (0x1F69, "M", "ὡ"), - (0x1F6A, "M", "ὢ"), - (0x1F6B, "M", "ὣ"), - (0x1F6C, "M", "ὤ"), - (0x1F6D, "M", "ὥ"), - (0x1F6E, "M", "ὦ"), - (0x1F6F, "M", "ὧ"), - (0x1F70, "V"), - (0x1F71, "M", "ά"), - (0x1F72, "V"), - (0x1F73, "M", "έ"), - (0x1F74, "V"), - (0x1F75, "M", "ή"), - (0x1F76, "V"), - (0x1F77, "M", "ί"), - (0x1F78, "V"), - (0x1F79, "M", "ό"), - (0x1F7A, "V"), - (0x1F7B, "M", "ύ"), - (0x1F7C, "V"), - (0x1F7D, "M", "ώ"), - (0x1F7E, "X"), - (0x1F80, "M", "ἀι"), - (0x1F81, "M", "ἁι"), - (0x1F82, "M", "ἂι"), - (0x1F83, "M", "ἃι"), - (0x1F84, "M", "ἄι"), - (0x1F85, "M", "ἅι"), - (0x1F86, "M", "ἆι"), - (0x1F87, "M", "ἇι"), - (0x1F88, "M", "ἀι"), - (0x1F89, "M", "ἁι"), - (0x1F8A, "M", "ἂι"), - (0x1F8B, "M", "ἃι"), - (0x1F8C, "M", "ἄι"), - (0x1F8D, "M", "ἅι"), - (0x1F8E, "M", "ἆι"), - (0x1F8F, "M", "ἇι"), - (0x1F90, "M", "ἠι"), - (0x1F91, "M", "ἡι"), - (0x1F92, "M", "ἢι"), - (0x1F93, "M", "ἣι"), - (0x1F94, "M", "ἤι"), - (0x1F95, "M", "ἥι"), - (0x1F96, "M", "ἦι"), - (0x1F97, "M", "ἧι"), - (0x1F98, "M", "ἠι"), - (0x1F99, "M", "ἡι"), - (0x1F9A, "M", "ἢι"), - (0x1F9B, "M", "ἣι"), - (0x1F9C, "M", "ἤι"), - (0x1F9D, "M", "ἥι"), - (0x1F9E, "M", "ἦι"), - (0x1F9F, "M", "ἧι"), - (0x1FA0, "M", "ὠι"), - (0x1FA1, "M", "ὡι"), - (0x1FA2, "M", "ὢι"), - (0x1FA3, "M", "ὣι"), - (0x1FA4, "M", "ὤι"), - (0x1FA5, "M", "ὥι"), - (0x1FA6, "M", "ὦι"), - (0x1FA7, "M", "ὧι"), - (0x1FA8, "M", "ὠι"), - (0x1FA9, "M", "ὡι"), - (0x1FAA, "M", "ὢι"), - (0x1FAB, "M", "ὣι"), - (0x1FAC, "M", "ὤι"), - (0x1FAD, "M", "ὥι"), - (0x1FAE, "M", "ὦι"), - (0x1FAF, "M", "ὧι"), - (0x1FB0, "V"), - (0x1FB2, "M", "ὰι"), - (0x1FB3, "M", "αι"), - (0x1FB4, "M", "άι"), - (0x1FB5, "X"), - (0x1FB6, "V"), - (0x1FB7, "M", "ᾶι"), - (0x1FB8, "M", "ᾰ"), - (0x1FB9, "M", "ᾱ"), - (0x1FBA, "M", "ὰ"), - (0x1FBB, "M", "ά"), - (0x1FBC, "M", "αι"), - (0x1FBD, "M", " ̓"), - (0x1FBE, "M", "ι"), - (0x1FBF, "M", " ̓"), - (0x1FC0, "M", " ͂"), - (0x1FC1, "M", " ̈͂"), - (0x1FC2, "M", "ὴι"), - (0x1FC3, "M", "ηι"), - (0x1FC4, "M", "ήι"), - (0x1FC5, "X"), - (0x1FC6, "V"), - (0x1FC7, "M", "ῆι"), - (0x1FC8, "M", "ὲ"), - (0x1FC9, "M", "έ"), - (0x1FCA, "M", "ὴ"), - ] - - -def _seg_21() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1FCB, "M", "ή"), - (0x1FCC, "M", "ηι"), - (0x1FCD, "M", " ̓̀"), - (0x1FCE, "M", " ̓́"), - (0x1FCF, "M", " ̓͂"), - (0x1FD0, "V"), - (0x1FD3, "M", "ΐ"), - (0x1FD4, "X"), - (0x1FD6, "V"), - (0x1FD8, "M", "ῐ"), - (0x1FD9, "M", "ῑ"), - (0x1FDA, "M", "ὶ"), - (0x1FDB, "M", "ί"), - (0x1FDC, "X"), - (0x1FDD, "M", " ̔̀"), - (0x1FDE, "M", " ̔́"), - (0x1FDF, "M", " ̔͂"), - (0x1FE0, "V"), - (0x1FE3, "M", "ΰ"), - (0x1FE4, "V"), - (0x1FE8, "M", "ῠ"), - (0x1FE9, "M", "ῡ"), - (0x1FEA, "M", "ὺ"), - (0x1FEB, "M", "ύ"), - (0x1FEC, "M", "ῥ"), - (0x1FED, "M", " ̈̀"), - (0x1FEE, "M", " ̈́"), - (0x1FEF, "M", "`"), - (0x1FF0, "X"), - (0x1FF2, "M", "ὼι"), - (0x1FF3, "M", "ωι"), - (0x1FF4, "M", "ώι"), - (0x1FF5, "X"), - (0x1FF6, "V"), - (0x1FF7, "M", "ῶι"), - (0x1FF8, "M", "ὸ"), - (0x1FF9, "M", "ό"), - (0x1FFA, "M", "ὼ"), - (0x1FFB, "M", "ώ"), - (0x1FFC, "M", "ωι"), - (0x1FFD, "M", " ́"), - (0x1FFE, "M", " ̔"), - (0x1FFF, "X"), - (0x2000, "M", " "), - (0x200B, "I"), - (0x200C, "D", ""), - (0x200E, "X"), - (0x2010, "V"), - (0x2011, "M", "‐"), - (0x2012, "V"), - (0x2017, "M", " ̳"), - (0x2018, "V"), - (0x2024, "X"), - (0x2027, "V"), - (0x2028, "X"), - (0x202F, "M", " "), - (0x2030, "V"), - (0x2033, "M", "′′"), - (0x2034, "M", "′′′"), - (0x2035, "V"), - (0x2036, "M", "‵‵"), - (0x2037, "M", "‵‵‵"), - (0x2038, "V"), - (0x203C, "M", "!!"), - (0x203D, "V"), - (0x203E, "M", " ̅"), - (0x203F, "V"), - (0x2047, "M", "??"), - (0x2048, "M", "?!"), - (0x2049, "M", "!?"), - (0x204A, "V"), - (0x2057, "M", "′′′′"), - (0x2058, "V"), - (0x205F, "M", " "), - (0x2060, "I"), - (0x2065, "X"), - (0x206A, "I"), - (0x2070, "M", "0"), - (0x2071, "M", "i"), - (0x2072, "X"), - (0x2074, "M", "4"), - (0x2075, "M", "5"), - (0x2076, "M", "6"), - (0x2077, "M", "7"), - (0x2078, "M", "8"), - (0x2079, "M", "9"), - (0x207A, "M", "+"), - (0x207B, "M", "−"), - (0x207C, "M", "="), - (0x207D, "M", "("), - (0x207E, "M", ")"), - (0x207F, "M", "n"), - (0x2080, "M", "0"), - (0x2081, "M", "1"), - (0x2082, "M", "2"), - (0x2083, "M", "3"), - (0x2084, "M", "4"), - (0x2085, "M", "5"), - (0x2086, "M", "6"), - (0x2087, "M", "7"), - ] - - -def _seg_22() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x2088, "M", "8"), - (0x2089, "M", "9"), - (0x208A, "M", "+"), - (0x208B, "M", "−"), - (0x208C, "M", "="), - (0x208D, "M", "("), - (0x208E, "M", ")"), - (0x208F, "X"), - (0x2090, "M", "a"), - (0x2091, "M", "e"), - (0x2092, "M", "o"), - (0x2093, "M", "x"), - (0x2094, "M", "ə"), - (0x2095, "M", "h"), - (0x2096, "M", "k"), - (0x2097, "M", "l"), - (0x2098, "M", "m"), - (0x2099, "M", "n"), - (0x209A, "M", "p"), - (0x209B, "M", "s"), - (0x209C, "M", "t"), - (0x209D, "X"), - (0x20A0, "V"), - (0x20A8, "M", "rs"), - (0x20A9, "V"), - (0x20C1, "X"), - (0x20D0, "V"), - (0x20F1, "X"), - (0x2100, "M", "a/c"), - (0x2101, "M", "a/s"), - (0x2102, "M", "c"), - (0x2103, "M", "°c"), - (0x2104, "V"), - (0x2105, "M", "c/o"), - (0x2106, "M", "c/u"), - (0x2107, "M", "ɛ"), - (0x2108, "V"), - (0x2109, "M", "°f"), - (0x210A, "M", "g"), - (0x210B, "M", "h"), - (0x210F, "M", "ħ"), - (0x2110, "M", "i"), - (0x2112, "M", "l"), - (0x2114, "V"), - (0x2115, "M", "n"), - (0x2116, "M", "no"), - (0x2117, "V"), - (0x2119, "M", "p"), - (0x211A, "M", "q"), - (0x211B, "M", "r"), - (0x211E, "V"), - (0x2120, "M", "sm"), - (0x2121, "M", "tel"), - (0x2122, "M", "tm"), - (0x2123, "V"), - (0x2124, "M", "z"), - (0x2125, "V"), - (0x2126, "M", "ω"), - (0x2127, "V"), - (0x2128, "M", "z"), - (0x2129, "V"), - (0x212A, "M", "k"), - (0x212B, "M", "å"), - (0x212C, "M", "b"), - (0x212D, "M", "c"), - (0x212E, "V"), - (0x212F, "M", "e"), - (0x2131, "M", "f"), - (0x2132, "M", "ⅎ"), - (0x2133, "M", "m"), - (0x2134, "M", "o"), - (0x2135, "M", "א"), - (0x2136, "M", "ב"), - (0x2137, "M", "ג"), - (0x2138, "M", "ד"), - (0x2139, "M", "i"), - (0x213A, "V"), - (0x213B, "M", "fax"), - (0x213C, "M", "π"), - (0x213D, "M", "γ"), - (0x213F, "M", "π"), - (0x2140, "M", "∑"), - (0x2141, "V"), - (0x2145, "M", "d"), - (0x2147, "M", "e"), - (0x2148, "M", "i"), - (0x2149, "M", "j"), - (0x214A, "V"), - (0x2150, "M", "1⁄7"), - (0x2151, "M", "1⁄9"), - (0x2152, "M", "1⁄10"), - (0x2153, "M", "1⁄3"), - (0x2154, "M", "2⁄3"), - (0x2155, "M", "1⁄5"), - (0x2156, "M", "2⁄5"), - (0x2157, "M", "3⁄5"), - (0x2158, "M", "4⁄5"), - (0x2159, "M", "1⁄6"), - (0x215A, "M", "5⁄6"), - (0x215B, "M", "1⁄8"), - ] - - -def _seg_23() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x215C, "M", "3⁄8"), - (0x215D, "M", "5⁄8"), - (0x215E, "M", "7⁄8"), - (0x215F, "M", "1⁄"), - (0x2160, "M", "i"), - (0x2161, "M", "ii"), - (0x2162, "M", "iii"), - (0x2163, "M", "iv"), - (0x2164, "M", "v"), - (0x2165, "M", "vi"), - (0x2166, "M", "vii"), - (0x2167, "M", "viii"), - (0x2168, "M", "ix"), - (0x2169, "M", "x"), - (0x216A, "M", "xi"), - (0x216B, "M", "xii"), - (0x216C, "M", "l"), - (0x216D, "M", "c"), - (0x216E, "M", "d"), - (0x216F, "M", "m"), - (0x2170, "M", "i"), - (0x2171, "M", "ii"), - (0x2172, "M", "iii"), - (0x2173, "M", "iv"), - (0x2174, "M", "v"), - (0x2175, "M", "vi"), - (0x2176, "M", "vii"), - (0x2177, "M", "viii"), - (0x2178, "M", "ix"), - (0x2179, "M", "x"), - (0x217A, "M", "xi"), - (0x217B, "M", "xii"), - (0x217C, "M", "l"), - (0x217D, "M", "c"), - (0x217E, "M", "d"), - (0x217F, "M", "m"), - (0x2180, "V"), - (0x2183, "M", "ↄ"), - (0x2184, "V"), - (0x2189, "M", "0⁄3"), - (0x218A, "V"), - (0x218C, "X"), - (0x2190, "V"), - (0x222C, "M", "∫∫"), - (0x222D, "M", "∫∫∫"), - (0x222E, "V"), - (0x222F, "M", "∮∮"), - (0x2230, "M", "∮∮∮"), - (0x2231, "V"), - (0x2329, "M", "〈"), - (0x232A, "M", "〉"), - (0x232B, "V"), - (0x242A, "X"), - (0x2440, "V"), - (0x244B, "X"), - (0x2460, "M", "1"), - (0x2461, "M", "2"), - (0x2462, "M", "3"), - (0x2463, "M", "4"), - (0x2464, "M", "5"), - (0x2465, "M", "6"), - (0x2466, "M", "7"), - (0x2467, "M", "8"), - (0x2468, "M", "9"), - (0x2469, "M", "10"), - (0x246A, "M", "11"), - (0x246B, "M", "12"), - (0x246C, "M", "13"), - (0x246D, "M", "14"), - (0x246E, "M", "15"), - (0x246F, "M", "16"), - (0x2470, "M", "17"), - (0x2471, "M", "18"), - (0x2472, "M", "19"), - (0x2473, "M", "20"), - (0x2474, "M", "(1)"), - (0x2475, "M", "(2)"), - (0x2476, "M", "(3)"), - (0x2477, "M", "(4)"), - (0x2478, "M", "(5)"), - (0x2479, "M", "(6)"), - (0x247A, "M", "(7)"), - (0x247B, "M", "(8)"), - (0x247C, "M", "(9)"), - (0x247D, "M", "(10)"), - (0x247E, "M", "(11)"), - (0x247F, "M", "(12)"), - (0x2480, "M", "(13)"), - (0x2481, "M", "(14)"), - (0x2482, "M", "(15)"), - (0x2483, "M", "(16)"), - (0x2484, "M", "(17)"), - (0x2485, "M", "(18)"), - (0x2486, "M", "(19)"), - (0x2487, "M", "(20)"), - (0x2488, "X"), - (0x249C, "M", "(a)"), - (0x249D, "M", "(b)"), - (0x249E, "M", "(c)"), - (0x249F, "M", "(d)"), - ] - - -def _seg_24() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x24A0, "M", "(e)"), - (0x24A1, "M", "(f)"), - (0x24A2, "M", "(g)"), - (0x24A3, "M", "(h)"), - (0x24A4, "M", "(i)"), - (0x24A5, "M", "(j)"), - (0x24A6, "M", "(k)"), - (0x24A7, "M", "(l)"), - (0x24A8, "M", "(m)"), - (0x24A9, "M", "(n)"), - (0x24AA, "M", "(o)"), - (0x24AB, "M", "(p)"), - (0x24AC, "M", "(q)"), - (0x24AD, "M", "(r)"), - (0x24AE, "M", "(s)"), - (0x24AF, "M", "(t)"), - (0x24B0, "M", "(u)"), - (0x24B1, "M", "(v)"), - (0x24B2, "M", "(w)"), - (0x24B3, "M", "(x)"), - (0x24B4, "M", "(y)"), - (0x24B5, "M", "(z)"), - (0x24B6, "M", "a"), - (0x24B7, "M", "b"), - (0x24B8, "M", "c"), - (0x24B9, "M", "d"), - (0x24BA, "M", "e"), - (0x24BB, "M", "f"), - (0x24BC, "M", "g"), - (0x24BD, "M", "h"), - (0x24BE, "M", "i"), - (0x24BF, "M", "j"), - (0x24C0, "M", "k"), - (0x24C1, "M", "l"), - (0x24C2, "M", "m"), - (0x24C3, "M", "n"), - (0x24C4, "M", "o"), - (0x24C5, "M", "p"), - (0x24C6, "M", "q"), - (0x24C7, "M", "r"), - (0x24C8, "M", "s"), - (0x24C9, "M", "t"), - (0x24CA, "M", "u"), - (0x24CB, "M", "v"), - (0x24CC, "M", "w"), - (0x24CD, "M", "x"), - (0x24CE, "M", "y"), - (0x24CF, "M", "z"), - (0x24D0, "M", "a"), - (0x24D1, "M", "b"), - (0x24D2, "M", "c"), - (0x24D3, "M", "d"), - (0x24D4, "M", "e"), - (0x24D5, "M", "f"), - (0x24D6, "M", "g"), - (0x24D7, "M", "h"), - (0x24D8, "M", "i"), - (0x24D9, "M", "j"), - (0x24DA, "M", "k"), - (0x24DB, "M", "l"), - (0x24DC, "M", "m"), - (0x24DD, "M", "n"), - (0x24DE, "M", "o"), - (0x24DF, "M", "p"), - (0x24E0, "M", "q"), - (0x24E1, "M", "r"), - (0x24E2, "M", "s"), - (0x24E3, "M", "t"), - (0x24E4, "M", "u"), - (0x24E5, "M", "v"), - (0x24E6, "M", "w"), - (0x24E7, "M", "x"), - (0x24E8, "M", "y"), - (0x24E9, "M", "z"), - (0x24EA, "M", "0"), - (0x24EB, "V"), - (0x2A0C, "M", "∫∫∫∫"), - (0x2A0D, "V"), - (0x2A74, "M", "::="), - (0x2A75, "M", "=="), - (0x2A76, "M", "==="), - (0x2A77, "V"), - (0x2ADC, "M", "⫝̸"), - (0x2ADD, "V"), - (0x2B74, "X"), - (0x2B76, "V"), - (0x2B96, "X"), - (0x2B97, "V"), - (0x2C00, "M", "ⰰ"), - (0x2C01, "M", "ⰱ"), - (0x2C02, "M", "ⰲ"), - (0x2C03, "M", "ⰳ"), - (0x2C04, "M", "ⰴ"), - (0x2C05, "M", "ⰵ"), - (0x2C06, "M", "ⰶ"), - (0x2C07, "M", "ⰷ"), - (0x2C08, "M", "ⰸ"), - (0x2C09, "M", "ⰹ"), - (0x2C0A, "M", "ⰺ"), - (0x2C0B, "M", "ⰻ"), - ] - - -def _seg_25() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x2C0C, "M", "ⰼ"), - (0x2C0D, "M", "ⰽ"), - (0x2C0E, "M", "ⰾ"), - (0x2C0F, "M", "ⰿ"), - (0x2C10, "M", "ⱀ"), - (0x2C11, "M", "ⱁ"), - (0x2C12, "M", "ⱂ"), - (0x2C13, "M", "ⱃ"), - (0x2C14, "M", "ⱄ"), - (0x2C15, "M", "ⱅ"), - (0x2C16, "M", "ⱆ"), - (0x2C17, "M", "ⱇ"), - (0x2C18, "M", "ⱈ"), - (0x2C19, "M", "ⱉ"), - (0x2C1A, "M", "ⱊ"), - (0x2C1B, "M", "ⱋ"), - (0x2C1C, "M", "ⱌ"), - (0x2C1D, "M", "ⱍ"), - (0x2C1E, "M", "ⱎ"), - (0x2C1F, "M", "ⱏ"), - (0x2C20, "M", "ⱐ"), - (0x2C21, "M", "ⱑ"), - (0x2C22, "M", "ⱒ"), - (0x2C23, "M", "ⱓ"), - (0x2C24, "M", "ⱔ"), - (0x2C25, "M", "ⱕ"), - (0x2C26, "M", "ⱖ"), - (0x2C27, "M", "ⱗ"), - (0x2C28, "M", "ⱘ"), - (0x2C29, "M", "ⱙ"), - (0x2C2A, "M", "ⱚ"), - (0x2C2B, "M", "ⱛ"), - (0x2C2C, "M", "ⱜ"), - (0x2C2D, "M", "ⱝ"), - (0x2C2E, "M", "ⱞ"), - (0x2C2F, "M", "ⱟ"), - (0x2C30, "V"), - (0x2C60, "M", "ⱡ"), - (0x2C61, "V"), - (0x2C62, "M", "ɫ"), - (0x2C63, "M", "ᵽ"), - (0x2C64, "M", "ɽ"), - (0x2C65, "V"), - (0x2C67, "M", "ⱨ"), - (0x2C68, "V"), - (0x2C69, "M", "ⱪ"), - (0x2C6A, "V"), - (0x2C6B, "M", "ⱬ"), - (0x2C6C, "V"), - (0x2C6D, "M", "ɑ"), - (0x2C6E, "M", "ɱ"), - (0x2C6F, "M", "ɐ"), - (0x2C70, "M", "ɒ"), - (0x2C71, "V"), - (0x2C72, "M", "ⱳ"), - (0x2C73, "V"), - (0x2C75, "M", "ⱶ"), - (0x2C76, "V"), - (0x2C7C, "M", "j"), - (0x2C7D, "M", "v"), - (0x2C7E, "M", "ȿ"), - (0x2C7F, "M", "ɀ"), - (0x2C80, "M", "ⲁ"), - (0x2C81, "V"), - (0x2C82, "M", "ⲃ"), - (0x2C83, "V"), - (0x2C84, "M", "ⲅ"), - (0x2C85, "V"), - (0x2C86, "M", "ⲇ"), - (0x2C87, "V"), - (0x2C88, "M", "ⲉ"), - (0x2C89, "V"), - (0x2C8A, "M", "ⲋ"), - (0x2C8B, "V"), - (0x2C8C, "M", "ⲍ"), - (0x2C8D, "V"), - (0x2C8E, "M", "ⲏ"), - (0x2C8F, "V"), - (0x2C90, "M", "ⲑ"), - (0x2C91, "V"), - (0x2C92, "M", "ⲓ"), - (0x2C93, "V"), - (0x2C94, "M", "ⲕ"), - (0x2C95, "V"), - (0x2C96, "M", "ⲗ"), - (0x2C97, "V"), - (0x2C98, "M", "ⲙ"), - (0x2C99, "V"), - (0x2C9A, "M", "ⲛ"), - (0x2C9B, "V"), - (0x2C9C, "M", "ⲝ"), - (0x2C9D, "V"), - (0x2C9E, "M", "ⲟ"), - (0x2C9F, "V"), - (0x2CA0, "M", "ⲡ"), - (0x2CA1, "V"), - (0x2CA2, "M", "ⲣ"), - (0x2CA3, "V"), - (0x2CA4, "M", "ⲥ"), - (0x2CA5, "V"), - ] - - -def _seg_26() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x2CA6, "M", "ⲧ"), - (0x2CA7, "V"), - (0x2CA8, "M", "ⲩ"), - (0x2CA9, "V"), - (0x2CAA, "M", "ⲫ"), - (0x2CAB, "V"), - (0x2CAC, "M", "ⲭ"), - (0x2CAD, "V"), - (0x2CAE, "M", "ⲯ"), - (0x2CAF, "V"), - (0x2CB0, "M", "ⲱ"), - (0x2CB1, "V"), - (0x2CB2, "M", "ⲳ"), - (0x2CB3, "V"), - (0x2CB4, "M", "ⲵ"), - (0x2CB5, "V"), - (0x2CB6, "M", "ⲷ"), - (0x2CB7, "V"), - (0x2CB8, "M", "ⲹ"), - (0x2CB9, "V"), - (0x2CBA, "M", "ⲻ"), - (0x2CBB, "V"), - (0x2CBC, "M", "ⲽ"), - (0x2CBD, "V"), - (0x2CBE, "M", "ⲿ"), - (0x2CBF, "V"), - (0x2CC0, "M", "ⳁ"), - (0x2CC1, "V"), - (0x2CC2, "M", "ⳃ"), - (0x2CC3, "V"), - (0x2CC4, "M", "ⳅ"), - (0x2CC5, "V"), - (0x2CC6, "M", "ⳇ"), - (0x2CC7, "V"), - (0x2CC8, "M", "ⳉ"), - (0x2CC9, "V"), - (0x2CCA, "M", "ⳋ"), - (0x2CCB, "V"), - (0x2CCC, "M", "ⳍ"), - (0x2CCD, "V"), - (0x2CCE, "M", "ⳏ"), - (0x2CCF, "V"), - (0x2CD0, "M", "ⳑ"), - (0x2CD1, "V"), - (0x2CD2, "M", "ⳓ"), - (0x2CD3, "V"), - (0x2CD4, "M", "ⳕ"), - (0x2CD5, "V"), - (0x2CD6, "M", "ⳗ"), - (0x2CD7, "V"), - (0x2CD8, "M", "ⳙ"), - (0x2CD9, "V"), - (0x2CDA, "M", "ⳛ"), - (0x2CDB, "V"), - (0x2CDC, "M", "ⳝ"), - (0x2CDD, "V"), - (0x2CDE, "M", "ⳟ"), - (0x2CDF, "V"), - (0x2CE0, "M", "ⳡ"), - (0x2CE1, "V"), - (0x2CE2, "M", "ⳣ"), - (0x2CE3, "V"), - (0x2CEB, "M", "ⳬ"), - (0x2CEC, "V"), - (0x2CED, "M", "ⳮ"), - (0x2CEE, "V"), - (0x2CF2, "M", "ⳳ"), - (0x2CF3, "V"), - (0x2CF4, "X"), - (0x2CF9, "V"), - (0x2D26, "X"), - (0x2D27, "V"), - (0x2D28, "X"), - (0x2D2D, "V"), - (0x2D2E, "X"), - (0x2D30, "V"), - (0x2D68, "X"), - (0x2D6F, "M", "ⵡ"), - (0x2D70, "V"), - (0x2D71, "X"), - (0x2D7F, "V"), - (0x2D97, "X"), - (0x2DA0, "V"), - (0x2DA7, "X"), - (0x2DA8, "V"), - (0x2DAF, "X"), - (0x2DB0, "V"), - (0x2DB7, "X"), - (0x2DB8, "V"), - (0x2DBF, "X"), - (0x2DC0, "V"), - (0x2DC7, "X"), - (0x2DC8, "V"), - (0x2DCF, "X"), - (0x2DD0, "V"), - (0x2DD7, "X"), - (0x2DD8, "V"), - (0x2DDF, "X"), - (0x2DE0, "V"), - (0x2E5E, "X"), - ] - - -def _seg_27() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x2E80, "V"), - (0x2E9A, "X"), - (0x2E9B, "V"), - (0x2E9F, "M", "母"), - (0x2EA0, "V"), - (0x2EF3, "M", "龟"), - (0x2EF4, "X"), - (0x2F00, "M", "一"), - (0x2F01, "M", "丨"), - (0x2F02, "M", "丶"), - (0x2F03, "M", "丿"), - (0x2F04, "M", "乙"), - (0x2F05, "M", "亅"), - (0x2F06, "M", "二"), - (0x2F07, "M", "亠"), - (0x2F08, "M", "人"), - (0x2F09, "M", "儿"), - (0x2F0A, "M", "入"), - (0x2F0B, "M", "八"), - (0x2F0C, "M", "冂"), - (0x2F0D, "M", "冖"), - (0x2F0E, "M", "冫"), - (0x2F0F, "M", "几"), - (0x2F10, "M", "凵"), - (0x2F11, "M", "刀"), - (0x2F12, "M", "力"), - (0x2F13, "M", "勹"), - (0x2F14, "M", "匕"), - (0x2F15, "M", "匚"), - (0x2F16, "M", "匸"), - (0x2F17, "M", "十"), - (0x2F18, "M", "卜"), - (0x2F19, "M", "卩"), - (0x2F1A, "M", "厂"), - (0x2F1B, "M", "厶"), - (0x2F1C, "M", "又"), - (0x2F1D, "M", "口"), - (0x2F1E, "M", "囗"), - (0x2F1F, "M", "土"), - (0x2F20, "M", "士"), - (0x2F21, "M", "夂"), - (0x2F22, "M", "夊"), - (0x2F23, "M", "夕"), - (0x2F24, "M", "大"), - (0x2F25, "M", "女"), - (0x2F26, "M", "子"), - (0x2F27, "M", "宀"), - (0x2F28, "M", "寸"), - (0x2F29, "M", "小"), - (0x2F2A, "M", "尢"), - (0x2F2B, "M", "尸"), - (0x2F2C, "M", "屮"), - (0x2F2D, "M", "山"), - (0x2F2E, "M", "巛"), - (0x2F2F, "M", "工"), - (0x2F30, "M", "己"), - (0x2F31, "M", "巾"), - (0x2F32, "M", "干"), - (0x2F33, "M", "幺"), - (0x2F34, "M", "广"), - (0x2F35, "M", "廴"), - (0x2F36, "M", "廾"), - (0x2F37, "M", "弋"), - (0x2F38, "M", "弓"), - (0x2F39, "M", "彐"), - (0x2F3A, "M", "彡"), - (0x2F3B, "M", "彳"), - (0x2F3C, "M", "心"), - (0x2F3D, "M", "戈"), - (0x2F3E, "M", "戶"), - (0x2F3F, "M", "手"), - (0x2F40, "M", "支"), - (0x2F41, "M", "攴"), - (0x2F42, "M", "文"), - (0x2F43, "M", "斗"), - (0x2F44, "M", "斤"), - (0x2F45, "M", "方"), - (0x2F46, "M", "无"), - (0x2F47, "M", "日"), - (0x2F48, "M", "曰"), - (0x2F49, "M", "月"), - (0x2F4A, "M", "木"), - (0x2F4B, "M", "欠"), - (0x2F4C, "M", "止"), - (0x2F4D, "M", "歹"), - (0x2F4E, "M", "殳"), - (0x2F4F, "M", "毋"), - (0x2F50, "M", "比"), - (0x2F51, "M", "毛"), - (0x2F52, "M", "氏"), - (0x2F53, "M", "气"), - (0x2F54, "M", "水"), - (0x2F55, "M", "火"), - (0x2F56, "M", "爪"), - (0x2F57, "M", "父"), - (0x2F58, "M", "爻"), - (0x2F59, "M", "爿"), - (0x2F5A, "M", "片"), - (0x2F5B, "M", "牙"), - (0x2F5C, "M", "牛"), - ] - - -def _seg_28() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x2F5D, "M", "犬"), - (0x2F5E, "M", "玄"), - (0x2F5F, "M", "玉"), - (0x2F60, "M", "瓜"), - (0x2F61, "M", "瓦"), - (0x2F62, "M", "甘"), - (0x2F63, "M", "生"), - (0x2F64, "M", "用"), - (0x2F65, "M", "田"), - (0x2F66, "M", "疋"), - (0x2F67, "M", "疒"), - (0x2F68, "M", "癶"), - (0x2F69, "M", "白"), - (0x2F6A, "M", "皮"), - (0x2F6B, "M", "皿"), - (0x2F6C, "M", "目"), - (0x2F6D, "M", "矛"), - (0x2F6E, "M", "矢"), - (0x2F6F, "M", "石"), - (0x2F70, "M", "示"), - (0x2F71, "M", "禸"), - (0x2F72, "M", "禾"), - (0x2F73, "M", "穴"), - (0x2F74, "M", "立"), - (0x2F75, "M", "竹"), - (0x2F76, "M", "米"), - (0x2F77, "M", "糸"), - (0x2F78, "M", "缶"), - (0x2F79, "M", "网"), - (0x2F7A, "M", "羊"), - (0x2F7B, "M", "羽"), - (0x2F7C, "M", "老"), - (0x2F7D, "M", "而"), - (0x2F7E, "M", "耒"), - (0x2F7F, "M", "耳"), - (0x2F80, "M", "聿"), - (0x2F81, "M", "肉"), - (0x2F82, "M", "臣"), - (0x2F83, "M", "自"), - (0x2F84, "M", "至"), - (0x2F85, "M", "臼"), - (0x2F86, "M", "舌"), - (0x2F87, "M", "舛"), - (0x2F88, "M", "舟"), - (0x2F89, "M", "艮"), - (0x2F8A, "M", "色"), - (0x2F8B, "M", "艸"), - (0x2F8C, "M", "虍"), - (0x2F8D, "M", "虫"), - (0x2F8E, "M", "血"), - (0x2F8F, "M", "行"), - (0x2F90, "M", "衣"), - (0x2F91, "M", "襾"), - (0x2F92, "M", "見"), - (0x2F93, "M", "角"), - (0x2F94, "M", "言"), - (0x2F95, "M", "谷"), - (0x2F96, "M", "豆"), - (0x2F97, "M", "豕"), - (0x2F98, "M", "豸"), - (0x2F99, "M", "貝"), - (0x2F9A, "M", "赤"), - (0x2F9B, "M", "走"), - (0x2F9C, "M", "足"), - (0x2F9D, "M", "身"), - (0x2F9E, "M", "車"), - (0x2F9F, "M", "辛"), - (0x2FA0, "M", "辰"), - (0x2FA1, "M", "辵"), - (0x2FA2, "M", "邑"), - (0x2FA3, "M", "酉"), - (0x2FA4, "M", "釆"), - (0x2FA5, "M", "里"), - (0x2FA6, "M", "金"), - (0x2FA7, "M", "長"), - (0x2FA8, "M", "門"), - (0x2FA9, "M", "阜"), - (0x2FAA, "M", "隶"), - (0x2FAB, "M", "隹"), - (0x2FAC, "M", "雨"), - (0x2FAD, "M", "靑"), - (0x2FAE, "M", "非"), - (0x2FAF, "M", "面"), - (0x2FB0, "M", "革"), - (0x2FB1, "M", "韋"), - (0x2FB2, "M", "韭"), - (0x2FB3, "M", "音"), - (0x2FB4, "M", "頁"), - (0x2FB5, "M", "風"), - (0x2FB6, "M", "飛"), - (0x2FB7, "M", "食"), - (0x2FB8, "M", "首"), - (0x2FB9, "M", "香"), - (0x2FBA, "M", "馬"), - (0x2FBB, "M", "骨"), - (0x2FBC, "M", "高"), - (0x2FBD, "M", "髟"), - (0x2FBE, "M", "鬥"), - (0x2FBF, "M", "鬯"), - (0x2FC0, "M", "鬲"), - ] - - -def _seg_29() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x2FC1, "M", "鬼"), - (0x2FC2, "M", "魚"), - (0x2FC3, "M", "鳥"), - (0x2FC4, "M", "鹵"), - (0x2FC5, "M", "鹿"), - (0x2FC6, "M", "麥"), - (0x2FC7, "M", "麻"), - (0x2FC8, "M", "黃"), - (0x2FC9, "M", "黍"), - (0x2FCA, "M", "黑"), - (0x2FCB, "M", "黹"), - (0x2FCC, "M", "黽"), - (0x2FCD, "M", "鼎"), - (0x2FCE, "M", "鼓"), - (0x2FCF, "M", "鼠"), - (0x2FD0, "M", "鼻"), - (0x2FD1, "M", "齊"), - (0x2FD2, "M", "齒"), - (0x2FD3, "M", "龍"), - (0x2FD4, "M", "龜"), - (0x2FD5, "M", "龠"), - (0x2FD6, "X"), - (0x3000, "M", " "), - (0x3001, "V"), - (0x3002, "M", "."), - (0x3003, "V"), - (0x3036, "M", "〒"), - (0x3037, "V"), - (0x3038, "M", "十"), - (0x3039, "M", "卄"), - (0x303A, "M", "卅"), - (0x303B, "V"), - (0x3040, "X"), - (0x3041, "V"), - (0x3097, "X"), - (0x3099, "V"), - (0x309B, "M", " ゙"), - (0x309C, "M", " ゚"), - (0x309D, "V"), - (0x309F, "M", "より"), - (0x30A0, "V"), - (0x30FF, "M", "コト"), - (0x3100, "X"), - (0x3105, "V"), - (0x3130, "X"), - (0x3131, "M", "ᄀ"), - (0x3132, "M", "ᄁ"), - (0x3133, "M", "ᆪ"), - (0x3134, "M", "ᄂ"), - (0x3135, "M", "ᆬ"), - (0x3136, "M", "ᆭ"), - (0x3137, "M", "ᄃ"), - (0x3138, "M", "ᄄ"), - (0x3139, "M", "ᄅ"), - (0x313A, "M", "ᆰ"), - (0x313B, "M", "ᆱ"), - (0x313C, "M", "ᆲ"), - (0x313D, "M", "ᆳ"), - (0x313E, "M", "ᆴ"), - (0x313F, "M", "ᆵ"), - (0x3140, "M", "ᄚ"), - (0x3141, "M", "ᄆ"), - (0x3142, "M", "ᄇ"), - (0x3143, "M", "ᄈ"), - (0x3144, "M", "ᄡ"), - (0x3145, "M", "ᄉ"), - (0x3146, "M", "ᄊ"), - (0x3147, "M", "ᄋ"), - (0x3148, "M", "ᄌ"), - (0x3149, "M", "ᄍ"), - (0x314A, "M", "ᄎ"), - (0x314B, "M", "ᄏ"), - (0x314C, "M", "ᄐ"), - (0x314D, "M", "ᄑ"), - (0x314E, "M", "ᄒ"), - (0x314F, "M", "ᅡ"), - (0x3150, "M", "ᅢ"), - (0x3151, "M", "ᅣ"), - (0x3152, "M", "ᅤ"), - (0x3153, "M", "ᅥ"), - (0x3154, "M", "ᅦ"), - (0x3155, "M", "ᅧ"), - (0x3156, "M", "ᅨ"), - (0x3157, "M", "ᅩ"), - (0x3158, "M", "ᅪ"), - (0x3159, "M", "ᅫ"), - (0x315A, "M", "ᅬ"), - (0x315B, "M", "ᅭ"), - (0x315C, "M", "ᅮ"), - (0x315D, "M", "ᅯ"), - (0x315E, "M", "ᅰ"), - (0x315F, "M", "ᅱ"), - (0x3160, "M", "ᅲ"), - (0x3161, "M", "ᅳ"), - (0x3162, "M", "ᅴ"), - (0x3163, "M", "ᅵ"), - (0x3164, "I"), - (0x3165, "M", "ᄔ"), - (0x3166, "M", "ᄕ"), - (0x3167, "M", "ᇇ"), - ] - - -def _seg_30() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x3168, "M", "ᇈ"), - (0x3169, "M", "ᇌ"), - (0x316A, "M", "ᇎ"), - (0x316B, "M", "ᇓ"), - (0x316C, "M", "ᇗ"), - (0x316D, "M", "ᇙ"), - (0x316E, "M", "ᄜ"), - (0x316F, "M", "ᇝ"), - (0x3170, "M", "ᇟ"), - (0x3171, "M", "ᄝ"), - (0x3172, "M", "ᄞ"), - (0x3173, "M", "ᄠ"), - (0x3174, "M", "ᄢ"), - (0x3175, "M", "ᄣ"), - (0x3176, "M", "ᄧ"), - (0x3177, "M", "ᄩ"), - (0x3178, "M", "ᄫ"), - (0x3179, "M", "ᄬ"), - (0x317A, "M", "ᄭ"), - (0x317B, "M", "ᄮ"), - (0x317C, "M", "ᄯ"), - (0x317D, "M", "ᄲ"), - (0x317E, "M", "ᄶ"), - (0x317F, "M", "ᅀ"), - (0x3180, "M", "ᅇ"), - (0x3181, "M", "ᅌ"), - (0x3182, "M", "ᇱ"), - (0x3183, "M", "ᇲ"), - (0x3184, "M", "ᅗ"), - (0x3185, "M", "ᅘ"), - (0x3186, "M", "ᅙ"), - (0x3187, "M", "ᆄ"), - (0x3188, "M", "ᆅ"), - (0x3189, "M", "ᆈ"), - (0x318A, "M", "ᆑ"), - (0x318B, "M", "ᆒ"), - (0x318C, "M", "ᆔ"), - (0x318D, "M", "ᆞ"), - (0x318E, "M", "ᆡ"), - (0x318F, "X"), - (0x3190, "V"), - (0x3192, "M", "一"), - (0x3193, "M", "二"), - (0x3194, "M", "三"), - (0x3195, "M", "四"), - (0x3196, "M", "上"), - (0x3197, "M", "中"), - (0x3198, "M", "下"), - (0x3199, "M", "甲"), - (0x319A, "M", "乙"), - (0x319B, "M", "丙"), - (0x319C, "M", "丁"), - (0x319D, "M", "天"), - (0x319E, "M", "地"), - (0x319F, "M", "人"), - (0x31A0, "V"), - (0x31E6, "X"), - (0x31F0, "V"), - (0x3200, "M", "(ᄀ)"), - (0x3201, "M", "(ᄂ)"), - (0x3202, "M", "(ᄃ)"), - (0x3203, "M", "(ᄅ)"), - (0x3204, "M", "(ᄆ)"), - (0x3205, "M", "(ᄇ)"), - (0x3206, "M", "(ᄉ)"), - (0x3207, "M", "(ᄋ)"), - (0x3208, "M", "(ᄌ)"), - (0x3209, "M", "(ᄎ)"), - (0x320A, "M", "(ᄏ)"), - (0x320B, "M", "(ᄐ)"), - (0x320C, "M", "(ᄑ)"), - (0x320D, "M", "(ᄒ)"), - (0x320E, "M", "(가)"), - (0x320F, "M", "(나)"), - (0x3210, "M", "(다)"), - (0x3211, "M", "(라)"), - (0x3212, "M", "(마)"), - (0x3213, "M", "(바)"), - (0x3214, "M", "(사)"), - (0x3215, "M", "(아)"), - (0x3216, "M", "(자)"), - (0x3217, "M", "(차)"), - (0x3218, "M", "(카)"), - (0x3219, "M", "(타)"), - (0x321A, "M", "(파)"), - (0x321B, "M", "(하)"), - (0x321C, "M", "(주)"), - (0x321D, "M", "(오전)"), - (0x321E, "M", "(오후)"), - (0x321F, "X"), - (0x3220, "M", "(一)"), - (0x3221, "M", "(二)"), - (0x3222, "M", "(三)"), - (0x3223, "M", "(四)"), - (0x3224, "M", "(五)"), - (0x3225, "M", "(六)"), - (0x3226, "M", "(七)"), - (0x3227, "M", "(八)"), - (0x3228, "M", "(九)"), - (0x3229, "M", "(十)"), - ] - - -def _seg_31() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x322A, "M", "(月)"), - (0x322B, "M", "(火)"), - (0x322C, "M", "(水)"), - (0x322D, "M", "(木)"), - (0x322E, "M", "(金)"), - (0x322F, "M", "(土)"), - (0x3230, "M", "(日)"), - (0x3231, "M", "(株)"), - (0x3232, "M", "(有)"), - (0x3233, "M", "(社)"), - (0x3234, "M", "(名)"), - (0x3235, "M", "(特)"), - (0x3236, "M", "(財)"), - (0x3237, "M", "(祝)"), - (0x3238, "M", "(労)"), - (0x3239, "M", "(代)"), - (0x323A, "M", "(呼)"), - (0x323B, "M", "(学)"), - (0x323C, "M", "(監)"), - (0x323D, "M", "(企)"), - (0x323E, "M", "(資)"), - (0x323F, "M", "(協)"), - (0x3240, "M", "(祭)"), - (0x3241, "M", "(休)"), - (0x3242, "M", "(自)"), - (0x3243, "M", "(至)"), - (0x3244, "M", "問"), - (0x3245, "M", "幼"), - (0x3246, "M", "文"), - (0x3247, "M", "箏"), - (0x3248, "V"), - (0x3250, "M", "pte"), - (0x3251, "M", "21"), - (0x3252, "M", "22"), - (0x3253, "M", "23"), - (0x3254, "M", "24"), - (0x3255, "M", "25"), - (0x3256, "M", "26"), - (0x3257, "M", "27"), - (0x3258, "M", "28"), - (0x3259, "M", "29"), - (0x325A, "M", "30"), - (0x325B, "M", "31"), - (0x325C, "M", "32"), - (0x325D, "M", "33"), - (0x325E, "M", "34"), - (0x325F, "M", "35"), - (0x3260, "M", "ᄀ"), - (0x3261, "M", "ᄂ"), - (0x3262, "M", "ᄃ"), - (0x3263, "M", "ᄅ"), - (0x3264, "M", "ᄆ"), - (0x3265, "M", "ᄇ"), - (0x3266, "M", "ᄉ"), - (0x3267, "M", "ᄋ"), - (0x3268, "M", "ᄌ"), - (0x3269, "M", "ᄎ"), - (0x326A, "M", "ᄏ"), - (0x326B, "M", "ᄐ"), - (0x326C, "M", "ᄑ"), - (0x326D, "M", "ᄒ"), - (0x326E, "M", "가"), - (0x326F, "M", "나"), - (0x3270, "M", "다"), - (0x3271, "M", "라"), - (0x3272, "M", "마"), - (0x3273, "M", "바"), - (0x3274, "M", "사"), - (0x3275, "M", "아"), - (0x3276, "M", "자"), - (0x3277, "M", "차"), - (0x3278, "M", "카"), - (0x3279, "M", "타"), - (0x327A, "M", "파"), - (0x327B, "M", "하"), - (0x327C, "M", "참고"), - (0x327D, "M", "주의"), - (0x327E, "M", "우"), - (0x327F, "V"), - (0x3280, "M", "一"), - (0x3281, "M", "二"), - (0x3282, "M", "三"), - (0x3283, "M", "四"), - (0x3284, "M", "五"), - (0x3285, "M", "六"), - (0x3286, "M", "七"), - (0x3287, "M", "八"), - (0x3288, "M", "九"), - (0x3289, "M", "十"), - (0x328A, "M", "月"), - (0x328B, "M", "火"), - (0x328C, "M", "水"), - (0x328D, "M", "木"), - (0x328E, "M", "金"), - (0x328F, "M", "土"), - (0x3290, "M", "日"), - (0x3291, "M", "株"), - (0x3292, "M", "有"), - (0x3293, "M", "社"), - (0x3294, "M", "名"), - ] - - -def _seg_32() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x3295, "M", "特"), - (0x3296, "M", "財"), - (0x3297, "M", "祝"), - (0x3298, "M", "労"), - (0x3299, "M", "秘"), - (0x329A, "M", "男"), - (0x329B, "M", "女"), - (0x329C, "M", "適"), - (0x329D, "M", "優"), - (0x329E, "M", "印"), - (0x329F, "M", "注"), - (0x32A0, "M", "項"), - (0x32A1, "M", "休"), - (0x32A2, "M", "写"), - (0x32A3, "M", "正"), - (0x32A4, "M", "上"), - (0x32A5, "M", "中"), - (0x32A6, "M", "下"), - (0x32A7, "M", "左"), - (0x32A8, "M", "右"), - (0x32A9, "M", "医"), - (0x32AA, "M", "宗"), - (0x32AB, "M", "学"), - (0x32AC, "M", "監"), - (0x32AD, "M", "企"), - (0x32AE, "M", "資"), - (0x32AF, "M", "協"), - (0x32B0, "M", "夜"), - (0x32B1, "M", "36"), - (0x32B2, "M", "37"), - (0x32B3, "M", "38"), - (0x32B4, "M", "39"), - (0x32B5, "M", "40"), - (0x32B6, "M", "41"), - (0x32B7, "M", "42"), - (0x32B8, "M", "43"), - (0x32B9, "M", "44"), - (0x32BA, "M", "45"), - (0x32BB, "M", "46"), - (0x32BC, "M", "47"), - (0x32BD, "M", "48"), - (0x32BE, "M", "49"), - (0x32BF, "M", "50"), - (0x32C0, "M", "1月"), - (0x32C1, "M", "2月"), - (0x32C2, "M", "3月"), - (0x32C3, "M", "4月"), - (0x32C4, "M", "5月"), - (0x32C5, "M", "6月"), - (0x32C6, "M", "7月"), - (0x32C7, "M", "8月"), - (0x32C8, "M", "9月"), - (0x32C9, "M", "10月"), - (0x32CA, "M", "11月"), - (0x32CB, "M", "12月"), - (0x32CC, "M", "hg"), - (0x32CD, "M", "erg"), - (0x32CE, "M", "ev"), - (0x32CF, "M", "ltd"), - (0x32D0, "M", "ア"), - (0x32D1, "M", "イ"), - (0x32D2, "M", "ウ"), - (0x32D3, "M", "エ"), - (0x32D4, "M", "オ"), - (0x32D5, "M", "カ"), - (0x32D6, "M", "キ"), - (0x32D7, "M", "ク"), - (0x32D8, "M", "ケ"), - (0x32D9, "M", "コ"), - (0x32DA, "M", "サ"), - (0x32DB, "M", "シ"), - (0x32DC, "M", "ス"), - (0x32DD, "M", "セ"), - (0x32DE, "M", "ソ"), - (0x32DF, "M", "タ"), - (0x32E0, "M", "チ"), - (0x32E1, "M", "ツ"), - (0x32E2, "M", "テ"), - (0x32E3, "M", "ト"), - (0x32E4, "M", "ナ"), - (0x32E5, "M", "ニ"), - (0x32E6, "M", "ヌ"), - (0x32E7, "M", "ネ"), - (0x32E8, "M", "ノ"), - (0x32E9, "M", "ハ"), - (0x32EA, "M", "ヒ"), - (0x32EB, "M", "フ"), - (0x32EC, "M", "ヘ"), - (0x32ED, "M", "ホ"), - (0x32EE, "M", "マ"), - (0x32EF, "M", "ミ"), - (0x32F0, "M", "ム"), - (0x32F1, "M", "メ"), - (0x32F2, "M", "モ"), - (0x32F3, "M", "ヤ"), - (0x32F4, "M", "ユ"), - (0x32F5, "M", "ヨ"), - (0x32F6, "M", "ラ"), - (0x32F7, "M", "リ"), - (0x32F8, "M", "ル"), - ] - - -def _seg_33() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x32F9, "M", "レ"), - (0x32FA, "M", "ロ"), - (0x32FB, "M", "ワ"), - (0x32FC, "M", "ヰ"), - (0x32FD, "M", "ヱ"), - (0x32FE, "M", "ヲ"), - (0x32FF, "M", "令和"), - (0x3300, "M", "アパート"), - (0x3301, "M", "アルファ"), - (0x3302, "M", "アンペア"), - (0x3303, "M", "アール"), - (0x3304, "M", "イニング"), - (0x3305, "M", "インチ"), - (0x3306, "M", "ウォン"), - (0x3307, "M", "エスクード"), - (0x3308, "M", "エーカー"), - (0x3309, "M", "オンス"), - (0x330A, "M", "オーム"), - (0x330B, "M", "カイリ"), - (0x330C, "M", "カラット"), - (0x330D, "M", "カロリー"), - (0x330E, "M", "ガロン"), - (0x330F, "M", "ガンマ"), - (0x3310, "M", "ギガ"), - (0x3311, "M", "ギニー"), - (0x3312, "M", "キュリー"), - (0x3313, "M", "ギルダー"), - (0x3314, "M", "キロ"), - (0x3315, "M", "キログラム"), - (0x3316, "M", "キロメートル"), - (0x3317, "M", "キロワット"), - (0x3318, "M", "グラム"), - (0x3319, "M", "グラムトン"), - (0x331A, "M", "クルゼイロ"), - (0x331B, "M", "クローネ"), - (0x331C, "M", "ケース"), - (0x331D, "M", "コルナ"), - (0x331E, "M", "コーポ"), - (0x331F, "M", "サイクル"), - (0x3320, "M", "サンチーム"), - (0x3321, "M", "シリング"), - (0x3322, "M", "センチ"), - (0x3323, "M", "セント"), - (0x3324, "M", "ダース"), - (0x3325, "M", "デシ"), - (0x3326, "M", "ドル"), - (0x3327, "M", "トン"), - (0x3328, "M", "ナノ"), - (0x3329, "M", "ノット"), - (0x332A, "M", "ハイツ"), - (0x332B, "M", "パーセント"), - (0x332C, "M", "パーツ"), - (0x332D, "M", "バーレル"), - (0x332E, "M", "ピアストル"), - (0x332F, "M", "ピクル"), - (0x3330, "M", "ピコ"), - (0x3331, "M", "ビル"), - (0x3332, "M", "ファラッド"), - (0x3333, "M", "フィート"), - (0x3334, "M", "ブッシェル"), - (0x3335, "M", "フラン"), - (0x3336, "M", "ヘクタール"), - (0x3337, "M", "ペソ"), - (0x3338, "M", "ペニヒ"), - (0x3339, "M", "ヘルツ"), - (0x333A, "M", "ペンス"), - (0x333B, "M", "ページ"), - (0x333C, "M", "ベータ"), - (0x333D, "M", "ポイント"), - (0x333E, "M", "ボルト"), - (0x333F, "M", "ホン"), - (0x3340, "M", "ポンド"), - (0x3341, "M", "ホール"), - (0x3342, "M", "ホーン"), - (0x3343, "M", "マイクロ"), - (0x3344, "M", "マイル"), - (0x3345, "M", "マッハ"), - (0x3346, "M", "マルク"), - (0x3347, "M", "マンション"), - (0x3348, "M", "ミクロン"), - (0x3349, "M", "ミリ"), - (0x334A, "M", "ミリバール"), - (0x334B, "M", "メガ"), - (0x334C, "M", "メガトン"), - (0x334D, "M", "メートル"), - (0x334E, "M", "ヤード"), - (0x334F, "M", "ヤール"), - (0x3350, "M", "ユアン"), - (0x3351, "M", "リットル"), - (0x3352, "M", "リラ"), - (0x3353, "M", "ルピー"), - (0x3354, "M", "ルーブル"), - (0x3355, "M", "レム"), - (0x3356, "M", "レントゲン"), - (0x3357, "M", "ワット"), - (0x3358, "M", "0点"), - (0x3359, "M", "1点"), - (0x335A, "M", "2点"), - (0x335B, "M", "3点"), - (0x335C, "M", "4点"), - ] - - -def _seg_34() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x335D, "M", "5点"), - (0x335E, "M", "6点"), - (0x335F, "M", "7点"), - (0x3360, "M", "8点"), - (0x3361, "M", "9点"), - (0x3362, "M", "10点"), - (0x3363, "M", "11点"), - (0x3364, "M", "12点"), - (0x3365, "M", "13点"), - (0x3366, "M", "14点"), - (0x3367, "M", "15点"), - (0x3368, "M", "16点"), - (0x3369, "M", "17点"), - (0x336A, "M", "18点"), - (0x336B, "M", "19点"), - (0x336C, "M", "20点"), - (0x336D, "M", "21点"), - (0x336E, "M", "22点"), - (0x336F, "M", "23点"), - (0x3370, "M", "24点"), - (0x3371, "M", "hpa"), - (0x3372, "M", "da"), - (0x3373, "M", "au"), - (0x3374, "M", "bar"), - (0x3375, "M", "ov"), - (0x3376, "M", "pc"), - (0x3377, "M", "dm"), - (0x3378, "M", "dm2"), - (0x3379, "M", "dm3"), - (0x337A, "M", "iu"), - (0x337B, "M", "平成"), - (0x337C, "M", "昭和"), - (0x337D, "M", "大正"), - (0x337E, "M", "明治"), - (0x337F, "M", "株式会社"), - (0x3380, "M", "pa"), - (0x3381, "M", "na"), - (0x3382, "M", "μa"), - (0x3383, "M", "ma"), - (0x3384, "M", "ka"), - (0x3385, "M", "kb"), - (0x3386, "M", "mb"), - (0x3387, "M", "gb"), - (0x3388, "M", "cal"), - (0x3389, "M", "kcal"), - (0x338A, "M", "pf"), - (0x338B, "M", "nf"), - (0x338C, "M", "μf"), - (0x338D, "M", "μg"), - (0x338E, "M", "mg"), - (0x338F, "M", "kg"), - (0x3390, "M", "hz"), - (0x3391, "M", "khz"), - (0x3392, "M", "mhz"), - (0x3393, "M", "ghz"), - (0x3394, "M", "thz"), - (0x3395, "M", "μl"), - (0x3396, "M", "ml"), - (0x3397, "M", "dl"), - (0x3398, "M", "kl"), - (0x3399, "M", "fm"), - (0x339A, "M", "nm"), - (0x339B, "M", "μm"), - (0x339C, "M", "mm"), - (0x339D, "M", "cm"), - (0x339E, "M", "km"), - (0x339F, "M", "mm2"), - (0x33A0, "M", "cm2"), - (0x33A1, "M", "m2"), - (0x33A2, "M", "km2"), - (0x33A3, "M", "mm3"), - (0x33A4, "M", "cm3"), - (0x33A5, "M", "m3"), - (0x33A6, "M", "km3"), - (0x33A7, "M", "m∕s"), - (0x33A8, "M", "m∕s2"), - (0x33A9, "M", "pa"), - (0x33AA, "M", "kpa"), - (0x33AB, "M", "mpa"), - (0x33AC, "M", "gpa"), - (0x33AD, "M", "rad"), - (0x33AE, "M", "rad∕s"), - (0x33AF, "M", "rad∕s2"), - (0x33B0, "M", "ps"), - (0x33B1, "M", "ns"), - (0x33B2, "M", "μs"), - (0x33B3, "M", "ms"), - (0x33B4, "M", "pv"), - (0x33B5, "M", "nv"), - (0x33B6, "M", "μv"), - (0x33B7, "M", "mv"), - (0x33B8, "M", "kv"), - (0x33B9, "M", "mv"), - (0x33BA, "M", "pw"), - (0x33BB, "M", "nw"), - (0x33BC, "M", "μw"), - (0x33BD, "M", "mw"), - (0x33BE, "M", "kw"), - (0x33BF, "M", "mw"), - (0x33C0, "M", "kω"), - ] - - -def _seg_35() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x33C1, "M", "mω"), - (0x33C2, "X"), - (0x33C3, "M", "bq"), - (0x33C4, "M", "cc"), - (0x33C5, "M", "cd"), - (0x33C6, "M", "c∕kg"), - (0x33C7, "X"), - (0x33C8, "M", "db"), - (0x33C9, "M", "gy"), - (0x33CA, "M", "ha"), - (0x33CB, "M", "hp"), - (0x33CC, "M", "in"), - (0x33CD, "M", "kk"), - (0x33CE, "M", "km"), - (0x33CF, "M", "kt"), - (0x33D0, "M", "lm"), - (0x33D1, "M", "ln"), - (0x33D2, "M", "log"), - (0x33D3, "M", "lx"), - (0x33D4, "M", "mb"), - (0x33D5, "M", "mil"), - (0x33D6, "M", "mol"), - (0x33D7, "M", "ph"), - (0x33D8, "X"), - (0x33D9, "M", "ppm"), - (0x33DA, "M", "pr"), - (0x33DB, "M", "sr"), - (0x33DC, "M", "sv"), - (0x33DD, "M", "wb"), - (0x33DE, "M", "v∕m"), - (0x33DF, "M", "a∕m"), - (0x33E0, "M", "1日"), - (0x33E1, "M", "2日"), - (0x33E2, "M", "3日"), - (0x33E3, "M", "4日"), - (0x33E4, "M", "5日"), - (0x33E5, "M", "6日"), - (0x33E6, "M", "7日"), - (0x33E7, "M", "8日"), - (0x33E8, "M", "9日"), - (0x33E9, "M", "10日"), - (0x33EA, "M", "11日"), - (0x33EB, "M", "12日"), - (0x33EC, "M", "13日"), - (0x33ED, "M", "14日"), - (0x33EE, "M", "15日"), - (0x33EF, "M", "16日"), - (0x33F0, "M", "17日"), - (0x33F1, "M", "18日"), - (0x33F2, "M", "19日"), - (0x33F3, "M", "20日"), - (0x33F4, "M", "21日"), - (0x33F5, "M", "22日"), - (0x33F6, "M", "23日"), - (0x33F7, "M", "24日"), - (0x33F8, "M", "25日"), - (0x33F9, "M", "26日"), - (0x33FA, "M", "27日"), - (0x33FB, "M", "28日"), - (0x33FC, "M", "29日"), - (0x33FD, "M", "30日"), - (0x33FE, "M", "31日"), - (0x33FF, "M", "gal"), - (0x3400, "V"), - (0xA48D, "X"), - (0xA490, "V"), - (0xA4C7, "X"), - (0xA4D0, "V"), - (0xA62C, "X"), - (0xA640, "M", "ꙁ"), - (0xA641, "V"), - (0xA642, "M", "ꙃ"), - (0xA643, "V"), - (0xA644, "M", "ꙅ"), - (0xA645, "V"), - (0xA646, "M", "ꙇ"), - (0xA647, "V"), - (0xA648, "M", "ꙉ"), - (0xA649, "V"), - (0xA64A, "M", "ꙋ"), - (0xA64B, "V"), - (0xA64C, "M", "ꙍ"), - (0xA64D, "V"), - (0xA64E, "M", "ꙏ"), - (0xA64F, "V"), - (0xA650, "M", "ꙑ"), - (0xA651, "V"), - (0xA652, "M", "ꙓ"), - (0xA653, "V"), - (0xA654, "M", "ꙕ"), - (0xA655, "V"), - (0xA656, "M", "ꙗ"), - (0xA657, "V"), - (0xA658, "M", "ꙙ"), - (0xA659, "V"), - (0xA65A, "M", "ꙛ"), - (0xA65B, "V"), - (0xA65C, "M", "ꙝ"), - (0xA65D, "V"), - (0xA65E, "M", "ꙟ"), - ] - - -def _seg_36() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xA65F, "V"), - (0xA660, "M", "ꙡ"), - (0xA661, "V"), - (0xA662, "M", "ꙣ"), - (0xA663, "V"), - (0xA664, "M", "ꙥ"), - (0xA665, "V"), - (0xA666, "M", "ꙧ"), - (0xA667, "V"), - (0xA668, "M", "ꙩ"), - (0xA669, "V"), - (0xA66A, "M", "ꙫ"), - (0xA66B, "V"), - (0xA66C, "M", "ꙭ"), - (0xA66D, "V"), - (0xA680, "M", "ꚁ"), - (0xA681, "V"), - (0xA682, "M", "ꚃ"), - (0xA683, "V"), - (0xA684, "M", "ꚅ"), - (0xA685, "V"), - (0xA686, "M", "ꚇ"), - (0xA687, "V"), - (0xA688, "M", "ꚉ"), - (0xA689, "V"), - (0xA68A, "M", "ꚋ"), - (0xA68B, "V"), - (0xA68C, "M", "ꚍ"), - (0xA68D, "V"), - (0xA68E, "M", "ꚏ"), - (0xA68F, "V"), - (0xA690, "M", "ꚑ"), - (0xA691, "V"), - (0xA692, "M", "ꚓ"), - (0xA693, "V"), - (0xA694, "M", "ꚕ"), - (0xA695, "V"), - (0xA696, "M", "ꚗ"), - (0xA697, "V"), - (0xA698, "M", "ꚙ"), - (0xA699, "V"), - (0xA69A, "M", "ꚛ"), - (0xA69B, "V"), - (0xA69C, "M", "ъ"), - (0xA69D, "M", "ь"), - (0xA69E, "V"), - (0xA6F8, "X"), - (0xA700, "V"), - (0xA722, "M", "ꜣ"), - (0xA723, "V"), - (0xA724, "M", "ꜥ"), - (0xA725, "V"), - (0xA726, "M", "ꜧ"), - (0xA727, "V"), - (0xA728, "M", "ꜩ"), - (0xA729, "V"), - (0xA72A, "M", "ꜫ"), - (0xA72B, "V"), - (0xA72C, "M", "ꜭ"), - (0xA72D, "V"), - (0xA72E, "M", "ꜯ"), - (0xA72F, "V"), - (0xA732, "M", "ꜳ"), - (0xA733, "V"), - (0xA734, "M", "ꜵ"), - (0xA735, "V"), - (0xA736, "M", "ꜷ"), - (0xA737, "V"), - (0xA738, "M", "ꜹ"), - (0xA739, "V"), - (0xA73A, "M", "ꜻ"), - (0xA73B, "V"), - (0xA73C, "M", "ꜽ"), - (0xA73D, "V"), - (0xA73E, "M", "ꜿ"), - (0xA73F, "V"), - (0xA740, "M", "ꝁ"), - (0xA741, "V"), - (0xA742, "M", "ꝃ"), - (0xA743, "V"), - (0xA744, "M", "ꝅ"), - (0xA745, "V"), - (0xA746, "M", "ꝇ"), - (0xA747, "V"), - (0xA748, "M", "ꝉ"), - (0xA749, "V"), - (0xA74A, "M", "ꝋ"), - (0xA74B, "V"), - (0xA74C, "M", "ꝍ"), - (0xA74D, "V"), - (0xA74E, "M", "ꝏ"), - (0xA74F, "V"), - (0xA750, "M", "ꝑ"), - (0xA751, "V"), - (0xA752, "M", "ꝓ"), - (0xA753, "V"), - (0xA754, "M", "ꝕ"), - (0xA755, "V"), - (0xA756, "M", "ꝗ"), - (0xA757, "V"), - ] - - -def _seg_37() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xA758, "M", "ꝙ"), - (0xA759, "V"), - (0xA75A, "M", "ꝛ"), - (0xA75B, "V"), - (0xA75C, "M", "ꝝ"), - (0xA75D, "V"), - (0xA75E, "M", "ꝟ"), - (0xA75F, "V"), - (0xA760, "M", "ꝡ"), - (0xA761, "V"), - (0xA762, "M", "ꝣ"), - (0xA763, "V"), - (0xA764, "M", "ꝥ"), - (0xA765, "V"), - (0xA766, "M", "ꝧ"), - (0xA767, "V"), - (0xA768, "M", "ꝩ"), - (0xA769, "V"), - (0xA76A, "M", "ꝫ"), - (0xA76B, "V"), - (0xA76C, "M", "ꝭ"), - (0xA76D, "V"), - (0xA76E, "M", "ꝯ"), - (0xA76F, "V"), - (0xA770, "M", "ꝯ"), - (0xA771, "V"), - (0xA779, "M", "ꝺ"), - (0xA77A, "V"), - (0xA77B, "M", "ꝼ"), - (0xA77C, "V"), - (0xA77D, "M", "ᵹ"), - (0xA77E, "M", "ꝿ"), - (0xA77F, "V"), - (0xA780, "M", "ꞁ"), - (0xA781, "V"), - (0xA782, "M", "ꞃ"), - (0xA783, "V"), - (0xA784, "M", "ꞅ"), - (0xA785, "V"), - (0xA786, "M", "ꞇ"), - (0xA787, "V"), - (0xA78B, "M", "ꞌ"), - (0xA78C, "V"), - (0xA78D, "M", "ɥ"), - (0xA78E, "V"), - (0xA790, "M", "ꞑ"), - (0xA791, "V"), - (0xA792, "M", "ꞓ"), - (0xA793, "V"), - (0xA796, "M", "ꞗ"), - (0xA797, "V"), - (0xA798, "M", "ꞙ"), - (0xA799, "V"), - (0xA79A, "M", "ꞛ"), - (0xA79B, "V"), - (0xA79C, "M", "ꞝ"), - (0xA79D, "V"), - (0xA79E, "M", "ꞟ"), - (0xA79F, "V"), - (0xA7A0, "M", "ꞡ"), - (0xA7A1, "V"), - (0xA7A2, "M", "ꞣ"), - (0xA7A3, "V"), - (0xA7A4, "M", "ꞥ"), - (0xA7A5, "V"), - (0xA7A6, "M", "ꞧ"), - (0xA7A7, "V"), - (0xA7A8, "M", "ꞩ"), - (0xA7A9, "V"), - (0xA7AA, "M", "ɦ"), - (0xA7AB, "M", "ɜ"), - (0xA7AC, "M", "ɡ"), - (0xA7AD, "M", "ɬ"), - (0xA7AE, "M", "ɪ"), - (0xA7AF, "V"), - (0xA7B0, "M", "ʞ"), - (0xA7B1, "M", "ʇ"), - (0xA7B2, "M", "ʝ"), - (0xA7B3, "M", "ꭓ"), - (0xA7B4, "M", "ꞵ"), - (0xA7B5, "V"), - (0xA7B6, "M", "ꞷ"), - (0xA7B7, "V"), - (0xA7B8, "M", "ꞹ"), - (0xA7B9, "V"), - (0xA7BA, "M", "ꞻ"), - (0xA7BB, "V"), - (0xA7BC, "M", "ꞽ"), - (0xA7BD, "V"), - (0xA7BE, "M", "ꞿ"), - (0xA7BF, "V"), - (0xA7C0, "M", "ꟁ"), - (0xA7C1, "V"), - (0xA7C2, "M", "ꟃ"), - (0xA7C3, "V"), - (0xA7C4, "M", "ꞔ"), - (0xA7C5, "M", "ʂ"), - (0xA7C6, "M", "ᶎ"), - (0xA7C7, "M", "ꟈ"), - (0xA7C8, "V"), - ] - - -def _seg_38() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xA7C9, "M", "ꟊ"), - (0xA7CA, "V"), - (0xA7CB, "M", "ɤ"), - (0xA7CC, "M", "ꟍ"), - (0xA7CD, "V"), - (0xA7CE, "X"), - (0xA7D0, "M", "ꟑ"), - (0xA7D1, "V"), - (0xA7D2, "X"), - (0xA7D3, "V"), - (0xA7D4, "X"), - (0xA7D5, "V"), - (0xA7D6, "M", "ꟗ"), - (0xA7D7, "V"), - (0xA7D8, "M", "ꟙ"), - (0xA7D9, "V"), - (0xA7DA, "M", "ꟛ"), - (0xA7DB, "V"), - (0xA7DC, "M", "ƛ"), - (0xA7DD, "X"), - (0xA7F2, "M", "c"), - (0xA7F3, "M", "f"), - (0xA7F4, "M", "q"), - (0xA7F5, "M", "ꟶ"), - (0xA7F6, "V"), - (0xA7F8, "M", "ħ"), - (0xA7F9, "M", "œ"), - (0xA7FA, "V"), - (0xA82D, "X"), - (0xA830, "V"), - (0xA83A, "X"), - (0xA840, "V"), - (0xA878, "X"), - (0xA880, "V"), - (0xA8C6, "X"), - (0xA8CE, "V"), - (0xA8DA, "X"), - (0xA8E0, "V"), - (0xA954, "X"), - (0xA95F, "V"), - (0xA97D, "X"), - (0xA980, "V"), - (0xA9CE, "X"), - (0xA9CF, "V"), - (0xA9DA, "X"), - (0xA9DE, "V"), - (0xA9FF, "X"), - (0xAA00, "V"), - (0xAA37, "X"), - (0xAA40, "V"), - (0xAA4E, "X"), - (0xAA50, "V"), - (0xAA5A, "X"), - (0xAA5C, "V"), - (0xAAC3, "X"), - (0xAADB, "V"), - (0xAAF7, "X"), - (0xAB01, "V"), - (0xAB07, "X"), - (0xAB09, "V"), - (0xAB0F, "X"), - (0xAB11, "V"), - (0xAB17, "X"), - (0xAB20, "V"), - (0xAB27, "X"), - (0xAB28, "V"), - (0xAB2F, "X"), - (0xAB30, "V"), - (0xAB5C, "M", "ꜧ"), - (0xAB5D, "M", "ꬷ"), - (0xAB5E, "M", "ɫ"), - (0xAB5F, "M", "ꭒ"), - (0xAB60, "V"), - (0xAB69, "M", "ʍ"), - (0xAB6A, "V"), - (0xAB6C, "X"), - (0xAB70, "M", "Ꭰ"), - (0xAB71, "M", "Ꭱ"), - (0xAB72, "M", "Ꭲ"), - (0xAB73, "M", "Ꭳ"), - (0xAB74, "M", "Ꭴ"), - (0xAB75, "M", "Ꭵ"), - (0xAB76, "M", "Ꭶ"), - (0xAB77, "M", "Ꭷ"), - (0xAB78, "M", "Ꭸ"), - (0xAB79, "M", "Ꭹ"), - (0xAB7A, "M", "Ꭺ"), - (0xAB7B, "M", "Ꭻ"), - (0xAB7C, "M", "Ꭼ"), - (0xAB7D, "M", "Ꭽ"), - (0xAB7E, "M", "Ꭾ"), - (0xAB7F, "M", "Ꭿ"), - (0xAB80, "M", "Ꮀ"), - (0xAB81, "M", "Ꮁ"), - (0xAB82, "M", "Ꮂ"), - (0xAB83, "M", "Ꮃ"), - (0xAB84, "M", "Ꮄ"), - (0xAB85, "M", "Ꮅ"), - (0xAB86, "M", "Ꮆ"), - (0xAB87, "M", "Ꮇ"), - ] - - -def _seg_39() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xAB88, "M", "Ꮈ"), - (0xAB89, "M", "Ꮉ"), - (0xAB8A, "M", "Ꮊ"), - (0xAB8B, "M", "Ꮋ"), - (0xAB8C, "M", "Ꮌ"), - (0xAB8D, "M", "Ꮍ"), - (0xAB8E, "M", "Ꮎ"), - (0xAB8F, "M", "Ꮏ"), - (0xAB90, "M", "Ꮐ"), - (0xAB91, "M", "Ꮑ"), - (0xAB92, "M", "Ꮒ"), - (0xAB93, "M", "Ꮓ"), - (0xAB94, "M", "Ꮔ"), - (0xAB95, "M", "Ꮕ"), - (0xAB96, "M", "Ꮖ"), - (0xAB97, "M", "Ꮗ"), - (0xAB98, "M", "Ꮘ"), - (0xAB99, "M", "Ꮙ"), - (0xAB9A, "M", "Ꮚ"), - (0xAB9B, "M", "Ꮛ"), - (0xAB9C, "M", "Ꮜ"), - (0xAB9D, "M", "Ꮝ"), - (0xAB9E, "M", "Ꮞ"), - (0xAB9F, "M", "Ꮟ"), - (0xABA0, "M", "Ꮠ"), - (0xABA1, "M", "Ꮡ"), - (0xABA2, "M", "Ꮢ"), - (0xABA3, "M", "Ꮣ"), - (0xABA4, "M", "Ꮤ"), - (0xABA5, "M", "Ꮥ"), - (0xABA6, "M", "Ꮦ"), - (0xABA7, "M", "Ꮧ"), - (0xABA8, "M", "Ꮨ"), - (0xABA9, "M", "Ꮩ"), - (0xABAA, "M", "Ꮪ"), - (0xABAB, "M", "Ꮫ"), - (0xABAC, "M", "Ꮬ"), - (0xABAD, "M", "Ꮭ"), - (0xABAE, "M", "Ꮮ"), - (0xABAF, "M", "Ꮯ"), - (0xABB0, "M", "Ꮰ"), - (0xABB1, "M", "Ꮱ"), - (0xABB2, "M", "Ꮲ"), - (0xABB3, "M", "Ꮳ"), - (0xABB4, "M", "Ꮴ"), - (0xABB5, "M", "Ꮵ"), - (0xABB6, "M", "Ꮶ"), - (0xABB7, "M", "Ꮷ"), - (0xABB8, "M", "Ꮸ"), - (0xABB9, "M", "Ꮹ"), - (0xABBA, "M", "Ꮺ"), - (0xABBB, "M", "Ꮻ"), - (0xABBC, "M", "Ꮼ"), - (0xABBD, "M", "Ꮽ"), - (0xABBE, "M", "Ꮾ"), - (0xABBF, "M", "Ꮿ"), - (0xABC0, "V"), - (0xABEE, "X"), - (0xABF0, "V"), - (0xABFA, "X"), - (0xAC00, "V"), - (0xD7A4, "X"), - (0xD7B0, "V"), - (0xD7C7, "X"), - (0xD7CB, "V"), - (0xD7FC, "X"), - (0xF900, "M", "豈"), - (0xF901, "M", "更"), - (0xF902, "M", "車"), - (0xF903, "M", "賈"), - (0xF904, "M", "滑"), - (0xF905, "M", "串"), - (0xF906, "M", "句"), - (0xF907, "M", "龜"), - (0xF909, "M", "契"), - (0xF90A, "M", "金"), - (0xF90B, "M", "喇"), - (0xF90C, "M", "奈"), - (0xF90D, "M", "懶"), - (0xF90E, "M", "癩"), - (0xF90F, "M", "羅"), - (0xF910, "M", "蘿"), - (0xF911, "M", "螺"), - (0xF912, "M", "裸"), - (0xF913, "M", "邏"), - (0xF914, "M", "樂"), - (0xF915, "M", "洛"), - (0xF916, "M", "烙"), - (0xF917, "M", "珞"), - (0xF918, "M", "落"), - (0xF919, "M", "酪"), - (0xF91A, "M", "駱"), - (0xF91B, "M", "亂"), - (0xF91C, "M", "卵"), - (0xF91D, "M", "欄"), - (0xF91E, "M", "爛"), - (0xF91F, "M", "蘭"), - (0xF920, "M", "鸞"), - (0xF921, "M", "嵐"), - (0xF922, "M", "濫"), - ] - - -def _seg_40() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xF923, "M", "藍"), - (0xF924, "M", "襤"), - (0xF925, "M", "拉"), - (0xF926, "M", "臘"), - (0xF927, "M", "蠟"), - (0xF928, "M", "廊"), - (0xF929, "M", "朗"), - (0xF92A, "M", "浪"), - (0xF92B, "M", "狼"), - (0xF92C, "M", "郎"), - (0xF92D, "M", "來"), - (0xF92E, "M", "冷"), - (0xF92F, "M", "勞"), - (0xF930, "M", "擄"), - (0xF931, "M", "櫓"), - (0xF932, "M", "爐"), - (0xF933, "M", "盧"), - (0xF934, "M", "老"), - (0xF935, "M", "蘆"), - (0xF936, "M", "虜"), - (0xF937, "M", "路"), - (0xF938, "M", "露"), - (0xF939, "M", "魯"), - (0xF93A, "M", "鷺"), - (0xF93B, "M", "碌"), - (0xF93C, "M", "祿"), - (0xF93D, "M", "綠"), - (0xF93E, "M", "菉"), - (0xF93F, "M", "錄"), - (0xF940, "M", "鹿"), - (0xF941, "M", "論"), - (0xF942, "M", "壟"), - (0xF943, "M", "弄"), - (0xF944, "M", "籠"), - (0xF945, "M", "聾"), - (0xF946, "M", "牢"), - (0xF947, "M", "磊"), - (0xF948, "M", "賂"), - (0xF949, "M", "雷"), - (0xF94A, "M", "壘"), - (0xF94B, "M", "屢"), - (0xF94C, "M", "樓"), - (0xF94D, "M", "淚"), - (0xF94E, "M", "漏"), - (0xF94F, "M", "累"), - (0xF950, "M", "縷"), - (0xF951, "M", "陋"), - (0xF952, "M", "勒"), - (0xF953, "M", "肋"), - (0xF954, "M", "凜"), - (0xF955, "M", "凌"), - (0xF956, "M", "稜"), - (0xF957, "M", "綾"), - (0xF958, "M", "菱"), - (0xF959, "M", "陵"), - (0xF95A, "M", "讀"), - (0xF95B, "M", "拏"), - (0xF95C, "M", "樂"), - (0xF95D, "M", "諾"), - (0xF95E, "M", "丹"), - (0xF95F, "M", "寧"), - (0xF960, "M", "怒"), - (0xF961, "M", "率"), - (0xF962, "M", "異"), - (0xF963, "M", "北"), - (0xF964, "M", "磻"), - (0xF965, "M", "便"), - (0xF966, "M", "復"), - (0xF967, "M", "不"), - (0xF968, "M", "泌"), - (0xF969, "M", "數"), - (0xF96A, "M", "索"), - (0xF96B, "M", "參"), - (0xF96C, "M", "塞"), - (0xF96D, "M", "省"), - (0xF96E, "M", "葉"), - (0xF96F, "M", "說"), - (0xF970, "M", "殺"), - (0xF971, "M", "辰"), - (0xF972, "M", "沈"), - (0xF973, "M", "拾"), - (0xF974, "M", "若"), - (0xF975, "M", "掠"), - (0xF976, "M", "略"), - (0xF977, "M", "亮"), - (0xF978, "M", "兩"), - (0xF979, "M", "凉"), - (0xF97A, "M", "梁"), - (0xF97B, "M", "糧"), - (0xF97C, "M", "良"), - (0xF97D, "M", "諒"), - (0xF97E, "M", "量"), - (0xF97F, "M", "勵"), - (0xF980, "M", "呂"), - (0xF981, "M", "女"), - (0xF982, "M", "廬"), - (0xF983, "M", "旅"), - (0xF984, "M", "濾"), - (0xF985, "M", "礪"), - (0xF986, "M", "閭"), - ] - - -def _seg_41() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xF987, "M", "驪"), - (0xF988, "M", "麗"), - (0xF989, "M", "黎"), - (0xF98A, "M", "力"), - (0xF98B, "M", "曆"), - (0xF98C, "M", "歷"), - (0xF98D, "M", "轢"), - (0xF98E, "M", "年"), - (0xF98F, "M", "憐"), - (0xF990, "M", "戀"), - (0xF991, "M", "撚"), - (0xF992, "M", "漣"), - (0xF993, "M", "煉"), - (0xF994, "M", "璉"), - (0xF995, "M", "秊"), - (0xF996, "M", "練"), - (0xF997, "M", "聯"), - (0xF998, "M", "輦"), - (0xF999, "M", "蓮"), - (0xF99A, "M", "連"), - (0xF99B, "M", "鍊"), - (0xF99C, "M", "列"), - (0xF99D, "M", "劣"), - (0xF99E, "M", "咽"), - (0xF99F, "M", "烈"), - (0xF9A0, "M", "裂"), - (0xF9A1, "M", "說"), - (0xF9A2, "M", "廉"), - (0xF9A3, "M", "念"), - (0xF9A4, "M", "捻"), - (0xF9A5, "M", "殮"), - (0xF9A6, "M", "簾"), - (0xF9A7, "M", "獵"), - (0xF9A8, "M", "令"), - (0xF9A9, "M", "囹"), - (0xF9AA, "M", "寧"), - (0xF9AB, "M", "嶺"), - (0xF9AC, "M", "怜"), - (0xF9AD, "M", "玲"), - (0xF9AE, "M", "瑩"), - (0xF9AF, "M", "羚"), - (0xF9B0, "M", "聆"), - (0xF9B1, "M", "鈴"), - (0xF9B2, "M", "零"), - (0xF9B3, "M", "靈"), - (0xF9B4, "M", "領"), - (0xF9B5, "M", "例"), - (0xF9B6, "M", "禮"), - (0xF9B7, "M", "醴"), - (0xF9B8, "M", "隸"), - (0xF9B9, "M", "惡"), - (0xF9BA, "M", "了"), - (0xF9BB, "M", "僚"), - (0xF9BC, "M", "寮"), - (0xF9BD, "M", "尿"), - (0xF9BE, "M", "料"), - (0xF9BF, "M", "樂"), - (0xF9C0, "M", "燎"), - (0xF9C1, "M", "療"), - (0xF9C2, "M", "蓼"), - (0xF9C3, "M", "遼"), - (0xF9C4, "M", "龍"), - (0xF9C5, "M", "暈"), - (0xF9C6, "M", "阮"), - (0xF9C7, "M", "劉"), - (0xF9C8, "M", "杻"), - (0xF9C9, "M", "柳"), - (0xF9CA, "M", "流"), - (0xF9CB, "M", "溜"), - (0xF9CC, "M", "琉"), - (0xF9CD, "M", "留"), - (0xF9CE, "M", "硫"), - (0xF9CF, "M", "紐"), - (0xF9D0, "M", "類"), - (0xF9D1, "M", "六"), - (0xF9D2, "M", "戮"), - (0xF9D3, "M", "陸"), - (0xF9D4, "M", "倫"), - (0xF9D5, "M", "崙"), - (0xF9D6, "M", "淪"), - (0xF9D7, "M", "輪"), - (0xF9D8, "M", "律"), - (0xF9D9, "M", "慄"), - (0xF9DA, "M", "栗"), - (0xF9DB, "M", "率"), - (0xF9DC, "M", "隆"), - (0xF9DD, "M", "利"), - (0xF9DE, "M", "吏"), - (0xF9DF, "M", "履"), - (0xF9E0, "M", "易"), - (0xF9E1, "M", "李"), - (0xF9E2, "M", "梨"), - (0xF9E3, "M", "泥"), - (0xF9E4, "M", "理"), - (0xF9E5, "M", "痢"), - (0xF9E6, "M", "罹"), - (0xF9E7, "M", "裏"), - (0xF9E8, "M", "裡"), - (0xF9E9, "M", "里"), - (0xF9EA, "M", "離"), - ] - - -def _seg_42() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xF9EB, "M", "匿"), - (0xF9EC, "M", "溺"), - (0xF9ED, "M", "吝"), - (0xF9EE, "M", "燐"), - (0xF9EF, "M", "璘"), - (0xF9F0, "M", "藺"), - (0xF9F1, "M", "隣"), - (0xF9F2, "M", "鱗"), - (0xF9F3, "M", "麟"), - (0xF9F4, "M", "林"), - (0xF9F5, "M", "淋"), - (0xF9F6, "M", "臨"), - (0xF9F7, "M", "立"), - (0xF9F8, "M", "笠"), - (0xF9F9, "M", "粒"), - (0xF9FA, "M", "狀"), - (0xF9FB, "M", "炙"), - (0xF9FC, "M", "識"), - (0xF9FD, "M", "什"), - (0xF9FE, "M", "茶"), - (0xF9FF, "M", "刺"), - (0xFA00, "M", "切"), - (0xFA01, "M", "度"), - (0xFA02, "M", "拓"), - (0xFA03, "M", "糖"), - (0xFA04, "M", "宅"), - (0xFA05, "M", "洞"), - (0xFA06, "M", "暴"), - (0xFA07, "M", "輻"), - (0xFA08, "M", "行"), - (0xFA09, "M", "降"), - (0xFA0A, "M", "見"), - (0xFA0B, "M", "廓"), - (0xFA0C, "M", "兀"), - (0xFA0D, "M", "嗀"), - (0xFA0E, "V"), - (0xFA10, "M", "塚"), - (0xFA11, "V"), - (0xFA12, "M", "晴"), - (0xFA13, "V"), - (0xFA15, "M", "凞"), - (0xFA16, "M", "猪"), - (0xFA17, "M", "益"), - (0xFA18, "M", "礼"), - (0xFA19, "M", "神"), - (0xFA1A, "M", "祥"), - (0xFA1B, "M", "福"), - (0xFA1C, "M", "靖"), - (0xFA1D, "M", "精"), - (0xFA1E, "M", "羽"), - (0xFA1F, "V"), - (0xFA20, "M", "蘒"), - (0xFA21, "V"), - (0xFA22, "M", "諸"), - (0xFA23, "V"), - (0xFA25, "M", "逸"), - (0xFA26, "M", "都"), - (0xFA27, "V"), - (0xFA2A, "M", "飯"), - (0xFA2B, "M", "飼"), - (0xFA2C, "M", "館"), - (0xFA2D, "M", "鶴"), - (0xFA2E, "M", "郞"), - (0xFA2F, "M", "隷"), - (0xFA30, "M", "侮"), - (0xFA31, "M", "僧"), - (0xFA32, "M", "免"), - (0xFA33, "M", "勉"), - (0xFA34, "M", "勤"), - (0xFA35, "M", "卑"), - (0xFA36, "M", "喝"), - (0xFA37, "M", "嘆"), - (0xFA38, "M", "器"), - (0xFA39, "M", "塀"), - (0xFA3A, "M", "墨"), - (0xFA3B, "M", "層"), - (0xFA3C, "M", "屮"), - (0xFA3D, "M", "悔"), - (0xFA3E, "M", "慨"), - (0xFA3F, "M", "憎"), - (0xFA40, "M", "懲"), - (0xFA41, "M", "敏"), - (0xFA42, "M", "既"), - (0xFA43, "M", "暑"), - (0xFA44, "M", "梅"), - (0xFA45, "M", "海"), - (0xFA46, "M", "渚"), - (0xFA47, "M", "漢"), - (0xFA48, "M", "煮"), - (0xFA49, "M", "爫"), - (0xFA4A, "M", "琢"), - (0xFA4B, "M", "碑"), - (0xFA4C, "M", "社"), - (0xFA4D, "M", "祉"), - (0xFA4E, "M", "祈"), - (0xFA4F, "M", "祐"), - (0xFA50, "M", "祖"), - (0xFA51, "M", "祝"), - (0xFA52, "M", "禍"), - (0xFA53, "M", "禎"), - ] - - -def _seg_43() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xFA54, "M", "穀"), - (0xFA55, "M", "突"), - (0xFA56, "M", "節"), - (0xFA57, "M", "練"), - (0xFA58, "M", "縉"), - (0xFA59, "M", "繁"), - (0xFA5A, "M", "署"), - (0xFA5B, "M", "者"), - (0xFA5C, "M", "臭"), - (0xFA5D, "M", "艹"), - (0xFA5F, "M", "著"), - (0xFA60, "M", "褐"), - (0xFA61, "M", "視"), - (0xFA62, "M", "謁"), - (0xFA63, "M", "謹"), - (0xFA64, "M", "賓"), - (0xFA65, "M", "贈"), - (0xFA66, "M", "辶"), - (0xFA67, "M", "逸"), - (0xFA68, "M", "難"), - (0xFA69, "M", "響"), - (0xFA6A, "M", "頻"), - (0xFA6B, "M", "恵"), - (0xFA6C, "M", "𤋮"), - (0xFA6D, "M", "舘"), - (0xFA6E, "X"), - (0xFA70, "M", "並"), - (0xFA71, "M", "况"), - (0xFA72, "M", "全"), - (0xFA73, "M", "侀"), - (0xFA74, "M", "充"), - (0xFA75, "M", "冀"), - (0xFA76, "M", "勇"), - (0xFA77, "M", "勺"), - (0xFA78, "M", "喝"), - (0xFA79, "M", "啕"), - (0xFA7A, "M", "喙"), - (0xFA7B, "M", "嗢"), - (0xFA7C, "M", "塚"), - (0xFA7D, "M", "墳"), - (0xFA7E, "M", "奄"), - (0xFA7F, "M", "奔"), - (0xFA80, "M", "婢"), - (0xFA81, "M", "嬨"), - (0xFA82, "M", "廒"), - (0xFA83, "M", "廙"), - (0xFA84, "M", "彩"), - (0xFA85, "M", "徭"), - (0xFA86, "M", "惘"), - (0xFA87, "M", "慎"), - (0xFA88, "M", "愈"), - (0xFA89, "M", "憎"), - (0xFA8A, "M", "慠"), - (0xFA8B, "M", "懲"), - (0xFA8C, "M", "戴"), - (0xFA8D, "M", "揄"), - (0xFA8E, "M", "搜"), - (0xFA8F, "M", "摒"), - (0xFA90, "M", "敖"), - (0xFA91, "M", "晴"), - (0xFA92, "M", "朗"), - (0xFA93, "M", "望"), - (0xFA94, "M", "杖"), - (0xFA95, "M", "歹"), - (0xFA96, "M", "殺"), - (0xFA97, "M", "流"), - (0xFA98, "M", "滛"), - (0xFA99, "M", "滋"), - (0xFA9A, "M", "漢"), - (0xFA9B, "M", "瀞"), - (0xFA9C, "M", "煮"), - (0xFA9D, "M", "瞧"), - (0xFA9E, "M", "爵"), - (0xFA9F, "M", "犯"), - (0xFAA0, "M", "猪"), - (0xFAA1, "M", "瑱"), - (0xFAA2, "M", "甆"), - (0xFAA3, "M", "画"), - (0xFAA4, "M", "瘝"), - (0xFAA5, "M", "瘟"), - (0xFAA6, "M", "益"), - (0xFAA7, "M", "盛"), - (0xFAA8, "M", "直"), - (0xFAA9, "M", "睊"), - (0xFAAA, "M", "着"), - (0xFAAB, "M", "磌"), - (0xFAAC, "M", "窱"), - (0xFAAD, "M", "節"), - (0xFAAE, "M", "类"), - (0xFAAF, "M", "絛"), - (0xFAB0, "M", "練"), - (0xFAB1, "M", "缾"), - (0xFAB2, "M", "者"), - (0xFAB3, "M", "荒"), - (0xFAB4, "M", "華"), - (0xFAB5, "M", "蝹"), - (0xFAB6, "M", "襁"), - (0xFAB7, "M", "覆"), - (0xFAB8, "M", "視"), - (0xFAB9, "M", "調"), - ] - - -def _seg_44() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xFABA, "M", "諸"), - (0xFABB, "M", "請"), - (0xFABC, "M", "謁"), - (0xFABD, "M", "諾"), - (0xFABE, "M", "諭"), - (0xFABF, "M", "謹"), - (0xFAC0, "M", "變"), - (0xFAC1, "M", "贈"), - (0xFAC2, "M", "輸"), - (0xFAC3, "M", "遲"), - (0xFAC4, "M", "醙"), - (0xFAC5, "M", "鉶"), - (0xFAC6, "M", "陼"), - (0xFAC7, "M", "難"), - (0xFAC8, "M", "靖"), - (0xFAC9, "M", "韛"), - (0xFACA, "M", "響"), - (0xFACB, "M", "頋"), - (0xFACC, "M", "頻"), - (0xFACD, "M", "鬒"), - (0xFACE, "M", "龜"), - (0xFACF, "M", "𢡊"), - (0xFAD0, "M", "𢡄"), - (0xFAD1, "M", "𣏕"), - (0xFAD2, "M", "㮝"), - (0xFAD3, "M", "䀘"), - (0xFAD4, "M", "䀹"), - (0xFAD5, "M", "𥉉"), - (0xFAD6, "M", "𥳐"), - (0xFAD7, "M", "𧻓"), - (0xFAD8, "M", "齃"), - (0xFAD9, "M", "龎"), - (0xFADA, "X"), - (0xFB00, "M", "ff"), - (0xFB01, "M", "fi"), - (0xFB02, "M", "fl"), - (0xFB03, "M", "ffi"), - (0xFB04, "M", "ffl"), - (0xFB05, "M", "st"), - (0xFB07, "X"), - (0xFB13, "M", "մն"), - (0xFB14, "M", "մե"), - (0xFB15, "M", "մի"), - (0xFB16, "M", "վն"), - (0xFB17, "M", "մխ"), - (0xFB18, "X"), - (0xFB1D, "M", "יִ"), - (0xFB1E, "V"), - (0xFB1F, "M", "ײַ"), - (0xFB20, "M", "ע"), - (0xFB21, "M", "א"), - (0xFB22, "M", "ד"), - (0xFB23, "M", "ה"), - (0xFB24, "M", "כ"), - (0xFB25, "M", "ל"), - (0xFB26, "M", "ם"), - (0xFB27, "M", "ר"), - (0xFB28, "M", "ת"), - (0xFB29, "M", "+"), - (0xFB2A, "M", "שׁ"), - (0xFB2B, "M", "שׂ"), - (0xFB2C, "M", "שּׁ"), - (0xFB2D, "M", "שּׂ"), - (0xFB2E, "M", "אַ"), - (0xFB2F, "M", "אָ"), - (0xFB30, "M", "אּ"), - (0xFB31, "M", "בּ"), - (0xFB32, "M", "גּ"), - (0xFB33, "M", "דּ"), - (0xFB34, "M", "הּ"), - (0xFB35, "M", "וּ"), - (0xFB36, "M", "זּ"), - (0xFB37, "X"), - (0xFB38, "M", "טּ"), - (0xFB39, "M", "יּ"), - (0xFB3A, "M", "ךּ"), - (0xFB3B, "M", "כּ"), - (0xFB3C, "M", "לּ"), - (0xFB3D, "X"), - (0xFB3E, "M", "מּ"), - (0xFB3F, "X"), - (0xFB40, "M", "נּ"), - (0xFB41, "M", "סּ"), - (0xFB42, "X"), - (0xFB43, "M", "ףּ"), - (0xFB44, "M", "פּ"), - (0xFB45, "X"), - (0xFB46, "M", "צּ"), - (0xFB47, "M", "קּ"), - (0xFB48, "M", "רּ"), - (0xFB49, "M", "שּ"), - (0xFB4A, "M", "תּ"), - (0xFB4B, "M", "וֹ"), - (0xFB4C, "M", "בֿ"), - (0xFB4D, "M", "כֿ"), - (0xFB4E, "M", "פֿ"), - (0xFB4F, "M", "אל"), - (0xFB50, "M", "ٱ"), - (0xFB52, "M", "ٻ"), - (0xFB56, "M", "پ"), - ] - - -def _seg_45() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xFB5A, "M", "ڀ"), - (0xFB5E, "M", "ٺ"), - (0xFB62, "M", "ٿ"), - (0xFB66, "M", "ٹ"), - (0xFB6A, "M", "ڤ"), - (0xFB6E, "M", "ڦ"), - (0xFB72, "M", "ڄ"), - (0xFB76, "M", "ڃ"), - (0xFB7A, "M", "چ"), - (0xFB7E, "M", "ڇ"), - (0xFB82, "M", "ڍ"), - (0xFB84, "M", "ڌ"), - (0xFB86, "M", "ڎ"), - (0xFB88, "M", "ڈ"), - (0xFB8A, "M", "ژ"), - (0xFB8C, "M", "ڑ"), - (0xFB8E, "M", "ک"), - (0xFB92, "M", "گ"), - (0xFB96, "M", "ڳ"), - (0xFB9A, "M", "ڱ"), - (0xFB9E, "M", "ں"), - (0xFBA0, "M", "ڻ"), - (0xFBA4, "M", "ۀ"), - (0xFBA6, "M", "ہ"), - (0xFBAA, "M", "ھ"), - (0xFBAE, "M", "ے"), - (0xFBB0, "M", "ۓ"), - (0xFBB2, "V"), - (0xFBC3, "X"), - (0xFBD3, "M", "ڭ"), - (0xFBD7, "M", "ۇ"), - (0xFBD9, "M", "ۆ"), - (0xFBDB, "M", "ۈ"), - (0xFBDD, "M", "ۇٴ"), - (0xFBDE, "M", "ۋ"), - (0xFBE0, "M", "ۅ"), - (0xFBE2, "M", "ۉ"), - (0xFBE4, "M", "ې"), - (0xFBE8, "M", "ى"), - (0xFBEA, "M", "ئا"), - (0xFBEC, "M", "ئە"), - (0xFBEE, "M", "ئو"), - (0xFBF0, "M", "ئۇ"), - (0xFBF2, "M", "ئۆ"), - (0xFBF4, "M", "ئۈ"), - (0xFBF6, "M", "ئې"), - (0xFBF9, "M", "ئى"), - (0xFBFC, "M", "ی"), - (0xFC00, "M", "ئج"), - (0xFC01, "M", "ئح"), - (0xFC02, "M", "ئم"), - (0xFC03, "M", "ئى"), - (0xFC04, "M", "ئي"), - (0xFC05, "M", "بج"), - (0xFC06, "M", "بح"), - (0xFC07, "M", "بخ"), - (0xFC08, "M", "بم"), - (0xFC09, "M", "بى"), - (0xFC0A, "M", "بي"), - (0xFC0B, "M", "تج"), - (0xFC0C, "M", "تح"), - (0xFC0D, "M", "تخ"), - (0xFC0E, "M", "تم"), - (0xFC0F, "M", "تى"), - (0xFC10, "M", "تي"), - (0xFC11, "M", "ثج"), - (0xFC12, "M", "ثم"), - (0xFC13, "M", "ثى"), - (0xFC14, "M", "ثي"), - (0xFC15, "M", "جح"), - (0xFC16, "M", "جم"), - (0xFC17, "M", "حج"), - (0xFC18, "M", "حم"), - (0xFC19, "M", "خج"), - (0xFC1A, "M", "خح"), - (0xFC1B, "M", "خم"), - (0xFC1C, "M", "سج"), - (0xFC1D, "M", "سح"), - (0xFC1E, "M", "سخ"), - (0xFC1F, "M", "سم"), - (0xFC20, "M", "صح"), - (0xFC21, "M", "صم"), - (0xFC22, "M", "ضج"), - (0xFC23, "M", "ضح"), - (0xFC24, "M", "ضخ"), - (0xFC25, "M", "ضم"), - (0xFC26, "M", "طح"), - (0xFC27, "M", "طم"), - (0xFC28, "M", "ظم"), - (0xFC29, "M", "عج"), - (0xFC2A, "M", "عم"), - (0xFC2B, "M", "غج"), - (0xFC2C, "M", "غم"), - (0xFC2D, "M", "فج"), - (0xFC2E, "M", "فح"), - (0xFC2F, "M", "فخ"), - (0xFC30, "M", "فم"), - (0xFC31, "M", "فى"), - (0xFC32, "M", "في"), - (0xFC33, "M", "قح"), - ] - - -def _seg_46() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xFC34, "M", "قم"), - (0xFC35, "M", "قى"), - (0xFC36, "M", "قي"), - (0xFC37, "M", "كا"), - (0xFC38, "M", "كج"), - (0xFC39, "M", "كح"), - (0xFC3A, "M", "كخ"), - (0xFC3B, "M", "كل"), - (0xFC3C, "M", "كم"), - (0xFC3D, "M", "كى"), - (0xFC3E, "M", "كي"), - (0xFC3F, "M", "لج"), - (0xFC40, "M", "لح"), - (0xFC41, "M", "لخ"), - (0xFC42, "M", "لم"), - (0xFC43, "M", "لى"), - (0xFC44, "M", "لي"), - (0xFC45, "M", "مج"), - (0xFC46, "M", "مح"), - (0xFC47, "M", "مخ"), - (0xFC48, "M", "مم"), - (0xFC49, "M", "مى"), - (0xFC4A, "M", "مي"), - (0xFC4B, "M", "نج"), - (0xFC4C, "M", "نح"), - (0xFC4D, "M", "نخ"), - (0xFC4E, "M", "نم"), - (0xFC4F, "M", "نى"), - (0xFC50, "M", "ني"), - (0xFC51, "M", "هج"), - (0xFC52, "M", "هم"), - (0xFC53, "M", "هى"), - (0xFC54, "M", "هي"), - (0xFC55, "M", "يج"), - (0xFC56, "M", "يح"), - (0xFC57, "M", "يخ"), - (0xFC58, "M", "يم"), - (0xFC59, "M", "يى"), - (0xFC5A, "M", "يي"), - (0xFC5B, "M", "ذٰ"), - (0xFC5C, "M", "رٰ"), - (0xFC5D, "M", "ىٰ"), - (0xFC5E, "M", " ٌّ"), - (0xFC5F, "M", " ٍّ"), - (0xFC60, "M", " َّ"), - (0xFC61, "M", " ُّ"), - (0xFC62, "M", " ِّ"), - (0xFC63, "M", " ّٰ"), - (0xFC64, "M", "ئر"), - (0xFC65, "M", "ئز"), - (0xFC66, "M", "ئم"), - (0xFC67, "M", "ئن"), - (0xFC68, "M", "ئى"), - (0xFC69, "M", "ئي"), - (0xFC6A, "M", "بر"), - (0xFC6B, "M", "بز"), - (0xFC6C, "M", "بم"), - (0xFC6D, "M", "بن"), - (0xFC6E, "M", "بى"), - (0xFC6F, "M", "بي"), - (0xFC70, "M", "تر"), - (0xFC71, "M", "تز"), - (0xFC72, "M", "تم"), - (0xFC73, "M", "تن"), - (0xFC74, "M", "تى"), - (0xFC75, "M", "تي"), - (0xFC76, "M", "ثر"), - (0xFC77, "M", "ثز"), - (0xFC78, "M", "ثم"), - (0xFC79, "M", "ثن"), - (0xFC7A, "M", "ثى"), - (0xFC7B, "M", "ثي"), - (0xFC7C, "M", "فى"), - (0xFC7D, "M", "في"), - (0xFC7E, "M", "قى"), - (0xFC7F, "M", "قي"), - (0xFC80, "M", "كا"), - (0xFC81, "M", "كل"), - (0xFC82, "M", "كم"), - (0xFC83, "M", "كى"), - (0xFC84, "M", "كي"), - (0xFC85, "M", "لم"), - (0xFC86, "M", "لى"), - (0xFC87, "M", "لي"), - (0xFC88, "M", "ما"), - (0xFC89, "M", "مم"), - (0xFC8A, "M", "نر"), - (0xFC8B, "M", "نز"), - (0xFC8C, "M", "نم"), - (0xFC8D, "M", "نن"), - (0xFC8E, "M", "نى"), - (0xFC8F, "M", "ني"), - (0xFC90, "M", "ىٰ"), - (0xFC91, "M", "ير"), - (0xFC92, "M", "يز"), - (0xFC93, "M", "يم"), - (0xFC94, "M", "ين"), - (0xFC95, "M", "يى"), - (0xFC96, "M", "يي"), - (0xFC97, "M", "ئج"), - ] - - -def _seg_47() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xFC98, "M", "ئح"), - (0xFC99, "M", "ئخ"), - (0xFC9A, "M", "ئم"), - (0xFC9B, "M", "ئه"), - (0xFC9C, "M", "بج"), - (0xFC9D, "M", "بح"), - (0xFC9E, "M", "بخ"), - (0xFC9F, "M", "بم"), - (0xFCA0, "M", "به"), - (0xFCA1, "M", "تج"), - (0xFCA2, "M", "تح"), - (0xFCA3, "M", "تخ"), - (0xFCA4, "M", "تم"), - (0xFCA5, "M", "ته"), - (0xFCA6, "M", "ثم"), - (0xFCA7, "M", "جح"), - (0xFCA8, "M", "جم"), - (0xFCA9, "M", "حج"), - (0xFCAA, "M", "حم"), - (0xFCAB, "M", "خج"), - (0xFCAC, "M", "خم"), - (0xFCAD, "M", "سج"), - (0xFCAE, "M", "سح"), - (0xFCAF, "M", "سخ"), - (0xFCB0, "M", "سم"), - (0xFCB1, "M", "صح"), - (0xFCB2, "M", "صخ"), - (0xFCB3, "M", "صم"), - (0xFCB4, "M", "ضج"), - (0xFCB5, "M", "ضح"), - (0xFCB6, "M", "ضخ"), - (0xFCB7, "M", "ضم"), - (0xFCB8, "M", "طح"), - (0xFCB9, "M", "ظم"), - (0xFCBA, "M", "عج"), - (0xFCBB, "M", "عم"), - (0xFCBC, "M", "غج"), - (0xFCBD, "M", "غم"), - (0xFCBE, "M", "فج"), - (0xFCBF, "M", "فح"), - (0xFCC0, "M", "فخ"), - (0xFCC1, "M", "فم"), - (0xFCC2, "M", "قح"), - (0xFCC3, "M", "قم"), - (0xFCC4, "M", "كج"), - (0xFCC5, "M", "كح"), - (0xFCC6, "M", "كخ"), - (0xFCC7, "M", "كل"), - (0xFCC8, "M", "كم"), - (0xFCC9, "M", "لج"), - (0xFCCA, "M", "لح"), - (0xFCCB, "M", "لخ"), - (0xFCCC, "M", "لم"), - (0xFCCD, "M", "له"), - (0xFCCE, "M", "مج"), - (0xFCCF, "M", "مح"), - (0xFCD0, "M", "مخ"), - (0xFCD1, "M", "مم"), - (0xFCD2, "M", "نج"), - (0xFCD3, "M", "نح"), - (0xFCD4, "M", "نخ"), - (0xFCD5, "M", "نم"), - (0xFCD6, "M", "نه"), - (0xFCD7, "M", "هج"), - (0xFCD8, "M", "هم"), - (0xFCD9, "M", "هٰ"), - (0xFCDA, "M", "يج"), - (0xFCDB, "M", "يح"), - (0xFCDC, "M", "يخ"), - (0xFCDD, "M", "يم"), - (0xFCDE, "M", "يه"), - (0xFCDF, "M", "ئم"), - (0xFCE0, "M", "ئه"), - (0xFCE1, "M", "بم"), - (0xFCE2, "M", "به"), - (0xFCE3, "M", "تم"), - (0xFCE4, "M", "ته"), - (0xFCE5, "M", "ثم"), - (0xFCE6, "M", "ثه"), - (0xFCE7, "M", "سم"), - (0xFCE8, "M", "سه"), - (0xFCE9, "M", "شم"), - (0xFCEA, "M", "شه"), - (0xFCEB, "M", "كل"), - (0xFCEC, "M", "كم"), - (0xFCED, "M", "لم"), - (0xFCEE, "M", "نم"), - (0xFCEF, "M", "نه"), - (0xFCF0, "M", "يم"), - (0xFCF1, "M", "يه"), - (0xFCF2, "M", "ـَّ"), - (0xFCF3, "M", "ـُّ"), - (0xFCF4, "M", "ـِّ"), - (0xFCF5, "M", "طى"), - (0xFCF6, "M", "طي"), - (0xFCF7, "M", "عى"), - (0xFCF8, "M", "عي"), - (0xFCF9, "M", "غى"), - (0xFCFA, "M", "غي"), - (0xFCFB, "M", "سى"), - ] - - -def _seg_48() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xFCFC, "M", "سي"), - (0xFCFD, "M", "شى"), - (0xFCFE, "M", "شي"), - (0xFCFF, "M", "حى"), - (0xFD00, "M", "حي"), - (0xFD01, "M", "جى"), - (0xFD02, "M", "جي"), - (0xFD03, "M", "خى"), - (0xFD04, "M", "خي"), - (0xFD05, "M", "صى"), - (0xFD06, "M", "صي"), - (0xFD07, "M", "ضى"), - (0xFD08, "M", "ضي"), - (0xFD09, "M", "شج"), - (0xFD0A, "M", "شح"), - (0xFD0B, "M", "شخ"), - (0xFD0C, "M", "شم"), - (0xFD0D, "M", "شر"), - (0xFD0E, "M", "سر"), - (0xFD0F, "M", "صر"), - (0xFD10, "M", "ضر"), - (0xFD11, "M", "طى"), - (0xFD12, "M", "طي"), - (0xFD13, "M", "عى"), - (0xFD14, "M", "عي"), - (0xFD15, "M", "غى"), - (0xFD16, "M", "غي"), - (0xFD17, "M", "سى"), - (0xFD18, "M", "سي"), - (0xFD19, "M", "شى"), - (0xFD1A, "M", "شي"), - (0xFD1B, "M", "حى"), - (0xFD1C, "M", "حي"), - (0xFD1D, "M", "جى"), - (0xFD1E, "M", "جي"), - (0xFD1F, "M", "خى"), - (0xFD20, "M", "خي"), - (0xFD21, "M", "صى"), - (0xFD22, "M", "صي"), - (0xFD23, "M", "ضى"), - (0xFD24, "M", "ضي"), - (0xFD25, "M", "شج"), - (0xFD26, "M", "شح"), - (0xFD27, "M", "شخ"), - (0xFD28, "M", "شم"), - (0xFD29, "M", "شر"), - (0xFD2A, "M", "سر"), - (0xFD2B, "M", "صر"), - (0xFD2C, "M", "ضر"), - (0xFD2D, "M", "شج"), - (0xFD2E, "M", "شح"), - (0xFD2F, "M", "شخ"), - (0xFD30, "M", "شم"), - (0xFD31, "M", "سه"), - (0xFD32, "M", "شه"), - (0xFD33, "M", "طم"), - (0xFD34, "M", "سج"), - (0xFD35, "M", "سح"), - (0xFD36, "M", "سخ"), - (0xFD37, "M", "شج"), - (0xFD38, "M", "شح"), - (0xFD39, "M", "شخ"), - (0xFD3A, "M", "طم"), - (0xFD3B, "M", "ظم"), - (0xFD3C, "M", "اً"), - (0xFD3E, "V"), - (0xFD50, "M", "تجم"), - (0xFD51, "M", "تحج"), - (0xFD53, "M", "تحم"), - (0xFD54, "M", "تخم"), - (0xFD55, "M", "تمج"), - (0xFD56, "M", "تمح"), - (0xFD57, "M", "تمخ"), - (0xFD58, "M", "جمح"), - (0xFD5A, "M", "حمي"), - (0xFD5B, "M", "حمى"), - (0xFD5C, "M", "سحج"), - (0xFD5D, "M", "سجح"), - (0xFD5E, "M", "سجى"), - (0xFD5F, "M", "سمح"), - (0xFD61, "M", "سمج"), - (0xFD62, "M", "سمم"), - (0xFD64, "M", "صحح"), - (0xFD66, "M", "صمم"), - (0xFD67, "M", "شحم"), - (0xFD69, "M", "شجي"), - (0xFD6A, "M", "شمخ"), - (0xFD6C, "M", "شمم"), - (0xFD6E, "M", "ضحى"), - (0xFD6F, "M", "ضخم"), - (0xFD71, "M", "طمح"), - (0xFD73, "M", "طمم"), - (0xFD74, "M", "طمي"), - (0xFD75, "M", "عجم"), - (0xFD76, "M", "عمم"), - (0xFD78, "M", "عمى"), - (0xFD79, "M", "غمم"), - (0xFD7A, "M", "غمي"), - (0xFD7B, "M", "غمى"), - (0xFD7C, "M", "فخم"), - ] - - -def _seg_49() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xFD7E, "M", "قمح"), - (0xFD7F, "M", "قمم"), - (0xFD80, "M", "لحم"), - (0xFD81, "M", "لحي"), - (0xFD82, "M", "لحى"), - (0xFD83, "M", "لجج"), - (0xFD85, "M", "لخم"), - (0xFD87, "M", "لمح"), - (0xFD89, "M", "محج"), - (0xFD8A, "M", "محم"), - (0xFD8B, "M", "محي"), - (0xFD8C, "M", "مجح"), - (0xFD8D, "M", "مجم"), - (0xFD8E, "M", "مخج"), - (0xFD8F, "M", "مخم"), - (0xFD90, "X"), - (0xFD92, "M", "مجخ"), - (0xFD93, "M", "همج"), - (0xFD94, "M", "همم"), - (0xFD95, "M", "نحم"), - (0xFD96, "M", "نحى"), - (0xFD97, "M", "نجم"), - (0xFD99, "M", "نجى"), - (0xFD9A, "M", "نمي"), - (0xFD9B, "M", "نمى"), - (0xFD9C, "M", "يمم"), - (0xFD9E, "M", "بخي"), - (0xFD9F, "M", "تجي"), - (0xFDA0, "M", "تجى"), - (0xFDA1, "M", "تخي"), - (0xFDA2, "M", "تخى"), - (0xFDA3, "M", "تمي"), - (0xFDA4, "M", "تمى"), - (0xFDA5, "M", "جمي"), - (0xFDA6, "M", "جحى"), - (0xFDA7, "M", "جمى"), - (0xFDA8, "M", "سخى"), - (0xFDA9, "M", "صحي"), - (0xFDAA, "M", "شحي"), - (0xFDAB, "M", "ضحي"), - (0xFDAC, "M", "لجي"), - (0xFDAD, "M", "لمي"), - (0xFDAE, "M", "يحي"), - (0xFDAF, "M", "يجي"), - (0xFDB0, "M", "يمي"), - (0xFDB1, "M", "ممي"), - (0xFDB2, "M", "قمي"), - (0xFDB3, "M", "نحي"), - (0xFDB4, "M", "قمح"), - (0xFDB5, "M", "لحم"), - (0xFDB6, "M", "عمي"), - (0xFDB7, "M", "كمي"), - (0xFDB8, "M", "نجح"), - (0xFDB9, "M", "مخي"), - (0xFDBA, "M", "لجم"), - (0xFDBB, "M", "كمم"), - (0xFDBC, "M", "لجم"), - (0xFDBD, "M", "نجح"), - (0xFDBE, "M", "جحي"), - (0xFDBF, "M", "حجي"), - (0xFDC0, "M", "مجي"), - (0xFDC1, "M", "فمي"), - (0xFDC2, "M", "بحي"), - (0xFDC3, "M", "كمم"), - (0xFDC4, "M", "عجم"), - (0xFDC5, "M", "صمم"), - (0xFDC6, "M", "سخي"), - (0xFDC7, "M", "نجي"), - (0xFDC8, "X"), - (0xFDCF, "V"), - (0xFDD0, "X"), - (0xFDF0, "M", "صلے"), - (0xFDF1, "M", "قلے"), - (0xFDF2, "M", "الله"), - (0xFDF3, "M", "اكبر"), - (0xFDF4, "M", "محمد"), - (0xFDF5, "M", "صلعم"), - (0xFDF6, "M", "رسول"), - (0xFDF7, "M", "عليه"), - (0xFDF8, "M", "وسلم"), - (0xFDF9, "M", "صلى"), - (0xFDFA, "M", "صلى الله عليه وسلم"), - (0xFDFB, "M", "جل جلاله"), - (0xFDFC, "M", "ریال"), - (0xFDFD, "V"), - (0xFE00, "I"), - (0xFE10, "M", ","), - (0xFE11, "M", "、"), - (0xFE12, "X"), - (0xFE13, "M", ":"), - (0xFE14, "M", ";"), - (0xFE15, "M", "!"), - (0xFE16, "M", "?"), - (0xFE17, "M", "〖"), - (0xFE18, "M", "〗"), - (0xFE19, "X"), - (0xFE20, "V"), - (0xFE30, "X"), - (0xFE31, "M", "—"), - (0xFE32, "M", "–"), - ] - - -def _seg_50() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xFE33, "M", "_"), - (0xFE35, "M", "("), - (0xFE36, "M", ")"), - (0xFE37, "M", "{"), - (0xFE38, "M", "}"), - (0xFE39, "M", "〔"), - (0xFE3A, "M", "〕"), - (0xFE3B, "M", "【"), - (0xFE3C, "M", "】"), - (0xFE3D, "M", "《"), - (0xFE3E, "M", "》"), - (0xFE3F, "M", "〈"), - (0xFE40, "M", "〉"), - (0xFE41, "M", "「"), - (0xFE42, "M", "」"), - (0xFE43, "M", "『"), - (0xFE44, "M", "』"), - (0xFE45, "V"), - (0xFE47, "M", "["), - (0xFE48, "M", "]"), - (0xFE49, "M", " ̅"), - (0xFE4D, "M", "_"), - (0xFE50, "M", ","), - (0xFE51, "M", "、"), - (0xFE52, "X"), - (0xFE54, "M", ";"), - (0xFE55, "M", ":"), - (0xFE56, "M", "?"), - (0xFE57, "M", "!"), - (0xFE58, "M", "—"), - (0xFE59, "M", "("), - (0xFE5A, "M", ")"), - (0xFE5B, "M", "{"), - (0xFE5C, "M", "}"), - (0xFE5D, "M", "〔"), - (0xFE5E, "M", "〕"), - (0xFE5F, "M", "#"), - (0xFE60, "M", "&"), - (0xFE61, "M", "*"), - (0xFE62, "M", "+"), - (0xFE63, "M", "-"), - (0xFE64, "M", "<"), - (0xFE65, "M", ">"), - (0xFE66, "M", "="), - (0xFE67, "X"), - (0xFE68, "M", "\\"), - (0xFE69, "M", "$"), - (0xFE6A, "M", "%"), - (0xFE6B, "M", "@"), - (0xFE6C, "X"), - (0xFE70, "M", " ً"), - (0xFE71, "M", "ـً"), - (0xFE72, "M", " ٌ"), - (0xFE73, "V"), - (0xFE74, "M", " ٍ"), - (0xFE75, "X"), - (0xFE76, "M", " َ"), - (0xFE77, "M", "ـَ"), - (0xFE78, "M", " ُ"), - (0xFE79, "M", "ـُ"), - (0xFE7A, "M", " ِ"), - (0xFE7B, "M", "ـِ"), - (0xFE7C, "M", " ّ"), - (0xFE7D, "M", "ـّ"), - (0xFE7E, "M", " ْ"), - (0xFE7F, "M", "ـْ"), - (0xFE80, "M", "ء"), - (0xFE81, "M", "آ"), - (0xFE83, "M", "أ"), - (0xFE85, "M", "ؤ"), - (0xFE87, "M", "إ"), - (0xFE89, "M", "ئ"), - (0xFE8D, "M", "ا"), - (0xFE8F, "M", "ب"), - (0xFE93, "M", "ة"), - (0xFE95, "M", "ت"), - (0xFE99, "M", "ث"), - (0xFE9D, "M", "ج"), - (0xFEA1, "M", "ح"), - (0xFEA5, "M", "خ"), - (0xFEA9, "M", "د"), - (0xFEAB, "M", "ذ"), - (0xFEAD, "M", "ر"), - (0xFEAF, "M", "ز"), - (0xFEB1, "M", "س"), - (0xFEB5, "M", "ش"), - (0xFEB9, "M", "ص"), - (0xFEBD, "M", "ض"), - (0xFEC1, "M", "ط"), - (0xFEC5, "M", "ظ"), - (0xFEC9, "M", "ع"), - (0xFECD, "M", "غ"), - (0xFED1, "M", "ف"), - (0xFED5, "M", "ق"), - (0xFED9, "M", "ك"), - (0xFEDD, "M", "ل"), - (0xFEE1, "M", "م"), - (0xFEE5, "M", "ن"), - (0xFEE9, "M", "ه"), - (0xFEED, "M", "و"), - ] - - -def _seg_51() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xFEEF, "M", "ى"), - (0xFEF1, "M", "ي"), - (0xFEF5, "M", "لآ"), - (0xFEF7, "M", "لأ"), - (0xFEF9, "M", "لإ"), - (0xFEFB, "M", "لا"), - (0xFEFD, "X"), - (0xFEFF, "I"), - (0xFF00, "X"), - (0xFF01, "M", "!"), - (0xFF02, "M", '"'), - (0xFF03, "M", "#"), - (0xFF04, "M", "$"), - (0xFF05, "M", "%"), - (0xFF06, "M", "&"), - (0xFF07, "M", "'"), - (0xFF08, "M", "("), - (0xFF09, "M", ")"), - (0xFF0A, "M", "*"), - (0xFF0B, "M", "+"), - (0xFF0C, "M", ","), - (0xFF0D, "M", "-"), - (0xFF0E, "M", "."), - (0xFF0F, "M", "/"), - (0xFF10, "M", "0"), - (0xFF11, "M", "1"), - (0xFF12, "M", "2"), - (0xFF13, "M", "3"), - (0xFF14, "M", "4"), - (0xFF15, "M", "5"), - (0xFF16, "M", "6"), - (0xFF17, "M", "7"), - (0xFF18, "M", "8"), - (0xFF19, "M", "9"), - (0xFF1A, "M", ":"), - (0xFF1B, "M", ";"), - (0xFF1C, "M", "<"), - (0xFF1D, "M", "="), - (0xFF1E, "M", ">"), - (0xFF1F, "M", "?"), - (0xFF20, "M", "@"), - (0xFF21, "M", "a"), - (0xFF22, "M", "b"), - (0xFF23, "M", "c"), - (0xFF24, "M", "d"), - (0xFF25, "M", "e"), - (0xFF26, "M", "f"), - (0xFF27, "M", "g"), - (0xFF28, "M", "h"), - (0xFF29, "M", "i"), - (0xFF2A, "M", "j"), - (0xFF2B, "M", "k"), - (0xFF2C, "M", "l"), - (0xFF2D, "M", "m"), - (0xFF2E, "M", "n"), - (0xFF2F, "M", "o"), - (0xFF30, "M", "p"), - (0xFF31, "M", "q"), - (0xFF32, "M", "r"), - (0xFF33, "M", "s"), - (0xFF34, "M", "t"), - (0xFF35, "M", "u"), - (0xFF36, "M", "v"), - (0xFF37, "M", "w"), - (0xFF38, "M", "x"), - (0xFF39, "M", "y"), - (0xFF3A, "M", "z"), - (0xFF3B, "M", "["), - (0xFF3C, "M", "\\"), - (0xFF3D, "M", "]"), - (0xFF3E, "M", "^"), - (0xFF3F, "M", "_"), - (0xFF40, "M", "`"), - (0xFF41, "M", "a"), - (0xFF42, "M", "b"), - (0xFF43, "M", "c"), - (0xFF44, "M", "d"), - (0xFF45, "M", "e"), - (0xFF46, "M", "f"), - (0xFF47, "M", "g"), - (0xFF48, "M", "h"), - (0xFF49, "M", "i"), - (0xFF4A, "M", "j"), - (0xFF4B, "M", "k"), - (0xFF4C, "M", "l"), - (0xFF4D, "M", "m"), - (0xFF4E, "M", "n"), - (0xFF4F, "M", "o"), - (0xFF50, "M", "p"), - (0xFF51, "M", "q"), - (0xFF52, "M", "r"), - (0xFF53, "M", "s"), - (0xFF54, "M", "t"), - (0xFF55, "M", "u"), - (0xFF56, "M", "v"), - (0xFF57, "M", "w"), - (0xFF58, "M", "x"), - (0xFF59, "M", "y"), - (0xFF5A, "M", "z"), - (0xFF5B, "M", "{"), - ] - - -def _seg_52() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xFF5C, "M", "|"), - (0xFF5D, "M", "}"), - (0xFF5E, "M", "~"), - (0xFF5F, "M", "⦅"), - (0xFF60, "M", "⦆"), - (0xFF61, "M", "."), - (0xFF62, "M", "「"), - (0xFF63, "M", "」"), - (0xFF64, "M", "、"), - (0xFF65, "M", "・"), - (0xFF66, "M", "ヲ"), - (0xFF67, "M", "ァ"), - (0xFF68, "M", "ィ"), - (0xFF69, "M", "ゥ"), - (0xFF6A, "M", "ェ"), - (0xFF6B, "M", "ォ"), - (0xFF6C, "M", "ャ"), - (0xFF6D, "M", "ュ"), - (0xFF6E, "M", "ョ"), - (0xFF6F, "M", "ッ"), - (0xFF70, "M", "ー"), - (0xFF71, "M", "ア"), - (0xFF72, "M", "イ"), - (0xFF73, "M", "ウ"), - (0xFF74, "M", "エ"), - (0xFF75, "M", "オ"), - (0xFF76, "M", "カ"), - (0xFF77, "M", "キ"), - (0xFF78, "M", "ク"), - (0xFF79, "M", "ケ"), - (0xFF7A, "M", "コ"), - (0xFF7B, "M", "サ"), - (0xFF7C, "M", "シ"), - (0xFF7D, "M", "ス"), - (0xFF7E, "M", "セ"), - (0xFF7F, "M", "ソ"), - (0xFF80, "M", "タ"), - (0xFF81, "M", "チ"), - (0xFF82, "M", "ツ"), - (0xFF83, "M", "テ"), - (0xFF84, "M", "ト"), - (0xFF85, "M", "ナ"), - (0xFF86, "M", "ニ"), - (0xFF87, "M", "ヌ"), - (0xFF88, "M", "ネ"), - (0xFF89, "M", "ノ"), - (0xFF8A, "M", "ハ"), - (0xFF8B, "M", "ヒ"), - (0xFF8C, "M", "フ"), - (0xFF8D, "M", "ヘ"), - (0xFF8E, "M", "ホ"), - (0xFF8F, "M", "マ"), - (0xFF90, "M", "ミ"), - (0xFF91, "M", "ム"), - (0xFF92, "M", "メ"), - (0xFF93, "M", "モ"), - (0xFF94, "M", "ヤ"), - (0xFF95, "M", "ユ"), - (0xFF96, "M", "ヨ"), - (0xFF97, "M", "ラ"), - (0xFF98, "M", "リ"), - (0xFF99, "M", "ル"), - (0xFF9A, "M", "レ"), - (0xFF9B, "M", "ロ"), - (0xFF9C, "M", "ワ"), - (0xFF9D, "M", "ン"), - (0xFF9E, "M", "゙"), - (0xFF9F, "M", "゚"), - (0xFFA0, "I"), - (0xFFA1, "M", "ᄀ"), - (0xFFA2, "M", "ᄁ"), - (0xFFA3, "M", "ᆪ"), - (0xFFA4, "M", "ᄂ"), - (0xFFA5, "M", "ᆬ"), - (0xFFA6, "M", "ᆭ"), - (0xFFA7, "M", "ᄃ"), - (0xFFA8, "M", "ᄄ"), - (0xFFA9, "M", "ᄅ"), - (0xFFAA, "M", "ᆰ"), - (0xFFAB, "M", "ᆱ"), - (0xFFAC, "M", "ᆲ"), - (0xFFAD, "M", "ᆳ"), - (0xFFAE, "M", "ᆴ"), - (0xFFAF, "M", "ᆵ"), - (0xFFB0, "M", "ᄚ"), - (0xFFB1, "M", "ᄆ"), - (0xFFB2, "M", "ᄇ"), - (0xFFB3, "M", "ᄈ"), - (0xFFB4, "M", "ᄡ"), - (0xFFB5, "M", "ᄉ"), - (0xFFB6, "M", "ᄊ"), - (0xFFB7, "M", "ᄋ"), - (0xFFB8, "M", "ᄌ"), - (0xFFB9, "M", "ᄍ"), - (0xFFBA, "M", "ᄎ"), - (0xFFBB, "M", "ᄏ"), - (0xFFBC, "M", "ᄐ"), - (0xFFBD, "M", "ᄑ"), - (0xFFBE, "M", "ᄒ"), - (0xFFBF, "X"), - ] - - -def _seg_53() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0xFFC2, "M", "ᅡ"), - (0xFFC3, "M", "ᅢ"), - (0xFFC4, "M", "ᅣ"), - (0xFFC5, "M", "ᅤ"), - (0xFFC6, "M", "ᅥ"), - (0xFFC7, "M", "ᅦ"), - (0xFFC8, "X"), - (0xFFCA, "M", "ᅧ"), - (0xFFCB, "M", "ᅨ"), - (0xFFCC, "M", "ᅩ"), - (0xFFCD, "M", "ᅪ"), - (0xFFCE, "M", "ᅫ"), - (0xFFCF, "M", "ᅬ"), - (0xFFD0, "X"), - (0xFFD2, "M", "ᅭ"), - (0xFFD3, "M", "ᅮ"), - (0xFFD4, "M", "ᅯ"), - (0xFFD5, "M", "ᅰ"), - (0xFFD6, "M", "ᅱ"), - (0xFFD7, "M", "ᅲ"), - (0xFFD8, "X"), - (0xFFDA, "M", "ᅳ"), - (0xFFDB, "M", "ᅴ"), - (0xFFDC, "M", "ᅵ"), - (0xFFDD, "X"), - (0xFFE0, "M", "¢"), - (0xFFE1, "M", "£"), - (0xFFE2, "M", "¬"), - (0xFFE3, "M", " ̄"), - (0xFFE4, "M", "¦"), - (0xFFE5, "M", "¥"), - (0xFFE6, "M", "₩"), - (0xFFE7, "X"), - (0xFFE8, "M", "│"), - (0xFFE9, "M", "←"), - (0xFFEA, "M", "↑"), - (0xFFEB, "M", "→"), - (0xFFEC, "M", "↓"), - (0xFFED, "M", "■"), - (0xFFEE, "M", "○"), - (0xFFEF, "X"), - (0x10000, "V"), - (0x1000C, "X"), - (0x1000D, "V"), - (0x10027, "X"), - (0x10028, "V"), - (0x1003B, "X"), - (0x1003C, "V"), - (0x1003E, "X"), - (0x1003F, "V"), - (0x1004E, "X"), - (0x10050, "V"), - (0x1005E, "X"), - (0x10080, "V"), - (0x100FB, "X"), - (0x10100, "V"), - (0x10103, "X"), - (0x10107, "V"), - (0x10134, "X"), - (0x10137, "V"), - (0x1018F, "X"), - (0x10190, "V"), - (0x1019D, "X"), - (0x101A0, "V"), - (0x101A1, "X"), - (0x101D0, "V"), - (0x101FE, "X"), - (0x10280, "V"), - (0x1029D, "X"), - (0x102A0, "V"), - (0x102D1, "X"), - (0x102E0, "V"), - (0x102FC, "X"), - (0x10300, "V"), - (0x10324, "X"), - (0x1032D, "V"), - (0x1034B, "X"), - (0x10350, "V"), - (0x1037B, "X"), - (0x10380, "V"), - (0x1039E, "X"), - (0x1039F, "V"), - (0x103C4, "X"), - (0x103C8, "V"), - (0x103D6, "X"), - (0x10400, "M", "𐐨"), - (0x10401, "M", "𐐩"), - (0x10402, "M", "𐐪"), - (0x10403, "M", "𐐫"), - (0x10404, "M", "𐐬"), - (0x10405, "M", "𐐭"), - (0x10406, "M", "𐐮"), - (0x10407, "M", "𐐯"), - (0x10408, "M", "𐐰"), - (0x10409, "M", "𐐱"), - (0x1040A, "M", "𐐲"), - (0x1040B, "M", "𐐳"), - (0x1040C, "M", "𐐴"), - (0x1040D, "M", "𐐵"), - (0x1040E, "M", "𐐶"), - ] - - -def _seg_54() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1040F, "M", "𐐷"), - (0x10410, "M", "𐐸"), - (0x10411, "M", "𐐹"), - (0x10412, "M", "𐐺"), - (0x10413, "M", "𐐻"), - (0x10414, "M", "𐐼"), - (0x10415, "M", "𐐽"), - (0x10416, "M", "𐐾"), - (0x10417, "M", "𐐿"), - (0x10418, "M", "𐑀"), - (0x10419, "M", "𐑁"), - (0x1041A, "M", "𐑂"), - (0x1041B, "M", "𐑃"), - (0x1041C, "M", "𐑄"), - (0x1041D, "M", "𐑅"), - (0x1041E, "M", "𐑆"), - (0x1041F, "M", "𐑇"), - (0x10420, "M", "𐑈"), - (0x10421, "M", "𐑉"), - (0x10422, "M", "𐑊"), - (0x10423, "M", "𐑋"), - (0x10424, "M", "𐑌"), - (0x10425, "M", "𐑍"), - (0x10426, "M", "𐑎"), - (0x10427, "M", "𐑏"), - (0x10428, "V"), - (0x1049E, "X"), - (0x104A0, "V"), - (0x104AA, "X"), - (0x104B0, "M", "𐓘"), - (0x104B1, "M", "𐓙"), - (0x104B2, "M", "𐓚"), - (0x104B3, "M", "𐓛"), - (0x104B4, "M", "𐓜"), - (0x104B5, "M", "𐓝"), - (0x104B6, "M", "𐓞"), - (0x104B7, "M", "𐓟"), - (0x104B8, "M", "𐓠"), - (0x104B9, "M", "𐓡"), - (0x104BA, "M", "𐓢"), - (0x104BB, "M", "𐓣"), - (0x104BC, "M", "𐓤"), - (0x104BD, "M", "𐓥"), - (0x104BE, "M", "𐓦"), - (0x104BF, "M", "𐓧"), - (0x104C0, "M", "𐓨"), - (0x104C1, "M", "𐓩"), - (0x104C2, "M", "𐓪"), - (0x104C3, "M", "𐓫"), - (0x104C4, "M", "𐓬"), - (0x104C5, "M", "𐓭"), - (0x104C6, "M", "𐓮"), - (0x104C7, "M", "𐓯"), - (0x104C8, "M", "𐓰"), - (0x104C9, "M", "𐓱"), - (0x104CA, "M", "𐓲"), - (0x104CB, "M", "𐓳"), - (0x104CC, "M", "𐓴"), - (0x104CD, "M", "𐓵"), - (0x104CE, "M", "𐓶"), - (0x104CF, "M", "𐓷"), - (0x104D0, "M", "𐓸"), - (0x104D1, "M", "𐓹"), - (0x104D2, "M", "𐓺"), - (0x104D3, "M", "𐓻"), - (0x104D4, "X"), - (0x104D8, "V"), - (0x104FC, "X"), - (0x10500, "V"), - (0x10528, "X"), - (0x10530, "V"), - (0x10564, "X"), - (0x1056F, "V"), - (0x10570, "M", "𐖗"), - (0x10571, "M", "𐖘"), - (0x10572, "M", "𐖙"), - (0x10573, "M", "𐖚"), - (0x10574, "M", "𐖛"), - (0x10575, "M", "𐖜"), - (0x10576, "M", "𐖝"), - (0x10577, "M", "𐖞"), - (0x10578, "M", "𐖟"), - (0x10579, "M", "𐖠"), - (0x1057A, "M", "𐖡"), - (0x1057B, "X"), - (0x1057C, "M", "𐖣"), - (0x1057D, "M", "𐖤"), - (0x1057E, "M", "𐖥"), - (0x1057F, "M", "𐖦"), - (0x10580, "M", "𐖧"), - (0x10581, "M", "𐖨"), - (0x10582, "M", "𐖩"), - (0x10583, "M", "𐖪"), - (0x10584, "M", "𐖫"), - (0x10585, "M", "𐖬"), - (0x10586, "M", "𐖭"), - (0x10587, "M", "𐖮"), - (0x10588, "M", "𐖯"), - (0x10589, "M", "𐖰"), - (0x1058A, "M", "𐖱"), - ] - - -def _seg_55() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1058B, "X"), - (0x1058C, "M", "𐖳"), - (0x1058D, "M", "𐖴"), - (0x1058E, "M", "𐖵"), - (0x1058F, "M", "𐖶"), - (0x10590, "M", "𐖷"), - (0x10591, "M", "𐖸"), - (0x10592, "M", "𐖹"), - (0x10593, "X"), - (0x10594, "M", "𐖻"), - (0x10595, "M", "𐖼"), - (0x10596, "X"), - (0x10597, "V"), - (0x105A2, "X"), - (0x105A3, "V"), - (0x105B2, "X"), - (0x105B3, "V"), - (0x105BA, "X"), - (0x105BB, "V"), - (0x105BD, "X"), - (0x105C0, "V"), - (0x105F4, "X"), - (0x10600, "V"), - (0x10737, "X"), - (0x10740, "V"), - (0x10756, "X"), - (0x10760, "V"), - (0x10768, "X"), - (0x10780, "V"), - (0x10781, "M", "ː"), - (0x10782, "M", "ˑ"), - (0x10783, "M", "æ"), - (0x10784, "M", "ʙ"), - (0x10785, "M", "ɓ"), - (0x10786, "X"), - (0x10787, "M", "ʣ"), - (0x10788, "M", "ꭦ"), - (0x10789, "M", "ʥ"), - (0x1078A, "M", "ʤ"), - (0x1078B, "M", "ɖ"), - (0x1078C, "M", "ɗ"), - (0x1078D, "M", "ᶑ"), - (0x1078E, "M", "ɘ"), - (0x1078F, "M", "ɞ"), - (0x10790, "M", "ʩ"), - (0x10791, "M", "ɤ"), - (0x10792, "M", "ɢ"), - (0x10793, "M", "ɠ"), - (0x10794, "M", "ʛ"), - (0x10795, "M", "ħ"), - (0x10796, "M", "ʜ"), - (0x10797, "M", "ɧ"), - (0x10798, "M", "ʄ"), - (0x10799, "M", "ʪ"), - (0x1079A, "M", "ʫ"), - (0x1079B, "M", "ɬ"), - (0x1079C, "M", "𝼄"), - (0x1079D, "M", "ꞎ"), - (0x1079E, "M", "ɮ"), - (0x1079F, "M", "𝼅"), - (0x107A0, "M", "ʎ"), - (0x107A1, "M", "𝼆"), - (0x107A2, "M", "ø"), - (0x107A3, "M", "ɶ"), - (0x107A4, "M", "ɷ"), - (0x107A5, "M", "q"), - (0x107A6, "M", "ɺ"), - (0x107A7, "M", "𝼈"), - (0x107A8, "M", "ɽ"), - (0x107A9, "M", "ɾ"), - (0x107AA, "M", "ʀ"), - (0x107AB, "M", "ʨ"), - (0x107AC, "M", "ʦ"), - (0x107AD, "M", "ꭧ"), - (0x107AE, "M", "ʧ"), - (0x107AF, "M", "ʈ"), - (0x107B0, "M", "ⱱ"), - (0x107B1, "X"), - (0x107B2, "M", "ʏ"), - (0x107B3, "M", "ʡ"), - (0x107B4, "M", "ʢ"), - (0x107B5, "M", "ʘ"), - (0x107B6, "M", "ǀ"), - (0x107B7, "M", "ǁ"), - (0x107B8, "M", "ǂ"), - (0x107B9, "M", "𝼊"), - (0x107BA, "M", "𝼞"), - (0x107BB, "X"), - (0x10800, "V"), - (0x10806, "X"), - (0x10808, "V"), - (0x10809, "X"), - (0x1080A, "V"), - (0x10836, "X"), - (0x10837, "V"), - (0x10839, "X"), - (0x1083C, "V"), - (0x1083D, "X"), - (0x1083F, "V"), - (0x10856, "X"), - ] - - -def _seg_56() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x10857, "V"), - (0x1089F, "X"), - (0x108A7, "V"), - (0x108B0, "X"), - (0x108E0, "V"), - (0x108F3, "X"), - (0x108F4, "V"), - (0x108F6, "X"), - (0x108FB, "V"), - (0x1091C, "X"), - (0x1091F, "V"), - (0x1093A, "X"), - (0x1093F, "V"), - (0x10940, "X"), - (0x10980, "V"), - (0x109B8, "X"), - (0x109BC, "V"), - (0x109D0, "X"), - (0x109D2, "V"), - (0x10A04, "X"), - (0x10A05, "V"), - (0x10A07, "X"), - (0x10A0C, "V"), - (0x10A14, "X"), - (0x10A15, "V"), - (0x10A18, "X"), - (0x10A19, "V"), - (0x10A36, "X"), - (0x10A38, "V"), - (0x10A3B, "X"), - (0x10A3F, "V"), - (0x10A49, "X"), - (0x10A50, "V"), - (0x10A59, "X"), - (0x10A60, "V"), - (0x10AA0, "X"), - (0x10AC0, "V"), - (0x10AE7, "X"), - (0x10AEB, "V"), - (0x10AF7, "X"), - (0x10B00, "V"), - (0x10B36, "X"), - (0x10B39, "V"), - (0x10B56, "X"), - (0x10B58, "V"), - (0x10B73, "X"), - (0x10B78, "V"), - (0x10B92, "X"), - (0x10B99, "V"), - (0x10B9D, "X"), - (0x10BA9, "V"), - (0x10BB0, "X"), - (0x10C00, "V"), - (0x10C49, "X"), - (0x10C80, "M", "𐳀"), - (0x10C81, "M", "𐳁"), - (0x10C82, "M", "𐳂"), - (0x10C83, "M", "𐳃"), - (0x10C84, "M", "𐳄"), - (0x10C85, "M", "𐳅"), - (0x10C86, "M", "𐳆"), - (0x10C87, "M", "𐳇"), - (0x10C88, "M", "𐳈"), - (0x10C89, "M", "𐳉"), - (0x10C8A, "M", "𐳊"), - (0x10C8B, "M", "𐳋"), - (0x10C8C, "M", "𐳌"), - (0x10C8D, "M", "𐳍"), - (0x10C8E, "M", "𐳎"), - (0x10C8F, "M", "𐳏"), - (0x10C90, "M", "𐳐"), - (0x10C91, "M", "𐳑"), - (0x10C92, "M", "𐳒"), - (0x10C93, "M", "𐳓"), - (0x10C94, "M", "𐳔"), - (0x10C95, "M", "𐳕"), - (0x10C96, "M", "𐳖"), - (0x10C97, "M", "𐳗"), - (0x10C98, "M", "𐳘"), - (0x10C99, "M", "𐳙"), - (0x10C9A, "M", "𐳚"), - (0x10C9B, "M", "𐳛"), - (0x10C9C, "M", "𐳜"), - (0x10C9D, "M", "𐳝"), - (0x10C9E, "M", "𐳞"), - (0x10C9F, "M", "𐳟"), - (0x10CA0, "M", "𐳠"), - (0x10CA1, "M", "𐳡"), - (0x10CA2, "M", "𐳢"), - (0x10CA3, "M", "𐳣"), - (0x10CA4, "M", "𐳤"), - (0x10CA5, "M", "𐳥"), - (0x10CA6, "M", "𐳦"), - (0x10CA7, "M", "𐳧"), - (0x10CA8, "M", "𐳨"), - (0x10CA9, "M", "𐳩"), - (0x10CAA, "M", "𐳪"), - (0x10CAB, "M", "𐳫"), - (0x10CAC, "M", "𐳬"), - (0x10CAD, "M", "𐳭"), - ] - - -def _seg_57() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x10CAE, "M", "𐳮"), - (0x10CAF, "M", "𐳯"), - (0x10CB0, "M", "𐳰"), - (0x10CB1, "M", "𐳱"), - (0x10CB2, "M", "𐳲"), - (0x10CB3, "X"), - (0x10CC0, "V"), - (0x10CF3, "X"), - (0x10CFA, "V"), - (0x10D28, "X"), - (0x10D30, "V"), - (0x10D3A, "X"), - (0x10D40, "V"), - (0x10D50, "M", "𐵰"), - (0x10D51, "M", "𐵱"), - (0x10D52, "M", "𐵲"), - (0x10D53, "M", "𐵳"), - (0x10D54, "M", "𐵴"), - (0x10D55, "M", "𐵵"), - (0x10D56, "M", "𐵶"), - (0x10D57, "M", "𐵷"), - (0x10D58, "M", "𐵸"), - (0x10D59, "M", "𐵹"), - (0x10D5A, "M", "𐵺"), - (0x10D5B, "M", "𐵻"), - (0x10D5C, "M", "𐵼"), - (0x10D5D, "M", "𐵽"), - (0x10D5E, "M", "𐵾"), - (0x10D5F, "M", "𐵿"), - (0x10D60, "M", "𐶀"), - (0x10D61, "M", "𐶁"), - (0x10D62, "M", "𐶂"), - (0x10D63, "M", "𐶃"), - (0x10D64, "M", "𐶄"), - (0x10D65, "M", "𐶅"), - (0x10D66, "X"), - (0x10D69, "V"), - (0x10D86, "X"), - (0x10D8E, "V"), - (0x10D90, "X"), - (0x10E60, "V"), - (0x10E7F, "X"), - (0x10E80, "V"), - (0x10EAA, "X"), - (0x10EAB, "V"), - (0x10EAE, "X"), - (0x10EB0, "V"), - (0x10EB2, "X"), - (0x10EC2, "V"), - (0x10EC5, "X"), - (0x10EFC, "V"), - (0x10F28, "X"), - (0x10F30, "V"), - (0x10F5A, "X"), - (0x10F70, "V"), - (0x10F8A, "X"), - (0x10FB0, "V"), - (0x10FCC, "X"), - (0x10FE0, "V"), - (0x10FF7, "X"), - (0x11000, "V"), - (0x1104E, "X"), - (0x11052, "V"), - (0x11076, "X"), - (0x1107F, "V"), - (0x110BD, "X"), - (0x110BE, "V"), - (0x110C3, "X"), - (0x110D0, "V"), - (0x110E9, "X"), - (0x110F0, "V"), - (0x110FA, "X"), - (0x11100, "V"), - (0x11135, "X"), - (0x11136, "V"), - (0x11148, "X"), - (0x11150, "V"), - (0x11177, "X"), - (0x11180, "V"), - (0x111E0, "X"), - (0x111E1, "V"), - (0x111F5, "X"), - (0x11200, "V"), - (0x11212, "X"), - (0x11213, "V"), - (0x11242, "X"), - (0x11280, "V"), - (0x11287, "X"), - (0x11288, "V"), - (0x11289, "X"), - (0x1128A, "V"), - (0x1128E, "X"), - (0x1128F, "V"), - (0x1129E, "X"), - (0x1129F, "V"), - (0x112AA, "X"), - (0x112B0, "V"), - (0x112EB, "X"), - (0x112F0, "V"), - (0x112FA, "X"), - ] - - -def _seg_58() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x11300, "V"), - (0x11304, "X"), - (0x11305, "V"), - (0x1130D, "X"), - (0x1130F, "V"), - (0x11311, "X"), - (0x11313, "V"), - (0x11329, "X"), - (0x1132A, "V"), - (0x11331, "X"), - (0x11332, "V"), - (0x11334, "X"), - (0x11335, "V"), - (0x1133A, "X"), - (0x1133B, "V"), - (0x11345, "X"), - (0x11347, "V"), - (0x11349, "X"), - (0x1134B, "V"), - (0x1134E, "X"), - (0x11350, "V"), - (0x11351, "X"), - (0x11357, "V"), - (0x11358, "X"), - (0x1135D, "V"), - (0x11364, "X"), - (0x11366, "V"), - (0x1136D, "X"), - (0x11370, "V"), - (0x11375, "X"), - (0x11380, "V"), - (0x1138A, "X"), - (0x1138B, "V"), - (0x1138C, "X"), - (0x1138E, "V"), - (0x1138F, "X"), - (0x11390, "V"), - (0x113B6, "X"), - (0x113B7, "V"), - (0x113C1, "X"), - (0x113C2, "V"), - (0x113C3, "X"), - (0x113C5, "V"), - (0x113C6, "X"), - (0x113C7, "V"), - (0x113CB, "X"), - (0x113CC, "V"), - (0x113D6, "X"), - (0x113D7, "V"), - (0x113D9, "X"), - (0x113E1, "V"), - (0x113E3, "X"), - (0x11400, "V"), - (0x1145C, "X"), - (0x1145D, "V"), - (0x11462, "X"), - (0x11480, "V"), - (0x114C8, "X"), - (0x114D0, "V"), - (0x114DA, "X"), - (0x11580, "V"), - (0x115B6, "X"), - (0x115B8, "V"), - (0x115DE, "X"), - (0x11600, "V"), - (0x11645, "X"), - (0x11650, "V"), - (0x1165A, "X"), - (0x11660, "V"), - (0x1166D, "X"), - (0x11680, "V"), - (0x116BA, "X"), - (0x116C0, "V"), - (0x116CA, "X"), - (0x116D0, "V"), - (0x116E4, "X"), - (0x11700, "V"), - (0x1171B, "X"), - (0x1171D, "V"), - (0x1172C, "X"), - (0x11730, "V"), - (0x11747, "X"), - (0x11800, "V"), - (0x1183C, "X"), - (0x118A0, "M", "𑣀"), - (0x118A1, "M", "𑣁"), - (0x118A2, "M", "𑣂"), - (0x118A3, "M", "𑣃"), - (0x118A4, "M", "𑣄"), - (0x118A5, "M", "𑣅"), - (0x118A6, "M", "𑣆"), - (0x118A7, "M", "𑣇"), - (0x118A8, "M", "𑣈"), - (0x118A9, "M", "𑣉"), - (0x118AA, "M", "𑣊"), - (0x118AB, "M", "𑣋"), - (0x118AC, "M", "𑣌"), - (0x118AD, "M", "𑣍"), - (0x118AE, "M", "𑣎"), - (0x118AF, "M", "𑣏"), - ] - - -def _seg_59() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x118B0, "M", "𑣐"), - (0x118B1, "M", "𑣑"), - (0x118B2, "M", "𑣒"), - (0x118B3, "M", "𑣓"), - (0x118B4, "M", "𑣔"), - (0x118B5, "M", "𑣕"), - (0x118B6, "M", "𑣖"), - (0x118B7, "M", "𑣗"), - (0x118B8, "M", "𑣘"), - (0x118B9, "M", "𑣙"), - (0x118BA, "M", "𑣚"), - (0x118BB, "M", "𑣛"), - (0x118BC, "M", "𑣜"), - (0x118BD, "M", "𑣝"), - (0x118BE, "M", "𑣞"), - (0x118BF, "M", "𑣟"), - (0x118C0, "V"), - (0x118F3, "X"), - (0x118FF, "V"), - (0x11907, "X"), - (0x11909, "V"), - (0x1190A, "X"), - (0x1190C, "V"), - (0x11914, "X"), - (0x11915, "V"), - (0x11917, "X"), - (0x11918, "V"), - (0x11936, "X"), - (0x11937, "V"), - (0x11939, "X"), - (0x1193B, "V"), - (0x11947, "X"), - (0x11950, "V"), - (0x1195A, "X"), - (0x119A0, "V"), - (0x119A8, "X"), - (0x119AA, "V"), - (0x119D8, "X"), - (0x119DA, "V"), - (0x119E5, "X"), - (0x11A00, "V"), - (0x11A48, "X"), - (0x11A50, "V"), - (0x11AA3, "X"), - (0x11AB0, "V"), - (0x11AF9, "X"), - (0x11B00, "V"), - (0x11B0A, "X"), - (0x11BC0, "V"), - (0x11BE2, "X"), - (0x11BF0, "V"), - (0x11BFA, "X"), - (0x11C00, "V"), - (0x11C09, "X"), - (0x11C0A, "V"), - (0x11C37, "X"), - (0x11C38, "V"), - (0x11C46, "X"), - (0x11C50, "V"), - (0x11C6D, "X"), - (0x11C70, "V"), - (0x11C90, "X"), - (0x11C92, "V"), - (0x11CA8, "X"), - (0x11CA9, "V"), - (0x11CB7, "X"), - (0x11D00, "V"), - (0x11D07, "X"), - (0x11D08, "V"), - (0x11D0A, "X"), - (0x11D0B, "V"), - (0x11D37, "X"), - (0x11D3A, "V"), - (0x11D3B, "X"), - (0x11D3C, "V"), - (0x11D3E, "X"), - (0x11D3F, "V"), - (0x11D48, "X"), - (0x11D50, "V"), - (0x11D5A, "X"), - (0x11D60, "V"), - (0x11D66, "X"), - (0x11D67, "V"), - (0x11D69, "X"), - (0x11D6A, "V"), - (0x11D8F, "X"), - (0x11D90, "V"), - (0x11D92, "X"), - (0x11D93, "V"), - (0x11D99, "X"), - (0x11DA0, "V"), - (0x11DAA, "X"), - (0x11EE0, "V"), - (0x11EF9, "X"), - (0x11F00, "V"), - (0x11F11, "X"), - (0x11F12, "V"), - (0x11F3B, "X"), - (0x11F3E, "V"), - (0x11F5B, "X"), - ] - - -def _seg_60() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x11FB0, "V"), - (0x11FB1, "X"), - (0x11FC0, "V"), - (0x11FF2, "X"), - (0x11FFF, "V"), - (0x1239A, "X"), - (0x12400, "V"), - (0x1246F, "X"), - (0x12470, "V"), - (0x12475, "X"), - (0x12480, "V"), - (0x12544, "X"), - (0x12F90, "V"), - (0x12FF3, "X"), - (0x13000, "V"), - (0x13430, "X"), - (0x13440, "V"), - (0x13456, "X"), - (0x13460, "V"), - (0x143FB, "X"), - (0x14400, "V"), - (0x14647, "X"), - (0x16100, "V"), - (0x1613A, "X"), - (0x16800, "V"), - (0x16A39, "X"), - (0x16A40, "V"), - (0x16A5F, "X"), - (0x16A60, "V"), - (0x16A6A, "X"), - (0x16A6E, "V"), - (0x16ABF, "X"), - (0x16AC0, "V"), - (0x16ACA, "X"), - (0x16AD0, "V"), - (0x16AEE, "X"), - (0x16AF0, "V"), - (0x16AF6, "X"), - (0x16B00, "V"), - (0x16B46, "X"), - (0x16B50, "V"), - (0x16B5A, "X"), - (0x16B5B, "V"), - (0x16B62, "X"), - (0x16B63, "V"), - (0x16B78, "X"), - (0x16B7D, "V"), - (0x16B90, "X"), - (0x16D40, "V"), - (0x16D7A, "X"), - (0x16E40, "M", "𖹠"), - (0x16E41, "M", "𖹡"), - (0x16E42, "M", "𖹢"), - (0x16E43, "M", "𖹣"), - (0x16E44, "M", "𖹤"), - (0x16E45, "M", "𖹥"), - (0x16E46, "M", "𖹦"), - (0x16E47, "M", "𖹧"), - (0x16E48, "M", "𖹨"), - (0x16E49, "M", "𖹩"), - (0x16E4A, "M", "𖹪"), - (0x16E4B, "M", "𖹫"), - (0x16E4C, "M", "𖹬"), - (0x16E4D, "M", "𖹭"), - (0x16E4E, "M", "𖹮"), - (0x16E4F, "M", "𖹯"), - (0x16E50, "M", "𖹰"), - (0x16E51, "M", "𖹱"), - (0x16E52, "M", "𖹲"), - (0x16E53, "M", "𖹳"), - (0x16E54, "M", "𖹴"), - (0x16E55, "M", "𖹵"), - (0x16E56, "M", "𖹶"), - (0x16E57, "M", "𖹷"), - (0x16E58, "M", "𖹸"), - (0x16E59, "M", "𖹹"), - (0x16E5A, "M", "𖹺"), - (0x16E5B, "M", "𖹻"), - (0x16E5C, "M", "𖹼"), - (0x16E5D, "M", "𖹽"), - (0x16E5E, "M", "𖹾"), - (0x16E5F, "M", "𖹿"), - (0x16E60, "V"), - (0x16E9B, "X"), - (0x16F00, "V"), - (0x16F4B, "X"), - (0x16F4F, "V"), - (0x16F88, "X"), - (0x16F8F, "V"), - (0x16FA0, "X"), - (0x16FE0, "V"), - (0x16FE5, "X"), - (0x16FF0, "V"), - (0x16FF2, "X"), - (0x17000, "V"), - (0x187F8, "X"), - (0x18800, "V"), - (0x18CD6, "X"), - (0x18CFF, "V"), - (0x18D09, "X"), - ] - - -def _seg_61() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1AFF0, "V"), - (0x1AFF4, "X"), - (0x1AFF5, "V"), - (0x1AFFC, "X"), - (0x1AFFD, "V"), - (0x1AFFF, "X"), - (0x1B000, "V"), - (0x1B123, "X"), - (0x1B132, "V"), - (0x1B133, "X"), - (0x1B150, "V"), - (0x1B153, "X"), - (0x1B155, "V"), - (0x1B156, "X"), - (0x1B164, "V"), - (0x1B168, "X"), - (0x1B170, "V"), - (0x1B2FC, "X"), - (0x1BC00, "V"), - (0x1BC6B, "X"), - (0x1BC70, "V"), - (0x1BC7D, "X"), - (0x1BC80, "V"), - (0x1BC89, "X"), - (0x1BC90, "V"), - (0x1BC9A, "X"), - (0x1BC9C, "V"), - (0x1BCA0, "I"), - (0x1BCA4, "X"), - (0x1CC00, "V"), - (0x1CCD6, "M", "a"), - (0x1CCD7, "M", "b"), - (0x1CCD8, "M", "c"), - (0x1CCD9, "M", "d"), - (0x1CCDA, "M", "e"), - (0x1CCDB, "M", "f"), - (0x1CCDC, "M", "g"), - (0x1CCDD, "M", "h"), - (0x1CCDE, "M", "i"), - (0x1CCDF, "M", "j"), - (0x1CCE0, "M", "k"), - (0x1CCE1, "M", "l"), - (0x1CCE2, "M", "m"), - (0x1CCE3, "M", "n"), - (0x1CCE4, "M", "o"), - (0x1CCE5, "M", "p"), - (0x1CCE6, "M", "q"), - (0x1CCE7, "M", "r"), - (0x1CCE8, "M", "s"), - (0x1CCE9, "M", "t"), - (0x1CCEA, "M", "u"), - (0x1CCEB, "M", "v"), - (0x1CCEC, "M", "w"), - (0x1CCED, "M", "x"), - (0x1CCEE, "M", "y"), - (0x1CCEF, "M", "z"), - (0x1CCF0, "M", "0"), - (0x1CCF1, "M", "1"), - (0x1CCF2, "M", "2"), - (0x1CCF3, "M", "3"), - (0x1CCF4, "M", "4"), - (0x1CCF5, "M", "5"), - (0x1CCF6, "M", "6"), - (0x1CCF7, "M", "7"), - (0x1CCF8, "M", "8"), - (0x1CCF9, "M", "9"), - (0x1CCFA, "X"), - (0x1CD00, "V"), - (0x1CEB4, "X"), - (0x1CF00, "V"), - (0x1CF2E, "X"), - (0x1CF30, "V"), - (0x1CF47, "X"), - (0x1CF50, "V"), - (0x1CFC4, "X"), - (0x1D000, "V"), - (0x1D0F6, "X"), - (0x1D100, "V"), - (0x1D127, "X"), - (0x1D129, "V"), - (0x1D15E, "M", "𝅗𝅥"), - (0x1D15F, "M", "𝅘𝅥"), - (0x1D160, "M", "𝅘𝅥𝅮"), - (0x1D161, "M", "𝅘𝅥𝅯"), - (0x1D162, "M", "𝅘𝅥𝅰"), - (0x1D163, "M", "𝅘𝅥𝅱"), - (0x1D164, "M", "𝅘𝅥𝅲"), - (0x1D165, "V"), - (0x1D173, "I"), - (0x1D17B, "V"), - (0x1D1BB, "M", "𝆹𝅥"), - (0x1D1BC, "M", "𝆺𝅥"), - (0x1D1BD, "M", "𝆹𝅥𝅮"), - (0x1D1BE, "M", "𝆺𝅥𝅮"), - (0x1D1BF, "M", "𝆹𝅥𝅯"), - (0x1D1C0, "M", "𝆺𝅥𝅯"), - (0x1D1C1, "V"), - (0x1D1EB, "X"), - (0x1D200, "V"), - (0x1D246, "X"), - ] - - -def _seg_62() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1D2C0, "V"), - (0x1D2D4, "X"), - (0x1D2E0, "V"), - (0x1D2F4, "X"), - (0x1D300, "V"), - (0x1D357, "X"), - (0x1D360, "V"), - (0x1D379, "X"), - (0x1D400, "M", "a"), - (0x1D401, "M", "b"), - (0x1D402, "M", "c"), - (0x1D403, "M", "d"), - (0x1D404, "M", "e"), - (0x1D405, "M", "f"), - (0x1D406, "M", "g"), - (0x1D407, "M", "h"), - (0x1D408, "M", "i"), - (0x1D409, "M", "j"), - (0x1D40A, "M", "k"), - (0x1D40B, "M", "l"), - (0x1D40C, "M", "m"), - (0x1D40D, "M", "n"), - (0x1D40E, "M", "o"), - (0x1D40F, "M", "p"), - (0x1D410, "M", "q"), - (0x1D411, "M", "r"), - (0x1D412, "M", "s"), - (0x1D413, "M", "t"), - (0x1D414, "M", "u"), - (0x1D415, "M", "v"), - (0x1D416, "M", "w"), - (0x1D417, "M", "x"), - (0x1D418, "M", "y"), - (0x1D419, "M", "z"), - (0x1D41A, "M", "a"), - (0x1D41B, "M", "b"), - (0x1D41C, "M", "c"), - (0x1D41D, "M", "d"), - (0x1D41E, "M", "e"), - (0x1D41F, "M", "f"), - (0x1D420, "M", "g"), - (0x1D421, "M", "h"), - (0x1D422, "M", "i"), - (0x1D423, "M", "j"), - (0x1D424, "M", "k"), - (0x1D425, "M", "l"), - (0x1D426, "M", "m"), - (0x1D427, "M", "n"), - (0x1D428, "M", "o"), - (0x1D429, "M", "p"), - (0x1D42A, "M", "q"), - (0x1D42B, "M", "r"), - (0x1D42C, "M", "s"), - (0x1D42D, "M", "t"), - (0x1D42E, "M", "u"), - (0x1D42F, "M", "v"), - (0x1D430, "M", "w"), - (0x1D431, "M", "x"), - (0x1D432, "M", "y"), - (0x1D433, "M", "z"), - (0x1D434, "M", "a"), - (0x1D435, "M", "b"), - (0x1D436, "M", "c"), - (0x1D437, "M", "d"), - (0x1D438, "M", "e"), - (0x1D439, "M", "f"), - (0x1D43A, "M", "g"), - (0x1D43B, "M", "h"), - (0x1D43C, "M", "i"), - (0x1D43D, "M", "j"), - (0x1D43E, "M", "k"), - (0x1D43F, "M", "l"), - (0x1D440, "M", "m"), - (0x1D441, "M", "n"), - (0x1D442, "M", "o"), - (0x1D443, "M", "p"), - (0x1D444, "M", "q"), - (0x1D445, "M", "r"), - (0x1D446, "M", "s"), - (0x1D447, "M", "t"), - (0x1D448, "M", "u"), - (0x1D449, "M", "v"), - (0x1D44A, "M", "w"), - (0x1D44B, "M", "x"), - (0x1D44C, "M", "y"), - (0x1D44D, "M", "z"), - (0x1D44E, "M", "a"), - (0x1D44F, "M", "b"), - (0x1D450, "M", "c"), - (0x1D451, "M", "d"), - (0x1D452, "M", "e"), - (0x1D453, "M", "f"), - (0x1D454, "M", "g"), - (0x1D455, "X"), - (0x1D456, "M", "i"), - (0x1D457, "M", "j"), - (0x1D458, "M", "k"), - (0x1D459, "M", "l"), - (0x1D45A, "M", "m"), - (0x1D45B, "M", "n"), - ] - - -def _seg_63() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1D45C, "M", "o"), - (0x1D45D, "M", "p"), - (0x1D45E, "M", "q"), - (0x1D45F, "M", "r"), - (0x1D460, "M", "s"), - (0x1D461, "M", "t"), - (0x1D462, "M", "u"), - (0x1D463, "M", "v"), - (0x1D464, "M", "w"), - (0x1D465, "M", "x"), - (0x1D466, "M", "y"), - (0x1D467, "M", "z"), - (0x1D468, "M", "a"), - (0x1D469, "M", "b"), - (0x1D46A, "M", "c"), - (0x1D46B, "M", "d"), - (0x1D46C, "M", "e"), - (0x1D46D, "M", "f"), - (0x1D46E, "M", "g"), - (0x1D46F, "M", "h"), - (0x1D470, "M", "i"), - (0x1D471, "M", "j"), - (0x1D472, "M", "k"), - (0x1D473, "M", "l"), - (0x1D474, "M", "m"), - (0x1D475, "M", "n"), - (0x1D476, "M", "o"), - (0x1D477, "M", "p"), - (0x1D478, "M", "q"), - (0x1D479, "M", "r"), - (0x1D47A, "M", "s"), - (0x1D47B, "M", "t"), - (0x1D47C, "M", "u"), - (0x1D47D, "M", "v"), - (0x1D47E, "M", "w"), - (0x1D47F, "M", "x"), - (0x1D480, "M", "y"), - (0x1D481, "M", "z"), - (0x1D482, "M", "a"), - (0x1D483, "M", "b"), - (0x1D484, "M", "c"), - (0x1D485, "M", "d"), - (0x1D486, "M", "e"), - (0x1D487, "M", "f"), - (0x1D488, "M", "g"), - (0x1D489, "M", "h"), - (0x1D48A, "M", "i"), - (0x1D48B, "M", "j"), - (0x1D48C, "M", "k"), - (0x1D48D, "M", "l"), - (0x1D48E, "M", "m"), - (0x1D48F, "M", "n"), - (0x1D490, "M", "o"), - (0x1D491, "M", "p"), - (0x1D492, "M", "q"), - (0x1D493, "M", "r"), - (0x1D494, "M", "s"), - (0x1D495, "M", "t"), - (0x1D496, "M", "u"), - (0x1D497, "M", "v"), - (0x1D498, "M", "w"), - (0x1D499, "M", "x"), - (0x1D49A, "M", "y"), - (0x1D49B, "M", "z"), - (0x1D49C, "M", "a"), - (0x1D49D, "X"), - (0x1D49E, "M", "c"), - (0x1D49F, "M", "d"), - (0x1D4A0, "X"), - (0x1D4A2, "M", "g"), - (0x1D4A3, "X"), - (0x1D4A5, "M", "j"), - (0x1D4A6, "M", "k"), - (0x1D4A7, "X"), - (0x1D4A9, "M", "n"), - (0x1D4AA, "M", "o"), - (0x1D4AB, "M", "p"), - (0x1D4AC, "M", "q"), - (0x1D4AD, "X"), - (0x1D4AE, "M", "s"), - (0x1D4AF, "M", "t"), - (0x1D4B0, "M", "u"), - (0x1D4B1, "M", "v"), - (0x1D4B2, "M", "w"), - (0x1D4B3, "M", "x"), - (0x1D4B4, "M", "y"), - (0x1D4B5, "M", "z"), - (0x1D4B6, "M", "a"), - (0x1D4B7, "M", "b"), - (0x1D4B8, "M", "c"), - (0x1D4B9, "M", "d"), - (0x1D4BA, "X"), - (0x1D4BB, "M", "f"), - (0x1D4BC, "X"), - (0x1D4BD, "M", "h"), - (0x1D4BE, "M", "i"), - (0x1D4BF, "M", "j"), - (0x1D4C0, "M", "k"), - (0x1D4C1, "M", "l"), - (0x1D4C2, "M", "m"), - ] - - -def _seg_64() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1D4C3, "M", "n"), - (0x1D4C4, "X"), - (0x1D4C5, "M", "p"), - (0x1D4C6, "M", "q"), - (0x1D4C7, "M", "r"), - (0x1D4C8, "M", "s"), - (0x1D4C9, "M", "t"), - (0x1D4CA, "M", "u"), - (0x1D4CB, "M", "v"), - (0x1D4CC, "M", "w"), - (0x1D4CD, "M", "x"), - (0x1D4CE, "M", "y"), - (0x1D4CF, "M", "z"), - (0x1D4D0, "M", "a"), - (0x1D4D1, "M", "b"), - (0x1D4D2, "M", "c"), - (0x1D4D3, "M", "d"), - (0x1D4D4, "M", "e"), - (0x1D4D5, "M", "f"), - (0x1D4D6, "M", "g"), - (0x1D4D7, "M", "h"), - (0x1D4D8, "M", "i"), - (0x1D4D9, "M", "j"), - (0x1D4DA, "M", "k"), - (0x1D4DB, "M", "l"), - (0x1D4DC, "M", "m"), - (0x1D4DD, "M", "n"), - (0x1D4DE, "M", "o"), - (0x1D4DF, "M", "p"), - (0x1D4E0, "M", "q"), - (0x1D4E1, "M", "r"), - (0x1D4E2, "M", "s"), - (0x1D4E3, "M", "t"), - (0x1D4E4, "M", "u"), - (0x1D4E5, "M", "v"), - (0x1D4E6, "M", "w"), - (0x1D4E7, "M", "x"), - (0x1D4E8, "M", "y"), - (0x1D4E9, "M", "z"), - (0x1D4EA, "M", "a"), - (0x1D4EB, "M", "b"), - (0x1D4EC, "M", "c"), - (0x1D4ED, "M", "d"), - (0x1D4EE, "M", "e"), - (0x1D4EF, "M", "f"), - (0x1D4F0, "M", "g"), - (0x1D4F1, "M", "h"), - (0x1D4F2, "M", "i"), - (0x1D4F3, "M", "j"), - (0x1D4F4, "M", "k"), - (0x1D4F5, "M", "l"), - (0x1D4F6, "M", "m"), - (0x1D4F7, "M", "n"), - (0x1D4F8, "M", "o"), - (0x1D4F9, "M", "p"), - (0x1D4FA, "M", "q"), - (0x1D4FB, "M", "r"), - (0x1D4FC, "M", "s"), - (0x1D4FD, "M", "t"), - (0x1D4FE, "M", "u"), - (0x1D4FF, "M", "v"), - (0x1D500, "M", "w"), - (0x1D501, "M", "x"), - (0x1D502, "M", "y"), - (0x1D503, "M", "z"), - (0x1D504, "M", "a"), - (0x1D505, "M", "b"), - (0x1D506, "X"), - (0x1D507, "M", "d"), - (0x1D508, "M", "e"), - (0x1D509, "M", "f"), - (0x1D50A, "M", "g"), - (0x1D50B, "X"), - (0x1D50D, "M", "j"), - (0x1D50E, "M", "k"), - (0x1D50F, "M", "l"), - (0x1D510, "M", "m"), - (0x1D511, "M", "n"), - (0x1D512, "M", "o"), - (0x1D513, "M", "p"), - (0x1D514, "M", "q"), - (0x1D515, "X"), - (0x1D516, "M", "s"), - (0x1D517, "M", "t"), - (0x1D518, "M", "u"), - (0x1D519, "M", "v"), - (0x1D51A, "M", "w"), - (0x1D51B, "M", "x"), - (0x1D51C, "M", "y"), - (0x1D51D, "X"), - (0x1D51E, "M", "a"), - (0x1D51F, "M", "b"), - (0x1D520, "M", "c"), - (0x1D521, "M", "d"), - (0x1D522, "M", "e"), - (0x1D523, "M", "f"), - (0x1D524, "M", "g"), - (0x1D525, "M", "h"), - (0x1D526, "M", "i"), - (0x1D527, "M", "j"), - ] - - -def _seg_65() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1D528, "M", "k"), - (0x1D529, "M", "l"), - (0x1D52A, "M", "m"), - (0x1D52B, "M", "n"), - (0x1D52C, "M", "o"), - (0x1D52D, "M", "p"), - (0x1D52E, "M", "q"), - (0x1D52F, "M", "r"), - (0x1D530, "M", "s"), - (0x1D531, "M", "t"), - (0x1D532, "M", "u"), - (0x1D533, "M", "v"), - (0x1D534, "M", "w"), - (0x1D535, "M", "x"), - (0x1D536, "M", "y"), - (0x1D537, "M", "z"), - (0x1D538, "M", "a"), - (0x1D539, "M", "b"), - (0x1D53A, "X"), - (0x1D53B, "M", "d"), - (0x1D53C, "M", "e"), - (0x1D53D, "M", "f"), - (0x1D53E, "M", "g"), - (0x1D53F, "X"), - (0x1D540, "M", "i"), - (0x1D541, "M", "j"), - (0x1D542, "M", "k"), - (0x1D543, "M", "l"), - (0x1D544, "M", "m"), - (0x1D545, "X"), - (0x1D546, "M", "o"), - (0x1D547, "X"), - (0x1D54A, "M", "s"), - (0x1D54B, "M", "t"), - (0x1D54C, "M", "u"), - (0x1D54D, "M", "v"), - (0x1D54E, "M", "w"), - (0x1D54F, "M", "x"), - (0x1D550, "M", "y"), - (0x1D551, "X"), - (0x1D552, "M", "a"), - (0x1D553, "M", "b"), - (0x1D554, "M", "c"), - (0x1D555, "M", "d"), - (0x1D556, "M", "e"), - (0x1D557, "M", "f"), - (0x1D558, "M", "g"), - (0x1D559, "M", "h"), - (0x1D55A, "M", "i"), - (0x1D55B, "M", "j"), - (0x1D55C, "M", "k"), - (0x1D55D, "M", "l"), - (0x1D55E, "M", "m"), - (0x1D55F, "M", "n"), - (0x1D560, "M", "o"), - (0x1D561, "M", "p"), - (0x1D562, "M", "q"), - (0x1D563, "M", "r"), - (0x1D564, "M", "s"), - (0x1D565, "M", "t"), - (0x1D566, "M", "u"), - (0x1D567, "M", "v"), - (0x1D568, "M", "w"), - (0x1D569, "M", "x"), - (0x1D56A, "M", "y"), - (0x1D56B, "M", "z"), - (0x1D56C, "M", "a"), - (0x1D56D, "M", "b"), - (0x1D56E, "M", "c"), - (0x1D56F, "M", "d"), - (0x1D570, "M", "e"), - (0x1D571, "M", "f"), - (0x1D572, "M", "g"), - (0x1D573, "M", "h"), - (0x1D574, "M", "i"), - (0x1D575, "M", "j"), - (0x1D576, "M", "k"), - (0x1D577, "M", "l"), - (0x1D578, "M", "m"), - (0x1D579, "M", "n"), - (0x1D57A, "M", "o"), - (0x1D57B, "M", "p"), - (0x1D57C, "M", "q"), - (0x1D57D, "M", "r"), - (0x1D57E, "M", "s"), - (0x1D57F, "M", "t"), - (0x1D580, "M", "u"), - (0x1D581, "M", "v"), - (0x1D582, "M", "w"), - (0x1D583, "M", "x"), - (0x1D584, "M", "y"), - (0x1D585, "M", "z"), - (0x1D586, "M", "a"), - (0x1D587, "M", "b"), - (0x1D588, "M", "c"), - (0x1D589, "M", "d"), - (0x1D58A, "M", "e"), - (0x1D58B, "M", "f"), - (0x1D58C, "M", "g"), - (0x1D58D, "M", "h"), - ] - - -def _seg_66() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1D58E, "M", "i"), - (0x1D58F, "M", "j"), - (0x1D590, "M", "k"), - (0x1D591, "M", "l"), - (0x1D592, "M", "m"), - (0x1D593, "M", "n"), - (0x1D594, "M", "o"), - (0x1D595, "M", "p"), - (0x1D596, "M", "q"), - (0x1D597, "M", "r"), - (0x1D598, "M", "s"), - (0x1D599, "M", "t"), - (0x1D59A, "M", "u"), - (0x1D59B, "M", "v"), - (0x1D59C, "M", "w"), - (0x1D59D, "M", "x"), - (0x1D59E, "M", "y"), - (0x1D59F, "M", "z"), - (0x1D5A0, "M", "a"), - (0x1D5A1, "M", "b"), - (0x1D5A2, "M", "c"), - (0x1D5A3, "M", "d"), - (0x1D5A4, "M", "e"), - (0x1D5A5, "M", "f"), - (0x1D5A6, "M", "g"), - (0x1D5A7, "M", "h"), - (0x1D5A8, "M", "i"), - (0x1D5A9, "M", "j"), - (0x1D5AA, "M", "k"), - (0x1D5AB, "M", "l"), - (0x1D5AC, "M", "m"), - (0x1D5AD, "M", "n"), - (0x1D5AE, "M", "o"), - (0x1D5AF, "M", "p"), - (0x1D5B0, "M", "q"), - (0x1D5B1, "M", "r"), - (0x1D5B2, "M", "s"), - (0x1D5B3, "M", "t"), - (0x1D5B4, "M", "u"), - (0x1D5B5, "M", "v"), - (0x1D5B6, "M", "w"), - (0x1D5B7, "M", "x"), - (0x1D5B8, "M", "y"), - (0x1D5B9, "M", "z"), - (0x1D5BA, "M", "a"), - (0x1D5BB, "M", "b"), - (0x1D5BC, "M", "c"), - (0x1D5BD, "M", "d"), - (0x1D5BE, "M", "e"), - (0x1D5BF, "M", "f"), - (0x1D5C0, "M", "g"), - (0x1D5C1, "M", "h"), - (0x1D5C2, "M", "i"), - (0x1D5C3, "M", "j"), - (0x1D5C4, "M", "k"), - (0x1D5C5, "M", "l"), - (0x1D5C6, "M", "m"), - (0x1D5C7, "M", "n"), - (0x1D5C8, "M", "o"), - (0x1D5C9, "M", "p"), - (0x1D5CA, "M", "q"), - (0x1D5CB, "M", "r"), - (0x1D5CC, "M", "s"), - (0x1D5CD, "M", "t"), - (0x1D5CE, "M", "u"), - (0x1D5CF, "M", "v"), - (0x1D5D0, "M", "w"), - (0x1D5D1, "M", "x"), - (0x1D5D2, "M", "y"), - (0x1D5D3, "M", "z"), - (0x1D5D4, "M", "a"), - (0x1D5D5, "M", "b"), - (0x1D5D6, "M", "c"), - (0x1D5D7, "M", "d"), - (0x1D5D8, "M", "e"), - (0x1D5D9, "M", "f"), - (0x1D5DA, "M", "g"), - (0x1D5DB, "M", "h"), - (0x1D5DC, "M", "i"), - (0x1D5DD, "M", "j"), - (0x1D5DE, "M", "k"), - (0x1D5DF, "M", "l"), - (0x1D5E0, "M", "m"), - (0x1D5E1, "M", "n"), - (0x1D5E2, "M", "o"), - (0x1D5E3, "M", "p"), - (0x1D5E4, "M", "q"), - (0x1D5E5, "M", "r"), - (0x1D5E6, "M", "s"), - (0x1D5E7, "M", "t"), - (0x1D5E8, "M", "u"), - (0x1D5E9, "M", "v"), - (0x1D5EA, "M", "w"), - (0x1D5EB, "M", "x"), - (0x1D5EC, "M", "y"), - (0x1D5ED, "M", "z"), - (0x1D5EE, "M", "a"), - (0x1D5EF, "M", "b"), - (0x1D5F0, "M", "c"), - (0x1D5F1, "M", "d"), - ] - - -def _seg_67() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1D5F2, "M", "e"), - (0x1D5F3, "M", "f"), - (0x1D5F4, "M", "g"), - (0x1D5F5, "M", "h"), - (0x1D5F6, "M", "i"), - (0x1D5F7, "M", "j"), - (0x1D5F8, "M", "k"), - (0x1D5F9, "M", "l"), - (0x1D5FA, "M", "m"), - (0x1D5FB, "M", "n"), - (0x1D5FC, "M", "o"), - (0x1D5FD, "M", "p"), - (0x1D5FE, "M", "q"), - (0x1D5FF, "M", "r"), - (0x1D600, "M", "s"), - (0x1D601, "M", "t"), - (0x1D602, "M", "u"), - (0x1D603, "M", "v"), - (0x1D604, "M", "w"), - (0x1D605, "M", "x"), - (0x1D606, "M", "y"), - (0x1D607, "M", "z"), - (0x1D608, "M", "a"), - (0x1D609, "M", "b"), - (0x1D60A, "M", "c"), - (0x1D60B, "M", "d"), - (0x1D60C, "M", "e"), - (0x1D60D, "M", "f"), - (0x1D60E, "M", "g"), - (0x1D60F, "M", "h"), - (0x1D610, "M", "i"), - (0x1D611, "M", "j"), - (0x1D612, "M", "k"), - (0x1D613, "M", "l"), - (0x1D614, "M", "m"), - (0x1D615, "M", "n"), - (0x1D616, "M", "o"), - (0x1D617, "M", "p"), - (0x1D618, "M", "q"), - (0x1D619, "M", "r"), - (0x1D61A, "M", "s"), - (0x1D61B, "M", "t"), - (0x1D61C, "M", "u"), - (0x1D61D, "M", "v"), - (0x1D61E, "M", "w"), - (0x1D61F, "M", "x"), - (0x1D620, "M", "y"), - (0x1D621, "M", "z"), - (0x1D622, "M", "a"), - (0x1D623, "M", "b"), - (0x1D624, "M", "c"), - (0x1D625, "M", "d"), - (0x1D626, "M", "e"), - (0x1D627, "M", "f"), - (0x1D628, "M", "g"), - (0x1D629, "M", "h"), - (0x1D62A, "M", "i"), - (0x1D62B, "M", "j"), - (0x1D62C, "M", "k"), - (0x1D62D, "M", "l"), - (0x1D62E, "M", "m"), - (0x1D62F, "M", "n"), - (0x1D630, "M", "o"), - (0x1D631, "M", "p"), - (0x1D632, "M", "q"), - (0x1D633, "M", "r"), - (0x1D634, "M", "s"), - (0x1D635, "M", "t"), - (0x1D636, "M", "u"), - (0x1D637, "M", "v"), - (0x1D638, "M", "w"), - (0x1D639, "M", "x"), - (0x1D63A, "M", "y"), - (0x1D63B, "M", "z"), - (0x1D63C, "M", "a"), - (0x1D63D, "M", "b"), - (0x1D63E, "M", "c"), - (0x1D63F, "M", "d"), - (0x1D640, "M", "e"), - (0x1D641, "M", "f"), - (0x1D642, "M", "g"), - (0x1D643, "M", "h"), - (0x1D644, "M", "i"), - (0x1D645, "M", "j"), - (0x1D646, "M", "k"), - (0x1D647, "M", "l"), - (0x1D648, "M", "m"), - (0x1D649, "M", "n"), - (0x1D64A, "M", "o"), - (0x1D64B, "M", "p"), - (0x1D64C, "M", "q"), - (0x1D64D, "M", "r"), - (0x1D64E, "M", "s"), - (0x1D64F, "M", "t"), - (0x1D650, "M", "u"), - (0x1D651, "M", "v"), - (0x1D652, "M", "w"), - (0x1D653, "M", "x"), - (0x1D654, "M", "y"), - (0x1D655, "M", "z"), - ] - - -def _seg_68() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1D656, "M", "a"), - (0x1D657, "M", "b"), - (0x1D658, "M", "c"), - (0x1D659, "M", "d"), - (0x1D65A, "M", "e"), - (0x1D65B, "M", "f"), - (0x1D65C, "M", "g"), - (0x1D65D, "M", "h"), - (0x1D65E, "M", "i"), - (0x1D65F, "M", "j"), - (0x1D660, "M", "k"), - (0x1D661, "M", "l"), - (0x1D662, "M", "m"), - (0x1D663, "M", "n"), - (0x1D664, "M", "o"), - (0x1D665, "M", "p"), - (0x1D666, "M", "q"), - (0x1D667, "M", "r"), - (0x1D668, "M", "s"), - (0x1D669, "M", "t"), - (0x1D66A, "M", "u"), - (0x1D66B, "M", "v"), - (0x1D66C, "M", "w"), - (0x1D66D, "M", "x"), - (0x1D66E, "M", "y"), - (0x1D66F, "M", "z"), - (0x1D670, "M", "a"), - (0x1D671, "M", "b"), - (0x1D672, "M", "c"), - (0x1D673, "M", "d"), - (0x1D674, "M", "e"), - (0x1D675, "M", "f"), - (0x1D676, "M", "g"), - (0x1D677, "M", "h"), - (0x1D678, "M", "i"), - (0x1D679, "M", "j"), - (0x1D67A, "M", "k"), - (0x1D67B, "M", "l"), - (0x1D67C, "M", "m"), - (0x1D67D, "M", "n"), - (0x1D67E, "M", "o"), - (0x1D67F, "M", "p"), - (0x1D680, "M", "q"), - (0x1D681, "M", "r"), - (0x1D682, "M", "s"), - (0x1D683, "M", "t"), - (0x1D684, "M", "u"), - (0x1D685, "M", "v"), - (0x1D686, "M", "w"), - (0x1D687, "M", "x"), - (0x1D688, "M", "y"), - (0x1D689, "M", "z"), - (0x1D68A, "M", "a"), - (0x1D68B, "M", "b"), - (0x1D68C, "M", "c"), - (0x1D68D, "M", "d"), - (0x1D68E, "M", "e"), - (0x1D68F, "M", "f"), - (0x1D690, "M", "g"), - (0x1D691, "M", "h"), - (0x1D692, "M", "i"), - (0x1D693, "M", "j"), - (0x1D694, "M", "k"), - (0x1D695, "M", "l"), - (0x1D696, "M", "m"), - (0x1D697, "M", "n"), - (0x1D698, "M", "o"), - (0x1D699, "M", "p"), - (0x1D69A, "M", "q"), - (0x1D69B, "M", "r"), - (0x1D69C, "M", "s"), - (0x1D69D, "M", "t"), - (0x1D69E, "M", "u"), - (0x1D69F, "M", "v"), - (0x1D6A0, "M", "w"), - (0x1D6A1, "M", "x"), - (0x1D6A2, "M", "y"), - (0x1D6A3, "M", "z"), - (0x1D6A4, "M", "ı"), - (0x1D6A5, "M", "ȷ"), - (0x1D6A6, "X"), - (0x1D6A8, "M", "α"), - (0x1D6A9, "M", "β"), - (0x1D6AA, "M", "γ"), - (0x1D6AB, "M", "δ"), - (0x1D6AC, "M", "ε"), - (0x1D6AD, "M", "ζ"), - (0x1D6AE, "M", "η"), - (0x1D6AF, "M", "θ"), - (0x1D6B0, "M", "ι"), - (0x1D6B1, "M", "κ"), - (0x1D6B2, "M", "λ"), - (0x1D6B3, "M", "μ"), - (0x1D6B4, "M", "ν"), - (0x1D6B5, "M", "ξ"), - (0x1D6B6, "M", "ο"), - (0x1D6B7, "M", "π"), - (0x1D6B8, "M", "ρ"), - (0x1D6B9, "M", "θ"), - (0x1D6BA, "M", "σ"), - ] - - -def _seg_69() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1D6BB, "M", "τ"), - (0x1D6BC, "M", "υ"), - (0x1D6BD, "M", "φ"), - (0x1D6BE, "M", "χ"), - (0x1D6BF, "M", "ψ"), - (0x1D6C0, "M", "ω"), - (0x1D6C1, "M", "∇"), - (0x1D6C2, "M", "α"), - (0x1D6C3, "M", "β"), - (0x1D6C4, "M", "γ"), - (0x1D6C5, "M", "δ"), - (0x1D6C6, "M", "ε"), - (0x1D6C7, "M", "ζ"), - (0x1D6C8, "M", "η"), - (0x1D6C9, "M", "θ"), - (0x1D6CA, "M", "ι"), - (0x1D6CB, "M", "κ"), - (0x1D6CC, "M", "λ"), - (0x1D6CD, "M", "μ"), - (0x1D6CE, "M", "ν"), - (0x1D6CF, "M", "ξ"), - (0x1D6D0, "M", "ο"), - (0x1D6D1, "M", "π"), - (0x1D6D2, "M", "ρ"), - (0x1D6D3, "M", "σ"), - (0x1D6D5, "M", "τ"), - (0x1D6D6, "M", "υ"), - (0x1D6D7, "M", "φ"), - (0x1D6D8, "M", "χ"), - (0x1D6D9, "M", "ψ"), - (0x1D6DA, "M", "ω"), - (0x1D6DB, "M", "∂"), - (0x1D6DC, "M", "ε"), - (0x1D6DD, "M", "θ"), - (0x1D6DE, "M", "κ"), - (0x1D6DF, "M", "φ"), - (0x1D6E0, "M", "ρ"), - (0x1D6E1, "M", "π"), - (0x1D6E2, "M", "α"), - (0x1D6E3, "M", "β"), - (0x1D6E4, "M", "γ"), - (0x1D6E5, "M", "δ"), - (0x1D6E6, "M", "ε"), - (0x1D6E7, "M", "ζ"), - (0x1D6E8, "M", "η"), - (0x1D6E9, "M", "θ"), - (0x1D6EA, "M", "ι"), - (0x1D6EB, "M", "κ"), - (0x1D6EC, "M", "λ"), - (0x1D6ED, "M", "μ"), - (0x1D6EE, "M", "ν"), - (0x1D6EF, "M", "ξ"), - (0x1D6F0, "M", "ο"), - (0x1D6F1, "M", "π"), - (0x1D6F2, "M", "ρ"), - (0x1D6F3, "M", "θ"), - (0x1D6F4, "M", "σ"), - (0x1D6F5, "M", "τ"), - (0x1D6F6, "M", "υ"), - (0x1D6F7, "M", "φ"), - (0x1D6F8, "M", "χ"), - (0x1D6F9, "M", "ψ"), - (0x1D6FA, "M", "ω"), - (0x1D6FB, "M", "∇"), - (0x1D6FC, "M", "α"), - (0x1D6FD, "M", "β"), - (0x1D6FE, "M", "γ"), - (0x1D6FF, "M", "δ"), - (0x1D700, "M", "ε"), - (0x1D701, "M", "ζ"), - (0x1D702, "M", "η"), - (0x1D703, "M", "θ"), - (0x1D704, "M", "ι"), - (0x1D705, "M", "κ"), - (0x1D706, "M", "λ"), - (0x1D707, "M", "μ"), - (0x1D708, "M", "ν"), - (0x1D709, "M", "ξ"), - (0x1D70A, "M", "ο"), - (0x1D70B, "M", "π"), - (0x1D70C, "M", "ρ"), - (0x1D70D, "M", "σ"), - (0x1D70F, "M", "τ"), - (0x1D710, "M", "υ"), - (0x1D711, "M", "φ"), - (0x1D712, "M", "χ"), - (0x1D713, "M", "ψ"), - (0x1D714, "M", "ω"), - (0x1D715, "M", "∂"), - (0x1D716, "M", "ε"), - (0x1D717, "M", "θ"), - (0x1D718, "M", "κ"), - (0x1D719, "M", "φ"), - (0x1D71A, "M", "ρ"), - (0x1D71B, "M", "π"), - (0x1D71C, "M", "α"), - (0x1D71D, "M", "β"), - (0x1D71E, "M", "γ"), - (0x1D71F, "M", "δ"), - (0x1D720, "M", "ε"), - ] - - -def _seg_70() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1D721, "M", "ζ"), - (0x1D722, "M", "η"), - (0x1D723, "M", "θ"), - (0x1D724, "M", "ι"), - (0x1D725, "M", "κ"), - (0x1D726, "M", "λ"), - (0x1D727, "M", "μ"), - (0x1D728, "M", "ν"), - (0x1D729, "M", "ξ"), - (0x1D72A, "M", "ο"), - (0x1D72B, "M", "π"), - (0x1D72C, "M", "ρ"), - (0x1D72D, "M", "θ"), - (0x1D72E, "M", "σ"), - (0x1D72F, "M", "τ"), - (0x1D730, "M", "υ"), - (0x1D731, "M", "φ"), - (0x1D732, "M", "χ"), - (0x1D733, "M", "ψ"), - (0x1D734, "M", "ω"), - (0x1D735, "M", "∇"), - (0x1D736, "M", "α"), - (0x1D737, "M", "β"), - (0x1D738, "M", "γ"), - (0x1D739, "M", "δ"), - (0x1D73A, "M", "ε"), - (0x1D73B, "M", "ζ"), - (0x1D73C, "M", "η"), - (0x1D73D, "M", "θ"), - (0x1D73E, "M", "ι"), - (0x1D73F, "M", "κ"), - (0x1D740, "M", "λ"), - (0x1D741, "M", "μ"), - (0x1D742, "M", "ν"), - (0x1D743, "M", "ξ"), - (0x1D744, "M", "ο"), - (0x1D745, "M", "π"), - (0x1D746, "M", "ρ"), - (0x1D747, "M", "σ"), - (0x1D749, "M", "τ"), - (0x1D74A, "M", "υ"), - (0x1D74B, "M", "φ"), - (0x1D74C, "M", "χ"), - (0x1D74D, "M", "ψ"), - (0x1D74E, "M", "ω"), - (0x1D74F, "M", "∂"), - (0x1D750, "M", "ε"), - (0x1D751, "M", "θ"), - (0x1D752, "M", "κ"), - (0x1D753, "M", "φ"), - (0x1D754, "M", "ρ"), - (0x1D755, "M", "π"), - (0x1D756, "M", "α"), - (0x1D757, "M", "β"), - (0x1D758, "M", "γ"), - (0x1D759, "M", "δ"), - (0x1D75A, "M", "ε"), - (0x1D75B, "M", "ζ"), - (0x1D75C, "M", "η"), - (0x1D75D, "M", "θ"), - (0x1D75E, "M", "ι"), - (0x1D75F, "M", "κ"), - (0x1D760, "M", "λ"), - (0x1D761, "M", "μ"), - (0x1D762, "M", "ν"), - (0x1D763, "M", "ξ"), - (0x1D764, "M", "ο"), - (0x1D765, "M", "π"), - (0x1D766, "M", "ρ"), - (0x1D767, "M", "θ"), - (0x1D768, "M", "σ"), - (0x1D769, "M", "τ"), - (0x1D76A, "M", "υ"), - (0x1D76B, "M", "φ"), - (0x1D76C, "M", "χ"), - (0x1D76D, "M", "ψ"), - (0x1D76E, "M", "ω"), - (0x1D76F, "M", "∇"), - (0x1D770, "M", "α"), - (0x1D771, "M", "β"), - (0x1D772, "M", "γ"), - (0x1D773, "M", "δ"), - (0x1D774, "M", "ε"), - (0x1D775, "M", "ζ"), - (0x1D776, "M", "η"), - (0x1D777, "M", "θ"), - (0x1D778, "M", "ι"), - (0x1D779, "M", "κ"), - (0x1D77A, "M", "λ"), - (0x1D77B, "M", "μ"), - (0x1D77C, "M", "ν"), - (0x1D77D, "M", "ξ"), - (0x1D77E, "M", "ο"), - (0x1D77F, "M", "π"), - (0x1D780, "M", "ρ"), - (0x1D781, "M", "σ"), - (0x1D783, "M", "τ"), - (0x1D784, "M", "υ"), - (0x1D785, "M", "φ"), - (0x1D786, "M", "χ"), - ] - - -def _seg_71() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1D787, "M", "ψ"), - (0x1D788, "M", "ω"), - (0x1D789, "M", "∂"), - (0x1D78A, "M", "ε"), - (0x1D78B, "M", "θ"), - (0x1D78C, "M", "κ"), - (0x1D78D, "M", "φ"), - (0x1D78E, "M", "ρ"), - (0x1D78F, "M", "π"), - (0x1D790, "M", "α"), - (0x1D791, "M", "β"), - (0x1D792, "M", "γ"), - (0x1D793, "M", "δ"), - (0x1D794, "M", "ε"), - (0x1D795, "M", "ζ"), - (0x1D796, "M", "η"), - (0x1D797, "M", "θ"), - (0x1D798, "M", "ι"), - (0x1D799, "M", "κ"), - (0x1D79A, "M", "λ"), - (0x1D79B, "M", "μ"), - (0x1D79C, "M", "ν"), - (0x1D79D, "M", "ξ"), - (0x1D79E, "M", "ο"), - (0x1D79F, "M", "π"), - (0x1D7A0, "M", "ρ"), - (0x1D7A1, "M", "θ"), - (0x1D7A2, "M", "σ"), - (0x1D7A3, "M", "τ"), - (0x1D7A4, "M", "υ"), - (0x1D7A5, "M", "φ"), - (0x1D7A6, "M", "χ"), - (0x1D7A7, "M", "ψ"), - (0x1D7A8, "M", "ω"), - (0x1D7A9, "M", "∇"), - (0x1D7AA, "M", "α"), - (0x1D7AB, "M", "β"), - (0x1D7AC, "M", "γ"), - (0x1D7AD, "M", "δ"), - (0x1D7AE, "M", "ε"), - (0x1D7AF, "M", "ζ"), - (0x1D7B0, "M", "η"), - (0x1D7B1, "M", "θ"), - (0x1D7B2, "M", "ι"), - (0x1D7B3, "M", "κ"), - (0x1D7B4, "M", "λ"), - (0x1D7B5, "M", "μ"), - (0x1D7B6, "M", "ν"), - (0x1D7B7, "M", "ξ"), - (0x1D7B8, "M", "ο"), - (0x1D7B9, "M", "π"), - (0x1D7BA, "M", "ρ"), - (0x1D7BB, "M", "σ"), - (0x1D7BD, "M", "τ"), - (0x1D7BE, "M", "υ"), - (0x1D7BF, "M", "φ"), - (0x1D7C0, "M", "χ"), - (0x1D7C1, "M", "ψ"), - (0x1D7C2, "M", "ω"), - (0x1D7C3, "M", "∂"), - (0x1D7C4, "M", "ε"), - (0x1D7C5, "M", "θ"), - (0x1D7C6, "M", "κ"), - (0x1D7C7, "M", "φ"), - (0x1D7C8, "M", "ρ"), - (0x1D7C9, "M", "π"), - (0x1D7CA, "M", "ϝ"), - (0x1D7CC, "X"), - (0x1D7CE, "M", "0"), - (0x1D7CF, "M", "1"), - (0x1D7D0, "M", "2"), - (0x1D7D1, "M", "3"), - (0x1D7D2, "M", "4"), - (0x1D7D3, "M", "5"), - (0x1D7D4, "M", "6"), - (0x1D7D5, "M", "7"), - (0x1D7D6, "M", "8"), - (0x1D7D7, "M", "9"), - (0x1D7D8, "M", "0"), - (0x1D7D9, "M", "1"), - (0x1D7DA, "M", "2"), - (0x1D7DB, "M", "3"), - (0x1D7DC, "M", "4"), - (0x1D7DD, "M", "5"), - (0x1D7DE, "M", "6"), - (0x1D7DF, "M", "7"), - (0x1D7E0, "M", "8"), - (0x1D7E1, "M", "9"), - (0x1D7E2, "M", "0"), - (0x1D7E3, "M", "1"), - (0x1D7E4, "M", "2"), - (0x1D7E5, "M", "3"), - (0x1D7E6, "M", "4"), - (0x1D7E7, "M", "5"), - (0x1D7E8, "M", "6"), - (0x1D7E9, "M", "7"), - (0x1D7EA, "M", "8"), - (0x1D7EB, "M", "9"), - (0x1D7EC, "M", "0"), - (0x1D7ED, "M", "1"), - ] - - -def _seg_72() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1D7EE, "M", "2"), - (0x1D7EF, "M", "3"), - (0x1D7F0, "M", "4"), - (0x1D7F1, "M", "5"), - (0x1D7F2, "M", "6"), - (0x1D7F3, "M", "7"), - (0x1D7F4, "M", "8"), - (0x1D7F5, "M", "9"), - (0x1D7F6, "M", "0"), - (0x1D7F7, "M", "1"), - (0x1D7F8, "M", "2"), - (0x1D7F9, "M", "3"), - (0x1D7FA, "M", "4"), - (0x1D7FB, "M", "5"), - (0x1D7FC, "M", "6"), - (0x1D7FD, "M", "7"), - (0x1D7FE, "M", "8"), - (0x1D7FF, "M", "9"), - (0x1D800, "V"), - (0x1DA8C, "X"), - (0x1DA9B, "V"), - (0x1DAA0, "X"), - (0x1DAA1, "V"), - (0x1DAB0, "X"), - (0x1DF00, "V"), - (0x1DF1F, "X"), - (0x1DF25, "V"), - (0x1DF2B, "X"), - (0x1E000, "V"), - (0x1E007, "X"), - (0x1E008, "V"), - (0x1E019, "X"), - (0x1E01B, "V"), - (0x1E022, "X"), - (0x1E023, "V"), - (0x1E025, "X"), - (0x1E026, "V"), - (0x1E02B, "X"), - (0x1E030, "M", "а"), - (0x1E031, "M", "б"), - (0x1E032, "M", "в"), - (0x1E033, "M", "г"), - (0x1E034, "M", "д"), - (0x1E035, "M", "е"), - (0x1E036, "M", "ж"), - (0x1E037, "M", "з"), - (0x1E038, "M", "и"), - (0x1E039, "M", "к"), - (0x1E03A, "M", "л"), - (0x1E03B, "M", "м"), - (0x1E03C, "M", "о"), - (0x1E03D, "M", "п"), - (0x1E03E, "M", "р"), - (0x1E03F, "M", "с"), - (0x1E040, "M", "т"), - (0x1E041, "M", "у"), - (0x1E042, "M", "ф"), - (0x1E043, "M", "х"), - (0x1E044, "M", "ц"), - (0x1E045, "M", "ч"), - (0x1E046, "M", "ш"), - (0x1E047, "M", "ы"), - (0x1E048, "M", "э"), - (0x1E049, "M", "ю"), - (0x1E04A, "M", "ꚉ"), - (0x1E04B, "M", "ә"), - (0x1E04C, "M", "і"), - (0x1E04D, "M", "ј"), - (0x1E04E, "M", "ө"), - (0x1E04F, "M", "ү"), - (0x1E050, "M", "ӏ"), - (0x1E051, "M", "а"), - (0x1E052, "M", "б"), - (0x1E053, "M", "в"), - (0x1E054, "M", "г"), - (0x1E055, "M", "д"), - (0x1E056, "M", "е"), - (0x1E057, "M", "ж"), - (0x1E058, "M", "з"), - (0x1E059, "M", "и"), - (0x1E05A, "M", "к"), - (0x1E05B, "M", "л"), - (0x1E05C, "M", "о"), - (0x1E05D, "M", "п"), - (0x1E05E, "M", "с"), - (0x1E05F, "M", "у"), - (0x1E060, "M", "ф"), - (0x1E061, "M", "х"), - (0x1E062, "M", "ц"), - (0x1E063, "M", "ч"), - (0x1E064, "M", "ш"), - (0x1E065, "M", "ъ"), - (0x1E066, "M", "ы"), - (0x1E067, "M", "ґ"), - (0x1E068, "M", "і"), - (0x1E069, "M", "ѕ"), - (0x1E06A, "M", "џ"), - (0x1E06B, "M", "ҫ"), - (0x1E06C, "M", "ꙑ"), - (0x1E06D, "M", "ұ"), - ] - - -def _seg_73() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1E06E, "X"), - (0x1E08F, "V"), - (0x1E090, "X"), - (0x1E100, "V"), - (0x1E12D, "X"), - (0x1E130, "V"), - (0x1E13E, "X"), - (0x1E140, "V"), - (0x1E14A, "X"), - (0x1E14E, "V"), - (0x1E150, "X"), - (0x1E290, "V"), - (0x1E2AF, "X"), - (0x1E2C0, "V"), - (0x1E2FA, "X"), - (0x1E2FF, "V"), - (0x1E300, "X"), - (0x1E4D0, "V"), - (0x1E4FA, "X"), - (0x1E5D0, "V"), - (0x1E5FB, "X"), - (0x1E5FF, "V"), - (0x1E600, "X"), - (0x1E7E0, "V"), - (0x1E7E7, "X"), - (0x1E7E8, "V"), - (0x1E7EC, "X"), - (0x1E7ED, "V"), - (0x1E7EF, "X"), - (0x1E7F0, "V"), - (0x1E7FF, "X"), - (0x1E800, "V"), - (0x1E8C5, "X"), - (0x1E8C7, "V"), - (0x1E8D7, "X"), - (0x1E900, "M", "𞤢"), - (0x1E901, "M", "𞤣"), - (0x1E902, "M", "𞤤"), - (0x1E903, "M", "𞤥"), - (0x1E904, "M", "𞤦"), - (0x1E905, "M", "𞤧"), - (0x1E906, "M", "𞤨"), - (0x1E907, "M", "𞤩"), - (0x1E908, "M", "𞤪"), - (0x1E909, "M", "𞤫"), - (0x1E90A, "M", "𞤬"), - (0x1E90B, "M", "𞤭"), - (0x1E90C, "M", "𞤮"), - (0x1E90D, "M", "𞤯"), - (0x1E90E, "M", "𞤰"), - (0x1E90F, "M", "𞤱"), - (0x1E910, "M", "𞤲"), - (0x1E911, "M", "𞤳"), - (0x1E912, "M", "𞤴"), - (0x1E913, "M", "𞤵"), - (0x1E914, "M", "𞤶"), - (0x1E915, "M", "𞤷"), - (0x1E916, "M", "𞤸"), - (0x1E917, "M", "𞤹"), - (0x1E918, "M", "𞤺"), - (0x1E919, "M", "𞤻"), - (0x1E91A, "M", "𞤼"), - (0x1E91B, "M", "𞤽"), - (0x1E91C, "M", "𞤾"), - (0x1E91D, "M", "𞤿"), - (0x1E91E, "M", "𞥀"), - (0x1E91F, "M", "𞥁"), - (0x1E920, "M", "𞥂"), - (0x1E921, "M", "𞥃"), - (0x1E922, "V"), - (0x1E94C, "X"), - (0x1E950, "V"), - (0x1E95A, "X"), - (0x1E95E, "V"), - (0x1E960, "X"), - (0x1EC71, "V"), - (0x1ECB5, "X"), - (0x1ED01, "V"), - (0x1ED3E, "X"), - (0x1EE00, "M", "ا"), - (0x1EE01, "M", "ب"), - (0x1EE02, "M", "ج"), - (0x1EE03, "M", "د"), - (0x1EE04, "X"), - (0x1EE05, "M", "و"), - (0x1EE06, "M", "ز"), - (0x1EE07, "M", "ح"), - (0x1EE08, "M", "ط"), - (0x1EE09, "M", "ي"), - (0x1EE0A, "M", "ك"), - (0x1EE0B, "M", "ل"), - (0x1EE0C, "M", "م"), - (0x1EE0D, "M", "ن"), - (0x1EE0E, "M", "س"), - (0x1EE0F, "M", "ع"), - (0x1EE10, "M", "ف"), - (0x1EE11, "M", "ص"), - (0x1EE12, "M", "ق"), - (0x1EE13, "M", "ر"), - (0x1EE14, "M", "ش"), - ] - - -def _seg_74() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1EE15, "M", "ت"), - (0x1EE16, "M", "ث"), - (0x1EE17, "M", "خ"), - (0x1EE18, "M", "ذ"), - (0x1EE19, "M", "ض"), - (0x1EE1A, "M", "ظ"), - (0x1EE1B, "M", "غ"), - (0x1EE1C, "M", "ٮ"), - (0x1EE1D, "M", "ں"), - (0x1EE1E, "M", "ڡ"), - (0x1EE1F, "M", "ٯ"), - (0x1EE20, "X"), - (0x1EE21, "M", "ب"), - (0x1EE22, "M", "ج"), - (0x1EE23, "X"), - (0x1EE24, "M", "ه"), - (0x1EE25, "X"), - (0x1EE27, "M", "ح"), - (0x1EE28, "X"), - (0x1EE29, "M", "ي"), - (0x1EE2A, "M", "ك"), - (0x1EE2B, "M", "ل"), - (0x1EE2C, "M", "م"), - (0x1EE2D, "M", "ن"), - (0x1EE2E, "M", "س"), - (0x1EE2F, "M", "ع"), - (0x1EE30, "M", "ف"), - (0x1EE31, "M", "ص"), - (0x1EE32, "M", "ق"), - (0x1EE33, "X"), - (0x1EE34, "M", "ش"), - (0x1EE35, "M", "ت"), - (0x1EE36, "M", "ث"), - (0x1EE37, "M", "خ"), - (0x1EE38, "X"), - (0x1EE39, "M", "ض"), - (0x1EE3A, "X"), - (0x1EE3B, "M", "غ"), - (0x1EE3C, "X"), - (0x1EE42, "M", "ج"), - (0x1EE43, "X"), - (0x1EE47, "M", "ح"), - (0x1EE48, "X"), - (0x1EE49, "M", "ي"), - (0x1EE4A, "X"), - (0x1EE4B, "M", "ل"), - (0x1EE4C, "X"), - (0x1EE4D, "M", "ن"), - (0x1EE4E, "M", "س"), - (0x1EE4F, "M", "ع"), - (0x1EE50, "X"), - (0x1EE51, "M", "ص"), - (0x1EE52, "M", "ق"), - (0x1EE53, "X"), - (0x1EE54, "M", "ش"), - (0x1EE55, "X"), - (0x1EE57, "M", "خ"), - (0x1EE58, "X"), - (0x1EE59, "M", "ض"), - (0x1EE5A, "X"), - (0x1EE5B, "M", "غ"), - (0x1EE5C, "X"), - (0x1EE5D, "M", "ں"), - (0x1EE5E, "X"), - (0x1EE5F, "M", "ٯ"), - (0x1EE60, "X"), - (0x1EE61, "M", "ب"), - (0x1EE62, "M", "ج"), - (0x1EE63, "X"), - (0x1EE64, "M", "ه"), - (0x1EE65, "X"), - (0x1EE67, "M", "ح"), - (0x1EE68, "M", "ط"), - (0x1EE69, "M", "ي"), - (0x1EE6A, "M", "ك"), - (0x1EE6B, "X"), - (0x1EE6C, "M", "م"), - (0x1EE6D, "M", "ن"), - (0x1EE6E, "M", "س"), - (0x1EE6F, "M", "ع"), - (0x1EE70, "M", "ف"), - (0x1EE71, "M", "ص"), - (0x1EE72, "M", "ق"), - (0x1EE73, "X"), - (0x1EE74, "M", "ش"), - (0x1EE75, "M", "ت"), - (0x1EE76, "M", "ث"), - (0x1EE77, "M", "خ"), - (0x1EE78, "X"), - (0x1EE79, "M", "ض"), - (0x1EE7A, "M", "ظ"), - (0x1EE7B, "M", "غ"), - (0x1EE7C, "M", "ٮ"), - (0x1EE7D, "X"), - (0x1EE7E, "M", "ڡ"), - (0x1EE7F, "X"), - (0x1EE80, "M", "ا"), - (0x1EE81, "M", "ب"), - (0x1EE82, "M", "ج"), - (0x1EE83, "M", "د"), - ] - - -def _seg_75() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1EE84, "M", "ه"), - (0x1EE85, "M", "و"), - (0x1EE86, "M", "ز"), - (0x1EE87, "M", "ح"), - (0x1EE88, "M", "ط"), - (0x1EE89, "M", "ي"), - (0x1EE8A, "X"), - (0x1EE8B, "M", "ل"), - (0x1EE8C, "M", "م"), - (0x1EE8D, "M", "ن"), - (0x1EE8E, "M", "س"), - (0x1EE8F, "M", "ع"), - (0x1EE90, "M", "ف"), - (0x1EE91, "M", "ص"), - (0x1EE92, "M", "ق"), - (0x1EE93, "M", "ر"), - (0x1EE94, "M", "ش"), - (0x1EE95, "M", "ت"), - (0x1EE96, "M", "ث"), - (0x1EE97, "M", "خ"), - (0x1EE98, "M", "ذ"), - (0x1EE99, "M", "ض"), - (0x1EE9A, "M", "ظ"), - (0x1EE9B, "M", "غ"), - (0x1EE9C, "X"), - (0x1EEA1, "M", "ب"), - (0x1EEA2, "M", "ج"), - (0x1EEA3, "M", "د"), - (0x1EEA4, "X"), - (0x1EEA5, "M", "و"), - (0x1EEA6, "M", "ز"), - (0x1EEA7, "M", "ح"), - (0x1EEA8, "M", "ط"), - (0x1EEA9, "M", "ي"), - (0x1EEAA, "X"), - (0x1EEAB, "M", "ل"), - (0x1EEAC, "M", "م"), - (0x1EEAD, "M", "ن"), - (0x1EEAE, "M", "س"), - (0x1EEAF, "M", "ع"), - (0x1EEB0, "M", "ف"), - (0x1EEB1, "M", "ص"), - (0x1EEB2, "M", "ق"), - (0x1EEB3, "M", "ر"), - (0x1EEB4, "M", "ش"), - (0x1EEB5, "M", "ت"), - (0x1EEB6, "M", "ث"), - (0x1EEB7, "M", "خ"), - (0x1EEB8, "M", "ذ"), - (0x1EEB9, "M", "ض"), - (0x1EEBA, "M", "ظ"), - (0x1EEBB, "M", "غ"), - (0x1EEBC, "X"), - (0x1EEF0, "V"), - (0x1EEF2, "X"), - (0x1F000, "V"), - (0x1F02C, "X"), - (0x1F030, "V"), - (0x1F094, "X"), - (0x1F0A0, "V"), - (0x1F0AF, "X"), - (0x1F0B1, "V"), - (0x1F0C0, "X"), - (0x1F0C1, "V"), - (0x1F0D0, "X"), - (0x1F0D1, "V"), - (0x1F0F6, "X"), - (0x1F101, "M", "0,"), - (0x1F102, "M", "1,"), - (0x1F103, "M", "2,"), - (0x1F104, "M", "3,"), - (0x1F105, "M", "4,"), - (0x1F106, "M", "5,"), - (0x1F107, "M", "6,"), - (0x1F108, "M", "7,"), - (0x1F109, "M", "8,"), - (0x1F10A, "M", "9,"), - (0x1F10B, "V"), - (0x1F110, "M", "(a)"), - (0x1F111, "M", "(b)"), - (0x1F112, "M", "(c)"), - (0x1F113, "M", "(d)"), - (0x1F114, "M", "(e)"), - (0x1F115, "M", "(f)"), - (0x1F116, "M", "(g)"), - (0x1F117, "M", "(h)"), - (0x1F118, "M", "(i)"), - (0x1F119, "M", "(j)"), - (0x1F11A, "M", "(k)"), - (0x1F11B, "M", "(l)"), - (0x1F11C, "M", "(m)"), - (0x1F11D, "M", "(n)"), - (0x1F11E, "M", "(o)"), - (0x1F11F, "M", "(p)"), - (0x1F120, "M", "(q)"), - (0x1F121, "M", "(r)"), - (0x1F122, "M", "(s)"), - (0x1F123, "M", "(t)"), - (0x1F124, "M", "(u)"), - (0x1F125, "M", "(v)"), - ] - - -def _seg_76() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1F126, "M", "(w)"), - (0x1F127, "M", "(x)"), - (0x1F128, "M", "(y)"), - (0x1F129, "M", "(z)"), - (0x1F12A, "M", "〔s〕"), - (0x1F12B, "M", "c"), - (0x1F12C, "M", "r"), - (0x1F12D, "M", "cd"), - (0x1F12E, "M", "wz"), - (0x1F12F, "V"), - (0x1F130, "M", "a"), - (0x1F131, "M", "b"), - (0x1F132, "M", "c"), - (0x1F133, "M", "d"), - (0x1F134, "M", "e"), - (0x1F135, "M", "f"), - (0x1F136, "M", "g"), - (0x1F137, "M", "h"), - (0x1F138, "M", "i"), - (0x1F139, "M", "j"), - (0x1F13A, "M", "k"), - (0x1F13B, "M", "l"), - (0x1F13C, "M", "m"), - (0x1F13D, "M", "n"), - (0x1F13E, "M", "o"), - (0x1F13F, "M", "p"), - (0x1F140, "M", "q"), - (0x1F141, "M", "r"), - (0x1F142, "M", "s"), - (0x1F143, "M", "t"), - (0x1F144, "M", "u"), - (0x1F145, "M", "v"), - (0x1F146, "M", "w"), - (0x1F147, "M", "x"), - (0x1F148, "M", "y"), - (0x1F149, "M", "z"), - (0x1F14A, "M", "hv"), - (0x1F14B, "M", "mv"), - (0x1F14C, "M", "sd"), - (0x1F14D, "M", "ss"), - (0x1F14E, "M", "ppv"), - (0x1F14F, "M", "wc"), - (0x1F150, "V"), - (0x1F16A, "M", "mc"), - (0x1F16B, "M", "md"), - (0x1F16C, "M", "mr"), - (0x1F16D, "V"), - (0x1F190, "M", "dj"), - (0x1F191, "V"), - (0x1F1AE, "X"), - (0x1F1E6, "V"), - (0x1F200, "M", "ほか"), - (0x1F201, "M", "ココ"), - (0x1F202, "M", "サ"), - (0x1F203, "X"), - (0x1F210, "M", "手"), - (0x1F211, "M", "字"), - (0x1F212, "M", "双"), - (0x1F213, "M", "デ"), - (0x1F214, "M", "二"), - (0x1F215, "M", "多"), - (0x1F216, "M", "解"), - (0x1F217, "M", "天"), - (0x1F218, "M", "交"), - (0x1F219, "M", "映"), - (0x1F21A, "M", "無"), - (0x1F21B, "M", "料"), - (0x1F21C, "M", "前"), - (0x1F21D, "M", "後"), - (0x1F21E, "M", "再"), - (0x1F21F, "M", "新"), - (0x1F220, "M", "初"), - (0x1F221, "M", "終"), - (0x1F222, "M", "生"), - (0x1F223, "M", "販"), - (0x1F224, "M", "声"), - (0x1F225, "M", "吹"), - (0x1F226, "M", "演"), - (0x1F227, "M", "投"), - (0x1F228, "M", "捕"), - (0x1F229, "M", "一"), - (0x1F22A, "M", "三"), - (0x1F22B, "M", "遊"), - (0x1F22C, "M", "左"), - (0x1F22D, "M", "中"), - (0x1F22E, "M", "右"), - (0x1F22F, "M", "指"), - (0x1F230, "M", "走"), - (0x1F231, "M", "打"), - (0x1F232, "M", "禁"), - (0x1F233, "M", "空"), - (0x1F234, "M", "合"), - (0x1F235, "M", "満"), - (0x1F236, "M", "有"), - (0x1F237, "M", "月"), - (0x1F238, "M", "申"), - (0x1F239, "M", "割"), - (0x1F23A, "M", "営"), - (0x1F23B, "M", "配"), - (0x1F23C, "X"), - ] - - -def _seg_77() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x1F240, "M", "〔本〕"), - (0x1F241, "M", "〔三〕"), - (0x1F242, "M", "〔二〕"), - (0x1F243, "M", "〔安〕"), - (0x1F244, "M", "〔点〕"), - (0x1F245, "M", "〔打〕"), - (0x1F246, "M", "〔盗〕"), - (0x1F247, "M", "〔勝〕"), - (0x1F248, "M", "〔敗〕"), - (0x1F249, "X"), - (0x1F250, "M", "得"), - (0x1F251, "M", "可"), - (0x1F252, "X"), - (0x1F260, "V"), - (0x1F266, "X"), - (0x1F300, "V"), - (0x1F6D8, "X"), - (0x1F6DC, "V"), - (0x1F6ED, "X"), - (0x1F6F0, "V"), - (0x1F6FD, "X"), - (0x1F700, "V"), - (0x1F777, "X"), - (0x1F77B, "V"), - (0x1F7DA, "X"), - (0x1F7E0, "V"), - (0x1F7EC, "X"), - (0x1F7F0, "V"), - (0x1F7F1, "X"), - (0x1F800, "V"), - (0x1F80C, "X"), - (0x1F810, "V"), - (0x1F848, "X"), - (0x1F850, "V"), - (0x1F85A, "X"), - (0x1F860, "V"), - (0x1F888, "X"), - (0x1F890, "V"), - (0x1F8AE, "X"), - (0x1F8B0, "V"), - (0x1F8BC, "X"), - (0x1F8C0, "V"), - (0x1F8C2, "X"), - (0x1F900, "V"), - (0x1FA54, "X"), - (0x1FA60, "V"), - (0x1FA6E, "X"), - (0x1FA70, "V"), - (0x1FA7D, "X"), - (0x1FA80, "V"), - (0x1FA8A, "X"), - (0x1FA8F, "V"), - (0x1FAC7, "X"), - (0x1FACE, "V"), - (0x1FADD, "X"), - (0x1FADF, "V"), - (0x1FAEA, "X"), - (0x1FAF0, "V"), - (0x1FAF9, "X"), - (0x1FB00, "V"), - (0x1FB93, "X"), - (0x1FB94, "V"), - (0x1FBF0, "M", "0"), - (0x1FBF1, "M", "1"), - (0x1FBF2, "M", "2"), - (0x1FBF3, "M", "3"), - (0x1FBF4, "M", "4"), - (0x1FBF5, "M", "5"), - (0x1FBF6, "M", "6"), - (0x1FBF7, "M", "7"), - (0x1FBF8, "M", "8"), - (0x1FBF9, "M", "9"), - (0x1FBFA, "X"), - (0x20000, "V"), - (0x2A6E0, "X"), - (0x2A700, "V"), - (0x2B73A, "X"), - (0x2B740, "V"), - (0x2B81E, "X"), - (0x2B820, "V"), - (0x2CEA2, "X"), - (0x2CEB0, "V"), - (0x2EBE1, "X"), - (0x2EBF0, "V"), - (0x2EE5E, "X"), - (0x2F800, "M", "丽"), - (0x2F801, "M", "丸"), - (0x2F802, "M", "乁"), - (0x2F803, "M", "𠄢"), - (0x2F804, "M", "你"), - (0x2F805, "M", "侮"), - (0x2F806, "M", "侻"), - (0x2F807, "M", "倂"), - (0x2F808, "M", "偺"), - (0x2F809, "M", "備"), - (0x2F80A, "M", "僧"), - (0x2F80B, "M", "像"), - (0x2F80C, "M", "㒞"), - (0x2F80D, "M", "𠘺"), - (0x2F80E, "M", "免"), - ] - - -def _seg_78() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x2F80F, "M", "兔"), - (0x2F810, "M", "兤"), - (0x2F811, "M", "具"), - (0x2F812, "M", "𠔜"), - (0x2F813, "M", "㒹"), - (0x2F814, "M", "內"), - (0x2F815, "M", "再"), - (0x2F816, "M", "𠕋"), - (0x2F817, "M", "冗"), - (0x2F818, "M", "冤"), - (0x2F819, "M", "仌"), - (0x2F81A, "M", "冬"), - (0x2F81B, "M", "况"), - (0x2F81C, "M", "𩇟"), - (0x2F81D, "M", "凵"), - (0x2F81E, "M", "刃"), - (0x2F81F, "M", "㓟"), - (0x2F820, "M", "刻"), - (0x2F821, "M", "剆"), - (0x2F822, "M", "割"), - (0x2F823, "M", "剷"), - (0x2F824, "M", "㔕"), - (0x2F825, "M", "勇"), - (0x2F826, "M", "勉"), - (0x2F827, "M", "勤"), - (0x2F828, "M", "勺"), - (0x2F829, "M", "包"), - (0x2F82A, "M", "匆"), - (0x2F82B, "M", "北"), - (0x2F82C, "M", "卉"), - (0x2F82D, "M", "卑"), - (0x2F82E, "M", "博"), - (0x2F82F, "M", "即"), - (0x2F830, "M", "卽"), - (0x2F831, "M", "卿"), - (0x2F834, "M", "𠨬"), - (0x2F835, "M", "灰"), - (0x2F836, "M", "及"), - (0x2F837, "M", "叟"), - (0x2F838, "M", "𠭣"), - (0x2F839, "M", "叫"), - (0x2F83A, "M", "叱"), - (0x2F83B, "M", "吆"), - (0x2F83C, "M", "咞"), - (0x2F83D, "M", "吸"), - (0x2F83E, "M", "呈"), - (0x2F83F, "M", "周"), - (0x2F840, "M", "咢"), - (0x2F841, "M", "哶"), - (0x2F842, "M", "唐"), - (0x2F843, "M", "啓"), - (0x2F844, "M", "啣"), - (0x2F845, "M", "善"), - (0x2F847, "M", "喙"), - (0x2F848, "M", "喫"), - (0x2F849, "M", "喳"), - (0x2F84A, "M", "嗂"), - (0x2F84B, "M", "圖"), - (0x2F84C, "M", "嘆"), - (0x2F84D, "M", "圗"), - (0x2F84E, "M", "噑"), - (0x2F84F, "M", "噴"), - (0x2F850, "M", "切"), - (0x2F851, "M", "壮"), - (0x2F852, "M", "城"), - (0x2F853, "M", "埴"), - (0x2F854, "M", "堍"), - (0x2F855, "M", "型"), - (0x2F856, "M", "堲"), - (0x2F857, "M", "報"), - (0x2F858, "M", "墬"), - (0x2F859, "M", "𡓤"), - (0x2F85A, "M", "売"), - (0x2F85B, "M", "壷"), - (0x2F85C, "M", "夆"), - (0x2F85D, "M", "多"), - (0x2F85E, "M", "夢"), - (0x2F85F, "M", "奢"), - (0x2F860, "M", "𡚨"), - (0x2F861, "M", "𡛪"), - (0x2F862, "M", "姬"), - (0x2F863, "M", "娛"), - (0x2F864, "M", "娧"), - (0x2F865, "M", "姘"), - (0x2F866, "M", "婦"), - (0x2F867, "M", "㛮"), - (0x2F868, "M", "㛼"), - (0x2F869, "M", "嬈"), - (0x2F86A, "M", "嬾"), - (0x2F86C, "M", "𡧈"), - (0x2F86D, "M", "寃"), - (0x2F86E, "M", "寘"), - (0x2F86F, "M", "寧"), - (0x2F870, "M", "寳"), - (0x2F871, "M", "𡬘"), - (0x2F872, "M", "寿"), - (0x2F873, "M", "将"), - (0x2F874, "M", "当"), - (0x2F875, "M", "尢"), - (0x2F876, "M", "㞁"), - ] - - -def _seg_79() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x2F877, "M", "屠"), - (0x2F878, "M", "屮"), - (0x2F879, "M", "峀"), - (0x2F87A, "M", "岍"), - (0x2F87B, "M", "𡷤"), - (0x2F87C, "M", "嵃"), - (0x2F87D, "M", "𡷦"), - (0x2F87E, "M", "嵮"), - (0x2F87F, "M", "嵫"), - (0x2F880, "M", "嵼"), - (0x2F881, "M", "巡"), - (0x2F882, "M", "巢"), - (0x2F883, "M", "㠯"), - (0x2F884, "M", "巽"), - (0x2F885, "M", "帨"), - (0x2F886, "M", "帽"), - (0x2F887, "M", "幩"), - (0x2F888, "M", "㡢"), - (0x2F889, "M", "𢆃"), - (0x2F88A, "M", "㡼"), - (0x2F88B, "M", "庰"), - (0x2F88C, "M", "庳"), - (0x2F88D, "M", "庶"), - (0x2F88E, "M", "廊"), - (0x2F88F, "M", "𪎒"), - (0x2F890, "M", "廾"), - (0x2F891, "M", "𢌱"), - (0x2F893, "M", "舁"), - (0x2F894, "M", "弢"), - (0x2F896, "M", "㣇"), - (0x2F897, "M", "𣊸"), - (0x2F898, "M", "𦇚"), - (0x2F899, "M", "形"), - (0x2F89A, "M", "彫"), - (0x2F89B, "M", "㣣"), - (0x2F89C, "M", "徚"), - (0x2F89D, "M", "忍"), - (0x2F89E, "M", "志"), - (0x2F89F, "M", "忹"), - (0x2F8A0, "M", "悁"), - (0x2F8A1, "M", "㤺"), - (0x2F8A2, "M", "㤜"), - (0x2F8A3, "M", "悔"), - (0x2F8A4, "M", "𢛔"), - (0x2F8A5, "M", "惇"), - (0x2F8A6, "M", "慈"), - (0x2F8A7, "M", "慌"), - (0x2F8A8, "M", "慎"), - (0x2F8A9, "M", "慌"), - (0x2F8AA, "M", "慺"), - (0x2F8AB, "M", "憎"), - (0x2F8AC, "M", "憲"), - (0x2F8AD, "M", "憤"), - (0x2F8AE, "M", "憯"), - (0x2F8AF, "M", "懞"), - (0x2F8B0, "M", "懲"), - (0x2F8B1, "M", "懶"), - (0x2F8B2, "M", "成"), - (0x2F8B3, "M", "戛"), - (0x2F8B4, "M", "扝"), - (0x2F8B5, "M", "抱"), - (0x2F8B6, "M", "拔"), - (0x2F8B7, "M", "捐"), - (0x2F8B8, "M", "𢬌"), - (0x2F8B9, "M", "挽"), - (0x2F8BA, "M", "拼"), - (0x2F8BB, "M", "捨"), - (0x2F8BC, "M", "掃"), - (0x2F8BD, "M", "揤"), - (0x2F8BE, "M", "𢯱"), - (0x2F8BF, "M", "搢"), - (0x2F8C0, "M", "揅"), - (0x2F8C1, "M", "掩"), - (0x2F8C2, "M", "㨮"), - (0x2F8C3, "M", "摩"), - (0x2F8C4, "M", "摾"), - (0x2F8C5, "M", "撝"), - (0x2F8C6, "M", "摷"), - (0x2F8C7, "M", "㩬"), - (0x2F8C8, "M", "敏"), - (0x2F8C9, "M", "敬"), - (0x2F8CA, "M", "𣀊"), - (0x2F8CB, "M", "旣"), - (0x2F8CC, "M", "書"), - (0x2F8CD, "M", "晉"), - (0x2F8CE, "M", "㬙"), - (0x2F8CF, "M", "暑"), - (0x2F8D0, "M", "㬈"), - (0x2F8D1, "M", "㫤"), - (0x2F8D2, "M", "冒"), - (0x2F8D3, "M", "冕"), - (0x2F8D4, "M", "最"), - (0x2F8D5, "M", "暜"), - (0x2F8D6, "M", "肭"), - (0x2F8D7, "M", "䏙"), - (0x2F8D8, "M", "朗"), - (0x2F8D9, "M", "望"), - (0x2F8DA, "M", "朡"), - (0x2F8DB, "M", "杞"), - (0x2F8DC, "M", "杓"), - ] - - -def _seg_80() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x2F8DD, "M", "𣏃"), - (0x2F8DE, "M", "㭉"), - (0x2F8DF, "M", "柺"), - (0x2F8E0, "M", "枅"), - (0x2F8E1, "M", "桒"), - (0x2F8E2, "M", "梅"), - (0x2F8E3, "M", "𣑭"), - (0x2F8E4, "M", "梎"), - (0x2F8E5, "M", "栟"), - (0x2F8E6, "M", "椔"), - (0x2F8E7, "M", "㮝"), - (0x2F8E8, "M", "楂"), - (0x2F8E9, "M", "榣"), - (0x2F8EA, "M", "槪"), - (0x2F8EB, "M", "檨"), - (0x2F8EC, "M", "𣚣"), - (0x2F8ED, "M", "櫛"), - (0x2F8EE, "M", "㰘"), - (0x2F8EF, "M", "次"), - (0x2F8F0, "M", "𣢧"), - (0x2F8F1, "M", "歔"), - (0x2F8F2, "M", "㱎"), - (0x2F8F3, "M", "歲"), - (0x2F8F4, "M", "殟"), - (0x2F8F5, "M", "殺"), - (0x2F8F6, "M", "殻"), - (0x2F8F7, "M", "𣪍"), - (0x2F8F8, "M", "𡴋"), - (0x2F8F9, "M", "𣫺"), - (0x2F8FA, "M", "汎"), - (0x2F8FB, "M", "𣲼"), - (0x2F8FC, "M", "沿"), - (0x2F8FD, "M", "泍"), - (0x2F8FE, "M", "汧"), - (0x2F8FF, "M", "洖"), - (0x2F900, "M", "派"), - (0x2F901, "M", "海"), - (0x2F902, "M", "流"), - (0x2F903, "M", "浩"), - (0x2F904, "M", "浸"), - (0x2F905, "M", "涅"), - (0x2F906, "M", "𣴞"), - (0x2F907, "M", "洴"), - (0x2F908, "M", "港"), - (0x2F909, "M", "湮"), - (0x2F90A, "M", "㴳"), - (0x2F90B, "M", "滋"), - (0x2F90C, "M", "滇"), - (0x2F90D, "M", "𣻑"), - (0x2F90E, "M", "淹"), - (0x2F90F, "M", "潮"), - (0x2F910, "M", "𣽞"), - (0x2F911, "M", "𣾎"), - (0x2F912, "M", "濆"), - (0x2F913, "M", "瀹"), - (0x2F914, "M", "瀞"), - (0x2F915, "M", "瀛"), - (0x2F916, "M", "㶖"), - (0x2F917, "M", "灊"), - (0x2F918, "M", "災"), - (0x2F919, "M", "灷"), - (0x2F91A, "M", "炭"), - (0x2F91B, "M", "𠔥"), - (0x2F91C, "M", "煅"), - (0x2F91D, "M", "𤉣"), - (0x2F91E, "M", "熜"), - (0x2F91F, "M", "𤎫"), - (0x2F920, "M", "爨"), - (0x2F921, "M", "爵"), - (0x2F922, "M", "牐"), - (0x2F923, "M", "𤘈"), - (0x2F924, "M", "犀"), - (0x2F925, "M", "犕"), - (0x2F926, "M", "𤜵"), - (0x2F927, "M", "𤠔"), - (0x2F928, "M", "獺"), - (0x2F929, "M", "王"), - (0x2F92A, "M", "㺬"), - (0x2F92B, "M", "玥"), - (0x2F92C, "M", "㺸"), - (0x2F92E, "M", "瑇"), - (0x2F92F, "M", "瑜"), - (0x2F930, "M", "瑱"), - (0x2F931, "M", "璅"), - (0x2F932, "M", "瓊"), - (0x2F933, "M", "㼛"), - (0x2F934, "M", "甤"), - (0x2F935, "M", "𤰶"), - (0x2F936, "M", "甾"), - (0x2F937, "M", "𤲒"), - (0x2F938, "M", "異"), - (0x2F939, "M", "𢆟"), - (0x2F93A, "M", "瘐"), - (0x2F93B, "M", "𤾡"), - (0x2F93C, "M", "𤾸"), - (0x2F93D, "M", "𥁄"), - (0x2F93E, "M", "㿼"), - (0x2F93F, "M", "䀈"), - (0x2F940, "M", "直"), - (0x2F941, "M", "𥃳"), - ] - - -def _seg_81() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x2F942, "M", "𥃲"), - (0x2F943, "M", "𥄙"), - (0x2F944, "M", "𥄳"), - (0x2F945, "M", "眞"), - (0x2F946, "M", "真"), - (0x2F948, "M", "睊"), - (0x2F949, "M", "䀹"), - (0x2F94A, "M", "瞋"), - (0x2F94B, "M", "䁆"), - (0x2F94C, "M", "䂖"), - (0x2F94D, "M", "𥐝"), - (0x2F94E, "M", "硎"), - (0x2F94F, "M", "碌"), - (0x2F950, "M", "磌"), - (0x2F951, "M", "䃣"), - (0x2F952, "M", "𥘦"), - (0x2F953, "M", "祖"), - (0x2F954, "M", "𥚚"), - (0x2F955, "M", "𥛅"), - (0x2F956, "M", "福"), - (0x2F957, "M", "秫"), - (0x2F958, "M", "䄯"), - (0x2F959, "M", "穀"), - (0x2F95A, "M", "穊"), - (0x2F95B, "M", "穏"), - (0x2F95C, "M", "𥥼"), - (0x2F95D, "M", "𥪧"), - (0x2F95F, "M", "竮"), - (0x2F960, "M", "䈂"), - (0x2F961, "M", "𥮫"), - (0x2F962, "M", "篆"), - (0x2F963, "M", "築"), - (0x2F964, "M", "䈧"), - (0x2F965, "M", "𥲀"), - (0x2F966, "M", "糒"), - (0x2F967, "M", "䊠"), - (0x2F968, "M", "糨"), - (0x2F969, "M", "糣"), - (0x2F96A, "M", "紀"), - (0x2F96B, "M", "𥾆"), - (0x2F96C, "M", "絣"), - (0x2F96D, "M", "䌁"), - (0x2F96E, "M", "緇"), - (0x2F96F, "M", "縂"), - (0x2F970, "M", "繅"), - (0x2F971, "M", "䌴"), - (0x2F972, "M", "𦈨"), - (0x2F973, "M", "𦉇"), - (0x2F974, "M", "䍙"), - (0x2F975, "M", "𦋙"), - (0x2F976, "M", "罺"), - (0x2F977, "M", "𦌾"), - (0x2F978, "M", "羕"), - (0x2F979, "M", "翺"), - (0x2F97A, "M", "者"), - (0x2F97B, "M", "𦓚"), - (0x2F97C, "M", "𦔣"), - (0x2F97D, "M", "聠"), - (0x2F97E, "M", "𦖨"), - (0x2F97F, "M", "聰"), - (0x2F980, "M", "𣍟"), - (0x2F981, "M", "䏕"), - (0x2F982, "M", "育"), - (0x2F983, "M", "脃"), - (0x2F984, "M", "䐋"), - (0x2F985, "M", "脾"), - (0x2F986, "M", "媵"), - (0x2F987, "M", "𦞧"), - (0x2F988, "M", "𦞵"), - (0x2F989, "M", "𣎓"), - (0x2F98A, "M", "𣎜"), - (0x2F98B, "M", "舁"), - (0x2F98C, "M", "舄"), - (0x2F98D, "M", "辞"), - (0x2F98E, "M", "䑫"), - (0x2F98F, "M", "芑"), - (0x2F990, "M", "芋"), - (0x2F991, "M", "芝"), - (0x2F992, "M", "劳"), - (0x2F993, "M", "花"), - (0x2F994, "M", "芳"), - (0x2F995, "M", "芽"), - (0x2F996, "M", "苦"), - (0x2F997, "M", "𦬼"), - (0x2F998, "M", "若"), - (0x2F999, "M", "茝"), - (0x2F99A, "M", "荣"), - (0x2F99B, "M", "莭"), - (0x2F99C, "M", "茣"), - (0x2F99D, "M", "莽"), - (0x2F99E, "M", "菧"), - (0x2F99F, "M", "著"), - (0x2F9A0, "M", "荓"), - (0x2F9A1, "M", "菊"), - (0x2F9A2, "M", "菌"), - (0x2F9A3, "M", "菜"), - (0x2F9A4, "M", "𦰶"), - (0x2F9A5, "M", "𦵫"), - (0x2F9A6, "M", "𦳕"), - (0x2F9A7, "M", "䔫"), - ] - - -def _seg_82() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x2F9A8, "M", "蓱"), - (0x2F9A9, "M", "蓳"), - (0x2F9AA, "M", "蔖"), - (0x2F9AB, "M", "𧏊"), - (0x2F9AC, "M", "蕤"), - (0x2F9AD, "M", "𦼬"), - (0x2F9AE, "M", "䕝"), - (0x2F9AF, "M", "䕡"), - (0x2F9B0, "M", "𦾱"), - (0x2F9B1, "M", "𧃒"), - (0x2F9B2, "M", "䕫"), - (0x2F9B3, "M", "虐"), - (0x2F9B4, "M", "虜"), - (0x2F9B5, "M", "虧"), - (0x2F9B6, "M", "虩"), - (0x2F9B7, "M", "蚩"), - (0x2F9B8, "M", "蚈"), - (0x2F9B9, "M", "蜎"), - (0x2F9BA, "M", "蛢"), - (0x2F9BB, "M", "蝹"), - (0x2F9BC, "M", "蜨"), - (0x2F9BD, "M", "蝫"), - (0x2F9BE, "M", "螆"), - (0x2F9BF, "M", "䗗"), - (0x2F9C0, "M", "蟡"), - (0x2F9C1, "M", "蠁"), - (0x2F9C2, "M", "䗹"), - (0x2F9C3, "M", "衠"), - (0x2F9C4, "M", "衣"), - (0x2F9C5, "M", "𧙧"), - (0x2F9C6, "M", "裗"), - (0x2F9C7, "M", "裞"), - (0x2F9C8, "M", "䘵"), - (0x2F9C9, "M", "裺"), - (0x2F9CA, "M", "㒻"), - (0x2F9CB, "M", "𧢮"), - (0x2F9CC, "M", "𧥦"), - (0x2F9CD, "M", "䚾"), - (0x2F9CE, "M", "䛇"), - (0x2F9CF, "M", "誠"), - (0x2F9D0, "M", "諭"), - (0x2F9D1, "M", "變"), - (0x2F9D2, "M", "豕"), - (0x2F9D3, "M", "𧲨"), - (0x2F9D4, "M", "貫"), - (0x2F9D5, "M", "賁"), - (0x2F9D6, "M", "贛"), - (0x2F9D7, "M", "起"), - (0x2F9D8, "M", "𧼯"), - (0x2F9D9, "M", "𠠄"), - (0x2F9DA, "M", "跋"), - (0x2F9DB, "M", "趼"), - (0x2F9DC, "M", "跰"), - (0x2F9DD, "M", "𠣞"), - (0x2F9DE, "M", "軔"), - (0x2F9DF, "M", "輸"), - (0x2F9E0, "M", "𨗒"), - (0x2F9E1, "M", "𨗭"), - (0x2F9E2, "M", "邔"), - (0x2F9E3, "M", "郱"), - (0x2F9E4, "M", "鄑"), - (0x2F9E5, "M", "𨜮"), - (0x2F9E6, "M", "鄛"), - (0x2F9E7, "M", "鈸"), - (0x2F9E8, "M", "鋗"), - (0x2F9E9, "M", "鋘"), - (0x2F9EA, "M", "鉼"), - (0x2F9EB, "M", "鏹"), - (0x2F9EC, "M", "鐕"), - (0x2F9ED, "M", "𨯺"), - (0x2F9EE, "M", "開"), - (0x2F9EF, "M", "䦕"), - (0x2F9F0, "M", "閷"), - (0x2F9F1, "M", "𨵷"), - (0x2F9F2, "M", "䧦"), - (0x2F9F3, "M", "雃"), - (0x2F9F4, "M", "嶲"), - (0x2F9F5, "M", "霣"), - (0x2F9F6, "M", "𩅅"), - (0x2F9F7, "M", "𩈚"), - (0x2F9F8, "M", "䩮"), - (0x2F9F9, "M", "䩶"), - (0x2F9FA, "M", "韠"), - (0x2F9FB, "M", "𩐊"), - (0x2F9FC, "M", "䪲"), - (0x2F9FD, "M", "𩒖"), - (0x2F9FE, "M", "頋"), - (0x2FA00, "M", "頩"), - (0x2FA01, "M", "𩖶"), - (0x2FA02, "M", "飢"), - (0x2FA03, "M", "䬳"), - (0x2FA04, "M", "餩"), - (0x2FA05, "M", "馧"), - (0x2FA06, "M", "駂"), - (0x2FA07, "M", "駾"), - (0x2FA08, "M", "䯎"), - (0x2FA09, "M", "𩬰"), - (0x2FA0A, "M", "鬒"), - (0x2FA0B, "M", "鱀"), - (0x2FA0C, "M", "鳽"), - ] - - -def _seg_83() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: - return [ - (0x2FA0D, "M", "䳎"), - (0x2FA0E, "M", "䳭"), - (0x2FA0F, "M", "鵧"), - (0x2FA10, "M", "𪃎"), - (0x2FA11, "M", "䳸"), - (0x2FA12, "M", "𪄅"), - (0x2FA13, "M", "𪈎"), - (0x2FA14, "M", "𪊑"), - (0x2FA15, "M", "麻"), - (0x2FA16, "M", "䵖"), - (0x2FA17, "M", "黹"), - (0x2FA18, "M", "黾"), - (0x2FA19, "M", "鼅"), - (0x2FA1A, "M", "鼏"), - (0x2FA1B, "M", "鼖"), - (0x2FA1C, "M", "鼻"), - (0x2FA1D, "M", "𪘀"), - (0x2FA1E, "X"), - (0x30000, "V"), - (0x3134B, "X"), - (0x31350, "V"), - (0x323B0, "X"), - (0xE0100, "I"), - (0xE01F0, "X"), - ] - - -uts46data = tuple( - _seg_0() - + _seg_1() - + _seg_2() - + _seg_3() - + _seg_4() - + _seg_5() - + _seg_6() - + _seg_7() - + _seg_8() - + _seg_9() - + _seg_10() - + _seg_11() - + _seg_12() - + _seg_13() - + _seg_14() - + _seg_15() - + _seg_16() - + _seg_17() - + _seg_18() - + _seg_19() - + _seg_20() - + _seg_21() - + _seg_22() - + _seg_23() - + _seg_24() - + _seg_25() - + _seg_26() - + _seg_27() - + _seg_28() - + _seg_29() - + _seg_30() - + _seg_31() - + _seg_32() - + _seg_33() - + _seg_34() - + _seg_35() - + _seg_36() - + _seg_37() - + _seg_38() - + _seg_39() - + _seg_40() - + _seg_41() - + _seg_42() - + _seg_43() - + _seg_44() - + _seg_45() - + _seg_46() - + _seg_47() - + _seg_48() - + _seg_49() - + _seg_50() - + _seg_51() - + _seg_52() - + _seg_53() - + _seg_54() - + _seg_55() - + _seg_56() - + _seg_57() - + _seg_58() - + _seg_59() - + _seg_60() - + _seg_61() - + _seg_62() - + _seg_63() - + _seg_64() - + _seg_65() - + _seg_66() - + _seg_67() - + _seg_68() - + _seg_69() - + _seg_70() - + _seg_71() - + _seg_72() - + _seg_73() - + _seg_74() - + _seg_75() - + _seg_76() - + _seg_77() - + _seg_78() - + _seg_79() - + _seg_80() - + _seg_81() - + _seg_82() - + _seg_83() -) # type: Tuple[Union[Tuple[int, str], Tuple[int, str, str]], ...] diff --git a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/INSTALLER deleted file mode 100755 index a1b589e3..00000000 --- a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/METADATA b/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/METADATA deleted file mode 100755 index 3200e601..00000000 --- a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/METADATA +++ /dev/null @@ -1,107 +0,0 @@ -Metadata-Version: 2.4 -Name: packaging -Version: 26.0 -Summary: Core utilities for Python packages -Author-email: Donald Stufft -Requires-Python: >=3.8 -Description-Content-Type: text/x-rst -License-Expression: Apache-2.0 OR BSD-2-Clause -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3.13 -Classifier: Programming Language :: Python :: 3.14 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Typing :: Typed -License-File: LICENSE -License-File: LICENSE.APACHE -License-File: LICENSE.BSD -Project-URL: Documentation, https://packaging.pypa.io/ -Project-URL: Source, https://github.com/pypa/packaging - -packaging -========= - -.. start-intro - -Reusable core utilities for various Python Packaging -`interoperability specifications `_. - -This library provides utilities that implement the interoperability -specifications which have clearly one correct behaviour (eg: :pep:`440`) -or benefit greatly from having a single shared implementation (eg: :pep:`425`). - -.. end-intro - -The ``packaging`` project includes the following: version handling, specifiers, -markers, requirements, tags, metadata, lockfiles, utilities. - -Documentation -------------- - -The `documentation`_ provides information and the API for the following: - -- Version Handling -- Specifiers -- Markers -- Requirements -- Tags -- Metadata -- Lockfiles -- Utilities - -Installation ------------- - -Use ``pip`` to install these utilities:: - - pip install packaging - -The ``packaging`` library uses calendar-based versioning (``YY.N``). - -Discussion ----------- - -If you run into bugs, you can file them in our `issue tracker`_. - -You can also join ``#pypa`` on Freenode to ask questions or get involved. - - -.. _`documentation`: https://packaging.pypa.io/ -.. _`issue tracker`: https://github.com/pypa/packaging/issues - - -Code of Conduct ---------------- - -Everyone interacting in the packaging project's codebases, issue trackers, chat -rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_. - -.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md - -Contributing ------------- - -The ``CONTRIBUTING.rst`` file outlines how to contribute to this project as -well as how to report a potential security issue. The documentation for this -project also covers information about `project development`_ and `security`_. - -.. _`project development`: https://packaging.pypa.io/en/latest/development/ -.. _`security`: https://packaging.pypa.io/en/latest/security/ - -Project History ---------------- - -Please review the ``CHANGELOG.rst`` file or the `Changelog documentation`_ for -recent changes and project history. - -.. _`Changelog documentation`: https://packaging.pypa.io/en/latest/changelog/ - diff --git a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/RECORD b/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/RECORD deleted file mode 100755 index 5e18df3d..00000000 --- a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/RECORD +++ /dev/null @@ -1,26 +0,0 @@ -packaging-26.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -packaging-26.0.dist-info/METADATA,sha256=M2K7fWom2iliuo2qpHhc0LrKwhq6kIoRlcyPWVgKJlo,3309 -packaging-26.0.dist-info/RECORD,, -packaging-26.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -packaging-26.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 -packaging-26.0.dist-info/licenses/LICENSE,sha256=ytHvW9NA1z4HS6YU0m996spceUDD2MNIUuZcSQlobEg,197 -packaging-26.0.dist-info/licenses/LICENSE.APACHE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174 -packaging-26.0.dist-info/licenses/LICENSE.BSD,sha256=tw5-m3QvHMb5SLNMFqo5_-zpQZY2S8iP8NIYDwAo-sU,1344 -packaging/__init__.py,sha256=y4lVbpeBzCGk-IPDw5BGBZ_b0P3ukEEJZAbGYc6Ey8c,494 -packaging/_elffile.py,sha256=-sKkptYqzYw2-x3QByJa5mB4rfPWu1pxkZHRx1WAFCY,3211 -packaging/_manylinux.py,sha256=Hf6nB0cOrayEs96-p3oIXAgGnFquv20DO5l-o2_Xnv0,9559 -packaging/_musllinux.py,sha256=Z6swjH3MA7XS3qXnmMN7QPhqP3fnoYI0eQ18e9-HgAE,2707 -packaging/_parser.py,sha256=U_DajsEx2VoC_F46fSVV3hDKNCWoQYkPkasO3dld0ig,10518 -packaging/_structures.py,sha256=Hn49Ta8zV9Wo8GiCL8Nl2ARZY983Un3pruZGVNldPwE,1514 -packaging/_tokenizer.py,sha256=M8EwNIdXeL9NMFuFrQtiOKwjka_xFx8KjRQnfE8O_z8,5421 -packaging/licenses/__init__.py,sha256=TwXLHZCXwSgdFwRLPxW602T6mSieunSFHM6fp8pgW78,5819 -packaging/licenses/_spdx.py,sha256=WW7DXiyg68up_YND_wpRYlr1SHhiV4FfJLQffghhMxQ,51122 -packaging/markers.py,sha256=ZX-cLvW1S3cZcEc0fHI4z7zSx5U2T19yMpDP_mE-CYw,12771 -packaging/metadata.py,sha256=CWVZpN_HfoYMSSDuCP7igOvGgqA9AOmpW8f3qTisfnc,39360 -packaging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -packaging/pylock.py,sha256=-R1uNfJ4PaLto7Mg62YsGOHgvskuiIEqPwxOywl42Jk,22537 -packaging/requirements.py,sha256=PMCAWD8aNMnVD-6uZMedhBuAVX2573eZ4yPBLXmz04I,2870 -packaging/specifiers.py,sha256=EPNPimY_zFivthv1vdjZYz5IqkKGsnKR2yKh-EVyvZw,40797 -packaging/tags.py,sha256=cXLV1pJD3UtJlDg7Wz3zrfdQhRZqr8jumSAKKAAd2xE,22856 -packaging/utils.py,sha256=N4c6oZzFJy6klTZ3AnkNz7sSkJesuFWPp68LA3B5dAo,5040 -packaging/version.py,sha256=7XWlL2IDYLwDYC0ht6cFEhapLwLWbmyo4rb7sEFj0x8,23272 diff --git a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/REQUESTED deleted file mode 100755 index e69de29b..00000000 diff --git a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/WHEEL deleted file mode 100755 index d8b9936d..00000000 --- a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: flit 3.12.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/licenses/LICENSE b/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/licenses/LICENSE deleted file mode 100755 index 6f62d44e..00000000 --- a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/licenses/LICENSE +++ /dev/null @@ -1,3 +0,0 @@ -This software is made available under the terms of *either* of the licenses -found in LICENSE.APACHE or LICENSE.BSD. Contributions to this software is made -under the terms of *both* these licenses. diff --git a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/licenses/LICENSE.APACHE b/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/licenses/LICENSE.APACHE deleted file mode 100755 index f433b1a5..00000000 --- a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/licenses/LICENSE.APACHE +++ /dev/null @@ -1,177 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS diff --git a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/licenses/LICENSE.BSD b/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/licenses/LICENSE.BSD deleted file mode 100755 index 42ce7b75..00000000 --- a/apps/bitwarden_event_logs/lib/packaging-26.0.dist-info/licenses/LICENSE.BSD +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) Donald Stufft and individual contributors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/apps/bitwarden_event_logs/lib/packaging/__init__.py b/apps/bitwarden_event_logs/lib/packaging/__init__.py deleted file mode 100755 index 21695a74..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -__title__ = "packaging" -__summary__ = "Core utilities for Python packages" -__uri__ = "https://github.com/pypa/packaging" - -__version__ = "26.0" - -__author__ = "Donald Stufft and individual contributors" -__email__ = "donald@stufft.io" - -__license__ = "BSD-2-Clause or Apache-2.0" -__copyright__ = f"2014 {__author__}" diff --git a/apps/bitwarden_event_logs/lib/packaging/_elffile.py b/apps/bitwarden_event_logs/lib/packaging/_elffile.py deleted file mode 100755 index 497b0645..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/_elffile.py +++ /dev/null @@ -1,108 +0,0 @@ -""" -ELF file parser. - -This provides a class ``ELFFile`` that parses an ELF executable in a similar -interface to ``ZipFile``. Only the read interface is implemented. - -ELF header: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html -""" - -from __future__ import annotations - -import enum -import os -import struct -from typing import IO - - -class ELFInvalid(ValueError): - pass - - -class EIClass(enum.IntEnum): - C32 = 1 - C64 = 2 - - -class EIData(enum.IntEnum): - Lsb = 1 - Msb = 2 - - -class EMachine(enum.IntEnum): - I386 = 3 - S390 = 22 - Arm = 40 - X8664 = 62 - AArc64 = 183 - - -class ELFFile: - """ - Representation of an ELF executable. - """ - - def __init__(self, f: IO[bytes]) -> None: - self._f = f - - try: - ident = self._read("16B") - except struct.error as e: - raise ELFInvalid("unable to parse identification") from e - magic = bytes(ident[:4]) - if magic != b"\x7fELF": - raise ELFInvalid(f"invalid magic: {magic!r}") - - self.capacity = ident[4] # Format for program header (bitness). - self.encoding = ident[5] # Data structure encoding (endianness). - - try: - # e_fmt: Format for program header. - # p_fmt: Format for section header. - # p_idx: Indexes to find p_type, p_offset, and p_filesz. - e_fmt, self._p_fmt, self._p_idx = { - (1, 1): ("HHIIIIIHHH", ">IIIIIIII", (0, 1, 4)), # 32-bit MSB. - (2, 1): ("HHIQQQIHHH", ">IIQQQQQQ", (0, 2, 5)), # 64-bit MSB. - }[(self.capacity, self.encoding)] - except KeyError as e: - raise ELFInvalid( - f"unrecognized capacity ({self.capacity}) or encoding ({self.encoding})" - ) from e - - try: - ( - _, - self.machine, # Architecture type. - _, - _, - self._e_phoff, # Offset of program header. - _, - self.flags, # Processor-specific flags. - _, - self._e_phentsize, # Size of section. - self._e_phnum, # Number of sections. - ) = self._read(e_fmt) - except struct.error as e: - raise ELFInvalid("unable to parse machine and section information") from e - - def _read(self, fmt: str) -> tuple[int, ...]: - return struct.unpack(fmt, self._f.read(struct.calcsize(fmt))) - - @property - def interpreter(self) -> str | None: - """ - The path recorded in the ``PT_INTERP`` section header. - """ - for index in range(self._e_phnum): - self._f.seek(self._e_phoff + self._e_phentsize * index) - try: - data = self._read(self._p_fmt) - except struct.error: - continue - if data[self._p_idx[0]] != 3: # Not PT_INTERP. - continue - self._f.seek(data[self._p_idx[1]]) - return os.fsdecode(self._f.read(data[self._p_idx[2]])).strip("\0") - return None diff --git a/apps/bitwarden_event_logs/lib/packaging/_manylinux.py b/apps/bitwarden_event_logs/lib/packaging/_manylinux.py deleted file mode 100755 index 0e79e8a8..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/_manylinux.py +++ /dev/null @@ -1,262 +0,0 @@ -from __future__ import annotations - -import collections -import contextlib -import functools -import os -import re -import sys -import warnings -from typing import Generator, Iterator, NamedTuple, Sequence - -from ._elffile import EIClass, EIData, ELFFile, EMachine - -EF_ARM_ABIMASK = 0xFF000000 -EF_ARM_ABI_VER5 = 0x05000000 -EF_ARM_ABI_FLOAT_HARD = 0x00000400 - -_ALLOWED_ARCHS = { - "x86_64", - "aarch64", - "ppc64", - "ppc64le", - "s390x", - "loongarch64", - "riscv64", -} - - -# `os.PathLike` not a generic type until Python 3.9, so sticking with `str` -# as the type for `path` until then. -@contextlib.contextmanager -def _parse_elf(path: str) -> Generator[ELFFile | None, None, None]: - try: - with open(path, "rb") as f: - yield ELFFile(f) - except (OSError, TypeError, ValueError): - yield None - - -def _is_linux_armhf(executable: str) -> bool: - # hard-float ABI can be detected from the ELF header of the running - # process - # https://static.docs.arm.com/ihi0044/g/aaelf32.pdf - with _parse_elf(executable) as f: - return ( - f is not None - and f.capacity == EIClass.C32 - and f.encoding == EIData.Lsb - and f.machine == EMachine.Arm - and f.flags & EF_ARM_ABIMASK == EF_ARM_ABI_VER5 - and f.flags & EF_ARM_ABI_FLOAT_HARD == EF_ARM_ABI_FLOAT_HARD - ) - - -def _is_linux_i686(executable: str) -> bool: - with _parse_elf(executable) as f: - return ( - f is not None - and f.capacity == EIClass.C32 - and f.encoding == EIData.Lsb - and f.machine == EMachine.I386 - ) - - -def _have_compatible_abi(executable: str, archs: Sequence[str]) -> bool: - if "armv7l" in archs: - return _is_linux_armhf(executable) - if "i686" in archs: - return _is_linux_i686(executable) - return any(arch in _ALLOWED_ARCHS for arch in archs) - - -# If glibc ever changes its major version, we need to know what the last -# minor version was, so we can build the complete list of all versions. -# For now, guess what the highest minor version might be, assume it will -# be 50 for testing. Once this actually happens, update the dictionary -# with the actual value. -_LAST_GLIBC_MINOR: dict[int, int] = collections.defaultdict(lambda: 50) - - -class _GLibCVersion(NamedTuple): - major: int - minor: int - - -def _glibc_version_string_confstr() -> str | None: - """ - Primary implementation of glibc_version_string using os.confstr. - """ - # os.confstr is quite a bit faster than ctypes.DLL. It's also less likely - # to be broken or missing. This strategy is used in the standard library - # platform module. - # https://github.com/python/cpython/blob/fcf1d003bf4f0100c/Lib/platform.py#L175-L183 - try: - # Should be a string like "glibc 2.17". - version_string: str | None = os.confstr("CS_GNU_LIBC_VERSION") - assert version_string is not None - _, version = version_string.rsplit() - except (AssertionError, AttributeError, OSError, ValueError): - # os.confstr() or CS_GNU_LIBC_VERSION not available (or a bad value)... - return None - return version - - -def _glibc_version_string_ctypes() -> str | None: - """ - Fallback implementation of glibc_version_string using ctypes. - """ - try: - import ctypes # noqa: PLC0415 - except ImportError: - return None - - # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen - # manpage says, "If filename is NULL, then the returned handle is for the - # main program". This way we can let the linker do the work to figure out - # which libc our process is actually using. - # - # We must also handle the special case where the executable is not a - # dynamically linked executable. This can occur when using musl libc, - # for example. In this situation, dlopen() will error, leading to an - # OSError. Interestingly, at least in the case of musl, there is no - # errno set on the OSError. The single string argument used to construct - # OSError comes from libc itself and is therefore not portable to - # hard code here. In any case, failure to call dlopen() means we - # can proceed, so we bail on our attempt. - try: - process_namespace = ctypes.CDLL(None) - except OSError: - return None - - try: - gnu_get_libc_version = process_namespace.gnu_get_libc_version - except AttributeError: - # Symbol doesn't exist -> therefore, we are not linked to - # glibc. - return None - - # Call gnu_get_libc_version, which returns a string like "2.5" - gnu_get_libc_version.restype = ctypes.c_char_p - version_str: str = gnu_get_libc_version() - # py2 / py3 compatibility: - if not isinstance(version_str, str): - version_str = version_str.decode("ascii") - - return version_str - - -def _glibc_version_string() -> str | None: - """Returns glibc version string, or None if not using glibc.""" - return _glibc_version_string_confstr() or _glibc_version_string_ctypes() - - -def _parse_glibc_version(version_str: str) -> _GLibCVersion: - """Parse glibc version. - - We use a regexp instead of str.split because we want to discard any - random junk that might come after the minor version -- this might happen - in patched/forked versions of glibc (e.g. Linaro's version of glibc - uses version strings like "2.20-2014.11"). See gh-3588. - """ - m = re.match(r"(?P[0-9]+)\.(?P[0-9]+)", version_str) - if not m: - warnings.warn( - f"Expected glibc version with 2 components major.minor, got: {version_str}", - RuntimeWarning, - stacklevel=2, - ) - return _GLibCVersion(-1, -1) - return _GLibCVersion(int(m.group("major")), int(m.group("minor"))) - - -@functools.lru_cache -def _get_glibc_version() -> _GLibCVersion: - version_str = _glibc_version_string() - if version_str is None: - return _GLibCVersion(-1, -1) - return _parse_glibc_version(version_str) - - -# From PEP 513, PEP 600 -def _is_compatible(arch: str, version: _GLibCVersion) -> bool: - sys_glibc = _get_glibc_version() - if sys_glibc < version: - return False - # Check for presence of _manylinux module. - try: - import _manylinux # noqa: PLC0415 - except ImportError: - return True - if hasattr(_manylinux, "manylinux_compatible"): - result = _manylinux.manylinux_compatible(version[0], version[1], arch) - if result is not None: - return bool(result) - return True - if version == _GLibCVersion(2, 5) and hasattr(_manylinux, "manylinux1_compatible"): - return bool(_manylinux.manylinux1_compatible) - if version == _GLibCVersion(2, 12) and hasattr( - _manylinux, "manylinux2010_compatible" - ): - return bool(_manylinux.manylinux2010_compatible) - if version == _GLibCVersion(2, 17) and hasattr( - _manylinux, "manylinux2014_compatible" - ): - return bool(_manylinux.manylinux2014_compatible) - return True - - -_LEGACY_MANYLINUX_MAP: dict[_GLibCVersion, str] = { - # CentOS 7 w/ glibc 2.17 (PEP 599) - _GLibCVersion(2, 17): "manylinux2014", - # CentOS 6 w/ glibc 2.12 (PEP 571) - _GLibCVersion(2, 12): "manylinux2010", - # CentOS 5 w/ glibc 2.5 (PEP 513) - _GLibCVersion(2, 5): "manylinux1", -} - - -def platform_tags(archs: Sequence[str]) -> Iterator[str]: - """Generate manylinux tags compatible to the current platform. - - :param archs: Sequence of compatible architectures. - The first one shall be the closest to the actual architecture and be the part of - platform tag after the ``linux_`` prefix, e.g. ``x86_64``. - The ``linux_`` prefix is assumed as a prerequisite for the current platform to - be manylinux-compatible. - - :returns: An iterator of compatible manylinux tags. - """ - if not _have_compatible_abi(sys.executable, archs): - return - # Oldest glibc to be supported regardless of architecture is (2, 17). - too_old_glibc2 = _GLibCVersion(2, 16) - if set(archs) & {"x86_64", "i686"}: - # On x86/i686 also oldest glibc to be supported is (2, 5). - too_old_glibc2 = _GLibCVersion(2, 4) - current_glibc = _GLibCVersion(*_get_glibc_version()) - glibc_max_list = [current_glibc] - # We can assume compatibility across glibc major versions. - # https://sourceware.org/bugzilla/show_bug.cgi?id=24636 - # - # Build a list of maximum glibc versions so that we can - # output the canonical list of all glibc from current_glibc - # down to too_old_glibc2, including all intermediary versions. - for glibc_major in range(current_glibc.major - 1, 1, -1): - glibc_minor = _LAST_GLIBC_MINOR[glibc_major] - glibc_max_list.append(_GLibCVersion(glibc_major, glibc_minor)) - for arch in archs: - for glibc_max in glibc_max_list: - if glibc_max.major == too_old_glibc2.major: - min_minor = too_old_glibc2.minor - else: - # For other glibc major versions oldest supported is (x, 0). - min_minor = -1 - for glibc_minor in range(glibc_max.minor, min_minor, -1): - glibc_version = _GLibCVersion(glibc_max.major, glibc_minor) - if _is_compatible(arch, glibc_version): - yield "manylinux_{}_{}_{}".format(*glibc_version, arch) - - # Handle the legacy manylinux1, manylinux2010, manylinux2014 tags. - if legacy_tag := _LEGACY_MANYLINUX_MAP.get(glibc_version): - yield f"{legacy_tag}_{arch}" diff --git a/apps/bitwarden_event_logs/lib/packaging/_musllinux.py b/apps/bitwarden_event_logs/lib/packaging/_musllinux.py deleted file mode 100755 index 4e8116a7..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/_musllinux.py +++ /dev/null @@ -1,85 +0,0 @@ -"""PEP 656 support. - -This module implements logic to detect if the currently running Python is -linked against musl, and what musl version is used. -""" - -from __future__ import annotations - -import functools -import re -import subprocess -import sys -from typing import Iterator, NamedTuple, Sequence - -from ._elffile import ELFFile - - -class _MuslVersion(NamedTuple): - major: int - minor: int - - -def _parse_musl_version(output: str) -> _MuslVersion | None: - lines = [n for n in (n.strip() for n in output.splitlines()) if n] - if len(lines) < 2 or lines[0][:4] != "musl": - return None - m = re.match(r"Version (\d+)\.(\d+)", lines[1]) - if not m: - return None - return _MuslVersion(major=int(m.group(1)), minor=int(m.group(2))) - - -@functools.lru_cache -def _get_musl_version(executable: str) -> _MuslVersion | None: - """Detect currently-running musl runtime version. - - This is done by checking the specified executable's dynamic linking - information, and invoking the loader to parse its output for a version - string. If the loader is musl, the output would be something like:: - - musl libc (x86_64) - Version 1.2.2 - Dynamic Program Loader - """ - try: - with open(executable, "rb") as f: - ld = ELFFile(f).interpreter - except (OSError, TypeError, ValueError): - return None - if ld is None or "musl" not in ld: - return None - proc = subprocess.run([ld], check=False, stderr=subprocess.PIPE, text=True) - return _parse_musl_version(proc.stderr) - - -def platform_tags(archs: Sequence[str]) -> Iterator[str]: - """Generate musllinux tags compatible to the current platform. - - :param archs: Sequence of compatible architectures. - The first one shall be the closest to the actual architecture and be the part of - platform tag after the ``linux_`` prefix, e.g. ``x86_64``. - The ``linux_`` prefix is assumed as a prerequisite for the current platform to - be musllinux-compatible. - - :returns: An iterator of compatible musllinux tags. - """ - sys_musl = _get_musl_version(sys.executable) - if sys_musl is None: # Python not dynamically linked against musl. - return - for arch in archs: - for minor in range(sys_musl.minor, -1, -1): - yield f"musllinux_{sys_musl.major}_{minor}_{arch}" - - -if __name__ == "__main__": # pragma: no cover - import sysconfig - - plat = sysconfig.get_platform() - assert plat.startswith("linux-"), "not linux" - - print("plat:", plat) - print("musl:", _get_musl_version(sys.executable)) - print("tags:", end=" ") - for t in platform_tags(re.sub(r"[.-]", "_", plat.split("-", 1)[-1])): - print(t, end="\n ") diff --git a/apps/bitwarden_event_logs/lib/packaging/_parser.py b/apps/bitwarden_event_logs/lib/packaging/_parser.py deleted file mode 100755 index f6c1f5cd..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/_parser.py +++ /dev/null @@ -1,365 +0,0 @@ -"""Handwritten parser of dependency specifiers. - -The docstring for each __parse_* function contains EBNF-inspired grammar representing -the implementation. -""" - -from __future__ import annotations - -import ast -from typing import List, Literal, NamedTuple, Sequence, Tuple, Union - -from ._tokenizer import DEFAULT_RULES, Tokenizer - - -class Node: - __slots__ = ("value",) - - def __init__(self, value: str) -> None: - self.value = value - - def __str__(self) -> str: - return self.value - - def __repr__(self) -> str: - return f"<{self.__class__.__name__}({self.value!r})>" - - def serialize(self) -> str: - raise NotImplementedError - - -class Variable(Node): - __slots__ = () - - def serialize(self) -> str: - return str(self) - - -class Value(Node): - __slots__ = () - - def serialize(self) -> str: - return f'"{self}"' - - -class Op(Node): - __slots__ = () - - def serialize(self) -> str: - return str(self) - - -MarkerLogical = Literal["and", "or"] -MarkerVar = Union[Variable, Value] -MarkerItem = Tuple[MarkerVar, Op, MarkerVar] -MarkerAtom = Union[MarkerItem, Sequence["MarkerAtom"]] -MarkerList = List[Union["MarkerList", MarkerAtom, MarkerLogical]] - - -class ParsedRequirement(NamedTuple): - name: str - url: str - extras: list[str] - specifier: str - marker: MarkerList | None - - -# -------------------------------------------------------------------------------------- -# Recursive descent parser for dependency specifier -# -------------------------------------------------------------------------------------- -def parse_requirement(source: str) -> ParsedRequirement: - return _parse_requirement(Tokenizer(source, rules=DEFAULT_RULES)) - - -def _parse_requirement(tokenizer: Tokenizer) -> ParsedRequirement: - """ - requirement = WS? IDENTIFIER WS? extras WS? requirement_details - """ - tokenizer.consume("WS") - - name_token = tokenizer.expect( - "IDENTIFIER", expected="package name at the start of dependency specifier" - ) - name = name_token.text - tokenizer.consume("WS") - - extras = _parse_extras(tokenizer) - tokenizer.consume("WS") - - url, specifier, marker = _parse_requirement_details(tokenizer) - tokenizer.expect("END", expected="end of dependency specifier") - - return ParsedRequirement(name, url, extras, specifier, marker) - - -def _parse_requirement_details( - tokenizer: Tokenizer, -) -> tuple[str, str, MarkerList | None]: - """ - requirement_details = AT URL (WS requirement_marker?)? - | specifier WS? (requirement_marker)? - """ - - specifier = "" - url = "" - marker = None - - if tokenizer.check("AT"): - tokenizer.read() - tokenizer.consume("WS") - - url_start = tokenizer.position - url = tokenizer.expect("URL", expected="URL after @").text - if tokenizer.check("END", peek=True): - return (url, specifier, marker) - - tokenizer.expect("WS", expected="whitespace after URL") - - # The input might end after whitespace. - if tokenizer.check("END", peek=True): - return (url, specifier, marker) - - marker = _parse_requirement_marker( - tokenizer, - span_start=url_start, - expected="semicolon (after URL and whitespace)", - ) - else: - specifier_start = tokenizer.position - specifier = _parse_specifier(tokenizer) - tokenizer.consume("WS") - - if tokenizer.check("END", peek=True): - return (url, specifier, marker) - - marker = _parse_requirement_marker( - tokenizer, - span_start=specifier_start, - expected=( - "comma (within version specifier), semicolon (after version specifier)" - if specifier - else "semicolon (after name with no version specifier)" - ), - ) - - return (url, specifier, marker) - - -def _parse_requirement_marker( - tokenizer: Tokenizer, *, span_start: int, expected: str -) -> MarkerList: - """ - requirement_marker = SEMICOLON marker WS? - """ - - if not tokenizer.check("SEMICOLON"): - tokenizer.raise_syntax_error( - f"Expected {expected} or end", - span_start=span_start, - span_end=None, - ) - tokenizer.read() - - marker = _parse_marker(tokenizer) - tokenizer.consume("WS") - - return marker - - -def _parse_extras(tokenizer: Tokenizer) -> list[str]: - """ - extras = (LEFT_BRACKET wsp* extras_list? wsp* RIGHT_BRACKET)? - """ - if not tokenizer.check("LEFT_BRACKET", peek=True): - return [] - - with tokenizer.enclosing_tokens( - "LEFT_BRACKET", - "RIGHT_BRACKET", - around="extras", - ): - tokenizer.consume("WS") - extras = _parse_extras_list(tokenizer) - tokenizer.consume("WS") - - return extras - - -def _parse_extras_list(tokenizer: Tokenizer) -> list[str]: - """ - extras_list = identifier (wsp* ',' wsp* identifier)* - """ - extras: list[str] = [] - - if not tokenizer.check("IDENTIFIER"): - return extras - - extras.append(tokenizer.read().text) - - while True: - tokenizer.consume("WS") - if tokenizer.check("IDENTIFIER", peek=True): - tokenizer.raise_syntax_error("Expected comma between extra names") - elif not tokenizer.check("COMMA"): - break - - tokenizer.read() - tokenizer.consume("WS") - - extra_token = tokenizer.expect("IDENTIFIER", expected="extra name after comma") - extras.append(extra_token.text) - - return extras - - -def _parse_specifier(tokenizer: Tokenizer) -> str: - """ - specifier = LEFT_PARENTHESIS WS? version_many WS? RIGHT_PARENTHESIS - | WS? version_many WS? - """ - with tokenizer.enclosing_tokens( - "LEFT_PARENTHESIS", - "RIGHT_PARENTHESIS", - around="version specifier", - ): - tokenizer.consume("WS") - parsed_specifiers = _parse_version_many(tokenizer) - tokenizer.consume("WS") - - return parsed_specifiers - - -def _parse_version_many(tokenizer: Tokenizer) -> str: - """ - version_many = (SPECIFIER (WS? COMMA WS? SPECIFIER)*)? - """ - parsed_specifiers = "" - while tokenizer.check("SPECIFIER"): - span_start = tokenizer.position - parsed_specifiers += tokenizer.read().text - if tokenizer.check("VERSION_PREFIX_TRAIL", peek=True): - tokenizer.raise_syntax_error( - ".* suffix can only be used with `==` or `!=` operators", - span_start=span_start, - span_end=tokenizer.position + 1, - ) - if tokenizer.check("VERSION_LOCAL_LABEL_TRAIL", peek=True): - tokenizer.raise_syntax_error( - "Local version label can only be used with `==` or `!=` operators", - span_start=span_start, - span_end=tokenizer.position, - ) - tokenizer.consume("WS") - if not tokenizer.check("COMMA"): - break - parsed_specifiers += tokenizer.read().text - tokenizer.consume("WS") - - return parsed_specifiers - - -# -------------------------------------------------------------------------------------- -# Recursive descent parser for marker expression -# -------------------------------------------------------------------------------------- -def parse_marker(source: str) -> MarkerList: - return _parse_full_marker(Tokenizer(source, rules=DEFAULT_RULES)) - - -def _parse_full_marker(tokenizer: Tokenizer) -> MarkerList: - retval = _parse_marker(tokenizer) - tokenizer.expect("END", expected="end of marker expression") - return retval - - -def _parse_marker(tokenizer: Tokenizer) -> MarkerList: - """ - marker = marker_atom (BOOLOP marker_atom)+ - """ - expression = [_parse_marker_atom(tokenizer)] - while tokenizer.check("BOOLOP"): - token = tokenizer.read() - expr_right = _parse_marker_atom(tokenizer) - expression.extend((token.text, expr_right)) - return expression - - -def _parse_marker_atom(tokenizer: Tokenizer) -> MarkerAtom: - """ - marker_atom = WS? LEFT_PARENTHESIS WS? marker WS? RIGHT_PARENTHESIS WS? - | WS? marker_item WS? - """ - - tokenizer.consume("WS") - if tokenizer.check("LEFT_PARENTHESIS", peek=True): - with tokenizer.enclosing_tokens( - "LEFT_PARENTHESIS", - "RIGHT_PARENTHESIS", - around="marker expression", - ): - tokenizer.consume("WS") - marker: MarkerAtom = _parse_marker(tokenizer) - tokenizer.consume("WS") - else: - marker = _parse_marker_item(tokenizer) - tokenizer.consume("WS") - return marker - - -def _parse_marker_item(tokenizer: Tokenizer) -> MarkerItem: - """ - marker_item = WS? marker_var WS? marker_op WS? marker_var WS? - """ - tokenizer.consume("WS") - marker_var_left = _parse_marker_var(tokenizer) - tokenizer.consume("WS") - marker_op = _parse_marker_op(tokenizer) - tokenizer.consume("WS") - marker_var_right = _parse_marker_var(tokenizer) - tokenizer.consume("WS") - return (marker_var_left, marker_op, marker_var_right) - - -def _parse_marker_var(tokenizer: Tokenizer) -> MarkerVar: # noqa: RET503 - """ - marker_var = VARIABLE | QUOTED_STRING - """ - if tokenizer.check("VARIABLE"): - return process_env_var(tokenizer.read().text.replace(".", "_")) - elif tokenizer.check("QUOTED_STRING"): - return process_python_str(tokenizer.read().text) - else: - tokenizer.raise_syntax_error( - message="Expected a marker variable or quoted string" - ) - - -def process_env_var(env_var: str) -> Variable: - if env_var in ("platform_python_implementation", "python_implementation"): - return Variable("platform_python_implementation") - else: - return Variable(env_var) - - -def process_python_str(python_str: str) -> Value: - value = ast.literal_eval(python_str) - return Value(str(value)) - - -def _parse_marker_op(tokenizer: Tokenizer) -> Op: - """ - marker_op = IN | NOT IN | OP - """ - if tokenizer.check("IN"): - tokenizer.read() - return Op("in") - elif tokenizer.check("NOT"): - tokenizer.read() - tokenizer.expect("WS", expected="whitespace after 'not'") - tokenizer.expect("IN", expected="'in' after 'not'") - return Op("not in") - elif tokenizer.check("OP"): - return Op(tokenizer.read().text) - else: - return tokenizer.raise_syntax_error( - "Expected marker operator, one of <=, <, !=, ==, >=, >, ~=, ===, in, not in" - ) diff --git a/apps/bitwarden_event_logs/lib/packaging/_structures.py b/apps/bitwarden_event_logs/lib/packaging/_structures.py deleted file mode 100755 index 225e2eee..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/_structures.py +++ /dev/null @@ -1,69 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - - -@typing.final -class InfinityType: - __slots__ = () - - def __repr__(self) -> str: - return "Infinity" - - def __hash__(self) -> int: - return hash(repr(self)) - - def __lt__(self, other: object) -> bool: - return False - - def __le__(self, other: object) -> bool: - return False - - def __eq__(self, other: object) -> bool: - return isinstance(other, self.__class__) - - def __gt__(self, other: object) -> bool: - return True - - def __ge__(self, other: object) -> bool: - return True - - def __neg__(self: object) -> "NegativeInfinityType": - return NegativeInfinity - - -Infinity = InfinityType() - - -@typing.final -class NegativeInfinityType: - __slots__ = () - - def __repr__(self) -> str: - return "-Infinity" - - def __hash__(self) -> int: - return hash(repr(self)) - - def __lt__(self, other: object) -> bool: - return True - - def __le__(self, other: object) -> bool: - return True - - def __eq__(self, other: object) -> bool: - return isinstance(other, self.__class__) - - def __gt__(self, other: object) -> bool: - return False - - def __ge__(self, other: object) -> bool: - return False - - def __neg__(self: object) -> InfinityType: - return Infinity - - -NegativeInfinity = NegativeInfinityType() diff --git a/apps/bitwarden_event_logs/lib/packaging/_tokenizer.py b/apps/bitwarden_event_logs/lib/packaging/_tokenizer.py deleted file mode 100755 index e6d20dd3..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/_tokenizer.py +++ /dev/null @@ -1,193 +0,0 @@ -from __future__ import annotations - -import contextlib -import re -from dataclasses import dataclass -from typing import Generator, Mapping, NoReturn - -from .specifiers import Specifier - - -@dataclass -class Token: - name: str - text: str - position: int - - -class ParserSyntaxError(Exception): - """The provided source text could not be parsed correctly.""" - - def __init__( - self, - message: str, - *, - source: str, - span: tuple[int, int], - ) -> None: - self.span = span - self.message = message - self.source = source - - super().__init__() - - def __str__(self) -> str: - marker = " " * self.span[0] + "~" * (self.span[1] - self.span[0]) + "^" - return f"{self.message}\n {self.source}\n {marker}" - - -DEFAULT_RULES: dict[str, re.Pattern[str]] = { - "LEFT_PARENTHESIS": re.compile(r"\("), - "RIGHT_PARENTHESIS": re.compile(r"\)"), - "LEFT_BRACKET": re.compile(r"\["), - "RIGHT_BRACKET": re.compile(r"\]"), - "SEMICOLON": re.compile(r";"), - "COMMA": re.compile(r","), - "QUOTED_STRING": re.compile( - r""" - ( - ('[^']*') - | - ("[^"]*") - ) - """, - re.VERBOSE, - ), - "OP": re.compile(r"(===|==|~=|!=|<=|>=|<|>)"), - "BOOLOP": re.compile(r"\b(or|and)\b"), - "IN": re.compile(r"\bin\b"), - "NOT": re.compile(r"\bnot\b"), - "VARIABLE": re.compile( - r""" - \b( - python_version - |python_full_version - |os[._]name - |sys[._]platform - |platform_(release|system) - |platform[._](version|machine|python_implementation) - |python_implementation - |implementation_(name|version) - |extras? - |dependency_groups - )\b - """, - re.VERBOSE, - ), - "SPECIFIER": re.compile( - Specifier._operator_regex_str + Specifier._version_regex_str, - re.VERBOSE | re.IGNORECASE, - ), - "AT": re.compile(r"\@"), - "URL": re.compile(r"[^ \t]+"), - "IDENTIFIER": re.compile(r"\b[a-zA-Z0-9][a-zA-Z0-9._-]*\b"), - "VERSION_PREFIX_TRAIL": re.compile(r"\.\*"), - "VERSION_LOCAL_LABEL_TRAIL": re.compile(r"\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*"), - "WS": re.compile(r"[ \t]+"), - "END": re.compile(r"$"), -} - - -class Tokenizer: - """Context-sensitive token parsing. - - Provides methods to examine the input stream to check whether the next token - matches. - """ - - def __init__( - self, - source: str, - *, - rules: Mapping[str, re.Pattern[str]], - ) -> None: - self.source = source - self.rules = rules - self.next_token: Token | None = None - self.position = 0 - - def consume(self, name: str) -> None: - """Move beyond provided token name, if at current position.""" - if self.check(name): - self.read() - - def check(self, name: str, *, peek: bool = False) -> bool: - """Check whether the next token has the provided name. - - By default, if the check succeeds, the token *must* be read before - another check. If `peek` is set to `True`, the token is not loaded and - would need to be checked again. - """ - assert self.next_token is None, ( - f"Cannot check for {name!r}, already have {self.next_token!r}" - ) - assert name in self.rules, f"Unknown token name: {name!r}" - - expression = self.rules[name] - - match = expression.match(self.source, self.position) - if match is None: - return False - if not peek: - self.next_token = Token(name, match[0], self.position) - return True - - def expect(self, name: str, *, expected: str) -> Token: - """Expect a certain token name next, failing with a syntax error otherwise. - - The token is *not* read. - """ - if not self.check(name): - raise self.raise_syntax_error(f"Expected {expected}") - return self.read() - - def read(self) -> Token: - """Consume the next token and return it.""" - token = self.next_token - assert token is not None - - self.position += len(token.text) - self.next_token = None - - return token - - def raise_syntax_error( - self, - message: str, - *, - span_start: int | None = None, - span_end: int | None = None, - ) -> NoReturn: - """Raise ParserSyntaxError at the given position.""" - span = ( - self.position if span_start is None else span_start, - self.position if span_end is None else span_end, - ) - raise ParserSyntaxError( - message, - source=self.source, - span=span, - ) - - @contextlib.contextmanager - def enclosing_tokens( - self, open_token: str, close_token: str, *, around: str - ) -> Generator[None, None, None]: - if self.check(open_token): - open_position = self.position - self.read() - else: - open_position = None - - yield - - if open_position is None: - return - - if not self.check(close_token): - self.raise_syntax_error( - f"Expected matching {close_token} for {open_token}, after {around}", - span_start=open_position, - ) - - self.read() diff --git a/apps/bitwarden_event_logs/lib/packaging/licenses/__init__.py b/apps/bitwarden_event_logs/lib/packaging/licenses/__init__.py deleted file mode 100755 index 335b275f..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/licenses/__init__.py +++ /dev/null @@ -1,147 +0,0 @@ -####################################################################################### -# -# Adapted from: -# https://github.com/pypa/hatch/blob/5352e44/backend/src/hatchling/licenses/parse.py -# -# MIT License -# -# Copyright (c) 2017-present Ofek Lev -# -# Permission is hereby granted, free of charge, to any person obtaining a copy of this -# software and associated documentation files (the "Software"), to deal in the Software -# without restriction, including without limitation the rights to use, copy, modify, -# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to the following -# conditions: -# -# The above copyright notice and this permission notice shall be included in all copies -# or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# -# With additional allowance of arbitrary `LicenseRef-` identifiers, not just -# `LicenseRef-Public-Domain` and `LicenseRef-Proprietary`. -# -####################################################################################### -from __future__ import annotations - -import re -from typing import NewType, cast - -from ._spdx import EXCEPTIONS, LICENSES - -__all__ = [ - "InvalidLicenseExpression", - "NormalizedLicenseExpression", - "canonicalize_license_expression", -] - -license_ref_allowed = re.compile("^[A-Za-z0-9.-]*$") - -NormalizedLicenseExpression = NewType("NormalizedLicenseExpression", str) - - -class InvalidLicenseExpression(ValueError): - """Raised when a license-expression string is invalid - - >>> canonicalize_license_expression("invalid") - Traceback (most recent call last): - ... - packaging.licenses.InvalidLicenseExpression: Invalid license expression: 'invalid' - """ - - -def canonicalize_license_expression( - raw_license_expression: str, -) -> NormalizedLicenseExpression: - if not raw_license_expression: - message = f"Invalid license expression: {raw_license_expression!r}" - raise InvalidLicenseExpression(message) - - # Pad any parentheses so tokenization can be achieved by merely splitting on - # whitespace. - license_expression = raw_license_expression.replace("(", " ( ").replace(")", " ) ") - licenseref_prefix = "LicenseRef-" - license_refs = { - ref.lower(): "LicenseRef-" + ref[len(licenseref_prefix) :] - for ref in license_expression.split() - if ref.lower().startswith(licenseref_prefix.lower()) - } - - # Normalize to lower case so we can look up licenses/exceptions - # and so boolean operators are Python-compatible. - license_expression = license_expression.lower() - - tokens = license_expression.split() - - # Rather than implementing a parenthesis/boolean logic parser, create an - # expression that Python can parse. Everything that is not involved with the - # grammar itself is replaced with the placeholder `False` and the resultant - # expression should become a valid Python expression. - python_tokens = [] - for token in tokens: - if token not in {"or", "and", "with", "(", ")"}: - python_tokens.append("False") - elif token == "with": - python_tokens.append("or") - elif ( - token == "(" - and python_tokens - and python_tokens[-1] not in {"or", "and", "("} - ) or (token == ")" and python_tokens and python_tokens[-1] == "("): - message = f"Invalid license expression: {raw_license_expression!r}" - raise InvalidLicenseExpression(message) - else: - python_tokens.append(token) - - python_expression = " ".join(python_tokens) - try: - compile(python_expression, "", "eval") - except SyntaxError: - message = f"Invalid license expression: {raw_license_expression!r}" - raise InvalidLicenseExpression(message) from None - - # Take a final pass to check for unknown licenses/exceptions. - normalized_tokens = [] - for token in tokens: - if token in {"or", "and", "with", "(", ")"}: - normalized_tokens.append(token.upper()) - continue - - if normalized_tokens and normalized_tokens[-1] == "WITH": - if token not in EXCEPTIONS: - message = f"Unknown license exception: {token!r}" - raise InvalidLicenseExpression(message) - - normalized_tokens.append(EXCEPTIONS[token]["id"]) - else: - if token.endswith("+"): - final_token = token[:-1] - suffix = "+" - else: - final_token = token - suffix = "" - - if final_token.startswith("licenseref-"): - if not license_ref_allowed.match(final_token): - message = f"Invalid licenseref: {final_token!r}" - raise InvalidLicenseExpression(message) - normalized_tokens.append(license_refs[final_token] + suffix) - else: - if final_token not in LICENSES: - message = f"Unknown license: {final_token!r}" - raise InvalidLicenseExpression(message) - normalized_tokens.append(LICENSES[final_token]["id"] + suffix) - - normalized_expression = " ".join(normalized_tokens) - - return cast( - "NormalizedLicenseExpression", - normalized_expression.replace("( ", "(").replace(" )", ")"), - ) diff --git a/apps/bitwarden_event_logs/lib/packaging/licenses/_spdx.py b/apps/bitwarden_event_logs/lib/packaging/licenses/_spdx.py deleted file mode 100755 index a277af28..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/licenses/_spdx.py +++ /dev/null @@ -1,799 +0,0 @@ - -from __future__ import annotations - -from typing import TypedDict - -class SPDXLicense(TypedDict): - id: str - deprecated: bool - -class SPDXException(TypedDict): - id: str - deprecated: bool - - -VERSION = '3.27.0' - -LICENSES: dict[str, SPDXLicense] = { - '0bsd': {'id': '0BSD', 'deprecated': False}, - '3d-slicer-1.0': {'id': '3D-Slicer-1.0', 'deprecated': False}, - 'aal': {'id': 'AAL', 'deprecated': False}, - 'abstyles': {'id': 'Abstyles', 'deprecated': False}, - 'adacore-doc': {'id': 'AdaCore-doc', 'deprecated': False}, - 'adobe-2006': {'id': 'Adobe-2006', 'deprecated': False}, - 'adobe-display-postscript': {'id': 'Adobe-Display-PostScript', 'deprecated': False}, - 'adobe-glyph': {'id': 'Adobe-Glyph', 'deprecated': False}, - 'adobe-utopia': {'id': 'Adobe-Utopia', 'deprecated': False}, - 'adsl': {'id': 'ADSL', 'deprecated': False}, - 'afl-1.1': {'id': 'AFL-1.1', 'deprecated': False}, - 'afl-1.2': {'id': 'AFL-1.2', 'deprecated': False}, - 'afl-2.0': {'id': 'AFL-2.0', 'deprecated': False}, - 'afl-2.1': {'id': 'AFL-2.1', 'deprecated': False}, - 'afl-3.0': {'id': 'AFL-3.0', 'deprecated': False}, - 'afmparse': {'id': 'Afmparse', 'deprecated': False}, - 'agpl-1.0': {'id': 'AGPL-1.0', 'deprecated': True}, - 'agpl-1.0-only': {'id': 'AGPL-1.0-only', 'deprecated': False}, - 'agpl-1.0-or-later': {'id': 'AGPL-1.0-or-later', 'deprecated': False}, - 'agpl-3.0': {'id': 'AGPL-3.0', 'deprecated': True}, - 'agpl-3.0-only': {'id': 'AGPL-3.0-only', 'deprecated': False}, - 'agpl-3.0-or-later': {'id': 'AGPL-3.0-or-later', 'deprecated': False}, - 'aladdin': {'id': 'Aladdin', 'deprecated': False}, - 'amd-newlib': {'id': 'AMD-newlib', 'deprecated': False}, - 'amdplpa': {'id': 'AMDPLPA', 'deprecated': False}, - 'aml': {'id': 'AML', 'deprecated': False}, - 'aml-glslang': {'id': 'AML-glslang', 'deprecated': False}, - 'ampas': {'id': 'AMPAS', 'deprecated': False}, - 'antlr-pd': {'id': 'ANTLR-PD', 'deprecated': False}, - 'antlr-pd-fallback': {'id': 'ANTLR-PD-fallback', 'deprecated': False}, - 'any-osi': {'id': 'any-OSI', 'deprecated': False}, - 'any-osi-perl-modules': {'id': 'any-OSI-perl-modules', 'deprecated': False}, - 'apache-1.0': {'id': 'Apache-1.0', 'deprecated': False}, - 'apache-1.1': {'id': 'Apache-1.1', 'deprecated': False}, - 'apache-2.0': {'id': 'Apache-2.0', 'deprecated': False}, - 'apafml': {'id': 'APAFML', 'deprecated': False}, - 'apl-1.0': {'id': 'APL-1.0', 'deprecated': False}, - 'app-s2p': {'id': 'App-s2p', 'deprecated': False}, - 'apsl-1.0': {'id': 'APSL-1.0', 'deprecated': False}, - 'apsl-1.1': {'id': 'APSL-1.1', 'deprecated': False}, - 'apsl-1.2': {'id': 'APSL-1.2', 'deprecated': False}, - 'apsl-2.0': {'id': 'APSL-2.0', 'deprecated': False}, - 'arphic-1999': {'id': 'Arphic-1999', 'deprecated': False}, - 'artistic-1.0': {'id': 'Artistic-1.0', 'deprecated': False}, - 'artistic-1.0-cl8': {'id': 'Artistic-1.0-cl8', 'deprecated': False}, - 'artistic-1.0-perl': {'id': 'Artistic-1.0-Perl', 'deprecated': False}, - 'artistic-2.0': {'id': 'Artistic-2.0', 'deprecated': False}, - 'artistic-dist': {'id': 'Artistic-dist', 'deprecated': False}, - 'aspell-ru': {'id': 'Aspell-RU', 'deprecated': False}, - 'aswf-digital-assets-1.0': {'id': 'ASWF-Digital-Assets-1.0', 'deprecated': False}, - 'aswf-digital-assets-1.1': {'id': 'ASWF-Digital-Assets-1.1', 'deprecated': False}, - 'baekmuk': {'id': 'Baekmuk', 'deprecated': False}, - 'bahyph': {'id': 'Bahyph', 'deprecated': False}, - 'barr': {'id': 'Barr', 'deprecated': False}, - 'bcrypt-solar-designer': {'id': 'bcrypt-Solar-Designer', 'deprecated': False}, - 'beerware': {'id': 'Beerware', 'deprecated': False}, - 'bitstream-charter': {'id': 'Bitstream-Charter', 'deprecated': False}, - 'bitstream-vera': {'id': 'Bitstream-Vera', 'deprecated': False}, - 'bittorrent-1.0': {'id': 'BitTorrent-1.0', 'deprecated': False}, - 'bittorrent-1.1': {'id': 'BitTorrent-1.1', 'deprecated': False}, - 'blessing': {'id': 'blessing', 'deprecated': False}, - 'blueoak-1.0.0': {'id': 'BlueOak-1.0.0', 'deprecated': False}, - 'boehm-gc': {'id': 'Boehm-GC', 'deprecated': False}, - 'boehm-gc-without-fee': {'id': 'Boehm-GC-without-fee', 'deprecated': False}, - 'borceux': {'id': 'Borceux', 'deprecated': False}, - 'brian-gladman-2-clause': {'id': 'Brian-Gladman-2-Clause', 'deprecated': False}, - 'brian-gladman-3-clause': {'id': 'Brian-Gladman-3-Clause', 'deprecated': False}, - 'bsd-1-clause': {'id': 'BSD-1-Clause', 'deprecated': False}, - 'bsd-2-clause': {'id': 'BSD-2-Clause', 'deprecated': False}, - 'bsd-2-clause-darwin': {'id': 'BSD-2-Clause-Darwin', 'deprecated': False}, - 'bsd-2-clause-first-lines': {'id': 'BSD-2-Clause-first-lines', 'deprecated': False}, - 'bsd-2-clause-freebsd': {'id': 'BSD-2-Clause-FreeBSD', 'deprecated': True}, - 'bsd-2-clause-netbsd': {'id': 'BSD-2-Clause-NetBSD', 'deprecated': True}, - 'bsd-2-clause-patent': {'id': 'BSD-2-Clause-Patent', 'deprecated': False}, - 'bsd-2-clause-pkgconf-disclaimer': {'id': 'BSD-2-Clause-pkgconf-disclaimer', 'deprecated': False}, - 'bsd-2-clause-views': {'id': 'BSD-2-Clause-Views', 'deprecated': False}, - 'bsd-3-clause': {'id': 'BSD-3-Clause', 'deprecated': False}, - 'bsd-3-clause-acpica': {'id': 'BSD-3-Clause-acpica', 'deprecated': False}, - 'bsd-3-clause-attribution': {'id': 'BSD-3-Clause-Attribution', 'deprecated': False}, - 'bsd-3-clause-clear': {'id': 'BSD-3-Clause-Clear', 'deprecated': False}, - 'bsd-3-clause-flex': {'id': 'BSD-3-Clause-flex', 'deprecated': False}, - 'bsd-3-clause-hp': {'id': 'BSD-3-Clause-HP', 'deprecated': False}, - 'bsd-3-clause-lbnl': {'id': 'BSD-3-Clause-LBNL', 'deprecated': False}, - 'bsd-3-clause-modification': {'id': 'BSD-3-Clause-Modification', 'deprecated': False}, - 'bsd-3-clause-no-military-license': {'id': 'BSD-3-Clause-No-Military-License', 'deprecated': False}, - 'bsd-3-clause-no-nuclear-license': {'id': 'BSD-3-Clause-No-Nuclear-License', 'deprecated': False}, - 'bsd-3-clause-no-nuclear-license-2014': {'id': 'BSD-3-Clause-No-Nuclear-License-2014', 'deprecated': False}, - 'bsd-3-clause-no-nuclear-warranty': {'id': 'BSD-3-Clause-No-Nuclear-Warranty', 'deprecated': False}, - 'bsd-3-clause-open-mpi': {'id': 'BSD-3-Clause-Open-MPI', 'deprecated': False}, - 'bsd-3-clause-sun': {'id': 'BSD-3-Clause-Sun', 'deprecated': False}, - 'bsd-4-clause': {'id': 'BSD-4-Clause', 'deprecated': False}, - 'bsd-4-clause-shortened': {'id': 'BSD-4-Clause-Shortened', 'deprecated': False}, - 'bsd-4-clause-uc': {'id': 'BSD-4-Clause-UC', 'deprecated': False}, - 'bsd-4.3reno': {'id': 'BSD-4.3RENO', 'deprecated': False}, - 'bsd-4.3tahoe': {'id': 'BSD-4.3TAHOE', 'deprecated': False}, - 'bsd-advertising-acknowledgement': {'id': 'BSD-Advertising-Acknowledgement', 'deprecated': False}, - 'bsd-attribution-hpnd-disclaimer': {'id': 'BSD-Attribution-HPND-disclaimer', 'deprecated': False}, - 'bsd-inferno-nettverk': {'id': 'BSD-Inferno-Nettverk', 'deprecated': False}, - 'bsd-protection': {'id': 'BSD-Protection', 'deprecated': False}, - 'bsd-source-beginning-file': {'id': 'BSD-Source-beginning-file', 'deprecated': False}, - 'bsd-source-code': {'id': 'BSD-Source-Code', 'deprecated': False}, - 'bsd-systemics': {'id': 'BSD-Systemics', 'deprecated': False}, - 'bsd-systemics-w3works': {'id': 'BSD-Systemics-W3Works', 'deprecated': False}, - 'bsl-1.0': {'id': 'BSL-1.0', 'deprecated': False}, - 'busl-1.1': {'id': 'BUSL-1.1', 'deprecated': False}, - 'bzip2-1.0.5': {'id': 'bzip2-1.0.5', 'deprecated': True}, - 'bzip2-1.0.6': {'id': 'bzip2-1.0.6', 'deprecated': False}, - 'c-uda-1.0': {'id': 'C-UDA-1.0', 'deprecated': False}, - 'cal-1.0': {'id': 'CAL-1.0', 'deprecated': False}, - 'cal-1.0-combined-work-exception': {'id': 'CAL-1.0-Combined-Work-Exception', 'deprecated': False}, - 'caldera': {'id': 'Caldera', 'deprecated': False}, - 'caldera-no-preamble': {'id': 'Caldera-no-preamble', 'deprecated': False}, - 'catharon': {'id': 'Catharon', 'deprecated': False}, - 'catosl-1.1': {'id': 'CATOSL-1.1', 'deprecated': False}, - 'cc-by-1.0': {'id': 'CC-BY-1.0', 'deprecated': False}, - 'cc-by-2.0': {'id': 'CC-BY-2.0', 'deprecated': False}, - 'cc-by-2.5': {'id': 'CC-BY-2.5', 'deprecated': False}, - 'cc-by-2.5-au': {'id': 'CC-BY-2.5-AU', 'deprecated': False}, - 'cc-by-3.0': {'id': 'CC-BY-3.0', 'deprecated': False}, - 'cc-by-3.0-at': {'id': 'CC-BY-3.0-AT', 'deprecated': False}, - 'cc-by-3.0-au': {'id': 'CC-BY-3.0-AU', 'deprecated': False}, - 'cc-by-3.0-de': {'id': 'CC-BY-3.0-DE', 'deprecated': False}, - 'cc-by-3.0-igo': {'id': 'CC-BY-3.0-IGO', 'deprecated': False}, - 'cc-by-3.0-nl': {'id': 'CC-BY-3.0-NL', 'deprecated': False}, - 'cc-by-3.0-us': {'id': 'CC-BY-3.0-US', 'deprecated': False}, - 'cc-by-4.0': {'id': 'CC-BY-4.0', 'deprecated': False}, - 'cc-by-nc-1.0': {'id': 'CC-BY-NC-1.0', 'deprecated': False}, - 'cc-by-nc-2.0': {'id': 'CC-BY-NC-2.0', 'deprecated': False}, - 'cc-by-nc-2.5': {'id': 'CC-BY-NC-2.5', 'deprecated': False}, - 'cc-by-nc-3.0': {'id': 'CC-BY-NC-3.0', 'deprecated': False}, - 'cc-by-nc-3.0-de': {'id': 'CC-BY-NC-3.0-DE', 'deprecated': False}, - 'cc-by-nc-4.0': {'id': 'CC-BY-NC-4.0', 'deprecated': False}, - 'cc-by-nc-nd-1.0': {'id': 'CC-BY-NC-ND-1.0', 'deprecated': False}, - 'cc-by-nc-nd-2.0': {'id': 'CC-BY-NC-ND-2.0', 'deprecated': False}, - 'cc-by-nc-nd-2.5': {'id': 'CC-BY-NC-ND-2.5', 'deprecated': False}, - 'cc-by-nc-nd-3.0': {'id': 'CC-BY-NC-ND-3.0', 'deprecated': False}, - 'cc-by-nc-nd-3.0-de': {'id': 'CC-BY-NC-ND-3.0-DE', 'deprecated': False}, - 'cc-by-nc-nd-3.0-igo': {'id': 'CC-BY-NC-ND-3.0-IGO', 'deprecated': False}, - 'cc-by-nc-nd-4.0': {'id': 'CC-BY-NC-ND-4.0', 'deprecated': False}, - 'cc-by-nc-sa-1.0': {'id': 'CC-BY-NC-SA-1.0', 'deprecated': False}, - 'cc-by-nc-sa-2.0': {'id': 'CC-BY-NC-SA-2.0', 'deprecated': False}, - 'cc-by-nc-sa-2.0-de': {'id': 'CC-BY-NC-SA-2.0-DE', 'deprecated': False}, - 'cc-by-nc-sa-2.0-fr': {'id': 'CC-BY-NC-SA-2.0-FR', 'deprecated': False}, - 'cc-by-nc-sa-2.0-uk': {'id': 'CC-BY-NC-SA-2.0-UK', 'deprecated': False}, - 'cc-by-nc-sa-2.5': {'id': 'CC-BY-NC-SA-2.5', 'deprecated': False}, - 'cc-by-nc-sa-3.0': {'id': 'CC-BY-NC-SA-3.0', 'deprecated': False}, - 'cc-by-nc-sa-3.0-de': {'id': 'CC-BY-NC-SA-3.0-DE', 'deprecated': False}, - 'cc-by-nc-sa-3.0-igo': {'id': 'CC-BY-NC-SA-3.0-IGO', 'deprecated': False}, - 'cc-by-nc-sa-4.0': {'id': 'CC-BY-NC-SA-4.0', 'deprecated': False}, - 'cc-by-nd-1.0': {'id': 'CC-BY-ND-1.0', 'deprecated': False}, - 'cc-by-nd-2.0': {'id': 'CC-BY-ND-2.0', 'deprecated': False}, - 'cc-by-nd-2.5': {'id': 'CC-BY-ND-2.5', 'deprecated': False}, - 'cc-by-nd-3.0': {'id': 'CC-BY-ND-3.0', 'deprecated': False}, - 'cc-by-nd-3.0-de': {'id': 'CC-BY-ND-3.0-DE', 'deprecated': False}, - 'cc-by-nd-4.0': {'id': 'CC-BY-ND-4.0', 'deprecated': False}, - 'cc-by-sa-1.0': {'id': 'CC-BY-SA-1.0', 'deprecated': False}, - 'cc-by-sa-2.0': {'id': 'CC-BY-SA-2.0', 'deprecated': False}, - 'cc-by-sa-2.0-uk': {'id': 'CC-BY-SA-2.0-UK', 'deprecated': False}, - 'cc-by-sa-2.1-jp': {'id': 'CC-BY-SA-2.1-JP', 'deprecated': False}, - 'cc-by-sa-2.5': {'id': 'CC-BY-SA-2.5', 'deprecated': False}, - 'cc-by-sa-3.0': {'id': 'CC-BY-SA-3.0', 'deprecated': False}, - 'cc-by-sa-3.0-at': {'id': 'CC-BY-SA-3.0-AT', 'deprecated': False}, - 'cc-by-sa-3.0-de': {'id': 'CC-BY-SA-3.0-DE', 'deprecated': False}, - 'cc-by-sa-3.0-igo': {'id': 'CC-BY-SA-3.0-IGO', 'deprecated': False}, - 'cc-by-sa-4.0': {'id': 'CC-BY-SA-4.0', 'deprecated': False}, - 'cc-pddc': {'id': 'CC-PDDC', 'deprecated': False}, - 'cc-pdm-1.0': {'id': 'CC-PDM-1.0', 'deprecated': False}, - 'cc-sa-1.0': {'id': 'CC-SA-1.0', 'deprecated': False}, - 'cc0-1.0': {'id': 'CC0-1.0', 'deprecated': False}, - 'cddl-1.0': {'id': 'CDDL-1.0', 'deprecated': False}, - 'cddl-1.1': {'id': 'CDDL-1.1', 'deprecated': False}, - 'cdl-1.0': {'id': 'CDL-1.0', 'deprecated': False}, - 'cdla-permissive-1.0': {'id': 'CDLA-Permissive-1.0', 'deprecated': False}, - 'cdla-permissive-2.0': {'id': 'CDLA-Permissive-2.0', 'deprecated': False}, - 'cdla-sharing-1.0': {'id': 'CDLA-Sharing-1.0', 'deprecated': False}, - 'cecill-1.0': {'id': 'CECILL-1.0', 'deprecated': False}, - 'cecill-1.1': {'id': 'CECILL-1.1', 'deprecated': False}, - 'cecill-2.0': {'id': 'CECILL-2.0', 'deprecated': False}, - 'cecill-2.1': {'id': 'CECILL-2.1', 'deprecated': False}, - 'cecill-b': {'id': 'CECILL-B', 'deprecated': False}, - 'cecill-c': {'id': 'CECILL-C', 'deprecated': False}, - 'cern-ohl-1.1': {'id': 'CERN-OHL-1.1', 'deprecated': False}, - 'cern-ohl-1.2': {'id': 'CERN-OHL-1.2', 'deprecated': False}, - 'cern-ohl-p-2.0': {'id': 'CERN-OHL-P-2.0', 'deprecated': False}, - 'cern-ohl-s-2.0': {'id': 'CERN-OHL-S-2.0', 'deprecated': False}, - 'cern-ohl-w-2.0': {'id': 'CERN-OHL-W-2.0', 'deprecated': False}, - 'cfitsio': {'id': 'CFITSIO', 'deprecated': False}, - 'check-cvs': {'id': 'check-cvs', 'deprecated': False}, - 'checkmk': {'id': 'checkmk', 'deprecated': False}, - 'clartistic': {'id': 'ClArtistic', 'deprecated': False}, - 'clips': {'id': 'Clips', 'deprecated': False}, - 'cmu-mach': {'id': 'CMU-Mach', 'deprecated': False}, - 'cmu-mach-nodoc': {'id': 'CMU-Mach-nodoc', 'deprecated': False}, - 'cnri-jython': {'id': 'CNRI-Jython', 'deprecated': False}, - 'cnri-python': {'id': 'CNRI-Python', 'deprecated': False}, - 'cnri-python-gpl-compatible': {'id': 'CNRI-Python-GPL-Compatible', 'deprecated': False}, - 'coil-1.0': {'id': 'COIL-1.0', 'deprecated': False}, - 'community-spec-1.0': {'id': 'Community-Spec-1.0', 'deprecated': False}, - 'condor-1.1': {'id': 'Condor-1.1', 'deprecated': False}, - 'copyleft-next-0.3.0': {'id': 'copyleft-next-0.3.0', 'deprecated': False}, - 'copyleft-next-0.3.1': {'id': 'copyleft-next-0.3.1', 'deprecated': False}, - 'cornell-lossless-jpeg': {'id': 'Cornell-Lossless-JPEG', 'deprecated': False}, - 'cpal-1.0': {'id': 'CPAL-1.0', 'deprecated': False}, - 'cpl-1.0': {'id': 'CPL-1.0', 'deprecated': False}, - 'cpol-1.02': {'id': 'CPOL-1.02', 'deprecated': False}, - 'cronyx': {'id': 'Cronyx', 'deprecated': False}, - 'crossword': {'id': 'Crossword', 'deprecated': False}, - 'cryptoswift': {'id': 'CryptoSwift', 'deprecated': False}, - 'crystalstacker': {'id': 'CrystalStacker', 'deprecated': False}, - 'cua-opl-1.0': {'id': 'CUA-OPL-1.0', 'deprecated': False}, - 'cube': {'id': 'Cube', 'deprecated': False}, - 'curl': {'id': 'curl', 'deprecated': False}, - 'cve-tou': {'id': 'cve-tou', 'deprecated': False}, - 'd-fsl-1.0': {'id': 'D-FSL-1.0', 'deprecated': False}, - 'dec-3-clause': {'id': 'DEC-3-Clause', 'deprecated': False}, - 'diffmark': {'id': 'diffmark', 'deprecated': False}, - 'dl-de-by-2.0': {'id': 'DL-DE-BY-2.0', 'deprecated': False}, - 'dl-de-zero-2.0': {'id': 'DL-DE-ZERO-2.0', 'deprecated': False}, - 'doc': {'id': 'DOC', 'deprecated': False}, - 'docbook-dtd': {'id': 'DocBook-DTD', 'deprecated': False}, - 'docbook-schema': {'id': 'DocBook-Schema', 'deprecated': False}, - 'docbook-stylesheet': {'id': 'DocBook-Stylesheet', 'deprecated': False}, - 'docbook-xml': {'id': 'DocBook-XML', 'deprecated': False}, - 'dotseqn': {'id': 'Dotseqn', 'deprecated': False}, - 'drl-1.0': {'id': 'DRL-1.0', 'deprecated': False}, - 'drl-1.1': {'id': 'DRL-1.1', 'deprecated': False}, - 'dsdp': {'id': 'DSDP', 'deprecated': False}, - 'dtoa': {'id': 'dtoa', 'deprecated': False}, - 'dvipdfm': {'id': 'dvipdfm', 'deprecated': False}, - 'ecl-1.0': {'id': 'ECL-1.0', 'deprecated': False}, - 'ecl-2.0': {'id': 'ECL-2.0', 'deprecated': False}, - 'ecos-2.0': {'id': 'eCos-2.0', 'deprecated': True}, - 'efl-1.0': {'id': 'EFL-1.0', 'deprecated': False}, - 'efl-2.0': {'id': 'EFL-2.0', 'deprecated': False}, - 'egenix': {'id': 'eGenix', 'deprecated': False}, - 'elastic-2.0': {'id': 'Elastic-2.0', 'deprecated': False}, - 'entessa': {'id': 'Entessa', 'deprecated': False}, - 'epics': {'id': 'EPICS', 'deprecated': False}, - 'epl-1.0': {'id': 'EPL-1.0', 'deprecated': False}, - 'epl-2.0': {'id': 'EPL-2.0', 'deprecated': False}, - 'erlpl-1.1': {'id': 'ErlPL-1.1', 'deprecated': False}, - 'etalab-2.0': {'id': 'etalab-2.0', 'deprecated': False}, - 'eudatagrid': {'id': 'EUDatagrid', 'deprecated': False}, - 'eupl-1.0': {'id': 'EUPL-1.0', 'deprecated': False}, - 'eupl-1.1': {'id': 'EUPL-1.1', 'deprecated': False}, - 'eupl-1.2': {'id': 'EUPL-1.2', 'deprecated': False}, - 'eurosym': {'id': 'Eurosym', 'deprecated': False}, - 'fair': {'id': 'Fair', 'deprecated': False}, - 'fbm': {'id': 'FBM', 'deprecated': False}, - 'fdk-aac': {'id': 'FDK-AAC', 'deprecated': False}, - 'ferguson-twofish': {'id': 'Ferguson-Twofish', 'deprecated': False}, - 'frameworx-1.0': {'id': 'Frameworx-1.0', 'deprecated': False}, - 'freebsd-doc': {'id': 'FreeBSD-DOC', 'deprecated': False}, - 'freeimage': {'id': 'FreeImage', 'deprecated': False}, - 'fsfap': {'id': 'FSFAP', 'deprecated': False}, - 'fsfap-no-warranty-disclaimer': {'id': 'FSFAP-no-warranty-disclaimer', 'deprecated': False}, - 'fsful': {'id': 'FSFUL', 'deprecated': False}, - 'fsfullr': {'id': 'FSFULLR', 'deprecated': False}, - 'fsfullrsd': {'id': 'FSFULLRSD', 'deprecated': False}, - 'fsfullrwd': {'id': 'FSFULLRWD', 'deprecated': False}, - 'fsl-1.1-alv2': {'id': 'FSL-1.1-ALv2', 'deprecated': False}, - 'fsl-1.1-mit': {'id': 'FSL-1.1-MIT', 'deprecated': False}, - 'ftl': {'id': 'FTL', 'deprecated': False}, - 'furuseth': {'id': 'Furuseth', 'deprecated': False}, - 'fwlw': {'id': 'fwlw', 'deprecated': False}, - 'game-programming-gems': {'id': 'Game-Programming-Gems', 'deprecated': False}, - 'gcr-docs': {'id': 'GCR-docs', 'deprecated': False}, - 'gd': {'id': 'GD', 'deprecated': False}, - 'generic-xts': {'id': 'generic-xts', 'deprecated': False}, - 'gfdl-1.1': {'id': 'GFDL-1.1', 'deprecated': True}, - 'gfdl-1.1-invariants-only': {'id': 'GFDL-1.1-invariants-only', 'deprecated': False}, - 'gfdl-1.1-invariants-or-later': {'id': 'GFDL-1.1-invariants-or-later', 'deprecated': False}, - 'gfdl-1.1-no-invariants-only': {'id': 'GFDL-1.1-no-invariants-only', 'deprecated': False}, - 'gfdl-1.1-no-invariants-or-later': {'id': 'GFDL-1.1-no-invariants-or-later', 'deprecated': False}, - 'gfdl-1.1-only': {'id': 'GFDL-1.1-only', 'deprecated': False}, - 'gfdl-1.1-or-later': {'id': 'GFDL-1.1-or-later', 'deprecated': False}, - 'gfdl-1.2': {'id': 'GFDL-1.2', 'deprecated': True}, - 'gfdl-1.2-invariants-only': {'id': 'GFDL-1.2-invariants-only', 'deprecated': False}, - 'gfdl-1.2-invariants-or-later': {'id': 'GFDL-1.2-invariants-or-later', 'deprecated': False}, - 'gfdl-1.2-no-invariants-only': {'id': 'GFDL-1.2-no-invariants-only', 'deprecated': False}, - 'gfdl-1.2-no-invariants-or-later': {'id': 'GFDL-1.2-no-invariants-or-later', 'deprecated': False}, - 'gfdl-1.2-only': {'id': 'GFDL-1.2-only', 'deprecated': False}, - 'gfdl-1.2-or-later': {'id': 'GFDL-1.2-or-later', 'deprecated': False}, - 'gfdl-1.3': {'id': 'GFDL-1.3', 'deprecated': True}, - 'gfdl-1.3-invariants-only': {'id': 'GFDL-1.3-invariants-only', 'deprecated': False}, - 'gfdl-1.3-invariants-or-later': {'id': 'GFDL-1.3-invariants-or-later', 'deprecated': False}, - 'gfdl-1.3-no-invariants-only': {'id': 'GFDL-1.3-no-invariants-only', 'deprecated': False}, - 'gfdl-1.3-no-invariants-or-later': {'id': 'GFDL-1.3-no-invariants-or-later', 'deprecated': False}, - 'gfdl-1.3-only': {'id': 'GFDL-1.3-only', 'deprecated': False}, - 'gfdl-1.3-or-later': {'id': 'GFDL-1.3-or-later', 'deprecated': False}, - 'giftware': {'id': 'Giftware', 'deprecated': False}, - 'gl2ps': {'id': 'GL2PS', 'deprecated': False}, - 'glide': {'id': 'Glide', 'deprecated': False}, - 'glulxe': {'id': 'Glulxe', 'deprecated': False}, - 'glwtpl': {'id': 'GLWTPL', 'deprecated': False}, - 'gnuplot': {'id': 'gnuplot', 'deprecated': False}, - 'gpl-1.0': {'id': 'GPL-1.0', 'deprecated': True}, - 'gpl-1.0+': {'id': 'GPL-1.0+', 'deprecated': True}, - 'gpl-1.0-only': {'id': 'GPL-1.0-only', 'deprecated': False}, - 'gpl-1.0-or-later': {'id': 'GPL-1.0-or-later', 'deprecated': False}, - 'gpl-2.0': {'id': 'GPL-2.0', 'deprecated': True}, - 'gpl-2.0+': {'id': 'GPL-2.0+', 'deprecated': True}, - 'gpl-2.0-only': {'id': 'GPL-2.0-only', 'deprecated': False}, - 'gpl-2.0-or-later': {'id': 'GPL-2.0-or-later', 'deprecated': False}, - 'gpl-2.0-with-autoconf-exception': {'id': 'GPL-2.0-with-autoconf-exception', 'deprecated': True}, - 'gpl-2.0-with-bison-exception': {'id': 'GPL-2.0-with-bison-exception', 'deprecated': True}, - 'gpl-2.0-with-classpath-exception': {'id': 'GPL-2.0-with-classpath-exception', 'deprecated': True}, - 'gpl-2.0-with-font-exception': {'id': 'GPL-2.0-with-font-exception', 'deprecated': True}, - 'gpl-2.0-with-gcc-exception': {'id': 'GPL-2.0-with-GCC-exception', 'deprecated': True}, - 'gpl-3.0': {'id': 'GPL-3.0', 'deprecated': True}, - 'gpl-3.0+': {'id': 'GPL-3.0+', 'deprecated': True}, - 'gpl-3.0-only': {'id': 'GPL-3.0-only', 'deprecated': False}, - 'gpl-3.0-or-later': {'id': 'GPL-3.0-or-later', 'deprecated': False}, - 'gpl-3.0-with-autoconf-exception': {'id': 'GPL-3.0-with-autoconf-exception', 'deprecated': True}, - 'gpl-3.0-with-gcc-exception': {'id': 'GPL-3.0-with-GCC-exception', 'deprecated': True}, - 'graphics-gems': {'id': 'Graphics-Gems', 'deprecated': False}, - 'gsoap-1.3b': {'id': 'gSOAP-1.3b', 'deprecated': False}, - 'gtkbook': {'id': 'gtkbook', 'deprecated': False}, - 'gutmann': {'id': 'Gutmann', 'deprecated': False}, - 'haskellreport': {'id': 'HaskellReport', 'deprecated': False}, - 'hdf5': {'id': 'HDF5', 'deprecated': False}, - 'hdparm': {'id': 'hdparm', 'deprecated': False}, - 'hidapi': {'id': 'HIDAPI', 'deprecated': False}, - 'hippocratic-2.1': {'id': 'Hippocratic-2.1', 'deprecated': False}, - 'hp-1986': {'id': 'HP-1986', 'deprecated': False}, - 'hp-1989': {'id': 'HP-1989', 'deprecated': False}, - 'hpnd': {'id': 'HPND', 'deprecated': False}, - 'hpnd-dec': {'id': 'HPND-DEC', 'deprecated': False}, - 'hpnd-doc': {'id': 'HPND-doc', 'deprecated': False}, - 'hpnd-doc-sell': {'id': 'HPND-doc-sell', 'deprecated': False}, - 'hpnd-export-us': {'id': 'HPND-export-US', 'deprecated': False}, - 'hpnd-export-us-acknowledgement': {'id': 'HPND-export-US-acknowledgement', 'deprecated': False}, - 'hpnd-export-us-modify': {'id': 'HPND-export-US-modify', 'deprecated': False}, - 'hpnd-export2-us': {'id': 'HPND-export2-US', 'deprecated': False}, - 'hpnd-fenneberg-livingston': {'id': 'HPND-Fenneberg-Livingston', 'deprecated': False}, - 'hpnd-inria-imag': {'id': 'HPND-INRIA-IMAG', 'deprecated': False}, - 'hpnd-intel': {'id': 'HPND-Intel', 'deprecated': False}, - 'hpnd-kevlin-henney': {'id': 'HPND-Kevlin-Henney', 'deprecated': False}, - 'hpnd-markus-kuhn': {'id': 'HPND-Markus-Kuhn', 'deprecated': False}, - 'hpnd-merchantability-variant': {'id': 'HPND-merchantability-variant', 'deprecated': False}, - 'hpnd-mit-disclaimer': {'id': 'HPND-MIT-disclaimer', 'deprecated': False}, - 'hpnd-netrek': {'id': 'HPND-Netrek', 'deprecated': False}, - 'hpnd-pbmplus': {'id': 'HPND-Pbmplus', 'deprecated': False}, - 'hpnd-sell-mit-disclaimer-xserver': {'id': 'HPND-sell-MIT-disclaimer-xserver', 'deprecated': False}, - 'hpnd-sell-regexpr': {'id': 'HPND-sell-regexpr', 'deprecated': False}, - 'hpnd-sell-variant': {'id': 'HPND-sell-variant', 'deprecated': False}, - 'hpnd-sell-variant-mit-disclaimer': {'id': 'HPND-sell-variant-MIT-disclaimer', 'deprecated': False}, - 'hpnd-sell-variant-mit-disclaimer-rev': {'id': 'HPND-sell-variant-MIT-disclaimer-rev', 'deprecated': False}, - 'hpnd-uc': {'id': 'HPND-UC', 'deprecated': False}, - 'hpnd-uc-export-us': {'id': 'HPND-UC-export-US', 'deprecated': False}, - 'htmltidy': {'id': 'HTMLTIDY', 'deprecated': False}, - 'ibm-pibs': {'id': 'IBM-pibs', 'deprecated': False}, - 'icu': {'id': 'ICU', 'deprecated': False}, - 'iec-code-components-eula': {'id': 'IEC-Code-Components-EULA', 'deprecated': False}, - 'ijg': {'id': 'IJG', 'deprecated': False}, - 'ijg-short': {'id': 'IJG-short', 'deprecated': False}, - 'imagemagick': {'id': 'ImageMagick', 'deprecated': False}, - 'imatix': {'id': 'iMatix', 'deprecated': False}, - 'imlib2': {'id': 'Imlib2', 'deprecated': False}, - 'info-zip': {'id': 'Info-ZIP', 'deprecated': False}, - 'inner-net-2.0': {'id': 'Inner-Net-2.0', 'deprecated': False}, - 'innosetup': {'id': 'InnoSetup', 'deprecated': False}, - 'intel': {'id': 'Intel', 'deprecated': False}, - 'intel-acpi': {'id': 'Intel-ACPI', 'deprecated': False}, - 'interbase-1.0': {'id': 'Interbase-1.0', 'deprecated': False}, - 'ipa': {'id': 'IPA', 'deprecated': False}, - 'ipl-1.0': {'id': 'IPL-1.0', 'deprecated': False}, - 'isc': {'id': 'ISC', 'deprecated': False}, - 'isc-veillard': {'id': 'ISC-Veillard', 'deprecated': False}, - 'jam': {'id': 'Jam', 'deprecated': False}, - 'jasper-2.0': {'id': 'JasPer-2.0', 'deprecated': False}, - 'jove': {'id': 'jove', 'deprecated': False}, - 'jpl-image': {'id': 'JPL-image', 'deprecated': False}, - 'jpnic': {'id': 'JPNIC', 'deprecated': False}, - 'json': {'id': 'JSON', 'deprecated': False}, - 'kastrup': {'id': 'Kastrup', 'deprecated': False}, - 'kazlib': {'id': 'Kazlib', 'deprecated': False}, - 'knuth-ctan': {'id': 'Knuth-CTAN', 'deprecated': False}, - 'lal-1.2': {'id': 'LAL-1.2', 'deprecated': False}, - 'lal-1.3': {'id': 'LAL-1.3', 'deprecated': False}, - 'latex2e': {'id': 'Latex2e', 'deprecated': False}, - 'latex2e-translated-notice': {'id': 'Latex2e-translated-notice', 'deprecated': False}, - 'leptonica': {'id': 'Leptonica', 'deprecated': False}, - 'lgpl-2.0': {'id': 'LGPL-2.0', 'deprecated': True}, - 'lgpl-2.0+': {'id': 'LGPL-2.0+', 'deprecated': True}, - 'lgpl-2.0-only': {'id': 'LGPL-2.0-only', 'deprecated': False}, - 'lgpl-2.0-or-later': {'id': 'LGPL-2.0-or-later', 'deprecated': False}, - 'lgpl-2.1': {'id': 'LGPL-2.1', 'deprecated': True}, - 'lgpl-2.1+': {'id': 'LGPL-2.1+', 'deprecated': True}, - 'lgpl-2.1-only': {'id': 'LGPL-2.1-only', 'deprecated': False}, - 'lgpl-2.1-or-later': {'id': 'LGPL-2.1-or-later', 'deprecated': False}, - 'lgpl-3.0': {'id': 'LGPL-3.0', 'deprecated': True}, - 'lgpl-3.0+': {'id': 'LGPL-3.0+', 'deprecated': True}, - 'lgpl-3.0-only': {'id': 'LGPL-3.0-only', 'deprecated': False}, - 'lgpl-3.0-or-later': {'id': 'LGPL-3.0-or-later', 'deprecated': False}, - 'lgpllr': {'id': 'LGPLLR', 'deprecated': False}, - 'libpng': {'id': 'Libpng', 'deprecated': False}, - 'libpng-1.6.35': {'id': 'libpng-1.6.35', 'deprecated': False}, - 'libpng-2.0': {'id': 'libpng-2.0', 'deprecated': False}, - 'libselinux-1.0': {'id': 'libselinux-1.0', 'deprecated': False}, - 'libtiff': {'id': 'libtiff', 'deprecated': False}, - 'libutil-david-nugent': {'id': 'libutil-David-Nugent', 'deprecated': False}, - 'liliq-p-1.1': {'id': 'LiLiQ-P-1.1', 'deprecated': False}, - 'liliq-r-1.1': {'id': 'LiLiQ-R-1.1', 'deprecated': False}, - 'liliq-rplus-1.1': {'id': 'LiLiQ-Rplus-1.1', 'deprecated': False}, - 'linux-man-pages-1-para': {'id': 'Linux-man-pages-1-para', 'deprecated': False}, - 'linux-man-pages-copyleft': {'id': 'Linux-man-pages-copyleft', 'deprecated': False}, - 'linux-man-pages-copyleft-2-para': {'id': 'Linux-man-pages-copyleft-2-para', 'deprecated': False}, - 'linux-man-pages-copyleft-var': {'id': 'Linux-man-pages-copyleft-var', 'deprecated': False}, - 'linux-openib': {'id': 'Linux-OpenIB', 'deprecated': False}, - 'loop': {'id': 'LOOP', 'deprecated': False}, - 'lpd-document': {'id': 'LPD-document', 'deprecated': False}, - 'lpl-1.0': {'id': 'LPL-1.0', 'deprecated': False}, - 'lpl-1.02': {'id': 'LPL-1.02', 'deprecated': False}, - 'lppl-1.0': {'id': 'LPPL-1.0', 'deprecated': False}, - 'lppl-1.1': {'id': 'LPPL-1.1', 'deprecated': False}, - 'lppl-1.2': {'id': 'LPPL-1.2', 'deprecated': False}, - 'lppl-1.3a': {'id': 'LPPL-1.3a', 'deprecated': False}, - 'lppl-1.3c': {'id': 'LPPL-1.3c', 'deprecated': False}, - 'lsof': {'id': 'lsof', 'deprecated': False}, - 'lucida-bitmap-fonts': {'id': 'Lucida-Bitmap-Fonts', 'deprecated': False}, - 'lzma-sdk-9.11-to-9.20': {'id': 'LZMA-SDK-9.11-to-9.20', 'deprecated': False}, - 'lzma-sdk-9.22': {'id': 'LZMA-SDK-9.22', 'deprecated': False}, - 'mackerras-3-clause': {'id': 'Mackerras-3-Clause', 'deprecated': False}, - 'mackerras-3-clause-acknowledgment': {'id': 'Mackerras-3-Clause-acknowledgment', 'deprecated': False}, - 'magaz': {'id': 'magaz', 'deprecated': False}, - 'mailprio': {'id': 'mailprio', 'deprecated': False}, - 'makeindex': {'id': 'MakeIndex', 'deprecated': False}, - 'man2html': {'id': 'man2html', 'deprecated': False}, - 'martin-birgmeier': {'id': 'Martin-Birgmeier', 'deprecated': False}, - 'mcphee-slideshow': {'id': 'McPhee-slideshow', 'deprecated': False}, - 'metamail': {'id': 'metamail', 'deprecated': False}, - 'minpack': {'id': 'Minpack', 'deprecated': False}, - 'mips': {'id': 'MIPS', 'deprecated': False}, - 'miros': {'id': 'MirOS', 'deprecated': False}, - 'mit': {'id': 'MIT', 'deprecated': False}, - 'mit-0': {'id': 'MIT-0', 'deprecated': False}, - 'mit-advertising': {'id': 'MIT-advertising', 'deprecated': False}, - 'mit-click': {'id': 'MIT-Click', 'deprecated': False}, - 'mit-cmu': {'id': 'MIT-CMU', 'deprecated': False}, - 'mit-enna': {'id': 'MIT-enna', 'deprecated': False}, - 'mit-feh': {'id': 'MIT-feh', 'deprecated': False}, - 'mit-festival': {'id': 'MIT-Festival', 'deprecated': False}, - 'mit-khronos-old': {'id': 'MIT-Khronos-old', 'deprecated': False}, - 'mit-modern-variant': {'id': 'MIT-Modern-Variant', 'deprecated': False}, - 'mit-open-group': {'id': 'MIT-open-group', 'deprecated': False}, - 'mit-testregex': {'id': 'MIT-testregex', 'deprecated': False}, - 'mit-wu': {'id': 'MIT-Wu', 'deprecated': False}, - 'mitnfa': {'id': 'MITNFA', 'deprecated': False}, - 'mmixware': {'id': 'MMIXware', 'deprecated': False}, - 'motosoto': {'id': 'Motosoto', 'deprecated': False}, - 'mpeg-ssg': {'id': 'MPEG-SSG', 'deprecated': False}, - 'mpi-permissive': {'id': 'mpi-permissive', 'deprecated': False}, - 'mpich2': {'id': 'mpich2', 'deprecated': False}, - 'mpl-1.0': {'id': 'MPL-1.0', 'deprecated': False}, - 'mpl-1.1': {'id': 'MPL-1.1', 'deprecated': False}, - 'mpl-2.0': {'id': 'MPL-2.0', 'deprecated': False}, - 'mpl-2.0-no-copyleft-exception': {'id': 'MPL-2.0-no-copyleft-exception', 'deprecated': False}, - 'mplus': {'id': 'mplus', 'deprecated': False}, - 'ms-lpl': {'id': 'MS-LPL', 'deprecated': False}, - 'ms-pl': {'id': 'MS-PL', 'deprecated': False}, - 'ms-rl': {'id': 'MS-RL', 'deprecated': False}, - 'mtll': {'id': 'MTLL', 'deprecated': False}, - 'mulanpsl-1.0': {'id': 'MulanPSL-1.0', 'deprecated': False}, - 'mulanpsl-2.0': {'id': 'MulanPSL-2.0', 'deprecated': False}, - 'multics': {'id': 'Multics', 'deprecated': False}, - 'mup': {'id': 'Mup', 'deprecated': False}, - 'naist-2003': {'id': 'NAIST-2003', 'deprecated': False}, - 'nasa-1.3': {'id': 'NASA-1.3', 'deprecated': False}, - 'naumen': {'id': 'Naumen', 'deprecated': False}, - 'nbpl-1.0': {'id': 'NBPL-1.0', 'deprecated': False}, - 'ncbi-pd': {'id': 'NCBI-PD', 'deprecated': False}, - 'ncgl-uk-2.0': {'id': 'NCGL-UK-2.0', 'deprecated': False}, - 'ncl': {'id': 'NCL', 'deprecated': False}, - 'ncsa': {'id': 'NCSA', 'deprecated': False}, - 'net-snmp': {'id': 'Net-SNMP', 'deprecated': True}, - 'netcdf': {'id': 'NetCDF', 'deprecated': False}, - 'newsletr': {'id': 'Newsletr', 'deprecated': False}, - 'ngpl': {'id': 'NGPL', 'deprecated': False}, - 'ngrep': {'id': 'ngrep', 'deprecated': False}, - 'nicta-1.0': {'id': 'NICTA-1.0', 'deprecated': False}, - 'nist-pd': {'id': 'NIST-PD', 'deprecated': False}, - 'nist-pd-fallback': {'id': 'NIST-PD-fallback', 'deprecated': False}, - 'nist-software': {'id': 'NIST-Software', 'deprecated': False}, - 'nlod-1.0': {'id': 'NLOD-1.0', 'deprecated': False}, - 'nlod-2.0': {'id': 'NLOD-2.0', 'deprecated': False}, - 'nlpl': {'id': 'NLPL', 'deprecated': False}, - 'nokia': {'id': 'Nokia', 'deprecated': False}, - 'nosl': {'id': 'NOSL', 'deprecated': False}, - 'noweb': {'id': 'Noweb', 'deprecated': False}, - 'npl-1.0': {'id': 'NPL-1.0', 'deprecated': False}, - 'npl-1.1': {'id': 'NPL-1.1', 'deprecated': False}, - 'nposl-3.0': {'id': 'NPOSL-3.0', 'deprecated': False}, - 'nrl': {'id': 'NRL', 'deprecated': False}, - 'ntia-pd': {'id': 'NTIA-PD', 'deprecated': False}, - 'ntp': {'id': 'NTP', 'deprecated': False}, - 'ntp-0': {'id': 'NTP-0', 'deprecated': False}, - 'nunit': {'id': 'Nunit', 'deprecated': True}, - 'o-uda-1.0': {'id': 'O-UDA-1.0', 'deprecated': False}, - 'oar': {'id': 'OAR', 'deprecated': False}, - 'occt-pl': {'id': 'OCCT-PL', 'deprecated': False}, - 'oclc-2.0': {'id': 'OCLC-2.0', 'deprecated': False}, - 'odbl-1.0': {'id': 'ODbL-1.0', 'deprecated': False}, - 'odc-by-1.0': {'id': 'ODC-By-1.0', 'deprecated': False}, - 'offis': {'id': 'OFFIS', 'deprecated': False}, - 'ofl-1.0': {'id': 'OFL-1.0', 'deprecated': False}, - 'ofl-1.0-no-rfn': {'id': 'OFL-1.0-no-RFN', 'deprecated': False}, - 'ofl-1.0-rfn': {'id': 'OFL-1.0-RFN', 'deprecated': False}, - 'ofl-1.1': {'id': 'OFL-1.1', 'deprecated': False}, - 'ofl-1.1-no-rfn': {'id': 'OFL-1.1-no-RFN', 'deprecated': False}, - 'ofl-1.1-rfn': {'id': 'OFL-1.1-RFN', 'deprecated': False}, - 'ogc-1.0': {'id': 'OGC-1.0', 'deprecated': False}, - 'ogdl-taiwan-1.0': {'id': 'OGDL-Taiwan-1.0', 'deprecated': False}, - 'ogl-canada-2.0': {'id': 'OGL-Canada-2.0', 'deprecated': False}, - 'ogl-uk-1.0': {'id': 'OGL-UK-1.0', 'deprecated': False}, - 'ogl-uk-2.0': {'id': 'OGL-UK-2.0', 'deprecated': False}, - 'ogl-uk-3.0': {'id': 'OGL-UK-3.0', 'deprecated': False}, - 'ogtsl': {'id': 'OGTSL', 'deprecated': False}, - 'oldap-1.1': {'id': 'OLDAP-1.1', 'deprecated': False}, - 'oldap-1.2': {'id': 'OLDAP-1.2', 'deprecated': False}, - 'oldap-1.3': {'id': 'OLDAP-1.3', 'deprecated': False}, - 'oldap-1.4': {'id': 'OLDAP-1.4', 'deprecated': False}, - 'oldap-2.0': {'id': 'OLDAP-2.0', 'deprecated': False}, - 'oldap-2.0.1': {'id': 'OLDAP-2.0.1', 'deprecated': False}, - 'oldap-2.1': {'id': 'OLDAP-2.1', 'deprecated': False}, - 'oldap-2.2': {'id': 'OLDAP-2.2', 'deprecated': False}, - 'oldap-2.2.1': {'id': 'OLDAP-2.2.1', 'deprecated': False}, - 'oldap-2.2.2': {'id': 'OLDAP-2.2.2', 'deprecated': False}, - 'oldap-2.3': {'id': 'OLDAP-2.3', 'deprecated': False}, - 'oldap-2.4': {'id': 'OLDAP-2.4', 'deprecated': False}, - 'oldap-2.5': {'id': 'OLDAP-2.5', 'deprecated': False}, - 'oldap-2.6': {'id': 'OLDAP-2.6', 'deprecated': False}, - 'oldap-2.7': {'id': 'OLDAP-2.7', 'deprecated': False}, - 'oldap-2.8': {'id': 'OLDAP-2.8', 'deprecated': False}, - 'olfl-1.3': {'id': 'OLFL-1.3', 'deprecated': False}, - 'oml': {'id': 'OML', 'deprecated': False}, - 'openpbs-2.3': {'id': 'OpenPBS-2.3', 'deprecated': False}, - 'openssl': {'id': 'OpenSSL', 'deprecated': False}, - 'openssl-standalone': {'id': 'OpenSSL-standalone', 'deprecated': False}, - 'openvision': {'id': 'OpenVision', 'deprecated': False}, - 'opl-1.0': {'id': 'OPL-1.0', 'deprecated': False}, - 'opl-uk-3.0': {'id': 'OPL-UK-3.0', 'deprecated': False}, - 'opubl-1.0': {'id': 'OPUBL-1.0', 'deprecated': False}, - 'oset-pl-2.1': {'id': 'OSET-PL-2.1', 'deprecated': False}, - 'osl-1.0': {'id': 'OSL-1.0', 'deprecated': False}, - 'osl-1.1': {'id': 'OSL-1.1', 'deprecated': False}, - 'osl-2.0': {'id': 'OSL-2.0', 'deprecated': False}, - 'osl-2.1': {'id': 'OSL-2.1', 'deprecated': False}, - 'osl-3.0': {'id': 'OSL-3.0', 'deprecated': False}, - 'padl': {'id': 'PADL', 'deprecated': False}, - 'parity-6.0.0': {'id': 'Parity-6.0.0', 'deprecated': False}, - 'parity-7.0.0': {'id': 'Parity-7.0.0', 'deprecated': False}, - 'pddl-1.0': {'id': 'PDDL-1.0', 'deprecated': False}, - 'php-3.0': {'id': 'PHP-3.0', 'deprecated': False}, - 'php-3.01': {'id': 'PHP-3.01', 'deprecated': False}, - 'pixar': {'id': 'Pixar', 'deprecated': False}, - 'pkgconf': {'id': 'pkgconf', 'deprecated': False}, - 'plexus': {'id': 'Plexus', 'deprecated': False}, - 'pnmstitch': {'id': 'pnmstitch', 'deprecated': False}, - 'polyform-noncommercial-1.0.0': {'id': 'PolyForm-Noncommercial-1.0.0', 'deprecated': False}, - 'polyform-small-business-1.0.0': {'id': 'PolyForm-Small-Business-1.0.0', 'deprecated': False}, - 'postgresql': {'id': 'PostgreSQL', 'deprecated': False}, - 'ppl': {'id': 'PPL', 'deprecated': False}, - 'psf-2.0': {'id': 'PSF-2.0', 'deprecated': False}, - 'psfrag': {'id': 'psfrag', 'deprecated': False}, - 'psutils': {'id': 'psutils', 'deprecated': False}, - 'python-2.0': {'id': 'Python-2.0', 'deprecated': False}, - 'python-2.0.1': {'id': 'Python-2.0.1', 'deprecated': False}, - 'python-ldap': {'id': 'python-ldap', 'deprecated': False}, - 'qhull': {'id': 'Qhull', 'deprecated': False}, - 'qpl-1.0': {'id': 'QPL-1.0', 'deprecated': False}, - 'qpl-1.0-inria-2004': {'id': 'QPL-1.0-INRIA-2004', 'deprecated': False}, - 'radvd': {'id': 'radvd', 'deprecated': False}, - 'rdisc': {'id': 'Rdisc', 'deprecated': False}, - 'rhecos-1.1': {'id': 'RHeCos-1.1', 'deprecated': False}, - 'rpl-1.1': {'id': 'RPL-1.1', 'deprecated': False}, - 'rpl-1.5': {'id': 'RPL-1.5', 'deprecated': False}, - 'rpsl-1.0': {'id': 'RPSL-1.0', 'deprecated': False}, - 'rsa-md': {'id': 'RSA-MD', 'deprecated': False}, - 'rscpl': {'id': 'RSCPL', 'deprecated': False}, - 'ruby': {'id': 'Ruby', 'deprecated': False}, - 'ruby-pty': {'id': 'Ruby-pty', 'deprecated': False}, - 'sax-pd': {'id': 'SAX-PD', 'deprecated': False}, - 'sax-pd-2.0': {'id': 'SAX-PD-2.0', 'deprecated': False}, - 'saxpath': {'id': 'Saxpath', 'deprecated': False}, - 'scea': {'id': 'SCEA', 'deprecated': False}, - 'schemereport': {'id': 'SchemeReport', 'deprecated': False}, - 'sendmail': {'id': 'Sendmail', 'deprecated': False}, - 'sendmail-8.23': {'id': 'Sendmail-8.23', 'deprecated': False}, - 'sendmail-open-source-1.1': {'id': 'Sendmail-Open-Source-1.1', 'deprecated': False}, - 'sgi-b-1.0': {'id': 'SGI-B-1.0', 'deprecated': False}, - 'sgi-b-1.1': {'id': 'SGI-B-1.1', 'deprecated': False}, - 'sgi-b-2.0': {'id': 'SGI-B-2.0', 'deprecated': False}, - 'sgi-opengl': {'id': 'SGI-OpenGL', 'deprecated': False}, - 'sgp4': {'id': 'SGP4', 'deprecated': False}, - 'shl-0.5': {'id': 'SHL-0.5', 'deprecated': False}, - 'shl-0.51': {'id': 'SHL-0.51', 'deprecated': False}, - 'simpl-2.0': {'id': 'SimPL-2.0', 'deprecated': False}, - 'sissl': {'id': 'SISSL', 'deprecated': False}, - 'sissl-1.2': {'id': 'SISSL-1.2', 'deprecated': False}, - 'sl': {'id': 'SL', 'deprecated': False}, - 'sleepycat': {'id': 'Sleepycat', 'deprecated': False}, - 'smail-gpl': {'id': 'SMAIL-GPL', 'deprecated': False}, - 'smlnj': {'id': 'SMLNJ', 'deprecated': False}, - 'smppl': {'id': 'SMPPL', 'deprecated': False}, - 'snia': {'id': 'SNIA', 'deprecated': False}, - 'snprintf': {'id': 'snprintf', 'deprecated': False}, - 'sofa': {'id': 'SOFA', 'deprecated': False}, - 'softsurfer': {'id': 'softSurfer', 'deprecated': False}, - 'soundex': {'id': 'Soundex', 'deprecated': False}, - 'spencer-86': {'id': 'Spencer-86', 'deprecated': False}, - 'spencer-94': {'id': 'Spencer-94', 'deprecated': False}, - 'spencer-99': {'id': 'Spencer-99', 'deprecated': False}, - 'spl-1.0': {'id': 'SPL-1.0', 'deprecated': False}, - 'ssh-keyscan': {'id': 'ssh-keyscan', 'deprecated': False}, - 'ssh-openssh': {'id': 'SSH-OpenSSH', 'deprecated': False}, - 'ssh-short': {'id': 'SSH-short', 'deprecated': False}, - 'ssleay-standalone': {'id': 'SSLeay-standalone', 'deprecated': False}, - 'sspl-1.0': {'id': 'SSPL-1.0', 'deprecated': False}, - 'standardml-nj': {'id': 'StandardML-NJ', 'deprecated': True}, - 'sugarcrm-1.1.3': {'id': 'SugarCRM-1.1.3', 'deprecated': False}, - 'sul-1.0': {'id': 'SUL-1.0', 'deprecated': False}, - 'sun-ppp': {'id': 'Sun-PPP', 'deprecated': False}, - 'sun-ppp-2000': {'id': 'Sun-PPP-2000', 'deprecated': False}, - 'sunpro': {'id': 'SunPro', 'deprecated': False}, - 'swl': {'id': 'SWL', 'deprecated': False}, - 'swrule': {'id': 'swrule', 'deprecated': False}, - 'symlinks': {'id': 'Symlinks', 'deprecated': False}, - 'tapr-ohl-1.0': {'id': 'TAPR-OHL-1.0', 'deprecated': False}, - 'tcl': {'id': 'TCL', 'deprecated': False}, - 'tcp-wrappers': {'id': 'TCP-wrappers', 'deprecated': False}, - 'termreadkey': {'id': 'TermReadKey', 'deprecated': False}, - 'tgppl-1.0': {'id': 'TGPPL-1.0', 'deprecated': False}, - 'thirdeye': {'id': 'ThirdEye', 'deprecated': False}, - 'threeparttable': {'id': 'threeparttable', 'deprecated': False}, - 'tmate': {'id': 'TMate', 'deprecated': False}, - 'torque-1.1': {'id': 'TORQUE-1.1', 'deprecated': False}, - 'tosl': {'id': 'TOSL', 'deprecated': False}, - 'tpdl': {'id': 'TPDL', 'deprecated': False}, - 'tpl-1.0': {'id': 'TPL-1.0', 'deprecated': False}, - 'trustedqsl': {'id': 'TrustedQSL', 'deprecated': False}, - 'ttwl': {'id': 'TTWL', 'deprecated': False}, - 'ttyp0': {'id': 'TTYP0', 'deprecated': False}, - 'tu-berlin-1.0': {'id': 'TU-Berlin-1.0', 'deprecated': False}, - 'tu-berlin-2.0': {'id': 'TU-Berlin-2.0', 'deprecated': False}, - 'ubuntu-font-1.0': {'id': 'Ubuntu-font-1.0', 'deprecated': False}, - 'ucar': {'id': 'UCAR', 'deprecated': False}, - 'ucl-1.0': {'id': 'UCL-1.0', 'deprecated': False}, - 'ulem': {'id': 'ulem', 'deprecated': False}, - 'umich-merit': {'id': 'UMich-Merit', 'deprecated': False}, - 'unicode-3.0': {'id': 'Unicode-3.0', 'deprecated': False}, - 'unicode-dfs-2015': {'id': 'Unicode-DFS-2015', 'deprecated': False}, - 'unicode-dfs-2016': {'id': 'Unicode-DFS-2016', 'deprecated': False}, - 'unicode-tou': {'id': 'Unicode-TOU', 'deprecated': False}, - 'unixcrypt': {'id': 'UnixCrypt', 'deprecated': False}, - 'unlicense': {'id': 'Unlicense', 'deprecated': False}, - 'unlicense-libtelnet': {'id': 'Unlicense-libtelnet', 'deprecated': False}, - 'unlicense-libwhirlpool': {'id': 'Unlicense-libwhirlpool', 'deprecated': False}, - 'upl-1.0': {'id': 'UPL-1.0', 'deprecated': False}, - 'urt-rle': {'id': 'URT-RLE', 'deprecated': False}, - 'vim': {'id': 'Vim', 'deprecated': False}, - 'vostrom': {'id': 'VOSTROM', 'deprecated': False}, - 'vsl-1.0': {'id': 'VSL-1.0', 'deprecated': False}, - 'w3c': {'id': 'W3C', 'deprecated': False}, - 'w3c-19980720': {'id': 'W3C-19980720', 'deprecated': False}, - 'w3c-20150513': {'id': 'W3C-20150513', 'deprecated': False}, - 'w3m': {'id': 'w3m', 'deprecated': False}, - 'watcom-1.0': {'id': 'Watcom-1.0', 'deprecated': False}, - 'widget-workshop': {'id': 'Widget-Workshop', 'deprecated': False}, - 'wsuipa': {'id': 'Wsuipa', 'deprecated': False}, - 'wtfpl': {'id': 'WTFPL', 'deprecated': False}, - 'wwl': {'id': 'wwl', 'deprecated': False}, - 'wxwindows': {'id': 'wxWindows', 'deprecated': True}, - 'x11': {'id': 'X11', 'deprecated': False}, - 'x11-distribute-modifications-variant': {'id': 'X11-distribute-modifications-variant', 'deprecated': False}, - 'x11-swapped': {'id': 'X11-swapped', 'deprecated': False}, - 'xdebug-1.03': {'id': 'Xdebug-1.03', 'deprecated': False}, - 'xerox': {'id': 'Xerox', 'deprecated': False}, - 'xfig': {'id': 'Xfig', 'deprecated': False}, - 'xfree86-1.1': {'id': 'XFree86-1.1', 'deprecated': False}, - 'xinetd': {'id': 'xinetd', 'deprecated': False}, - 'xkeyboard-config-zinoviev': {'id': 'xkeyboard-config-Zinoviev', 'deprecated': False}, - 'xlock': {'id': 'xlock', 'deprecated': False}, - 'xnet': {'id': 'Xnet', 'deprecated': False}, - 'xpp': {'id': 'xpp', 'deprecated': False}, - 'xskat': {'id': 'XSkat', 'deprecated': False}, - 'xzoom': {'id': 'xzoom', 'deprecated': False}, - 'ypl-1.0': {'id': 'YPL-1.0', 'deprecated': False}, - 'ypl-1.1': {'id': 'YPL-1.1', 'deprecated': False}, - 'zed': {'id': 'Zed', 'deprecated': False}, - 'zeeff': {'id': 'Zeeff', 'deprecated': False}, - 'zend-2.0': {'id': 'Zend-2.0', 'deprecated': False}, - 'zimbra-1.3': {'id': 'Zimbra-1.3', 'deprecated': False}, - 'zimbra-1.4': {'id': 'Zimbra-1.4', 'deprecated': False}, - 'zlib': {'id': 'Zlib', 'deprecated': False}, - 'zlib-acknowledgement': {'id': 'zlib-acknowledgement', 'deprecated': False}, - 'zpl-1.1': {'id': 'ZPL-1.1', 'deprecated': False}, - 'zpl-2.0': {'id': 'ZPL-2.0', 'deprecated': False}, - 'zpl-2.1': {'id': 'ZPL-2.1', 'deprecated': False}, -} - -EXCEPTIONS: dict[str, SPDXException] = { - '389-exception': {'id': '389-exception', 'deprecated': False}, - 'asterisk-exception': {'id': 'Asterisk-exception', 'deprecated': False}, - 'asterisk-linking-protocols-exception': {'id': 'Asterisk-linking-protocols-exception', 'deprecated': False}, - 'autoconf-exception-2.0': {'id': 'Autoconf-exception-2.0', 'deprecated': False}, - 'autoconf-exception-3.0': {'id': 'Autoconf-exception-3.0', 'deprecated': False}, - 'autoconf-exception-generic': {'id': 'Autoconf-exception-generic', 'deprecated': False}, - 'autoconf-exception-generic-3.0': {'id': 'Autoconf-exception-generic-3.0', 'deprecated': False}, - 'autoconf-exception-macro': {'id': 'Autoconf-exception-macro', 'deprecated': False}, - 'bison-exception-1.24': {'id': 'Bison-exception-1.24', 'deprecated': False}, - 'bison-exception-2.2': {'id': 'Bison-exception-2.2', 'deprecated': False}, - 'bootloader-exception': {'id': 'Bootloader-exception', 'deprecated': False}, - 'cgal-linking-exception': {'id': 'CGAL-linking-exception', 'deprecated': False}, - 'classpath-exception-2.0': {'id': 'Classpath-exception-2.0', 'deprecated': False}, - 'clisp-exception-2.0': {'id': 'CLISP-exception-2.0', 'deprecated': False}, - 'cryptsetup-openssl-exception': {'id': 'cryptsetup-OpenSSL-exception', 'deprecated': False}, - 'digia-qt-lgpl-exception-1.1': {'id': 'Digia-Qt-LGPL-exception-1.1', 'deprecated': False}, - 'digirule-foss-exception': {'id': 'DigiRule-FOSS-exception', 'deprecated': False}, - 'ecos-exception-2.0': {'id': 'eCos-exception-2.0', 'deprecated': False}, - 'erlang-otp-linking-exception': {'id': 'erlang-otp-linking-exception', 'deprecated': False}, - 'fawkes-runtime-exception': {'id': 'Fawkes-Runtime-exception', 'deprecated': False}, - 'fltk-exception': {'id': 'FLTK-exception', 'deprecated': False}, - 'fmt-exception': {'id': 'fmt-exception', 'deprecated': False}, - 'font-exception-2.0': {'id': 'Font-exception-2.0', 'deprecated': False}, - 'freertos-exception-2.0': {'id': 'freertos-exception-2.0', 'deprecated': False}, - 'gcc-exception-2.0': {'id': 'GCC-exception-2.0', 'deprecated': False}, - 'gcc-exception-2.0-note': {'id': 'GCC-exception-2.0-note', 'deprecated': False}, - 'gcc-exception-3.1': {'id': 'GCC-exception-3.1', 'deprecated': False}, - 'gmsh-exception': {'id': 'Gmsh-exception', 'deprecated': False}, - 'gnat-exception': {'id': 'GNAT-exception', 'deprecated': False}, - 'gnome-examples-exception': {'id': 'GNOME-examples-exception', 'deprecated': False}, - 'gnu-compiler-exception': {'id': 'GNU-compiler-exception', 'deprecated': False}, - 'gnu-javamail-exception': {'id': 'gnu-javamail-exception', 'deprecated': False}, - 'gpl-3.0-389-ds-base-exception': {'id': 'GPL-3.0-389-ds-base-exception', 'deprecated': False}, - 'gpl-3.0-interface-exception': {'id': 'GPL-3.0-interface-exception', 'deprecated': False}, - 'gpl-3.0-linking-exception': {'id': 'GPL-3.0-linking-exception', 'deprecated': False}, - 'gpl-3.0-linking-source-exception': {'id': 'GPL-3.0-linking-source-exception', 'deprecated': False}, - 'gpl-cc-1.0': {'id': 'GPL-CC-1.0', 'deprecated': False}, - 'gstreamer-exception-2005': {'id': 'GStreamer-exception-2005', 'deprecated': False}, - 'gstreamer-exception-2008': {'id': 'GStreamer-exception-2008', 'deprecated': False}, - 'harbour-exception': {'id': 'harbour-exception', 'deprecated': False}, - 'i2p-gpl-java-exception': {'id': 'i2p-gpl-java-exception', 'deprecated': False}, - 'independent-modules-exception': {'id': 'Independent-modules-exception', 'deprecated': False}, - 'kicad-libraries-exception': {'id': 'KiCad-libraries-exception', 'deprecated': False}, - 'lgpl-3.0-linking-exception': {'id': 'LGPL-3.0-linking-exception', 'deprecated': False}, - 'libpri-openh323-exception': {'id': 'libpri-OpenH323-exception', 'deprecated': False}, - 'libtool-exception': {'id': 'Libtool-exception', 'deprecated': False}, - 'linux-syscall-note': {'id': 'Linux-syscall-note', 'deprecated': False}, - 'llgpl': {'id': 'LLGPL', 'deprecated': False}, - 'llvm-exception': {'id': 'LLVM-exception', 'deprecated': False}, - 'lzma-exception': {'id': 'LZMA-exception', 'deprecated': False}, - 'mif-exception': {'id': 'mif-exception', 'deprecated': False}, - 'mxml-exception': {'id': 'mxml-exception', 'deprecated': False}, - 'nokia-qt-exception-1.1': {'id': 'Nokia-Qt-exception-1.1', 'deprecated': True}, - 'ocaml-lgpl-linking-exception': {'id': 'OCaml-LGPL-linking-exception', 'deprecated': False}, - 'occt-exception-1.0': {'id': 'OCCT-exception-1.0', 'deprecated': False}, - 'openjdk-assembly-exception-1.0': {'id': 'OpenJDK-assembly-exception-1.0', 'deprecated': False}, - 'openvpn-openssl-exception': {'id': 'openvpn-openssl-exception', 'deprecated': False}, - 'pcre2-exception': {'id': 'PCRE2-exception', 'deprecated': False}, - 'polyparse-exception': {'id': 'polyparse-exception', 'deprecated': False}, - 'ps-or-pdf-font-exception-20170817': {'id': 'PS-or-PDF-font-exception-20170817', 'deprecated': False}, - 'qpl-1.0-inria-2004-exception': {'id': 'QPL-1.0-INRIA-2004-exception', 'deprecated': False}, - 'qt-gpl-exception-1.0': {'id': 'Qt-GPL-exception-1.0', 'deprecated': False}, - 'qt-lgpl-exception-1.1': {'id': 'Qt-LGPL-exception-1.1', 'deprecated': False}, - 'qwt-exception-1.0': {'id': 'Qwt-exception-1.0', 'deprecated': False}, - 'romic-exception': {'id': 'romic-exception', 'deprecated': False}, - 'rrdtool-floss-exception-2.0': {'id': 'RRDtool-FLOSS-exception-2.0', 'deprecated': False}, - 'sane-exception': {'id': 'SANE-exception', 'deprecated': False}, - 'shl-2.0': {'id': 'SHL-2.0', 'deprecated': False}, - 'shl-2.1': {'id': 'SHL-2.1', 'deprecated': False}, - 'stunnel-exception': {'id': 'stunnel-exception', 'deprecated': False}, - 'swi-exception': {'id': 'SWI-exception', 'deprecated': False}, - 'swift-exception': {'id': 'Swift-exception', 'deprecated': False}, - 'texinfo-exception': {'id': 'Texinfo-exception', 'deprecated': False}, - 'u-boot-exception-2.0': {'id': 'u-boot-exception-2.0', 'deprecated': False}, - 'ubdl-exception': {'id': 'UBDL-exception', 'deprecated': False}, - 'universal-foss-exception-1.0': {'id': 'Universal-FOSS-exception-1.0', 'deprecated': False}, - 'vsftpd-openssl-exception': {'id': 'vsftpd-openssl-exception', 'deprecated': False}, - 'wxwindows-exception-3.1': {'id': 'WxWindows-exception-3.1', 'deprecated': False}, - 'x11vnc-openssl-exception': {'id': 'x11vnc-openssl-exception', 'deprecated': False}, -} diff --git a/apps/bitwarden_event_logs/lib/packaging/markers.py b/apps/bitwarden_event_logs/lib/packaging/markers.py deleted file mode 100755 index ca3706fe..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/markers.py +++ /dev/null @@ -1,388 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import operator -import os -import platform -import sys -from typing import AbstractSet, Callable, Literal, Mapping, TypedDict, Union, cast - -from ._parser import MarkerAtom, MarkerList, Op, Value, Variable -from ._parser import parse_marker as _parse_marker -from ._tokenizer import ParserSyntaxError -from .specifiers import InvalidSpecifier, Specifier -from .utils import canonicalize_name - -__all__ = [ - "Environment", - "EvaluateContext", - "InvalidMarker", - "Marker", - "UndefinedComparison", - "UndefinedEnvironmentName", - "default_environment", -] - -Operator = Callable[[str, Union[str, AbstractSet[str]]], bool] -EvaluateContext = Literal["metadata", "lock_file", "requirement"] -MARKERS_ALLOWING_SET = {"extras", "dependency_groups"} -MARKERS_REQUIRING_VERSION = { - "implementation_version", - "platform_release", - "python_full_version", - "python_version", -} - - -class InvalidMarker(ValueError): - """ - An invalid marker was found, users should refer to PEP 508. - """ - - -class UndefinedComparison(ValueError): - """ - An invalid operation was attempted on a value that doesn't support it. - """ - - -class UndefinedEnvironmentName(ValueError): - """ - A name was attempted to be used that does not exist inside of the - environment. - """ - - -class Environment(TypedDict): - implementation_name: str - """The implementation's identifier, e.g. ``'cpython'``.""" - - implementation_version: str - """ - The implementation's version, e.g. ``'3.13.0a2'`` for CPython 3.13.0a2, or - ``'7.3.13'`` for PyPy3.10 v7.3.13. - """ - - os_name: str - """ - The value of :py:data:`os.name`. The name of the operating system dependent module - imported, e.g. ``'posix'``. - """ - - platform_machine: str - """ - Returns the machine type, e.g. ``'i386'``. - - An empty string if the value cannot be determined. - """ - - platform_release: str - """ - The system's release, e.g. ``'2.2.0'`` or ``'NT'``. - - An empty string if the value cannot be determined. - """ - - platform_system: str - """ - The system/OS name, e.g. ``'Linux'``, ``'Windows'`` or ``'Java'``. - - An empty string if the value cannot be determined. - """ - - platform_version: str - """ - The system's release version, e.g. ``'#3 on degas'``. - - An empty string if the value cannot be determined. - """ - - python_full_version: str - """ - The Python version as string ``'major.minor.patchlevel'``. - - Note that unlike the Python :py:data:`sys.version`, this value will always include - the patchlevel (it defaults to 0). - """ - - platform_python_implementation: str - """ - A string identifying the Python implementation, e.g. ``'CPython'``. - """ - - python_version: str - """The Python version as string ``'major.minor'``.""" - - sys_platform: str - """ - This string contains a platform identifier that can be used to append - platform-specific components to :py:data:`sys.path`, for instance. - - For Unix systems, except on Linux and AIX, this is the lowercased OS name as - returned by ``uname -s`` with the first part of the version as returned by - ``uname -r`` appended, e.g. ``'sunos5'`` or ``'freebsd8'``, at the time when Python - was built. - """ - - -def _normalize_extras( - result: MarkerList | MarkerAtom | str, -) -> MarkerList | MarkerAtom | str: - if not isinstance(result, tuple): - return result - - lhs, op, rhs = result - if isinstance(lhs, Variable) and lhs.value == "extra": - normalized_extra = canonicalize_name(rhs.value) - rhs = Value(normalized_extra) - elif isinstance(rhs, Variable) and rhs.value == "extra": - normalized_extra = canonicalize_name(lhs.value) - lhs = Value(normalized_extra) - return lhs, op, rhs - - -def _normalize_extra_values(results: MarkerList) -> MarkerList: - """ - Normalize extra values. - """ - - return [_normalize_extras(r) for r in results] - - -def _format_marker( - marker: list[str] | MarkerAtom | str, first: bool | None = True -) -> str: - assert isinstance(marker, (list, tuple, str)) - - # Sometimes we have a structure like [[...]] which is a single item list - # where the single item is itself it's own list. In that case we want skip - # the rest of this function so that we don't get extraneous () on the - # outside. - if ( - isinstance(marker, list) - and len(marker) == 1 - and isinstance(marker[0], (list, tuple)) - ): - return _format_marker(marker[0]) - - if isinstance(marker, list): - inner = (_format_marker(m, first=False) for m in marker) - if first: - return " ".join(inner) - else: - return "(" + " ".join(inner) + ")" - elif isinstance(marker, tuple): - return " ".join([m.serialize() for m in marker]) - else: - return marker - - -_operators: dict[str, Operator] = { - "in": lambda lhs, rhs: lhs in rhs, - "not in": lambda lhs, rhs: lhs not in rhs, - "<": lambda _lhs, _rhs: False, - "<=": operator.eq, - "==": operator.eq, - "!=": operator.ne, - ">=": operator.eq, - ">": lambda _lhs, _rhs: False, -} - - -def _eval_op(lhs: str, op: Op, rhs: str | AbstractSet[str], *, key: str) -> bool: - op_str = op.serialize() - if key in MARKERS_REQUIRING_VERSION: - try: - spec = Specifier(f"{op_str}{rhs}") - except InvalidSpecifier: - pass - else: - return spec.contains(lhs, prereleases=True) - - oper: Operator | None = _operators.get(op_str) - if oper is None: - raise UndefinedComparison(f"Undefined {op!r} on {lhs!r} and {rhs!r}.") - - return oper(lhs, rhs) - - -def _normalize( - lhs: str, rhs: str | AbstractSet[str], key: str -) -> tuple[str, str | AbstractSet[str]]: - # PEP 685 - Comparison of extra names for optional distribution dependencies - # https://peps.python.org/pep-0685/ - # > When comparing extra names, tools MUST normalize the names being - # > compared using the semantics outlined in PEP 503 for names - if key == "extra": - assert isinstance(rhs, str), "extra value must be a string" - # Both sides are normalized at this point already - return (lhs, rhs) - if key in MARKERS_ALLOWING_SET: - if isinstance(rhs, str): # pragma: no cover - return (canonicalize_name(lhs), canonicalize_name(rhs)) - else: - return (canonicalize_name(lhs), {canonicalize_name(v) for v in rhs}) - - # other environment markers don't have such standards - return lhs, rhs - - -def _evaluate_markers( - markers: MarkerList, environment: dict[str, str | AbstractSet[str]] -) -> bool: - groups: list[list[bool]] = [[]] - - for marker in markers: - if isinstance(marker, list): - groups[-1].append(_evaluate_markers(marker, environment)) - elif isinstance(marker, tuple): - lhs, op, rhs = marker - - if isinstance(lhs, Variable): - environment_key = lhs.value - lhs_value = environment[environment_key] - rhs_value = rhs.value - else: - lhs_value = lhs.value - environment_key = rhs.value - rhs_value = environment[environment_key] - - assert isinstance(lhs_value, str), "lhs must be a string" - lhs_value, rhs_value = _normalize(lhs_value, rhs_value, key=environment_key) - groups[-1].append(_eval_op(lhs_value, op, rhs_value, key=environment_key)) - elif marker == "or": - groups.append([]) - elif marker == "and": - pass - else: # pragma: nocover - raise TypeError(f"Unexpected marker {marker!r}") - - return any(all(item) for item in groups) - - -def format_full_version(info: sys._version_info) -> str: - version = f"{info.major}.{info.minor}.{info.micro}" - kind = info.releaselevel - if kind != "final": - version += kind[0] + str(info.serial) - return version - - -def default_environment() -> Environment: - iver = format_full_version(sys.implementation.version) - implementation_name = sys.implementation.name - return { - "implementation_name": implementation_name, - "implementation_version": iver, - "os_name": os.name, - "platform_machine": platform.machine(), - "platform_release": platform.release(), - "platform_system": platform.system(), - "platform_version": platform.version(), - "python_full_version": platform.python_version(), - "platform_python_implementation": platform.python_implementation(), - "python_version": ".".join(platform.python_version_tuple()[:2]), - "sys_platform": sys.platform, - } - - -class Marker: - def __init__(self, marker: str) -> None: - # Note: We create a Marker object without calling this constructor in - # packaging.requirements.Requirement. If any additional logic is - # added here, make sure to mirror/adapt Requirement. - - # If this fails and throws an error, the repr still expects _markers to - # be defined. - self._markers: MarkerList = [] - - try: - self._markers = _normalize_extra_values(_parse_marker(marker)) - # The attribute `_markers` can be described in terms of a recursive type: - # MarkerList = List[Union[Tuple[Node, ...], str, MarkerList]] - # - # For example, the following expression: - # python_version > "3.6" or (python_version == "3.6" and os_name == "unix") - # - # is parsed into: - # [ - # (, ')>, ), - # 'and', - # [ - # (, , ), - # 'or', - # (, , ) - # ] - # ] - except ParserSyntaxError as e: - raise InvalidMarker(str(e)) from e - - def __str__(self) -> str: - return _format_marker(self._markers) - - def __repr__(self) -> str: - return f"<{self.__class__.__name__}('{self}')>" - - def __hash__(self) -> int: - return hash(str(self)) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, Marker): - return NotImplemented - - return str(self) == str(other) - - def evaluate( - self, - environment: Mapping[str, str | AbstractSet[str]] | None = None, - context: EvaluateContext = "metadata", - ) -> bool: - """Evaluate a marker. - - Return the boolean from evaluating the given marker against the - environment. environment is an optional argument to override all or - part of the determined environment. The *context* parameter specifies what - context the markers are being evaluated for, which influences what markers - are considered valid. Acceptable values are "metadata" (for core metadata; - default), "lock_file", and "requirement" (i.e. all other situations). - - The environment is determined from the current Python process. - """ - current_environment = cast( - "dict[str, str | AbstractSet[str]]", default_environment() - ) - if context == "lock_file": - current_environment.update( - extras=frozenset(), dependency_groups=frozenset() - ) - elif context == "metadata": - current_environment["extra"] = "" - - if environment is not None: - current_environment.update(environment) - if "extra" in current_environment: - # The API used to allow setting extra to None. We need to handle - # this case for backwards compatibility. Also skip running - # normalize name if extra is empty. - extra = cast("str | None", current_environment["extra"]) - current_environment["extra"] = canonicalize_name(extra) if extra else "" - - return _evaluate_markers( - self._markers, _repair_python_full_version(current_environment) - ) - - -def _repair_python_full_version( - env: dict[str, str | AbstractSet[str]], -) -> dict[str, str | AbstractSet[str]]: - """ - Work around platform.python_version() returning something that is not PEP 440 - compliant for non-tagged Python builds. - """ - python_full_version = cast("str", env["python_full_version"]) - if python_full_version.endswith("+"): - env["python_full_version"] = f"{python_full_version}local" - return env diff --git a/apps/bitwarden_event_logs/lib/packaging/metadata.py b/apps/bitwarden_event_logs/lib/packaging/metadata.py deleted file mode 100755 index 253f6b1b..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/metadata.py +++ /dev/null @@ -1,978 +0,0 @@ -from __future__ import annotations - -import email.feedparser -import email.header -import email.message -import email.parser -import email.policy -import keyword -import pathlib -import sys -import typing -from typing import ( - Any, - Callable, - Generic, - Literal, - TypedDict, - cast, -) - -from . import licenses, requirements, specifiers, utils -from . import version as version_module - -if typing.TYPE_CHECKING: - from .licenses import NormalizedLicenseExpression - -T = typing.TypeVar("T") - - -if sys.version_info >= (3, 11): # pragma: no cover - ExceptionGroup = ExceptionGroup # noqa: F821 -else: # pragma: no cover - - class ExceptionGroup(Exception): - """A minimal implementation of :external:exc:`ExceptionGroup` from Python 3.11. - - If :external:exc:`ExceptionGroup` is already defined by Python itself, - that version is used instead. - """ - - message: str - exceptions: list[Exception] - - def __init__(self, message: str, exceptions: list[Exception]) -> None: - self.message = message - self.exceptions = exceptions - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.message!r}, {self.exceptions!r})" - - -class InvalidMetadata(ValueError): - """A metadata field contains invalid data.""" - - field: str - """The name of the field that contains invalid data.""" - - def __init__(self, field: str, message: str) -> None: - self.field = field - super().__init__(message) - - -# The RawMetadata class attempts to make as few assumptions about the underlying -# serialization formats as possible. The idea is that as long as a serialization -# formats offer some very basic primitives in *some* way then we can support -# serializing to and from that format. -class RawMetadata(TypedDict, total=False): - """A dictionary of raw core metadata. - - Each field in core metadata maps to a key of this dictionary (when data is - provided). The key is lower-case and underscores are used instead of dashes - compared to the equivalent core metadata field. Any core metadata field that - can be specified multiple times or can hold multiple values in a single - field have a key with a plural name. See :class:`Metadata` whose attributes - match the keys of this dictionary. - - Core metadata fields that can be specified multiple times are stored as a - list or dict depending on which is appropriate for the field. Any fields - which hold multiple values in a single field are stored as a list. - - """ - - # Metadata 1.0 - PEP 241 - metadata_version: str - name: str - version: str - platforms: list[str] - summary: str - description: str - keywords: list[str] - home_page: str - author: str - author_email: str - license: str - - # Metadata 1.1 - PEP 314 - supported_platforms: list[str] - download_url: str - classifiers: list[str] - requires: list[str] - provides: list[str] - obsoletes: list[str] - - # Metadata 1.2 - PEP 345 - maintainer: str - maintainer_email: str - requires_dist: list[str] - provides_dist: list[str] - obsoletes_dist: list[str] - requires_python: str - requires_external: list[str] - project_urls: dict[str, str] - - # Metadata 2.0 - # PEP 426 attempted to completely revamp the metadata format - # but got stuck without ever being able to build consensus on - # it and ultimately ended up withdrawn. - # - # However, a number of tools had started emitting METADATA with - # `2.0` Metadata-Version, so for historical reasons, this version - # was skipped. - - # Metadata 2.1 - PEP 566 - description_content_type: str - provides_extra: list[str] - - # Metadata 2.2 - PEP 643 - dynamic: list[str] - - # Metadata 2.3 - PEP 685 - # No new fields were added in PEP 685, just some edge case were - # tightened up to provide better interoperability. - - # Metadata 2.4 - PEP 639 - license_expression: str - license_files: list[str] - - # Metadata 2.5 - PEP 794 - import_names: list[str] - import_namespaces: list[str] - - -# 'keywords' is special as it's a string in the core metadata spec, but we -# represent it as a list. -_STRING_FIELDS = { - "author", - "author_email", - "description", - "description_content_type", - "download_url", - "home_page", - "license", - "license_expression", - "maintainer", - "maintainer_email", - "metadata_version", - "name", - "requires_python", - "summary", - "version", -} - -_LIST_FIELDS = { - "classifiers", - "dynamic", - "license_files", - "obsoletes", - "obsoletes_dist", - "platforms", - "provides", - "provides_dist", - "provides_extra", - "requires", - "requires_dist", - "requires_external", - "supported_platforms", - "import_names", - "import_namespaces", -} - -_DICT_FIELDS = { - "project_urls", -} - - -def _parse_keywords(data: str) -> list[str]: - """Split a string of comma-separated keywords into a list of keywords.""" - return [k.strip() for k in data.split(",")] - - -def _parse_project_urls(data: list[str]) -> dict[str, str]: - """Parse a list of label/URL string pairings separated by a comma.""" - urls = {} - for pair in data: - # Our logic is slightly tricky here as we want to try and do - # *something* reasonable with malformed data. - # - # The main thing that we have to worry about, is data that does - # not have a ',' at all to split the label from the Value. There - # isn't a singular right answer here, and we will fail validation - # later on (if the caller is validating) so it doesn't *really* - # matter, but since the missing value has to be an empty str - # and our return value is dict[str, str], if we let the key - # be the missing value, then they'd have multiple '' values that - # overwrite each other in a accumulating dict. - # - # The other potential issue is that it's possible to have the - # same label multiple times in the metadata, with no solid "right" - # answer with what to do in that case. As such, we'll do the only - # thing we can, which is treat the field as unparsable and add it - # to our list of unparsed fields. - # - # TODO: The spec doesn't say anything about if the keys should be - # considered case sensitive or not... logically they should - # be case-preserving and case-insensitive, but doing that - # would open up more cases where we might have duplicate - # entries. - label, _, url = (s.strip() for s in pair.partition(",")) - - if label in urls: - # The label already exists in our set of urls, so this field - # is unparsable, and we can just add the whole thing to our - # unparsable data and stop processing it. - raise KeyError("duplicate labels in project urls") - urls[label] = url - - return urls - - -def _get_payload(msg: email.message.Message, source: bytes | str) -> str: - """Get the body of the message.""" - # If our source is a str, then our caller has managed encodings for us, - # and we don't need to deal with it. - if isinstance(source, str): - payload = msg.get_payload() - assert isinstance(payload, str) - return payload - # If our source is a bytes, then we're managing the encoding and we need - # to deal with it. - else: - bpayload = msg.get_payload(decode=True) - assert isinstance(bpayload, bytes) - try: - return bpayload.decode("utf8", "strict") - except UnicodeDecodeError as exc: - raise ValueError("payload in an invalid encoding") from exc - - -# The various parse_FORMAT functions here are intended to be as lenient as -# possible in their parsing, while still returning a correctly typed -# RawMetadata. -# -# To aid in this, we also generally want to do as little touching of the -# data as possible, except where there are possibly some historic holdovers -# that make valid data awkward to work with. -# -# While this is a lower level, intermediate format than our ``Metadata`` -# class, some light touch ups can make a massive difference in usability. - -# Map METADATA fields to RawMetadata. -_EMAIL_TO_RAW_MAPPING = { - "author": "author", - "author-email": "author_email", - "classifier": "classifiers", - "description": "description", - "description-content-type": "description_content_type", - "download-url": "download_url", - "dynamic": "dynamic", - "home-page": "home_page", - "import-name": "import_names", - "import-namespace": "import_namespaces", - "keywords": "keywords", - "license": "license", - "license-expression": "license_expression", - "license-file": "license_files", - "maintainer": "maintainer", - "maintainer-email": "maintainer_email", - "metadata-version": "metadata_version", - "name": "name", - "obsoletes": "obsoletes", - "obsoletes-dist": "obsoletes_dist", - "platform": "platforms", - "project-url": "project_urls", - "provides": "provides", - "provides-dist": "provides_dist", - "provides-extra": "provides_extra", - "requires": "requires", - "requires-dist": "requires_dist", - "requires-external": "requires_external", - "requires-python": "requires_python", - "summary": "summary", - "supported-platform": "supported_platforms", - "version": "version", -} -_RAW_TO_EMAIL_MAPPING = {raw: email for email, raw in _EMAIL_TO_RAW_MAPPING.items()} - - -# This class is for writing RFC822 messages -class RFC822Policy(email.policy.EmailPolicy): - """ - This is :class:`email.policy.EmailPolicy`, but with a simple ``header_store_parse`` - implementation that handles multi-line values, and some nice defaults. - """ - - utf8 = True - mangle_from_ = False - max_line_length = 0 - - def header_store_parse(self, name: str, value: str) -> tuple[str, str]: - size = len(name) + 2 - value = value.replace("\n", "\n" + " " * size) - return (name, value) - - -# This class is for writing RFC822 messages -class RFC822Message(email.message.EmailMessage): - """ - This is :class:`email.message.EmailMessage` with two small changes: it defaults to - our `RFC822Policy`, and it correctly writes unicode when being called - with `bytes()`. - """ - - def __init__(self) -> None: - super().__init__(policy=RFC822Policy()) - - def as_bytes( - self, unixfrom: bool = False, policy: email.policy.Policy | None = None - ) -> bytes: - """ - Return the bytes representation of the message. - - This handles unicode encoding. - """ - return self.as_string(unixfrom, policy=policy).encode("utf-8") - - -def parse_email(data: bytes | str) -> tuple[RawMetadata, dict[str, list[str]]]: - """Parse a distribution's metadata stored as email headers (e.g. from ``METADATA``). - - This function returns a two-item tuple of dicts. The first dict is of - recognized fields from the core metadata specification. Fields that can be - parsed and translated into Python's built-in types are converted - appropriately. All other fields are left as-is. Fields that are allowed to - appear multiple times are stored as lists. - - The second dict contains all other fields from the metadata. This includes - any unrecognized fields. It also includes any fields which are expected to - be parsed into a built-in type but were not formatted appropriately. Finally, - any fields that are expected to appear only once but are repeated are - included in this dict. - - """ - raw: dict[str, str | list[str] | dict[str, str]] = {} - unparsed: dict[str, list[str]] = {} - - if isinstance(data, str): - parsed = email.parser.Parser(policy=email.policy.compat32).parsestr(data) - else: - parsed = email.parser.BytesParser(policy=email.policy.compat32).parsebytes(data) - - # We have to wrap parsed.keys() in a set, because in the case of multiple - # values for a key (a list), the key will appear multiple times in the - # list of keys, but we're avoiding that by using get_all(). - for name_with_case in frozenset(parsed.keys()): - # Header names in RFC are case insensitive, so we'll normalize to all - # lower case to make comparisons easier. - name = name_with_case.lower() - - # We use get_all() here, even for fields that aren't multiple use, - # because otherwise someone could have e.g. two Name fields, and we - # would just silently ignore it rather than doing something about it. - headers = parsed.get_all(name) or [] - - # The way the email module works when parsing bytes is that it - # unconditionally decodes the bytes as ascii using the surrogateescape - # handler. When you pull that data back out (such as with get_all() ), - # it looks to see if the str has any surrogate escapes, and if it does - # it wraps it in a Header object instead of returning the string. - # - # As such, we'll look for those Header objects, and fix up the encoding. - value = [] - # Flag if we have run into any issues processing the headers, thus - # signalling that the data belongs in 'unparsed'. - valid_encoding = True - for h in headers: - # It's unclear if this can return more types than just a Header or - # a str, so we'll just assert here to make sure. - assert isinstance(h, (email.header.Header, str)) - - # If it's a header object, we need to do our little dance to get - # the real data out of it. In cases where there is invalid data - # we're going to end up with mojibake, but there's no obvious, good - # way around that without reimplementing parts of the Header object - # ourselves. - # - # That should be fine since, if mojibacked happens, this key is - # going into the unparsed dict anyways. - if isinstance(h, email.header.Header): - # The Header object stores it's data as chunks, and each chunk - # can be independently encoded, so we'll need to check each - # of them. - chunks: list[tuple[bytes, str | None]] = [] - for binary, _encoding in email.header.decode_header(h): - try: - binary.decode("utf8", "strict") - except UnicodeDecodeError: - # Enable mojibake. - encoding = "latin1" - valid_encoding = False - else: - encoding = "utf8" - chunks.append((binary, encoding)) - - # Turn our chunks back into a Header object, then let that - # Header object do the right thing to turn them into a - # string for us. - value.append(str(email.header.make_header(chunks))) - # This is already a string, so just add it. - else: - value.append(h) - - # We've processed all of our values to get them into a list of str, - # but we may have mojibake data, in which case this is an unparsed - # field. - if not valid_encoding: - unparsed[name] = value - continue - - raw_name = _EMAIL_TO_RAW_MAPPING.get(name) - if raw_name is None: - # This is a bit of a weird situation, we've encountered a key that - # we don't know what it means, so we don't know whether it's meant - # to be a list or not. - # - # Since we can't really tell one way or another, we'll just leave it - # as a list, even though it may be a single item list, because that's - # what makes the most sense for email headers. - unparsed[name] = value - continue - - # If this is one of our string fields, then we'll check to see if our - # value is a list of a single item. If it is then we'll assume that - # it was emitted as a single string, and unwrap the str from inside - # the list. - # - # If it's any other kind of data, then we haven't the faintest clue - # what we should parse it as, and we have to just add it to our list - # of unparsed stuff. - if raw_name in _STRING_FIELDS and len(value) == 1: - raw[raw_name] = value[0] - # If this is import_names, we need to special case the empty field - # case, which converts to an empty list instead of None. We can't let - # the empty case slip through, as it will fail validation. - elif raw_name == "import_names" and value == [""]: - raw[raw_name] = [] - # If this is one of our list of string fields, then we can just assign - # the value, since email *only* has strings, and our get_all() call - # above ensures that this is a list. - elif raw_name in _LIST_FIELDS: - raw[raw_name] = value - # Special Case: Keywords - # The keywords field is implemented in the metadata spec as a str, - # but it conceptually is a list of strings, and is serialized using - # ", ".join(keywords), so we'll do some light data massaging to turn - # this into what it logically is. - elif raw_name == "keywords" and len(value) == 1: - raw[raw_name] = _parse_keywords(value[0]) - # Special Case: Project-URL - # The project urls is implemented in the metadata spec as a list of - # specially-formatted strings that represent a key and a value, which - # is fundamentally a mapping, however the email format doesn't support - # mappings in a sane way, so it was crammed into a list of strings - # instead. - # - # We will do a little light data massaging to turn this into a map as - # it logically should be. - elif raw_name == "project_urls": - try: - raw[raw_name] = _parse_project_urls(value) - except KeyError: - unparsed[name] = value - # Nothing that we've done has managed to parse this, so it'll just - # throw it in our unparsable data and move on. - else: - unparsed[name] = value - - # We need to support getting the Description from the message payload in - # addition to getting it from the the headers. This does mean, though, there - # is the possibility of it being set both ways, in which case we put both - # in 'unparsed' since we don't know which is right. - try: - payload = _get_payload(parsed, data) - except ValueError: - unparsed.setdefault("description", []).append( - parsed.get_payload(decode=isinstance(data, bytes)) # type: ignore[call-overload] - ) - else: - if payload: - # Check to see if we've already got a description, if so then both - # it, and this body move to unparsable. - if "description" in raw: - description_header = cast("str", raw.pop("description")) - unparsed.setdefault("description", []).extend( - [description_header, payload] - ) - elif "description" in unparsed: - unparsed["description"].append(payload) - else: - raw["description"] = payload - - # We need to cast our `raw` to a metadata, because a TypedDict only support - # literal key names, but we're computing our key names on purpose, but the - # way this function is implemented, our `TypedDict` can only have valid key - # names. - return cast("RawMetadata", raw), unparsed - - -_NOT_FOUND = object() - - -# Keep the two values in sync. -_VALID_METADATA_VERSIONS = ["1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4", "2.5"] -_MetadataVersion = Literal["1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4", "2.5"] - -_REQUIRED_ATTRS = frozenset(["metadata_version", "name", "version"]) - - -class _Validator(Generic[T]): - """Validate a metadata field. - - All _process_*() methods correspond to a core metadata field. The method is - called with the field's raw value. If the raw value is valid it is returned - in its "enriched" form (e.g. ``version.Version`` for the ``Version`` field). - If the raw value is invalid, :exc:`InvalidMetadata` is raised (with a cause - as appropriate). - """ - - name: str - raw_name: str - added: _MetadataVersion - - def __init__( - self, - *, - added: _MetadataVersion = "1.0", - ) -> None: - self.added = added - - def __set_name__(self, _owner: Metadata, name: str) -> None: - self.name = name - self.raw_name = _RAW_TO_EMAIL_MAPPING[name] - - def __get__(self, instance: Metadata, _owner: type[Metadata]) -> T: - # With Python 3.8, the caching can be replaced with functools.cached_property(). - # No need to check the cache as attribute lookup will resolve into the - # instance's __dict__ before __get__ is called. - cache = instance.__dict__ - value = instance._raw.get(self.name) - - # To make the _process_* methods easier, we'll check if the value is None - # and if this field is NOT a required attribute, and if both of those - # things are true, we'll skip the the converter. This will mean that the - # converters never have to deal with the None union. - if self.name in _REQUIRED_ATTRS or value is not None: - try: - converter: Callable[[Any], T] = getattr(self, f"_process_{self.name}") - except AttributeError: - pass - else: - value = converter(value) - - cache[self.name] = value - try: - del instance._raw[self.name] # type: ignore[misc] - except KeyError: - pass - - return cast("T", value) - - def _invalid_metadata( - self, msg: str, cause: Exception | None = None - ) -> InvalidMetadata: - exc = InvalidMetadata( - self.raw_name, msg.format_map({"field": repr(self.raw_name)}) - ) - exc.__cause__ = cause - return exc - - def _process_metadata_version(self, value: str) -> _MetadataVersion: - # Implicitly makes Metadata-Version required. - if value not in _VALID_METADATA_VERSIONS: - raise self._invalid_metadata(f"{value!r} is not a valid metadata version") - return cast("_MetadataVersion", value) - - def _process_name(self, value: str) -> str: - if not value: - raise self._invalid_metadata("{field} is a required field") - # Validate the name as a side-effect. - try: - utils.canonicalize_name(value, validate=True) - except utils.InvalidName as exc: - raise self._invalid_metadata( - f"{value!r} is invalid for {{field}}", cause=exc - ) from exc - else: - return value - - def _process_version(self, value: str) -> version_module.Version: - if not value: - raise self._invalid_metadata("{field} is a required field") - try: - return version_module.parse(value) - except version_module.InvalidVersion as exc: - raise self._invalid_metadata( - f"{value!r} is invalid for {{field}}", cause=exc - ) from exc - - def _process_summary(self, value: str) -> str: - """Check the field contains no newlines.""" - if "\n" in value: - raise self._invalid_metadata("{field} must be a single line") - return value - - def _process_description_content_type(self, value: str) -> str: - content_types = {"text/plain", "text/x-rst", "text/markdown"} - message = email.message.EmailMessage() - message["content-type"] = value - - content_type, parameters = ( - # Defaults to `text/plain` if parsing failed. - message.get_content_type().lower(), - message["content-type"].params, - ) - # Check if content-type is valid or defaulted to `text/plain` and thus was - # not parseable. - if content_type not in content_types or content_type not in value.lower(): - raise self._invalid_metadata( - f"{{field}} must be one of {list(content_types)}, not {value!r}" - ) - - charset = parameters.get("charset", "UTF-8") - if charset != "UTF-8": - raise self._invalid_metadata( - f"{{field}} can only specify the UTF-8 charset, not {list(charset)}" - ) - - markdown_variants = {"GFM", "CommonMark"} - variant = parameters.get("variant", "GFM") # Use an acceptable default. - if content_type == "text/markdown" and variant not in markdown_variants: - raise self._invalid_metadata( - f"valid Markdown variants for {{field}} are {list(markdown_variants)}, " - f"not {variant!r}", - ) - return value - - def _process_dynamic(self, value: list[str]) -> list[str]: - for dynamic_field in map(str.lower, value): - if dynamic_field in {"name", "version", "metadata-version"}: - raise self._invalid_metadata( - f"{dynamic_field!r} is not allowed as a dynamic field" - ) - elif dynamic_field not in _EMAIL_TO_RAW_MAPPING: - raise self._invalid_metadata( - f"{dynamic_field!r} is not a valid dynamic field" - ) - return list(map(str.lower, value)) - - def _process_provides_extra( - self, - value: list[str], - ) -> list[utils.NormalizedName]: - normalized_names = [] - try: - for name in value: - normalized_names.append(utils.canonicalize_name(name, validate=True)) - except utils.InvalidName as exc: - raise self._invalid_metadata( - f"{name!r} is invalid for {{field}}", cause=exc - ) from exc - else: - return normalized_names - - def _process_requires_python(self, value: str) -> specifiers.SpecifierSet: - try: - return specifiers.SpecifierSet(value) - except specifiers.InvalidSpecifier as exc: - raise self._invalid_metadata( - f"{value!r} is invalid for {{field}}", cause=exc - ) from exc - - def _process_requires_dist( - self, - value: list[str], - ) -> list[requirements.Requirement]: - reqs = [] - try: - for req in value: - reqs.append(requirements.Requirement(req)) - except requirements.InvalidRequirement as exc: - raise self._invalid_metadata( - f"{req!r} is invalid for {{field}}", cause=exc - ) from exc - else: - return reqs - - def _process_license_expression(self, value: str) -> NormalizedLicenseExpression: - try: - return licenses.canonicalize_license_expression(value) - except ValueError as exc: - raise self._invalid_metadata( - f"{value!r} is invalid for {{field}}", cause=exc - ) from exc - - def _process_license_files(self, value: list[str]) -> list[str]: - paths = [] - for path in value: - if ".." in path: - raise self._invalid_metadata( - f"{path!r} is invalid for {{field}}, " - "parent directory indicators are not allowed" - ) - if "*" in path: - raise self._invalid_metadata( - f"{path!r} is invalid for {{field}}, paths must be resolved" - ) - if ( - pathlib.PurePosixPath(path).is_absolute() - or pathlib.PureWindowsPath(path).is_absolute() - ): - raise self._invalid_metadata( - f"{path!r} is invalid for {{field}}, paths must be relative" - ) - if pathlib.PureWindowsPath(path).as_posix() != path: - raise self._invalid_metadata( - f"{path!r} is invalid for {{field}}, paths must use '/' delimiter" - ) - paths.append(path) - return paths - - def _process_import_names(self, value: list[str]) -> list[str]: - for import_name in value: - name, semicolon, private = import_name.partition(";") - name = name.rstrip() - for identifier in name.split("."): - if not identifier.isidentifier(): - raise self._invalid_metadata( - f"{name!r} is invalid for {{field}}; " - f"{identifier!r} is not a valid identifier" - ) - elif keyword.iskeyword(identifier): - raise self._invalid_metadata( - f"{name!r} is invalid for {{field}}; " - f"{identifier!r} is a keyword" - ) - if semicolon and private.lstrip() != "private": - raise self._invalid_metadata( - f"{import_name!r} is invalid for {{field}}; " - "the only valid option is 'private'" - ) - return value - - _process_import_namespaces = _process_import_names - - -class Metadata: - """Representation of distribution metadata. - - Compared to :class:`RawMetadata`, this class provides objects representing - metadata fields instead of only using built-in types. Any invalid metadata - will cause :exc:`InvalidMetadata` to be raised (with a - :py:attr:`~BaseException.__cause__` attribute as appropriate). - """ - - _raw: RawMetadata - - @classmethod - def from_raw(cls, data: RawMetadata, *, validate: bool = True) -> Metadata: - """Create an instance from :class:`RawMetadata`. - - If *validate* is true, all metadata will be validated. All exceptions - related to validation will be gathered and raised as an :class:`ExceptionGroup`. - """ - ins = cls() - ins._raw = data.copy() # Mutations occur due to caching enriched values. - - if validate: - exceptions: list[Exception] = [] - try: - metadata_version = ins.metadata_version - metadata_age = _VALID_METADATA_VERSIONS.index(metadata_version) - except InvalidMetadata as metadata_version_exc: - exceptions.append(metadata_version_exc) - metadata_version = None - - # Make sure to check for the fields that are present, the required - # fields (so their absence can be reported). - fields_to_check = frozenset(ins._raw) | _REQUIRED_ATTRS - # Remove fields that have already been checked. - fields_to_check -= {"metadata_version"} - - for key in fields_to_check: - try: - if metadata_version: - # Can't use getattr() as that triggers descriptor protocol which - # will fail due to no value for the instance argument. - try: - field_metadata_version = cls.__dict__[key].added - except KeyError: - exc = InvalidMetadata(key, f"unrecognized field: {key!r}") - exceptions.append(exc) - continue - field_age = _VALID_METADATA_VERSIONS.index( - field_metadata_version - ) - if field_age > metadata_age: - field = _RAW_TO_EMAIL_MAPPING[key] - exc = InvalidMetadata( - field, - f"{field} introduced in metadata version " - f"{field_metadata_version}, not {metadata_version}", - ) - exceptions.append(exc) - continue - getattr(ins, key) - except InvalidMetadata as exc: - exceptions.append(exc) - - if exceptions: - raise ExceptionGroup("invalid metadata", exceptions) - - return ins - - @classmethod - def from_email(cls, data: bytes | str, *, validate: bool = True) -> Metadata: - """Parse metadata from email headers. - - If *validate* is true, the metadata will be validated. All exceptions - related to validation will be gathered and raised as an :class:`ExceptionGroup`. - """ - raw, unparsed = parse_email(data) - - if validate: - exceptions: list[Exception] = [] - for unparsed_key in unparsed: - if unparsed_key in _EMAIL_TO_RAW_MAPPING: - message = f"{unparsed_key!r} has invalid data" - else: - message = f"unrecognized field: {unparsed_key!r}" - exceptions.append(InvalidMetadata(unparsed_key, message)) - - if exceptions: - raise ExceptionGroup("unparsed", exceptions) - - try: - return cls.from_raw(raw, validate=validate) - except ExceptionGroup as exc_group: - raise ExceptionGroup( - "invalid or unparsed metadata", exc_group.exceptions - ) from None - - metadata_version: _Validator[_MetadataVersion] = _Validator() - """:external:ref:`core-metadata-metadata-version` - (required; validated to be a valid metadata version)""" - # `name` is not normalized/typed to NormalizedName so as to provide access to - # the original/raw name. - name: _Validator[str] = _Validator() - """:external:ref:`core-metadata-name` - (required; validated using :func:`~packaging.utils.canonicalize_name` and its - *validate* parameter)""" - version: _Validator[version_module.Version] = _Validator() - """:external:ref:`core-metadata-version` (required)""" - dynamic: _Validator[list[str] | None] = _Validator( - added="2.2", - ) - """:external:ref:`core-metadata-dynamic` - (validated against core metadata field names and lowercased)""" - platforms: _Validator[list[str] | None] = _Validator() - """:external:ref:`core-metadata-platform`""" - supported_platforms: _Validator[list[str] | None] = _Validator(added="1.1") - """:external:ref:`core-metadata-supported-platform`""" - summary: _Validator[str | None] = _Validator() - """:external:ref:`core-metadata-summary` (validated to contain no newlines)""" - description: _Validator[str | None] = _Validator() # TODO 2.1: can be in body - """:external:ref:`core-metadata-description`""" - description_content_type: _Validator[str | None] = _Validator(added="2.1") - """:external:ref:`core-metadata-description-content-type` (validated)""" - keywords: _Validator[list[str] | None] = _Validator() - """:external:ref:`core-metadata-keywords`""" - home_page: _Validator[str | None] = _Validator() - """:external:ref:`core-metadata-home-page`""" - download_url: _Validator[str | None] = _Validator(added="1.1") - """:external:ref:`core-metadata-download-url`""" - author: _Validator[str | None] = _Validator() - """:external:ref:`core-metadata-author`""" - author_email: _Validator[str | None] = _Validator() - """:external:ref:`core-metadata-author-email`""" - maintainer: _Validator[str | None] = _Validator(added="1.2") - """:external:ref:`core-metadata-maintainer`""" - maintainer_email: _Validator[str | None] = _Validator(added="1.2") - """:external:ref:`core-metadata-maintainer-email`""" - license: _Validator[str | None] = _Validator() - """:external:ref:`core-metadata-license`""" - license_expression: _Validator[NormalizedLicenseExpression | None] = _Validator( - added="2.4" - ) - """:external:ref:`core-metadata-license-expression`""" - license_files: _Validator[list[str] | None] = _Validator(added="2.4") - """:external:ref:`core-metadata-license-file`""" - classifiers: _Validator[list[str] | None] = _Validator(added="1.1") - """:external:ref:`core-metadata-classifier`""" - requires_dist: _Validator[list[requirements.Requirement] | None] = _Validator( - added="1.2" - ) - """:external:ref:`core-metadata-requires-dist`""" - requires_python: _Validator[specifiers.SpecifierSet | None] = _Validator( - added="1.2" - ) - """:external:ref:`core-metadata-requires-python`""" - # Because `Requires-External` allows for non-PEP 440 version specifiers, we - # don't do any processing on the values. - requires_external: _Validator[list[str] | None] = _Validator(added="1.2") - """:external:ref:`core-metadata-requires-external`""" - project_urls: _Validator[dict[str, str] | None] = _Validator(added="1.2") - """:external:ref:`core-metadata-project-url`""" - # PEP 685 lets us raise an error if an extra doesn't pass `Name` validation - # regardless of metadata version. - provides_extra: _Validator[list[utils.NormalizedName] | None] = _Validator( - added="2.1", - ) - """:external:ref:`core-metadata-provides-extra`""" - provides_dist: _Validator[list[str] | None] = _Validator(added="1.2") - """:external:ref:`core-metadata-provides-dist`""" - obsoletes_dist: _Validator[list[str] | None] = _Validator(added="1.2") - """:external:ref:`core-metadata-obsoletes-dist`""" - import_names: _Validator[list[str] | None] = _Validator(added="2.5") - """:external:ref:`core-metadata-import-name`""" - import_namespaces: _Validator[list[str] | None] = _Validator(added="2.5") - """:external:ref:`core-metadata-import-namespace`""" - requires: _Validator[list[str] | None] = _Validator(added="1.1") - """``Requires`` (deprecated)""" - provides: _Validator[list[str] | None] = _Validator(added="1.1") - """``Provides`` (deprecated)""" - obsoletes: _Validator[list[str] | None] = _Validator(added="1.1") - """``Obsoletes`` (deprecated)""" - - def as_rfc822(self) -> RFC822Message: - """ - Return an RFC822 message with the metadata. - """ - message = RFC822Message() - self._write_metadata(message) - return message - - def _write_metadata(self, message: RFC822Message) -> None: - """ - Return an RFC822 message with the metadata. - """ - for name, validator in self.__class__.__dict__.items(): - if isinstance(validator, _Validator) and name != "description": - value = getattr(self, name) - email_name = _RAW_TO_EMAIL_MAPPING[name] - if value is not None: - if email_name == "project-url": - for label, url in value.items(): - message[email_name] = f"{label}, {url}" - elif email_name == "keywords": - message[email_name] = ",".join(value) - elif email_name == "import-name" and value == []: - message[email_name] = "" - elif isinstance(value, list): - for item in value: - message[email_name] = str(item) - else: - message[email_name] = str(value) - - # The description is a special case because it is in the body of the message. - if self.description is not None: - message.set_payload(self.description) diff --git a/apps/bitwarden_event_logs/lib/packaging/py.typed b/apps/bitwarden_event_logs/lib/packaging/py.typed deleted file mode 100755 index e69de29b..00000000 diff --git a/apps/bitwarden_event_logs/lib/packaging/pylock.py b/apps/bitwarden_event_logs/lib/packaging/pylock.py deleted file mode 100755 index a564f152..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/pylock.py +++ /dev/null @@ -1,635 +0,0 @@ -from __future__ import annotations - -import dataclasses -import logging -import re -from collections.abc import Mapping, Sequence -from dataclasses import dataclass -from datetime import datetime -from typing import ( - TYPE_CHECKING, - Any, - Callable, - Protocol, - TypeVar, -) - -from .markers import Marker -from .specifiers import SpecifierSet -from .utils import NormalizedName, is_normalized_name -from .version import Version - -if TYPE_CHECKING: # pragma: no cover - from pathlib import Path - - from typing_extensions import Self - -_logger = logging.getLogger(__name__) - -__all__ = [ - "Package", - "PackageArchive", - "PackageDirectory", - "PackageSdist", - "PackageVcs", - "PackageWheel", - "Pylock", - "PylockUnsupportedVersionError", - "PylockValidationError", - "is_valid_pylock_path", -] - -_T = TypeVar("_T") -_T2 = TypeVar("_T2") - - -class _FromMappingProtocol(Protocol): # pragma: no cover - @classmethod - def _from_dict(cls, d: Mapping[str, Any]) -> Self: ... - - -_FromMappingProtocolT = TypeVar("_FromMappingProtocolT", bound=_FromMappingProtocol) - - -_PYLOCK_FILE_NAME_RE = re.compile(r"^pylock\.([^.]+)\.toml$") - - -def is_valid_pylock_path(path: Path) -> bool: - """Check if the given path is a valid pylock file path.""" - return path.name == "pylock.toml" or bool(_PYLOCK_FILE_NAME_RE.match(path.name)) - - -def _toml_key(key: str) -> str: - return key.replace("_", "-") - - -def _toml_value(key: str, value: Any) -> Any: # noqa: ANN401 - if isinstance(value, (Version, Marker, SpecifierSet)): - return str(value) - if isinstance(value, Sequence) and key == "environments": - return [str(v) for v in value] - return value - - -def _toml_dict_factory(data: list[tuple[str, Any]]) -> dict[str, Any]: - return { - _toml_key(key): _toml_value(key, value) - for key, value in data - if value is not None - } - - -def _get(d: Mapping[str, Any], expected_type: type[_T], key: str) -> _T | None: - """Get a value from the dictionary and verify it's the expected type.""" - if (value := d.get(key)) is None: - return None - if not isinstance(value, expected_type): - raise PylockValidationError( - f"Unexpected type {type(value).__name__} " - f"(expected {expected_type.__name__})", - context=key, - ) - return value - - -def _get_required(d: Mapping[str, Any], expected_type: type[_T], key: str) -> _T: - """Get a required value from the dictionary and verify it's the expected type.""" - if (value := _get(d, expected_type, key)) is None: - raise _PylockRequiredKeyError(key) - return value - - -def _get_sequence( - d: Mapping[str, Any], expected_item_type: type[_T], key: str -) -> Sequence[_T] | None: - """Get a list value from the dictionary and verify it's the expected items type.""" - if (value := _get(d, Sequence, key)) is None: # type: ignore[type-abstract] - return None - if isinstance(value, (str, bytes)): - # special case: str and bytes are Sequences, but we want to reject it - raise PylockValidationError( - f"Unexpected type {type(value).__name__} (expected Sequence)", - context=key, - ) - for i, item in enumerate(value): - if not isinstance(item, expected_item_type): - raise PylockValidationError( - f"Unexpected type {type(item).__name__} " - f"(expected {expected_item_type.__name__})", - context=f"{key}[{i}]", - ) - return value - - -def _get_as( - d: Mapping[str, Any], - expected_type: type[_T], - target_type: Callable[[_T], _T2], - key: str, -) -> _T2 | None: - """Get a value from the dictionary, verify it's the expected type, - and convert to the target type. - - This assumes the target_type constructor accepts the value. - """ - if (value := _get(d, expected_type, key)) is None: - return None - try: - return target_type(value) - except Exception as e: - raise PylockValidationError(e, context=key) from e - - -def _get_required_as( - d: Mapping[str, Any], - expected_type: type[_T], - target_type: Callable[[_T], _T2], - key: str, -) -> _T2: - """Get a required value from the dict, verify it's the expected type, - and convert to the target type.""" - if (value := _get_as(d, expected_type, target_type, key)) is None: - raise _PylockRequiredKeyError(key) - return value - - -def _get_sequence_as( - d: Mapping[str, Any], - expected_item_type: type[_T], - target_item_type: Callable[[_T], _T2], - key: str, -) -> list[_T2] | None: - """Get list value from dictionary and verify expected items type.""" - if (value := _get_sequence(d, expected_item_type, key)) is None: - return None - result = [] - try: - for item in value: - typed_item = target_item_type(item) - result.append(typed_item) - except Exception as e: - raise PylockValidationError(e, context=f"{key}[{len(result)}]") from e - return result - - -def _get_object( - d: Mapping[str, Any], target_type: type[_FromMappingProtocolT], key: str -) -> _FromMappingProtocolT | None: - """Get a dictionary value from the dictionary and convert it to a dataclass.""" - if (value := _get(d, Mapping, key)) is None: # type: ignore[type-abstract] - return None - try: - return target_type._from_dict(value) - except Exception as e: - raise PylockValidationError(e, context=key) from e - - -def _get_sequence_of_objects( - d: Mapping[str, Any], target_item_type: type[_FromMappingProtocolT], key: str -) -> list[_FromMappingProtocolT] | None: - """Get a list value from the dictionary and convert its items to a dataclass.""" - if (value := _get_sequence(d, Mapping, key)) is None: # type: ignore[type-abstract] - return None - result: list[_FromMappingProtocolT] = [] - try: - for item in value: - typed_item = target_item_type._from_dict(item) - result.append(typed_item) - except Exception as e: - raise PylockValidationError(e, context=f"{key}[{len(result)}]") from e - return result - - -def _get_required_sequence_of_objects( - d: Mapping[str, Any], target_item_type: type[_FromMappingProtocolT], key: str -) -> Sequence[_FromMappingProtocolT]: - """Get a required list value from the dictionary and convert its items to a - dataclass.""" - if (result := _get_sequence_of_objects(d, target_item_type, key)) is None: - raise _PylockRequiredKeyError(key) - return result - - -def _validate_normalized_name(name: str) -> NormalizedName: - """Validate that a string is a NormalizedName.""" - if not is_normalized_name(name): - raise PylockValidationError(f"Name {name!r} is not normalized") - return NormalizedName(name) - - -def _validate_path_url(path: str | None, url: str | None) -> None: - if not path and not url: - raise PylockValidationError("path or url must be provided") - - -def _validate_hashes(hashes: Mapping[str, Any]) -> Mapping[str, Any]: - if not hashes: - raise PylockValidationError("At least one hash must be provided") - if not all(isinstance(hash_val, str) for hash_val in hashes.values()): - raise PylockValidationError("Hash values must be strings") - return hashes - - -class PylockValidationError(Exception): - """Raised when when input data is not spec-compliant.""" - - context: str | None = None - message: str - - def __init__( - self, - cause: str | Exception, - *, - context: str | None = None, - ) -> None: - if isinstance(cause, PylockValidationError): - if cause.context: - self.context = ( - f"{context}.{cause.context}" if context else cause.context - ) - else: - self.context = context - self.message = cause.message - else: - self.context = context - self.message = str(cause) - - def __str__(self) -> str: - if self.context: - return f"{self.message} in {self.context!r}" - return self.message - - -class _PylockRequiredKeyError(PylockValidationError): - def __init__(self, key: str) -> None: - super().__init__("Missing required value", context=key) - - -class PylockUnsupportedVersionError(PylockValidationError): - """Raised when encountering an unsupported `lock_version`.""" - - -@dataclass(frozen=True, init=False) -class PackageVcs: - type: str - url: str | None = None - path: str | None = None - requested_revision: str | None = None - commit_id: str # type: ignore[misc] - subdirectory: str | None = None - - def __init__( - self, - *, - type: str, - url: str | None = None, - path: str | None = None, - requested_revision: str | None = None, - commit_id: str, - subdirectory: str | None = None, - ) -> None: - # In Python 3.10+ make dataclass kw_only=True and remove __init__ - object.__setattr__(self, "type", type) - object.__setattr__(self, "url", url) - object.__setattr__(self, "path", path) - object.__setattr__(self, "requested_revision", requested_revision) - object.__setattr__(self, "commit_id", commit_id) - object.__setattr__(self, "subdirectory", subdirectory) - - @classmethod - def _from_dict(cls, d: Mapping[str, Any]) -> Self: - package_vcs = cls( - type=_get_required(d, str, "type"), - url=_get(d, str, "url"), - path=_get(d, str, "path"), - requested_revision=_get(d, str, "requested-revision"), - commit_id=_get_required(d, str, "commit-id"), - subdirectory=_get(d, str, "subdirectory"), - ) - _validate_path_url(package_vcs.path, package_vcs.url) - return package_vcs - - -@dataclass(frozen=True, init=False) -class PackageDirectory: - path: str - editable: bool | None = None - subdirectory: str | None = None - - def __init__( - self, - *, - path: str, - editable: bool | None = None, - subdirectory: str | None = None, - ) -> None: - # In Python 3.10+ make dataclass kw_only=True and remove __init__ - object.__setattr__(self, "path", path) - object.__setattr__(self, "editable", editable) - object.__setattr__(self, "subdirectory", subdirectory) - - @classmethod - def _from_dict(cls, d: Mapping[str, Any]) -> Self: - return cls( - path=_get_required(d, str, "path"), - editable=_get(d, bool, "editable"), - subdirectory=_get(d, str, "subdirectory"), - ) - - -@dataclass(frozen=True, init=False) -class PackageArchive: - url: str | None = None - path: str | None = None - size: int | None = None - upload_time: datetime | None = None - hashes: Mapping[str, str] # type: ignore[misc] - subdirectory: str | None = None - - def __init__( - self, - *, - url: str | None = None, - path: str | None = None, - size: int | None = None, - upload_time: datetime | None = None, - hashes: Mapping[str, str], - subdirectory: str | None = None, - ) -> None: - # In Python 3.10+ make dataclass kw_only=True and remove __init__ - object.__setattr__(self, "url", url) - object.__setattr__(self, "path", path) - object.__setattr__(self, "size", size) - object.__setattr__(self, "upload_time", upload_time) - object.__setattr__(self, "hashes", hashes) - object.__setattr__(self, "subdirectory", subdirectory) - - @classmethod - def _from_dict(cls, d: Mapping[str, Any]) -> Self: - package_archive = cls( - url=_get(d, str, "url"), - path=_get(d, str, "path"), - size=_get(d, int, "size"), - upload_time=_get(d, datetime, "upload-time"), - hashes=_get_required_as(d, Mapping, _validate_hashes, "hashes"), # type: ignore[type-abstract] - subdirectory=_get(d, str, "subdirectory"), - ) - _validate_path_url(package_archive.path, package_archive.url) - return package_archive - - -@dataclass(frozen=True, init=False) -class PackageSdist: - name: str | None = None - upload_time: datetime | None = None - url: str | None = None - path: str | None = None - size: int | None = None - hashes: Mapping[str, str] # type: ignore[misc] - - def __init__( - self, - *, - name: str | None = None, - upload_time: datetime | None = None, - url: str | None = None, - path: str | None = None, - size: int | None = None, - hashes: Mapping[str, str], - ) -> None: - # In Python 3.10+ make dataclass kw_only=True and remove __init__ - object.__setattr__(self, "name", name) - object.__setattr__(self, "upload_time", upload_time) - object.__setattr__(self, "url", url) - object.__setattr__(self, "path", path) - object.__setattr__(self, "size", size) - object.__setattr__(self, "hashes", hashes) - - @classmethod - def _from_dict(cls, d: Mapping[str, Any]) -> Self: - package_sdist = cls( - name=_get(d, str, "name"), - upload_time=_get(d, datetime, "upload-time"), - url=_get(d, str, "url"), - path=_get(d, str, "path"), - size=_get(d, int, "size"), - hashes=_get_required_as(d, Mapping, _validate_hashes, "hashes"), # type: ignore[type-abstract] - ) - _validate_path_url(package_sdist.path, package_sdist.url) - return package_sdist - - -@dataclass(frozen=True, init=False) -class PackageWheel: - name: str | None = None - upload_time: datetime | None = None - url: str | None = None - path: str | None = None - size: int | None = None - hashes: Mapping[str, str] # type: ignore[misc] - - def __init__( - self, - *, - name: str | None = None, - upload_time: datetime | None = None, - url: str | None = None, - path: str | None = None, - size: int | None = None, - hashes: Mapping[str, str], - ) -> None: - # In Python 3.10+ make dataclass kw_only=True and remove __init__ - object.__setattr__(self, "name", name) - object.__setattr__(self, "upload_time", upload_time) - object.__setattr__(self, "url", url) - object.__setattr__(self, "path", path) - object.__setattr__(self, "size", size) - object.__setattr__(self, "hashes", hashes) - - @classmethod - def _from_dict(cls, d: Mapping[str, Any]) -> Self: - package_wheel = cls( - name=_get(d, str, "name"), - upload_time=_get(d, datetime, "upload-time"), - url=_get(d, str, "url"), - path=_get(d, str, "path"), - size=_get(d, int, "size"), - hashes=_get_required_as(d, Mapping, _validate_hashes, "hashes"), # type: ignore[type-abstract] - ) - _validate_path_url(package_wheel.path, package_wheel.url) - return package_wheel - - -@dataclass(frozen=True, init=False) -class Package: - name: NormalizedName - version: Version | None = None - marker: Marker | None = None - requires_python: SpecifierSet | None = None - dependencies: Sequence[Mapping[str, Any]] | None = None - vcs: PackageVcs | None = None - directory: PackageDirectory | None = None - archive: PackageArchive | None = None - index: str | None = None - sdist: PackageSdist | None = None - wheels: Sequence[PackageWheel] | None = None - attestation_identities: Sequence[Mapping[str, Any]] | None = None - tool: Mapping[str, Any] | None = None - - def __init__( - self, - *, - name: NormalizedName, - version: Version | None = None, - marker: Marker | None = None, - requires_python: SpecifierSet | None = None, - dependencies: Sequence[Mapping[str, Any]] | None = None, - vcs: PackageVcs | None = None, - directory: PackageDirectory | None = None, - archive: PackageArchive | None = None, - index: str | None = None, - sdist: PackageSdist | None = None, - wheels: Sequence[PackageWheel] | None = None, - attestation_identities: Sequence[Mapping[str, Any]] | None = None, - tool: Mapping[str, Any] | None = None, - ) -> None: - # In Python 3.10+ make dataclass kw_only=True and remove __init__ - object.__setattr__(self, "name", name) - object.__setattr__(self, "version", version) - object.__setattr__(self, "marker", marker) - object.__setattr__(self, "requires_python", requires_python) - object.__setattr__(self, "dependencies", dependencies) - object.__setattr__(self, "vcs", vcs) - object.__setattr__(self, "directory", directory) - object.__setattr__(self, "archive", archive) - object.__setattr__(self, "index", index) - object.__setattr__(self, "sdist", sdist) - object.__setattr__(self, "wheels", wheels) - object.__setattr__(self, "attestation_identities", attestation_identities) - object.__setattr__(self, "tool", tool) - - @classmethod - def _from_dict(cls, d: Mapping[str, Any]) -> Self: - package = cls( - name=_get_required_as(d, str, _validate_normalized_name, "name"), - version=_get_as(d, str, Version, "version"), - requires_python=_get_as(d, str, SpecifierSet, "requires-python"), - dependencies=_get_sequence(d, Mapping, "dependencies"), # type: ignore[type-abstract] - marker=_get_as(d, str, Marker, "marker"), - vcs=_get_object(d, PackageVcs, "vcs"), - directory=_get_object(d, PackageDirectory, "directory"), - archive=_get_object(d, PackageArchive, "archive"), - index=_get(d, str, "index"), - sdist=_get_object(d, PackageSdist, "sdist"), - wheels=_get_sequence_of_objects(d, PackageWheel, "wheels"), - attestation_identities=_get_sequence(d, Mapping, "attestation-identities"), # type: ignore[type-abstract] - tool=_get(d, Mapping, "tool"), # type: ignore[type-abstract] - ) - distributions = bool(package.sdist) + len(package.wheels or []) - direct_urls = ( - bool(package.vcs) + bool(package.directory) + bool(package.archive) - ) - if distributions > 0 and direct_urls > 0: - raise PylockValidationError( - "None of vcs, directory, archive must be set if sdist or wheels are set" - ) - if distributions == 0 and direct_urls != 1: - raise PylockValidationError( - "Exactly one of vcs, directory, archive must be set " - "if sdist and wheels are not set" - ) - try: - for i, attestation_identity in enumerate( # noqa: B007 - package.attestation_identities or [] - ): - _get_required(attestation_identity, str, "kind") - except Exception as e: - raise PylockValidationError( - e, context=f"attestation-identities[{i}]" - ) from e - return package - - @property - def is_direct(self) -> bool: - return not (self.sdist or self.wheels) - - -@dataclass(frozen=True, init=False) -class Pylock: - """A class representing a pylock file.""" - - lock_version: Version - environments: Sequence[Marker] | None = None - requires_python: SpecifierSet | None = None - extras: Sequence[NormalizedName] | None = None - dependency_groups: Sequence[str] | None = None - default_groups: Sequence[str] | None = None - created_by: str # type: ignore[misc] - packages: Sequence[Package] # type: ignore[misc] - tool: Mapping[str, Any] | None = None - - def __init__( - self, - *, - lock_version: Version, - environments: Sequence[Marker] | None = None, - requires_python: SpecifierSet | None = None, - extras: Sequence[NormalizedName] | None = None, - dependency_groups: Sequence[str] | None = None, - default_groups: Sequence[str] | None = None, - created_by: str, - packages: Sequence[Package], - tool: Mapping[str, Any] | None = None, - ) -> None: - # In Python 3.10+ make dataclass kw_only=True and remove __init__ - object.__setattr__(self, "lock_version", lock_version) - object.__setattr__(self, "environments", environments) - object.__setattr__(self, "requires_python", requires_python) - object.__setattr__(self, "extras", extras) - object.__setattr__(self, "dependency_groups", dependency_groups) - object.__setattr__(self, "default_groups", default_groups) - object.__setattr__(self, "created_by", created_by) - object.__setattr__(self, "packages", packages) - object.__setattr__(self, "tool", tool) - - @classmethod - def _from_dict(cls, d: Mapping[str, Any]) -> Self: - pylock = cls( - lock_version=_get_required_as(d, str, Version, "lock-version"), - environments=_get_sequence_as(d, str, Marker, "environments"), - extras=_get_sequence_as(d, str, _validate_normalized_name, "extras"), - dependency_groups=_get_sequence(d, str, "dependency-groups"), - default_groups=_get_sequence(d, str, "default-groups"), - created_by=_get_required(d, str, "created-by"), - requires_python=_get_as(d, str, SpecifierSet, "requires-python"), - packages=_get_required_sequence_of_objects(d, Package, "packages"), - tool=_get(d, Mapping, "tool"), # type: ignore[type-abstract] - ) - if not Version("1") <= pylock.lock_version < Version("2"): - raise PylockUnsupportedVersionError( - f"pylock version {pylock.lock_version} is not supported" - ) - if pylock.lock_version > Version("1.0"): - _logger.warning( - "pylock minor version %s is not supported", pylock.lock_version - ) - return pylock - - @classmethod - def from_dict(cls, d: Mapping[str, Any], /) -> Self: - """Create and validate a Pylock instance from a TOML dictionary. - - Raises :class:`PylockValidationError` if the input data is not - spec-compliant. - """ - return cls._from_dict(d) - - def to_dict(self) -> Mapping[str, Any]: - """Convert the Pylock instance to a TOML dictionary.""" - return dataclasses.asdict(self, dict_factory=_toml_dict_factory) - - def validate(self) -> None: - """Validate the Pylock instance against the specification. - - Raises :class:`PylockValidationError` otherwise.""" - self.from_dict(self.to_dict()) diff --git a/apps/bitwarden_event_logs/lib/packaging/requirements.py b/apps/bitwarden_event_logs/lib/packaging/requirements.py deleted file mode 100755 index 3079be69..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/requirements.py +++ /dev/null @@ -1,86 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. -from __future__ import annotations - -from typing import Iterator - -from ._parser import parse_requirement as _parse_requirement -from ._tokenizer import ParserSyntaxError -from .markers import Marker, _normalize_extra_values -from .specifiers import SpecifierSet -from .utils import canonicalize_name - - -class InvalidRequirement(ValueError): - """ - An invalid requirement was found, users should refer to PEP 508. - """ - - -class Requirement: - """Parse a requirement. - - Parse a given requirement string into its parts, such as name, specifier, - URL, and extras. Raises InvalidRequirement on a badly-formed requirement - string. - """ - - # TODO: Can we test whether something is contained within a requirement? - # If so how do we do that? Do we need to test against the _name_ of - # the thing as well as the version? What about the markers? - # TODO: Can we normalize the name and extra name? - - def __init__(self, requirement_string: str) -> None: - try: - parsed = _parse_requirement(requirement_string) - except ParserSyntaxError as e: - raise InvalidRequirement(str(e)) from e - - self.name: str = parsed.name - self.url: str | None = parsed.url or None - self.extras: set[str] = set(parsed.extras or []) - self.specifier: SpecifierSet = SpecifierSet(parsed.specifier) - self.marker: Marker | None = None - if parsed.marker is not None: - self.marker = Marker.__new__(Marker) - self.marker._markers = _normalize_extra_values(parsed.marker) - - def _iter_parts(self, name: str) -> Iterator[str]: - yield name - - if self.extras: - formatted_extras = ",".join(sorted(self.extras)) - yield f"[{formatted_extras}]" - - if self.specifier: - yield str(self.specifier) - - if self.url: - yield f" @ {self.url}" - if self.marker: - yield " " - - if self.marker: - yield f"; {self.marker}" - - def __str__(self) -> str: - return "".join(self._iter_parts(self.name)) - - def __repr__(self) -> str: - return f"<{self.__class__.__name__}('{self}')>" - - def __hash__(self) -> int: - return hash(tuple(self._iter_parts(canonicalize_name(self.name)))) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, Requirement): - return NotImplemented - - return ( - canonicalize_name(self.name) == canonicalize_name(other.name) - and self.extras == other.extras - and self.specifier == other.specifier - and self.url == other.url - and self.marker == other.marker - ) diff --git a/apps/bitwarden_event_logs/lib/packaging/specifiers.py b/apps/bitwarden_event_logs/lib/packaging/specifiers.py deleted file mode 100755 index 5d26b0d1..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/specifiers.py +++ /dev/null @@ -1,1068 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. -""" -.. testsetup:: - - from packaging.specifiers import Specifier, SpecifierSet, InvalidSpecifier - from packaging.version import Version -""" - -from __future__ import annotations - -import abc -import itertools -import re -from typing import Callable, Final, Iterable, Iterator, TypeVar, Union - -from .utils import canonicalize_version -from .version import InvalidVersion, Version - -UnparsedVersion = Union[Version, str] -UnparsedVersionVar = TypeVar("UnparsedVersionVar", bound=UnparsedVersion) -CallableOperator = Callable[[Version, str], bool] - - -def _coerce_version(version: UnparsedVersion) -> Version | None: - if not isinstance(version, Version): - try: - version = Version(version) - except InvalidVersion: - return None - return version - - -def _public_version(version: Version) -> Version: - return version.__replace__(local=None) - - -def _base_version(version: Version) -> Version: - return version.__replace__(pre=None, post=None, dev=None, local=None) - - -class InvalidSpecifier(ValueError): - """ - Raised when attempting to create a :class:`Specifier` with a specifier - string that is invalid. - - >>> Specifier("lolwat") - Traceback (most recent call last): - ... - packaging.specifiers.InvalidSpecifier: Invalid specifier: 'lolwat' - """ - - -class BaseSpecifier(metaclass=abc.ABCMeta): - __slots__ = () - __match_args__ = ("_str",) - - @property - def _str(self) -> str: - """Internal property for match_args""" - return str(self) - - @abc.abstractmethod - def __str__(self) -> str: - """ - Returns the str representation of this Specifier-like object. This - should be representative of the Specifier itself. - """ - - @abc.abstractmethod - def __hash__(self) -> int: - """ - Returns a hash value for this Specifier-like object. - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Returns a boolean representing whether or not the two Specifier-like - objects are equal. - - :param other: The other object to check against. - """ - - @property - @abc.abstractmethod - def prereleases(self) -> bool | None: - """Whether or not pre-releases as a whole are allowed. - - This can be set to either ``True`` or ``False`` to explicitly enable or disable - prereleases or it can be set to ``None`` (the default) to use default semantics. - """ - - @prereleases.setter # noqa: B027 - def prereleases(self, value: bool) -> None: - """Setter for :attr:`prereleases`. - - :param value: The value to set. - """ - - @abc.abstractmethod - def contains(self, item: str, prereleases: bool | None = None) -> bool: - """ - Determines if the given item is contained within this specifier. - """ - - @abc.abstractmethod - def filter( - self, iterable: Iterable[UnparsedVersionVar], prereleases: bool | None = None - ) -> Iterator[UnparsedVersionVar]: - """ - Takes an iterable of items and filters them so that only items which - are contained within this specifier are allowed in it. - """ - - -class Specifier(BaseSpecifier): - """This class abstracts handling of version specifiers. - - .. tip:: - - It is generally not required to instantiate this manually. You should instead - prefer to work with :class:`SpecifierSet` instead, which can parse - comma-separated version specifiers (which is what package metadata contains). - """ - - __slots__ = ("_prereleases", "_spec", "_spec_version") - - _operator_regex_str = r""" - (?P(~=|==|!=|<=|>=|<|>|===)) - """ - _version_regex_str = r""" - (?P - (?: - # The identity operators allow for an escape hatch that will - # do an exact string match of the version you wish to install. - # This will not be parsed by PEP 440 and we cannot determine - # any semantic meaning from it. This operator is discouraged - # but included entirely as an escape hatch. - (?<====) # Only match for the identity operator - \s* - [^\s;)]* # The arbitrary version can be just about anything, - # we match everything except for whitespace, a - # semi-colon for marker support, and a closing paren - # since versions can be enclosed in them. - ) - | - (?: - # The (non)equality operators allow for wild card and local - # versions to be specified so we have to define these two - # operators separately to enable that. - (?<===|!=) # Only match for equals and not equals - - \s* - v? - (?:[0-9]+!)? # epoch - [0-9]+(?:\.[0-9]+)* # release - - # You cannot use a wild card and a pre-release, post-release, a dev or - # local version together so group them with a | and make them optional. - (?: - \.\* # Wild card syntax of .* - | - (?: # pre release - [-_\.]? - (alpha|beta|preview|pre|a|b|c|rc) - [-_\.]? - [0-9]* - )? - (?: # post release - (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) - )? - (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release - (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local - )? - ) - | - (?: - # The compatible operator requires at least two digits in the - # release segment. - (?<=~=) # Only match for the compatible operator - - \s* - v? - (?:[0-9]+!)? # epoch - [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) - (?: # pre release - [-_\.]? - (alpha|beta|preview|pre|a|b|c|rc) - [-_\.]? - [0-9]* - )? - (?: # post release - (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) - )? - (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release - ) - | - (?: - # All other operators only allow a sub set of what the - # (non)equality operators do. Specifically they do not allow - # local versions to be specified nor do they allow the prefix - # matching wild cards. - (?=": "greater_than_equal", - "<": "less_than", - ">": "greater_than", - "===": "arbitrary", - } - - def __init__(self, spec: str = "", prereleases: bool | None = None) -> None: - """Initialize a Specifier instance. - - :param spec: - The string representation of a specifier which will be parsed and - normalized before use. - :param prereleases: - This tells the specifier if it should accept prerelease versions if - applicable or not. The default of ``None`` will autodetect it from the - given specifiers. - :raises InvalidSpecifier: - If the given specifier is invalid (i.e. bad syntax). - """ - match = self._regex.fullmatch(spec) - if not match: - raise InvalidSpecifier(f"Invalid specifier: {spec!r}") - - self._spec: tuple[str, str] = ( - match.group("operator").strip(), - match.group("version").strip(), - ) - - # Store whether or not this Specifier should accept prereleases - self._prereleases = prereleases - - # Specifier version cache - self._spec_version: tuple[str, Version] | None = None - - def _get_spec_version(self, version: str) -> Version | None: - """One element cache, as only one spec Version is needed per Specifier.""" - if self._spec_version is not None and self._spec_version[0] == version: - return self._spec_version[1] - - version_specifier = _coerce_version(version) - if version_specifier is None: - return None - - self._spec_version = (version, version_specifier) - return version_specifier - - def _require_spec_version(self, version: str) -> Version: - """Get spec version, asserting it's valid (not for === operator). - - This method should only be called for operators where version - strings are guaranteed to be valid PEP 440 versions (not ===). - """ - spec_version = self._get_spec_version(version) - assert spec_version is not None - return spec_version - - @property - def prereleases(self) -> bool | None: - # If there is an explicit prereleases set for this, then we'll just - # blindly use that. - if self._prereleases is not None: - return self._prereleases - - # Only the "!=" operator does not imply prereleases when - # the version in the specifier is a prerelease. - operator, version_str = self._spec - if operator != "!=": - # The == specifier with trailing .* cannot include prereleases - # e.g. "==1.0a1.*" is not valid. - if operator == "==" and version_str.endswith(".*"): - return False - - # "===" can have arbitrary string versions, so we cannot parse - # those, we take prereleases as unknown (None) for those. - version = self._get_spec_version(version_str) - if version is None: - return None - - # For all other operators, use the check if spec Version - # object implies pre-releases. - if version.is_prerelease: - return True - - return False - - @prereleases.setter - def prereleases(self, value: bool | None) -> None: - self._prereleases = value - - @property - def operator(self) -> str: - """The operator of this specifier. - - >>> Specifier("==1.2.3").operator - '==' - """ - return self._spec[0] - - @property - def version(self) -> str: - """The version of this specifier. - - >>> Specifier("==1.2.3").version - '1.2.3' - """ - return self._spec[1] - - def __repr__(self) -> str: - """A representation of the Specifier that shows all internal state. - - >>> Specifier('>=1.0.0') - =1.0.0')> - >>> Specifier('>=1.0.0', prereleases=False) - =1.0.0', prereleases=False)> - >>> Specifier('>=1.0.0', prereleases=True) - =1.0.0', prereleases=True)> - """ - pre = ( - f", prereleases={self.prereleases!r}" - if self._prereleases is not None - else "" - ) - - return f"<{self.__class__.__name__}({str(self)!r}{pre})>" - - def __str__(self) -> str: - """A string representation of the Specifier that can be round-tripped. - - >>> str(Specifier('>=1.0.0')) - '>=1.0.0' - >>> str(Specifier('>=1.0.0', prereleases=False)) - '>=1.0.0' - """ - return "{}{}".format(*self._spec) - - @property - def _canonical_spec(self) -> tuple[str, str]: - operator, version = self._spec - if operator == "===" or version.endswith(".*"): - return operator, version - - spec_version = self._require_spec_version(version) - - canonical_version = canonicalize_version( - spec_version, strip_trailing_zero=(operator != "~=") - ) - - return operator, canonical_version - - def __hash__(self) -> int: - return hash(self._canonical_spec) - - def __eq__(self, other: object) -> bool: - """Whether or not the two Specifier-like objects are equal. - - :param other: The other object to check against. - - The value of :attr:`prereleases` is ignored. - - >>> Specifier("==1.2.3") == Specifier("== 1.2.3.0") - True - >>> (Specifier("==1.2.3", prereleases=False) == - ... Specifier("==1.2.3", prereleases=True)) - True - >>> Specifier("==1.2.3") == "==1.2.3" - True - >>> Specifier("==1.2.3") == Specifier("==1.2.4") - False - >>> Specifier("==1.2.3") == Specifier("~=1.2.3") - False - """ - if isinstance(other, str): - try: - other = self.__class__(str(other)) - except InvalidSpecifier: - return NotImplemented - elif not isinstance(other, self.__class__): - return NotImplemented - - return self._canonical_spec == other._canonical_spec - - def _get_operator(self, op: str) -> CallableOperator: - operator_callable: CallableOperator = getattr( - self, f"_compare_{self._operators[op]}" - ) - return operator_callable - - def _compare_compatible(self, prospective: Version, spec: str) -> bool: - # Compatible releases have an equivalent combination of >= and ==. That - # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to - # implement this in terms of the other specifiers instead of - # implementing it ourselves. The only thing we need to do is construct - # the other specifiers. - - # We want everything but the last item in the version, but we want to - # ignore suffix segments. - prefix = _version_join( - list(itertools.takewhile(_is_not_suffix, _version_split(spec)))[:-1] - ) - - # Add the prefix notation to the end of our string - prefix += ".*" - - return self._get_operator(">=")(prospective, spec) and self._get_operator("==")( - prospective, prefix - ) - - def _compare_equal(self, prospective: Version, spec: str) -> bool: - # We need special logic to handle prefix matching - if spec.endswith(".*"): - # In the case of prefix matching we want to ignore local segment. - normalized_prospective = canonicalize_version( - _public_version(prospective), strip_trailing_zero=False - ) - # Get the normalized version string ignoring the trailing .* - normalized_spec = canonicalize_version(spec[:-2], strip_trailing_zero=False) - # Split the spec out by bangs and dots, and pretend that there is - # an implicit dot in between a release segment and a pre-release segment. - split_spec = _version_split(normalized_spec) - - # Split the prospective version out by bangs and dots, and pretend - # that there is an implicit dot in between a release segment and - # a pre-release segment. - split_prospective = _version_split(normalized_prospective) - - # 0-pad the prospective version before shortening it to get the correct - # shortened version. - padded_prospective, _ = _pad_version(split_prospective, split_spec) - - # Shorten the prospective version to be the same length as the spec - # so that we can determine if the specifier is a prefix of the - # prospective version or not. - shortened_prospective = padded_prospective[: len(split_spec)] - - return shortened_prospective == split_spec - else: - # Convert our spec string into a Version - spec_version = self._require_spec_version(spec) - - # If the specifier does not have a local segment, then we want to - # act as if the prospective version also does not have a local - # segment. - if not spec_version.local: - prospective = _public_version(prospective) - - return prospective == spec_version - - def _compare_not_equal(self, prospective: Version, spec: str) -> bool: - return not self._compare_equal(prospective, spec) - - def _compare_less_than_equal(self, prospective: Version, spec: str) -> bool: - # NB: Local version identifiers are NOT permitted in the version - # specifier, so local version labels can be universally removed from - # the prospective version. - return _public_version(prospective) <= self._require_spec_version(spec) - - def _compare_greater_than_equal(self, prospective: Version, spec: str) -> bool: - # NB: Local version identifiers are NOT permitted in the version - # specifier, so local version labels can be universally removed from - # the prospective version. - return _public_version(prospective) >= self._require_spec_version(spec) - - def _compare_less_than(self, prospective: Version, spec_str: str) -> bool: - # Convert our spec to a Version instance, since we'll want to work with - # it as a version. - spec = self._require_spec_version(spec_str) - - # Check to see if the prospective version is less than the spec - # version. If it's not we can short circuit and just return False now - # instead of doing extra unneeded work. - if not prospective < spec: - return False - - # This special case is here so that, unless the specifier itself - # includes is a pre-release version, that we do not accept pre-release - # versions for the version mentioned in the specifier (e.g. <3.1 should - # not match 3.1.dev0, but should match 3.0.dev0). - if ( - not spec.is_prerelease - and prospective.is_prerelease - and _base_version(prospective) == _base_version(spec) - ): - return False - - # If we've gotten to here, it means that prospective version is both - # less than the spec version *and* it's not a pre-release of the same - # version in the spec. - return True - - def _compare_greater_than(self, prospective: Version, spec_str: str) -> bool: - # Convert our spec to a Version instance, since we'll want to work with - # it as a version. - spec = self._require_spec_version(spec_str) - - # Check to see if the prospective version is greater than the spec - # version. If it's not we can short circuit and just return False now - # instead of doing extra unneeded work. - if not prospective > spec: - return False - - # This special case is here so that, unless the specifier itself - # includes is a post-release version, that we do not accept - # post-release versions for the version mentioned in the specifier - # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). - if ( - not spec.is_postrelease - and prospective.is_postrelease - and _base_version(prospective) == _base_version(spec) - ): - return False - - # Ensure that we do not allow a local version of the version mentioned - # in the specifier, which is technically greater than, to match. - if prospective.local is not None and _base_version( - prospective - ) == _base_version(spec): - return False - - # If we've gotten to here, it means that prospective version is both - # greater than the spec version *and* it's not a pre-release of the - # same version in the spec. - return True - - def _compare_arbitrary(self, prospective: Version | str, spec: str) -> bool: - return str(prospective).lower() == str(spec).lower() - - def __contains__(self, item: str | Version) -> bool: - """Return whether or not the item is contained in this specifier. - - :param item: The item to check for. - - This is used for the ``in`` operator and behaves the same as - :meth:`contains` with no ``prereleases`` argument passed. - - >>> "1.2.3" in Specifier(">=1.2.3") - True - >>> Version("1.2.3") in Specifier(">=1.2.3") - True - >>> "1.0.0" in Specifier(">=1.2.3") - False - >>> "1.3.0a1" in Specifier(">=1.2.3") - True - >>> "1.3.0a1" in Specifier(">=1.2.3", prereleases=True) - True - """ - return self.contains(item) - - def contains(self, item: UnparsedVersion, prereleases: bool | None = None) -> bool: - """Return whether or not the item is contained in this specifier. - - :param item: - The item to check for, which can be a version string or a - :class:`Version` instance. - :param prereleases: - Whether or not to match prereleases with this Specifier. If set to - ``None`` (the default), it will follow the recommendation from - :pep:`440` and match prereleases, as there are no other versions. - - >>> Specifier(">=1.2.3").contains("1.2.3") - True - >>> Specifier(">=1.2.3").contains(Version("1.2.3")) - True - >>> Specifier(">=1.2.3").contains("1.0.0") - False - >>> Specifier(">=1.2.3").contains("1.3.0a1") - True - >>> Specifier(">=1.2.3", prereleases=False).contains("1.3.0a1") - False - >>> Specifier(">=1.2.3").contains("1.3.0a1") - True - """ - - return bool(list(self.filter([item], prereleases=prereleases))) - - def filter( - self, iterable: Iterable[UnparsedVersionVar], prereleases: bool | None = None - ) -> Iterator[UnparsedVersionVar]: - """Filter items in the given iterable, that match the specifier. - - :param iterable: - An iterable that can contain version strings and :class:`Version` instances. - The items in the iterable will be filtered according to the specifier. - :param prereleases: - Whether or not to allow prereleases in the returned iterator. If set to - ``None`` (the default), it will follow the recommendation from :pep:`440` - and match prereleases if there are no other versions. - - >>> list(Specifier(">=1.2.3").filter(["1.2", "1.3", "1.5a1"])) - ['1.3'] - >>> list(Specifier(">=1.2.3").filter(["1.2", "1.2.3", "1.3", Version("1.4")])) - ['1.2.3', '1.3', ] - >>> list(Specifier(">=1.2.3").filter(["1.2", "1.5a1"])) - ['1.5a1'] - >>> list(Specifier(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True)) - ['1.3', '1.5a1'] - >>> list(Specifier(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"])) - ['1.3', '1.5a1'] - """ - prereleases_versions = [] - found_non_prereleases = False - - # Determine if to include prereleases by default - include_prereleases = ( - prereleases if prereleases is not None else self.prereleases - ) - - # Get the matching operator - operator_callable = self._get_operator(self.operator) - - # Filter versions - for version in iterable: - parsed_version = _coerce_version(version) - if parsed_version is None: - # === operator can match arbitrary (non-version) strings - if self.operator == "===" and self._compare_arbitrary( - version, self.version - ): - yield version - elif operator_callable(parsed_version, self.version): - # If it's not a prerelease or prereleases are allowed, yield it directly - if not parsed_version.is_prerelease or include_prereleases: - found_non_prereleases = True - yield version - # Otherwise collect prereleases for potential later use - elif prereleases is None and self._prereleases is not False: - prereleases_versions.append(version) - - # If no non-prereleases were found and prereleases weren't - # explicitly forbidden, yield the collected prereleases - if ( - not found_non_prereleases - and prereleases is None - and self._prereleases is not False - ): - yield from prereleases_versions - - -_prefix_regex = re.compile(r"([0-9]+)((?:a|b|c|rc)[0-9]+)") - - -def _version_split(version: str) -> list[str]: - """Split version into components. - - The split components are intended for version comparison. The logic does - not attempt to retain the original version string, so joining the - components back with :func:`_version_join` may not produce the original - version string. - """ - result: list[str] = [] - - epoch, _, rest = version.rpartition("!") - result.append(epoch or "0") - - for item in rest.split("."): - match = _prefix_regex.fullmatch(item) - if match: - result.extend(match.groups()) - else: - result.append(item) - return result - - -def _version_join(components: list[str]) -> str: - """Join split version components into a version string. - - This function assumes the input came from :func:`_version_split`, where the - first component must be the epoch (either empty or numeric), and all other - components numeric. - """ - epoch, *rest = components - return f"{epoch}!{'.'.join(rest)}" - - -def _is_not_suffix(segment: str) -> bool: - return not any( - segment.startswith(prefix) for prefix in ("dev", "a", "b", "rc", "post") - ) - - -def _pad_version(left: list[str], right: list[str]) -> tuple[list[str], list[str]]: - left_split, right_split = [], [] - - # Get the release segment of our versions - left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) - right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) - - # Get the rest of our versions - left_split.append(left[len(left_split[0]) :]) - right_split.append(right[len(right_split[0]) :]) - - # Insert our padding - left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0]))) - right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0]))) - - return ( - list(itertools.chain.from_iterable(left_split)), - list(itertools.chain.from_iterable(right_split)), - ) - - -class SpecifierSet(BaseSpecifier): - """This class abstracts handling of a set of version specifiers. - - It can be passed a single specifier (``>=3.0``), a comma-separated list of - specifiers (``>=3.0,!=3.1``), or no specifier at all. - """ - - __slots__ = ("_prereleases", "_specs") - - def __init__( - self, - specifiers: str | Iterable[Specifier] = "", - prereleases: bool | None = None, - ) -> None: - """Initialize a SpecifierSet instance. - - :param specifiers: - The string representation of a specifier or a comma-separated list of - specifiers which will be parsed and normalized before use. - May also be an iterable of ``Specifier`` instances, which will be used - as is. - :param prereleases: - This tells the SpecifierSet if it should accept prerelease versions if - applicable or not. The default of ``None`` will autodetect it from the - given specifiers. - - :raises InvalidSpecifier: - If the given ``specifiers`` are not parseable than this exception will be - raised. - """ - - if isinstance(specifiers, str): - # Split on `,` to break each individual specifier into its own item, and - # strip each item to remove leading/trailing whitespace. - split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] - - # Make each individual specifier a Specifier and save in a frozen set - # for later. - self._specs = frozenset(map(Specifier, split_specifiers)) - else: - # Save the supplied specifiers in a frozen set. - self._specs = frozenset(specifiers) - - # Store our prereleases value so we can use it later to determine if - # we accept prereleases or not. - self._prereleases = prereleases - - @property - def prereleases(self) -> bool | None: - # If we have been given an explicit prerelease modifier, then we'll - # pass that through here. - if self._prereleases is not None: - return self._prereleases - - # If we don't have any specifiers, and we don't have a forced value, - # then we'll just return None since we don't know if this should have - # pre-releases or not. - if not self._specs: - return None - - # Otherwise we'll see if any of the given specifiers accept - # prereleases, if any of them do we'll return True, otherwise False. - if any(s.prereleases for s in self._specs): - return True - - return None - - @prereleases.setter - def prereleases(self, value: bool | None) -> None: - self._prereleases = value - - def __repr__(self) -> str: - """A representation of the specifier set that shows all internal state. - - Note that the ordering of the individual specifiers within the set may not - match the input string. - - >>> SpecifierSet('>=1.0.0,!=2.0.0') - =1.0.0')> - >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=False) - =1.0.0', prereleases=False)> - >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=True) - =1.0.0', prereleases=True)> - """ - pre = ( - f", prereleases={self.prereleases!r}" - if self._prereleases is not None - else "" - ) - - return f"" - - def __str__(self) -> str: - """A string representation of the specifier set that can be round-tripped. - - Note that the ordering of the individual specifiers within the set may not - match the input string. - - >>> str(SpecifierSet(">=1.0.0,!=1.0.1")) - '!=1.0.1,>=1.0.0' - >>> str(SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False)) - '!=1.0.1,>=1.0.0' - """ - return ",".join(sorted(str(s) for s in self._specs)) - - def __hash__(self) -> int: - return hash(self._specs) - - def __and__(self, other: SpecifierSet | str) -> SpecifierSet: - """Return a SpecifierSet which is a combination of the two sets. - - :param other: The other object to combine with. - - >>> SpecifierSet(">=1.0.0,!=1.0.1") & '<=2.0.0,!=2.0.1' - =1.0.0')> - >>> SpecifierSet(">=1.0.0,!=1.0.1") & SpecifierSet('<=2.0.0,!=2.0.1') - =1.0.0')> - """ - if isinstance(other, str): - other = SpecifierSet(other) - elif not isinstance(other, SpecifierSet): - return NotImplemented - - specifier = SpecifierSet() - specifier._specs = frozenset(self._specs | other._specs) - - if self._prereleases is None and other._prereleases is not None: - specifier._prereleases = other._prereleases - elif ( - self._prereleases is not None and other._prereleases is None - ) or self._prereleases == other._prereleases: - specifier._prereleases = self._prereleases - else: - raise ValueError( - "Cannot combine SpecifierSets with True and False prerelease overrides." - ) - - return specifier - - def __eq__(self, other: object) -> bool: - """Whether or not the two SpecifierSet-like objects are equal. - - :param other: The other object to check against. - - The value of :attr:`prereleases` is ignored. - - >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.1") - True - >>> (SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False) == - ... SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True)) - True - >>> SpecifierSet(">=1.0.0,!=1.0.1") == ">=1.0.0,!=1.0.1" - True - >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0") - False - >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.2") - False - """ - if isinstance(other, (str, Specifier)): - other = SpecifierSet(str(other)) - elif not isinstance(other, SpecifierSet): - return NotImplemented - - return self._specs == other._specs - - def __len__(self) -> int: - """Returns the number of specifiers in this specifier set.""" - return len(self._specs) - - def __iter__(self) -> Iterator[Specifier]: - """ - Returns an iterator over all the underlying :class:`Specifier` instances - in this specifier set. - - >>> sorted(SpecifierSet(">=1.0.0,!=1.0.1"), key=str) - [, =1.0.0')>] - """ - return iter(self._specs) - - def __contains__(self, item: UnparsedVersion) -> bool: - """Return whether or not the item is contained in this specifier. - - :param item: The item to check for. - - This is used for the ``in`` operator and behaves the same as - :meth:`contains` with no ``prereleases`` argument passed. - - >>> "1.2.3" in SpecifierSet(">=1.0.0,!=1.0.1") - True - >>> Version("1.2.3") in SpecifierSet(">=1.0.0,!=1.0.1") - True - >>> "1.0.1" in SpecifierSet(">=1.0.0,!=1.0.1") - False - >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1") - True - >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True) - True - """ - return self.contains(item) - - def contains( - self, - item: UnparsedVersion, - prereleases: bool | None = None, - installed: bool | None = None, - ) -> bool: - """Return whether or not the item is contained in this SpecifierSet. - - :param item: - The item to check for, which can be a version string or a - :class:`Version` instance. - :param prereleases: - Whether or not to match prereleases with this SpecifierSet. If set to - ``None`` (the default), it will follow the recommendation from :pep:`440` - and match prereleases, as there are no other versions. - :param installed: - Whether or not the item is installed. If set to ``True``, it will - accept prerelease versions even if the specifier does not allow them. - - >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.2.3") - True - >>> SpecifierSet(">=1.0.0,!=1.0.1").contains(Version("1.2.3")) - True - >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.0.1") - False - >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1") - True - >>> SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False).contains("1.3.0a1") - False - >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1", prereleases=True) - True - """ - version = _coerce_version(item) - - if version is not None and installed and version.is_prerelease: - prereleases = True - - check_item = item if version is None else version - return bool(list(self.filter([check_item], prereleases=prereleases))) - - def filter( - self, iterable: Iterable[UnparsedVersionVar], prereleases: bool | None = None - ) -> Iterator[UnparsedVersionVar]: - """Filter items in the given iterable, that match the specifiers in this set. - - :param iterable: - An iterable that can contain version strings and :class:`Version` instances. - The items in the iterable will be filtered according to the specifier. - :param prereleases: - Whether or not to allow prereleases in the returned iterator. If set to - ``None`` (the default), it will follow the recommendation from :pep:`440` - and match prereleases if there are no other versions. - - >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", "1.5a1"])) - ['1.3'] - >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", Version("1.4")])) - ['1.3', ] - >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.5a1"])) - ['1.5a1'] - >>> list(SpecifierSet(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True)) - ['1.3', '1.5a1'] - >>> list(SpecifierSet(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"])) - ['1.3', '1.5a1'] - - An "empty" SpecifierSet will filter items based on the presence of prerelease - versions in the set. - - >>> list(SpecifierSet("").filter(["1.3", "1.5a1"])) - ['1.3'] - >>> list(SpecifierSet("").filter(["1.5a1"])) - ['1.5a1'] - >>> list(SpecifierSet("", prereleases=True).filter(["1.3", "1.5a1"])) - ['1.3', '1.5a1'] - >>> list(SpecifierSet("").filter(["1.3", "1.5a1"], prereleases=True)) - ['1.3', '1.5a1'] - """ - # Determine if we're forcing a prerelease or not, if we're not forcing - # one for this particular filter call, then we'll use whatever the - # SpecifierSet thinks for whether or not we should support prereleases. - if prereleases is None and self.prereleases is not None: - prereleases = self.prereleases - - # If we have any specifiers, then we want to wrap our iterable in the - # filter method for each one, this will act as a logical AND amongst - # each specifier. - if self._specs: - # When prereleases is None, we need to let all versions through - # the individual filters, then decide about prereleases at the end - # based on whether any non-prereleases matched ALL specs. - for spec in self._specs: - iterable = spec.filter( - iterable, prereleases=True if prereleases is None else prereleases - ) - - if prereleases is not None: - # If we have a forced prereleases value, - # we can immediately return the iterator. - return iter(iterable) - else: - # Handle empty SpecifierSet cases where prereleases is not None. - if prereleases is True: - return iter(iterable) - - if prereleases is False: - return ( - item - for item in iterable - if (version := _coerce_version(item)) is None - or not version.is_prerelease - ) - - # Finally if prereleases is None, apply PEP 440 logic: - # exclude prereleases unless there are no final releases that matched. - filtered_items: list[UnparsedVersionVar] = [] - found_prereleases: list[UnparsedVersionVar] = [] - found_final_release = False - - for item in iterable: - parsed_version = _coerce_version(item) - # Arbitrary strings are always included as it is not - # possible to determine if they are prereleases, - # and they have already passed all specifiers. - if parsed_version is None: - filtered_items.append(item) - found_prereleases.append(item) - elif parsed_version.is_prerelease: - found_prereleases.append(item) - else: - filtered_items.append(item) - found_final_release = True - - return iter(filtered_items if found_final_release else found_prereleases) diff --git a/apps/bitwarden_event_logs/lib/packaging/tags.py b/apps/bitwarden_event_logs/lib/packaging/tags.py deleted file mode 100755 index 5ef27c89..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/tags.py +++ /dev/null @@ -1,651 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import logging -import platform -import re -import struct -import subprocess -import sys -import sysconfig -from importlib.machinery import EXTENSION_SUFFIXES -from typing import ( - Any, - Iterable, - Iterator, - Sequence, - Tuple, - cast, -) - -from . import _manylinux, _musllinux - -logger = logging.getLogger(__name__) - -PythonVersion = Sequence[int] -AppleVersion = Tuple[int, int] - -INTERPRETER_SHORT_NAMES: dict[str, str] = { - "python": "py", # Generic. - "cpython": "cp", - "pypy": "pp", - "ironpython": "ip", - "jython": "jy", -} - - -_32_BIT_INTERPRETER = struct.calcsize("P") == 4 - - -class Tag: - """ - A representation of the tag triple for a wheel. - - Instances are considered immutable and thus are hashable. Equality checking - is also supported. - """ - - __slots__ = ["_abi", "_hash", "_interpreter", "_platform"] - - def __init__(self, interpreter: str, abi: str, platform: str) -> None: - self._interpreter = interpreter.lower() - self._abi = abi.lower() - self._platform = platform.lower() - # The __hash__ of every single element in a Set[Tag] will be evaluated each time - # that a set calls its `.disjoint()` method, which may be called hundreds of - # times when scanning a page of links for packages with tags matching that - # Set[Tag]. Pre-computing the value here produces significant speedups for - # downstream consumers. - self._hash = hash((self._interpreter, self._abi, self._platform)) - - @property - def interpreter(self) -> str: - return self._interpreter - - @property - def abi(self) -> str: - return self._abi - - @property - def platform(self) -> str: - return self._platform - - def __eq__(self, other: object) -> bool: - if not isinstance(other, Tag): - return NotImplemented - - return ( - (self._hash == other._hash) # Short-circuit ASAP for perf reasons. - and (self._platform == other._platform) - and (self._abi == other._abi) - and (self._interpreter == other._interpreter) - ) - - def __hash__(self) -> int: - return self._hash - - def __str__(self) -> str: - return f"{self._interpreter}-{self._abi}-{self._platform}" - - def __repr__(self) -> str: - return f"<{self} @ {id(self)}>" - - def __setstate__(self, state: tuple[None, dict[str, Any]]) -> None: - # The cached _hash is wrong when unpickling. - _, slots = state - for k, v in slots.items(): - setattr(self, k, v) - self._hash = hash((self._interpreter, self._abi, self._platform)) - - -def parse_tag(tag: str) -> frozenset[Tag]: - """ - Parses the provided tag (e.g. `py3-none-any`) into a frozenset of Tag instances. - - Returning a set is required due to the possibility that the tag is a - compressed tag set. - """ - tags = set() - interpreters, abis, platforms = tag.split("-") - for interpreter in interpreters.split("."): - for abi in abis.split("."): - for platform_ in platforms.split("."): - tags.add(Tag(interpreter, abi, platform_)) - return frozenset(tags) - - -def _get_config_var(name: str, warn: bool = False) -> int | str | None: - value: int | str | None = sysconfig.get_config_var(name) - if value is None and warn: - logger.debug( - "Config variable '%s' is unset, Python ABI tag may be incorrect", name - ) - return value - - -def _normalize_string(string: str) -> str: - return string.replace(".", "_").replace("-", "_").replace(" ", "_") - - -def _is_threaded_cpython(abis: list[str]) -> bool: - """ - Determine if the ABI corresponds to a threaded (`--disable-gil`) build. - - The threaded builds are indicated by a "t" in the abiflags. - """ - if len(abis) == 0: - return False - # expect e.g., cp313 - m = re.match(r"cp\d+(.*)", abis[0]) - if not m: - return False - abiflags = m.group(1) - return "t" in abiflags - - -def _abi3_applies(python_version: PythonVersion, threading: bool) -> bool: - """ - Determine if the Python version supports abi3. - - PEP 384 was first implemented in Python 3.2. The threaded (`--disable-gil`) - builds do not support abi3. - """ - return len(python_version) > 1 and tuple(python_version) >= (3, 2) and not threading - - -def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> list[str]: - py_version = tuple(py_version) # To allow for version comparison. - abis = [] - version = _version_nodot(py_version[:2]) - threading = debug = pymalloc = ucs4 = "" - with_debug = _get_config_var("Py_DEBUG", warn) - has_refcount = hasattr(sys, "gettotalrefcount") - # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled - # extension modules is the best option. - # https://github.com/pypa/pip/issues/3383#issuecomment-173267692 - has_ext = "_d.pyd" in EXTENSION_SUFFIXES - if with_debug or (with_debug is None and (has_refcount or has_ext)): - debug = "d" - if py_version >= (3, 13) and _get_config_var("Py_GIL_DISABLED", warn): - threading = "t" - if py_version < (3, 8): - with_pymalloc = _get_config_var("WITH_PYMALLOC", warn) - if with_pymalloc or with_pymalloc is None: - pymalloc = "m" - if py_version < (3, 3): - unicode_size = _get_config_var("Py_UNICODE_SIZE", warn) - if unicode_size == 4 or ( - unicode_size is None and sys.maxunicode == 0x10FFFF - ): - ucs4 = "u" - elif debug: - # Debug builds can also load "normal" extension modules. - # We can also assume no UCS-4 or pymalloc requirement. - abis.append(f"cp{version}{threading}") - abis.insert(0, f"cp{version}{threading}{debug}{pymalloc}{ucs4}") - return abis - - -def cpython_tags( - python_version: PythonVersion | None = None, - abis: Iterable[str] | None = None, - platforms: Iterable[str] | None = None, - *, - warn: bool = False, -) -> Iterator[Tag]: - """ - Yields the tags for a CPython interpreter. - - The tags consist of: - - cp-- - - cp-abi3- - - cp-none- - - cp-abi3- # Older Python versions down to 3.2. - - If python_version only specifies a major version then user-provided ABIs and - the 'none' ABItag will be used. - - If 'abi3' or 'none' are specified in 'abis' then they will be yielded at - their normal position and not at the beginning. - """ - if not python_version: - python_version = sys.version_info[:2] - - interpreter = f"cp{_version_nodot(python_version[:2])}" - - if abis is None: - abis = _cpython_abis(python_version, warn) if len(python_version) > 1 else [] - abis = list(abis) - # 'abi3' and 'none' are explicitly handled later. - for explicit_abi in ("abi3", "none"): - try: - abis.remove(explicit_abi) - except ValueError: # noqa: PERF203 - pass - - platforms = list(platforms or platform_tags()) - for abi in abis: - for platform_ in platforms: - yield Tag(interpreter, abi, platform_) - - threading = _is_threaded_cpython(abis) - use_abi3 = _abi3_applies(python_version, threading) - if use_abi3: - yield from (Tag(interpreter, "abi3", platform_) for platform_ in platforms) - yield from (Tag(interpreter, "none", platform_) for platform_ in platforms) - - if use_abi3: - for minor_version in range(python_version[1] - 1, 1, -1): - for platform_ in platforms: - version = _version_nodot((python_version[0], minor_version)) - interpreter = f"cp{version}" - yield Tag(interpreter, "abi3", platform_) - - -def _generic_abi() -> list[str]: - """ - Return the ABI tag based on EXT_SUFFIX. - """ - # The following are examples of `EXT_SUFFIX`. - # We want to keep the parts which are related to the ABI and remove the - # parts which are related to the platform: - # - linux: '.cpython-310-x86_64-linux-gnu.so' => cp310 - # - mac: '.cpython-310-darwin.so' => cp310 - # - win: '.cp310-win_amd64.pyd' => cp310 - # - win: '.pyd' => cp37 (uses _cpython_abis()) - # - pypy: '.pypy38-pp73-x86_64-linux-gnu.so' => pypy38_pp73 - # - graalpy: '.graalpy-38-native-x86_64-darwin.dylib' - # => graalpy_38_native - - ext_suffix = _get_config_var("EXT_SUFFIX", warn=True) - if not isinstance(ext_suffix, str) or ext_suffix[0] != ".": - raise SystemError("invalid sysconfig.get_config_var('EXT_SUFFIX')") - parts = ext_suffix.split(".") - if len(parts) < 3: - # CPython3.7 and earlier uses ".pyd" on Windows. - return _cpython_abis(sys.version_info[:2]) - soabi = parts[1] - if soabi.startswith("cpython"): - # non-windows - abi = "cp" + soabi.split("-")[1] - elif soabi.startswith("cp"): - # windows - abi = soabi.split("-")[0] - elif soabi.startswith("pypy"): - abi = "-".join(soabi.split("-")[:2]) - elif soabi.startswith("graalpy"): - abi = "-".join(soabi.split("-")[:3]) - elif soabi: - # pyston, ironpython, others? - abi = soabi - else: - return [] - return [_normalize_string(abi)] - - -def generic_tags( - interpreter: str | None = None, - abis: Iterable[str] | None = None, - platforms: Iterable[str] | None = None, - *, - warn: bool = False, -) -> Iterator[Tag]: - """ - Yields the tags for a generic interpreter. - - The tags consist of: - - -- - - The "none" ABI will be added if it was not explicitly provided. - """ - if not interpreter: - interp_name = interpreter_name() - interp_version = interpreter_version(warn=warn) - interpreter = f"{interp_name}{interp_version}" - abis = _generic_abi() if abis is None else list(abis) - platforms = list(platforms or platform_tags()) - if "none" not in abis: - abis.append("none") - for abi in abis: - for platform_ in platforms: - yield Tag(interpreter, abi, platform_) - - -def _py_interpreter_range(py_version: PythonVersion) -> Iterator[str]: - """ - Yields Python versions in descending order. - - After the latest version, the major-only version will be yielded, and then - all previous versions of that major version. - """ - if len(py_version) > 1: - yield f"py{_version_nodot(py_version[:2])}" - yield f"py{py_version[0]}" - if len(py_version) > 1: - for minor in range(py_version[1] - 1, -1, -1): - yield f"py{_version_nodot((py_version[0], minor))}" - - -def compatible_tags( - python_version: PythonVersion | None = None, - interpreter: str | None = None, - platforms: Iterable[str] | None = None, -) -> Iterator[Tag]: - """ - Yields the sequence of tags that are compatible with a specific version of Python. - - The tags consist of: - - py*-none- - - -none-any # ... if `interpreter` is provided. - - py*-none-any - """ - if not python_version: - python_version = sys.version_info[:2] - platforms = list(platforms or platform_tags()) - for version in _py_interpreter_range(python_version): - for platform_ in platforms: - yield Tag(version, "none", platform_) - if interpreter: - yield Tag(interpreter, "none", "any") - for version in _py_interpreter_range(python_version): - yield Tag(version, "none", "any") - - -def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str: - if not is_32bit: - return arch - - if arch.startswith("ppc"): - return "ppc" - - return "i386" - - -def _mac_binary_formats(version: AppleVersion, cpu_arch: str) -> list[str]: - formats = [cpu_arch] - if cpu_arch == "x86_64": - if version < (10, 4): - return [] - formats.extend(["intel", "fat64", "fat32"]) - - elif cpu_arch == "i386": - if version < (10, 4): - return [] - formats.extend(["intel", "fat32", "fat"]) - - elif cpu_arch == "ppc64": - # TODO: Need to care about 32-bit PPC for ppc64 through 10.2? - if version > (10, 5) or version < (10, 4): - return [] - formats.append("fat64") - - elif cpu_arch == "ppc": - if version > (10, 6): - return [] - formats.extend(["fat32", "fat"]) - - if cpu_arch in {"arm64", "x86_64"}: - formats.append("universal2") - - if cpu_arch in {"x86_64", "i386", "ppc64", "ppc", "intel"}: - formats.append("universal") - - return formats - - -def mac_platforms( - version: AppleVersion | None = None, arch: str | None = None -) -> Iterator[str]: - """ - Yields the platform tags for a macOS system. - - The `version` parameter is a two-item tuple specifying the macOS version to - generate platform tags for. The `arch` parameter is the CPU architecture to - generate platform tags for. Both parameters default to the appropriate value - for the current system. - """ - version_str, _, cpu_arch = platform.mac_ver() - if version is None: - version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2]))) - if version == (10, 16): - # When built against an older macOS SDK, Python will report macOS 10.16 - # instead of the real version. - version_str = subprocess.run( - [ - sys.executable, - "-sS", - "-c", - "import platform; print(platform.mac_ver()[0])", - ], - check=True, - env={"SYSTEM_VERSION_COMPAT": "0"}, - stdout=subprocess.PIPE, - text=True, - ).stdout - version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2]))) - - if arch is None: - arch = _mac_arch(cpu_arch) - - if (10, 0) <= version < (11, 0): - # Prior to Mac OS 11, each yearly release of Mac OS bumped the - # "minor" version number. The major version was always 10. - major_version = 10 - for minor_version in range(version[1], -1, -1): - compat_version = major_version, minor_version - binary_formats = _mac_binary_formats(compat_version, arch) - for binary_format in binary_formats: - yield f"macosx_{major_version}_{minor_version}_{binary_format}" - - if version >= (11, 0): - # Starting with Mac OS 11, each yearly release bumps the major version - # number. The minor versions are now the midyear updates. - minor_version = 0 - for major_version in range(version[0], 10, -1): - compat_version = major_version, minor_version - binary_formats = _mac_binary_formats(compat_version, arch) - for binary_format in binary_formats: - yield f"macosx_{major_version}_{minor_version}_{binary_format}" - - if version >= (11, 0): - # Mac OS 11 on x86_64 is compatible with binaries from previous releases. - # Arm64 support was introduced in 11.0, so no Arm binaries from previous - # releases exist. - # - # However, the "universal2" binary format can have a - # macOS version earlier than 11.0 when the x86_64 part of the binary supports - # that version of macOS. - major_version = 10 - if arch == "x86_64": - for minor_version in range(16, 3, -1): - compat_version = major_version, minor_version - binary_formats = _mac_binary_formats(compat_version, arch) - for binary_format in binary_formats: - yield f"macosx_{major_version}_{minor_version}_{binary_format}" - else: - for minor_version in range(16, 3, -1): - compat_version = major_version, minor_version - binary_format = "universal2" - yield f"macosx_{major_version}_{minor_version}_{binary_format}" - - -def ios_platforms( - version: AppleVersion | None = None, multiarch: str | None = None -) -> Iterator[str]: - """ - Yields the platform tags for an iOS system. - - :param version: A two-item tuple specifying the iOS version to generate - platform tags for. Defaults to the current iOS version. - :param multiarch: The CPU architecture+ABI to generate platform tags for - - (the value used by `sys.implementation._multiarch` e.g., - `arm64_iphoneos` or `x84_64_iphonesimulator`). Defaults to the current - multiarch value. - """ - if version is None: - # if iOS is the current platform, ios_ver *must* be defined. However, - # it won't exist for CPython versions before 3.13, which causes a mypy - # error. - _, release, _, _ = platform.ios_ver() # type: ignore[attr-defined, unused-ignore] - version = cast("AppleVersion", tuple(map(int, release.split(".")[:2]))) - - if multiarch is None: - multiarch = sys.implementation._multiarch - multiarch = multiarch.replace("-", "_") - - ios_platform_template = "ios_{major}_{minor}_{multiarch}" - - # Consider any iOS major.minor version from the version requested, down to - # 12.0. 12.0 is the first iOS version that is known to have enough features - # to support CPython. Consider every possible minor release up to X.9. There - # highest the minor has ever gone is 8 (14.8 and 15.8) but having some extra - # candidates that won't ever match doesn't really hurt, and it saves us from - # having to keep an explicit list of known iOS versions in the code. Return - # the results descending order of version number. - - # If the requested major version is less than 12, there won't be any matches. - if version[0] < 12: - return - - # Consider the actual X.Y version that was requested. - yield ios_platform_template.format( - major=version[0], minor=version[1], multiarch=multiarch - ) - - # Consider every minor version from X.0 to the minor version prior to the - # version requested by the platform. - for minor in range(version[1] - 1, -1, -1): - yield ios_platform_template.format( - major=version[0], minor=minor, multiarch=multiarch - ) - - for major in range(version[0] - 1, 11, -1): - for minor in range(9, -1, -1): - yield ios_platform_template.format( - major=major, minor=minor, multiarch=multiarch - ) - - -def android_platforms( - api_level: int | None = None, abi: str | None = None -) -> Iterator[str]: - """ - Yields the :attr:`~Tag.platform` tags for Android. If this function is invoked on - non-Android platforms, the ``api_level`` and ``abi`` arguments are required. - - :param int api_level: The maximum `API level - `__ to return. Defaults - to the current system's version, as returned by ``platform.android_ver``. - :param str abi: The `Android ABI `__, - e.g. ``arm64_v8a``. Defaults to the current system's ABI , as returned by - ``sysconfig.get_platform``. Hyphens and periods will be replaced with - underscores. - """ - if platform.system() != "Android" and (api_level is None or abi is None): - raise TypeError( - "on non-Android platforms, the api_level and abi arguments are required" - ) - - if api_level is None: - # Python 3.13 was the first version to return platform.system() == "Android", - # and also the first version to define platform.android_ver(). - api_level = platform.android_ver().api_level # type: ignore[attr-defined] - - if abi is None: - abi = sysconfig.get_platform().split("-")[-1] - abi = _normalize_string(abi) - - # 16 is the minimum API level known to have enough features to support CPython - # without major patching. Yield every API level from the maximum down to the - # minimum, inclusive. - min_api_level = 16 - for ver in range(api_level, min_api_level - 1, -1): - yield f"android_{ver}_{abi}" - - -def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]: - linux = _normalize_string(sysconfig.get_platform()) - if not linux.startswith("linux_"): - # we should never be here, just yield the sysconfig one and return - yield linux - return - if is_32bit: - if linux == "linux_x86_64": - linux = "linux_i686" - elif linux == "linux_aarch64": - linux = "linux_armv8l" - _, arch = linux.split("_", 1) - archs = {"armv8l": ["armv8l", "armv7l"]}.get(arch, [arch]) - yield from _manylinux.platform_tags(archs) - yield from _musllinux.platform_tags(archs) - for arch in archs: - yield f"linux_{arch}" - - -def _generic_platforms() -> Iterator[str]: - yield _normalize_string(sysconfig.get_platform()) - - -def platform_tags() -> Iterator[str]: - """ - Provides the platform tags for this installation. - """ - if platform.system() == "Darwin": - return mac_platforms() - elif platform.system() == "iOS": - return ios_platforms() - elif platform.system() == "Android": - return android_platforms() - elif platform.system() == "Linux": - return _linux_platforms() - else: - return _generic_platforms() - - -def interpreter_name() -> str: - """ - Returns the name of the running interpreter. - - Some implementations have a reserved, two-letter abbreviation which will - be returned when appropriate. - """ - name = sys.implementation.name - return INTERPRETER_SHORT_NAMES.get(name) or name - - -def interpreter_version(*, warn: bool = False) -> str: - """ - Returns the version of the running interpreter. - """ - version = _get_config_var("py_version_nodot", warn=warn) - return str(version) if version else _version_nodot(sys.version_info[:2]) - - -def _version_nodot(version: PythonVersion) -> str: - return "".join(map(str, version)) - - -def sys_tags(*, warn: bool = False) -> Iterator[Tag]: - """ - Returns the sequence of tag triples for the running interpreter. - - The order of the sequence corresponds to priority order for the - interpreter, from most to least important. - """ - - interp_name = interpreter_name() - if interp_name == "cp": - yield from cpython_tags(warn=warn) - else: - yield from generic_tags() - - if interp_name == "pp": - interp = "pp3" - elif interp_name == "cp": - interp = "cp" + interpreter_version(warn=warn) - else: - interp = None - yield from compatible_tags(interpreter=interp) diff --git a/apps/bitwarden_event_logs/lib/packaging/utils.py b/apps/bitwarden_event_logs/lib/packaging/utils.py deleted file mode 100755 index c41c8137..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/utils.py +++ /dev/null @@ -1,158 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import re -from typing import NewType, Tuple, Union, cast - -from .tags import Tag, parse_tag -from .version import InvalidVersion, Version, _TrimmedRelease - -BuildTag = Union[Tuple[()], Tuple[int, str]] -NormalizedName = NewType("NormalizedName", str) - - -class InvalidName(ValueError): - """ - An invalid distribution name; users should refer to the packaging user guide. - """ - - -class InvalidWheelFilename(ValueError): - """ - An invalid wheel filename was found, users should refer to PEP 427. - """ - - -class InvalidSdistFilename(ValueError): - """ - An invalid sdist filename was found, users should refer to the packaging user guide. - """ - - -# Core metadata spec for `Name` -_validate_regex = re.compile(r"[A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9]", re.IGNORECASE) -_normalized_regex = re.compile(r"[a-z0-9]|[a-z0-9]([a-z0-9-](?!--))*[a-z0-9]") -# PEP 427: The build number must start with a digit. -_build_tag_regex = re.compile(r"(\d+)(.*)") - - -def canonicalize_name(name: str, *, validate: bool = False) -> NormalizedName: - if validate and not _validate_regex.fullmatch(name): - raise InvalidName(f"name is invalid: {name!r}") - # Ensure all ``.`` and ``_`` are ``-`` - # Emulates ``re.sub(r"[-_.]+", "-", name).lower()`` from PEP 503 - # Much faster than re, and even faster than str.translate - value = name.lower().replace("_", "-").replace(".", "-") - # Condense repeats (faster than regex) - while "--" in value: - value = value.replace("--", "-") - return cast("NormalizedName", value) - - -def is_normalized_name(name: str) -> bool: - return _normalized_regex.fullmatch(name) is not None - - -def canonicalize_version( - version: Version | str, *, strip_trailing_zero: bool = True -) -> str: - """ - Return a canonical form of a version as a string. - - >>> canonicalize_version('1.0.1') - '1.0.1' - - Per PEP 625, versions may have multiple canonical forms, differing - only by trailing zeros. - - >>> canonicalize_version('1.0.0') - '1' - >>> canonicalize_version('1.0.0', strip_trailing_zero=False) - '1.0.0' - - Invalid versions are returned unaltered. - - >>> canonicalize_version('foo bar baz') - 'foo bar baz' - """ - if isinstance(version, str): - try: - version = Version(version) - except InvalidVersion: - return str(version) - return str(_TrimmedRelease(version) if strip_trailing_zero else version) - - -def parse_wheel_filename( - filename: str, -) -> tuple[NormalizedName, Version, BuildTag, frozenset[Tag]]: - if not filename.endswith(".whl"): - raise InvalidWheelFilename( - f"Invalid wheel filename (extension must be '.whl'): {filename!r}" - ) - - filename = filename[:-4] - dashes = filename.count("-") - if dashes not in (4, 5): - raise InvalidWheelFilename( - f"Invalid wheel filename (wrong number of parts): {filename!r}" - ) - - parts = filename.split("-", dashes - 2) - name_part = parts[0] - # See PEP 427 for the rules on escaping the project name. - if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None: - raise InvalidWheelFilename(f"Invalid project name: {filename!r}") - name = canonicalize_name(name_part) - - try: - version = Version(parts[1]) - except InvalidVersion as e: - raise InvalidWheelFilename( - f"Invalid wheel filename (invalid version): {filename!r}" - ) from e - - if dashes == 5: - build_part = parts[2] - build_match = _build_tag_regex.match(build_part) - if build_match is None: - raise InvalidWheelFilename( - f"Invalid build number: {build_part} in {filename!r}" - ) - build = cast("BuildTag", (int(build_match.group(1)), build_match.group(2))) - else: - build = () - tags = parse_tag(parts[-1]) - return (name, version, build, tags) - - -def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]: - if filename.endswith(".tar.gz"): - file_stem = filename[: -len(".tar.gz")] - elif filename.endswith(".zip"): - file_stem = filename[: -len(".zip")] - else: - raise InvalidSdistFilename( - f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):" - f" {filename!r}" - ) - - # We are requiring a PEP 440 version, which cannot contain dashes, - # so we split on the last dash. - name_part, sep, version_part = file_stem.rpartition("-") - if not sep: - raise InvalidSdistFilename(f"Invalid sdist filename: {filename!r}") - - name = canonicalize_name(name_part) - - try: - version = Version(version_part) - except InvalidVersion as e: - raise InvalidSdistFilename( - f"Invalid sdist filename (invalid version): {filename!r}" - ) from e - - return (name, version) diff --git a/apps/bitwarden_event_logs/lib/packaging/version.py b/apps/bitwarden_event_logs/lib/packaging/version.py deleted file mode 100755 index 1206c462..00000000 --- a/apps/bitwarden_event_logs/lib/packaging/version.py +++ /dev/null @@ -1,792 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. -""" -.. testsetup:: - - from packaging.version import parse, Version -""" - -from __future__ import annotations - -import re -import sys -import typing -from typing import ( - Any, - Callable, - Literal, - NamedTuple, - SupportsInt, - Tuple, - TypedDict, - Union, -) - -from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType - -if typing.TYPE_CHECKING: - from typing_extensions import Self, Unpack - -if sys.version_info >= (3, 13): # pragma: no cover - from warnings import deprecated as _deprecated -elif typing.TYPE_CHECKING: - from typing_extensions import deprecated as _deprecated -else: # pragma: no cover - import functools - import warnings - - def _deprecated(message: str) -> object: - def decorator(func: object) -> object: - @functools.wraps(func) - def wrapper(*args: object, **kwargs: object) -> object: - warnings.warn( - message, - category=DeprecationWarning, - stacklevel=2, - ) - return func(*args, **kwargs) - - return wrapper - - return decorator - - -_LETTER_NORMALIZATION = { - "alpha": "a", - "beta": "b", - "c": "rc", - "pre": "rc", - "preview": "rc", - "rev": "post", - "r": "post", -} - -__all__ = ["VERSION_PATTERN", "InvalidVersion", "Version", "parse"] - -LocalType = Tuple[Union[int, str], ...] - -CmpPrePostDevType = Union[InfinityType, NegativeInfinityType, Tuple[str, int]] -CmpLocalType = Union[ - NegativeInfinityType, - Tuple[Union[Tuple[int, str], Tuple[NegativeInfinityType, Union[int, str]]], ...], -] -CmpKey = Tuple[ - int, - Tuple[int, ...], - CmpPrePostDevType, - CmpPrePostDevType, - CmpPrePostDevType, - CmpLocalType, -] -VersionComparisonMethod = Callable[[CmpKey, CmpKey], bool] - - -class _VersionReplace(TypedDict, total=False): - epoch: int | None - release: tuple[int, ...] | None - pre: tuple[Literal["a", "b", "rc"], int] | None - post: int | None - dev: int | None - local: str | None - - -def parse(version: str) -> Version: - """Parse the given version string. - - >>> parse('1.0.dev1') - - - :param version: The version string to parse. - :raises InvalidVersion: When the version string is not a valid version. - """ - return Version(version) - - -class InvalidVersion(ValueError): - """Raised when a version string is not a valid version. - - >>> Version("invalid") - Traceback (most recent call last): - ... - packaging.version.InvalidVersion: Invalid version: 'invalid' - """ - - -class _BaseVersion: - __slots__ = () - - # This can also be a normal member (see the packaging_legacy package); - # we are just requiring it to be readable. Actually defining a property - # has runtime effect on subclasses, so it's typing only. - if typing.TYPE_CHECKING: - - @property - def _key(self) -> tuple[Any, ...]: ... - - def __hash__(self) -> int: - return hash(self._key) - - # Please keep the duplicated `isinstance` check - # in the six comparisons hereunder - # unless you find a way to avoid adding overhead function calls. - def __lt__(self, other: _BaseVersion) -> bool: - if not isinstance(other, _BaseVersion): - return NotImplemented - - return self._key < other._key - - def __le__(self, other: _BaseVersion) -> bool: - if not isinstance(other, _BaseVersion): - return NotImplemented - - return self._key <= other._key - - def __eq__(self, other: object) -> bool: - if not isinstance(other, _BaseVersion): - return NotImplemented - - return self._key == other._key - - def __ge__(self, other: _BaseVersion) -> bool: - if not isinstance(other, _BaseVersion): - return NotImplemented - - return self._key >= other._key - - def __gt__(self, other: _BaseVersion) -> bool: - if not isinstance(other, _BaseVersion): - return NotImplemented - - return self._key > other._key - - def __ne__(self, other: object) -> bool: - if not isinstance(other, _BaseVersion): - return NotImplemented - - return self._key != other._key - - -# Deliberately not anchored to the start and end of the string, to make it -# easier for 3rd party code to reuse - -# Note that ++ doesn't behave identically on CPython and PyPy, so not using it here -_VERSION_PATTERN = r""" - v?+ # optional leading v - (?: - (?:(?P[0-9]+)!)?+ # epoch - (?P[0-9]+(?:\.[0-9]+)*+) # release segment - (?P
                                          # pre-release
-            [._-]?+
-            (?Palpha|a|beta|b|preview|pre|c|rc)
-            [._-]?+
-            (?P[0-9]+)?
-        )?+
-        (?P                                         # post release
-            (?:-(?P[0-9]+))
-            |
-            (?:
-                [._-]?
-                (?Ppost|rev|r)
-                [._-]?
-                (?P[0-9]+)?
-            )
-        )?+
-        (?P                                          # dev release
-            [._-]?+
-            (?Pdev)
-            [._-]?+
-            (?P[0-9]+)?
-        )?+
-    )
-    (?:\+
-        (?P                                        # local version
-            [a-z0-9]+
-            (?:[._-][a-z0-9]+)*+
-        )
-    )?+
-"""
-
-_VERSION_PATTERN_OLD = _VERSION_PATTERN.replace("*+", "*").replace("?+", "?")
-
-# Possessive qualifiers were added in Python 3.11.
-# CPython 3.11.0-3.11.4 had a bug: https://github.com/python/cpython/pull/107795
-# Older PyPy also had a bug.
-VERSION_PATTERN = (
-    _VERSION_PATTERN_OLD
-    if (sys.implementation.name == "cpython" and sys.version_info < (3, 11, 5))
-    or (sys.implementation.name == "pypy" and sys.version_info < (3, 11, 13))
-    or sys.version_info < (3, 11)
-    else _VERSION_PATTERN
-)
-"""
-A string containing the regular expression used to match a valid version.
-
-The pattern is not anchored at either end, and is intended for embedding in larger
-expressions (for example, matching a version number as part of a file name). The
-regular expression should be compiled with the ``re.VERBOSE`` and ``re.IGNORECASE``
-flags set.
-
-:meta hide-value:
-"""
-
-
-# Validation pattern for local version in replace()
-_LOCAL_PATTERN = re.compile(r"[a-z0-9]+(?:[._-][a-z0-9]+)*", re.IGNORECASE)
-
-
-def _validate_epoch(value: object, /) -> int:
-    epoch = value or 0
-    if isinstance(epoch, int) and epoch >= 0:
-        return epoch
-    msg = f"epoch must be non-negative integer, got {epoch}"
-    raise InvalidVersion(msg)
-
-
-def _validate_release(value: object, /) -> tuple[int, ...]:
-    release = (0,) if value is None else value
-    if (
-        isinstance(release, tuple)
-        and len(release) > 0
-        and all(isinstance(i, int) and i >= 0 for i in release)
-    ):
-        return release
-    msg = f"release must be a non-empty tuple of non-negative integers, got {release}"
-    raise InvalidVersion(msg)
-
-
-def _validate_pre(value: object, /) -> tuple[Literal["a", "b", "rc"], int] | None:
-    if value is None:
-        return value
-    if (
-        isinstance(value, tuple)
-        and len(value) == 2
-        and value[0] in ("a", "b", "rc")
-        and isinstance(value[1], int)
-        and value[1] >= 0
-    ):
-        return value
-    msg = f"pre must be a tuple of ('a'|'b'|'rc', non-negative int), got {value}"
-    raise InvalidVersion(msg)
-
-
-def _validate_post(value: object, /) -> tuple[Literal["post"], int] | None:
-    if value is None:
-        return value
-    if isinstance(value, int) and value >= 0:
-        return ("post", value)
-    msg = f"post must be non-negative integer, got {value}"
-    raise InvalidVersion(msg)
-
-
-def _validate_dev(value: object, /) -> tuple[Literal["dev"], int] | None:
-    if value is None:
-        return value
-    if isinstance(value, int) and value >= 0:
-        return ("dev", value)
-    msg = f"dev must be non-negative integer, got {value}"
-    raise InvalidVersion(msg)
-
-
-def _validate_local(value: object, /) -> LocalType | None:
-    if value is None:
-        return value
-    if isinstance(value, str) and _LOCAL_PATTERN.fullmatch(value):
-        return _parse_local_version(value)
-    msg = f"local must be a valid version string, got {value!r}"
-    raise InvalidVersion(msg)
-
-
-# Backward compatibility for internals before 26.0. Do not use.
-class _Version(NamedTuple):
-    epoch: int
-    release: tuple[int, ...]
-    dev: tuple[str, int] | None
-    pre: tuple[str, int] | None
-    post: tuple[str, int] | None
-    local: LocalType | None
-
-
-class Version(_BaseVersion):
-    """This class abstracts handling of a project's versions.
-
-    A :class:`Version` instance is comparison aware and can be compared and
-    sorted using the standard Python interfaces.
-
-    >>> v1 = Version("1.0a5")
-    >>> v2 = Version("1.0")
-    >>> v1
-    
-    >>> v2
-    
-    >>> v1 < v2
-    True
-    >>> v1 == v2
-    False
-    >>> v1 > v2
-    False
-    >>> v1 >= v2
-    False
-    >>> v1 <= v2
-    True
-    """
-
-    __slots__ = ("_dev", "_epoch", "_key_cache", "_local", "_post", "_pre", "_release")
-    __match_args__ = ("_str",)
-
-    _regex = re.compile(r"\s*" + VERSION_PATTERN + r"\s*", re.VERBOSE | re.IGNORECASE)
-
-    _epoch: int
-    _release: tuple[int, ...]
-    _dev: tuple[str, int] | None
-    _pre: tuple[str, int] | None
-    _post: tuple[str, int] | None
-    _local: LocalType | None
-
-    _key_cache: CmpKey | None
-
-    def __init__(self, version: str) -> None:
-        """Initialize a Version object.
-
-        :param version:
-            The string representation of a version which will be parsed and normalized
-            before use.
-        :raises InvalidVersion:
-            If the ``version`` does not conform to PEP 440 in any way then this
-            exception will be raised.
-        """
-        # Validate the version and parse it into pieces
-        match = self._regex.fullmatch(version)
-        if not match:
-            raise InvalidVersion(f"Invalid version: {version!r}")
-        self._epoch = int(match.group("epoch")) if match.group("epoch") else 0
-        self._release = tuple(map(int, match.group("release").split(".")))
-        self._pre = _parse_letter_version(match.group("pre_l"), match.group("pre_n"))
-        self._post = _parse_letter_version(
-            match.group("post_l"), match.group("post_n1") or match.group("post_n2")
-        )
-        self._dev = _parse_letter_version(match.group("dev_l"), match.group("dev_n"))
-        self._local = _parse_local_version(match.group("local"))
-
-        # Key which will be used for sorting
-        self._key_cache = None
-
-    def __replace__(self, **kwargs: Unpack[_VersionReplace]) -> Self:
-        epoch = _validate_epoch(kwargs["epoch"]) if "epoch" in kwargs else self._epoch
-        release = (
-            _validate_release(kwargs["release"])
-            if "release" in kwargs
-            else self._release
-        )
-        pre = _validate_pre(kwargs["pre"]) if "pre" in kwargs else self._pre
-        post = _validate_post(kwargs["post"]) if "post" in kwargs else self._post
-        dev = _validate_dev(kwargs["dev"]) if "dev" in kwargs else self._dev
-        local = _validate_local(kwargs["local"]) if "local" in kwargs else self._local
-
-        if (
-            epoch == self._epoch
-            and release == self._release
-            and pre == self._pre
-            and post == self._post
-            and dev == self._dev
-            and local == self._local
-        ):
-            return self
-
-        new_version = self.__class__.__new__(self.__class__)
-        new_version._key_cache = None
-        new_version._epoch = epoch
-        new_version._release = release
-        new_version._pre = pre
-        new_version._post = post
-        new_version._dev = dev
-        new_version._local = local
-
-        return new_version
-
-    @property
-    def _key(self) -> CmpKey:
-        if self._key_cache is None:
-            self._key_cache = _cmpkey(
-                self._epoch,
-                self._release,
-                self._pre,
-                self._post,
-                self._dev,
-                self._local,
-            )
-        return self._key_cache
-
-    @property
-    @_deprecated("Version._version is private and will be removed soon")
-    def _version(self) -> _Version:
-        return _Version(
-            self._epoch, self._release, self._dev, self._pre, self._post, self._local
-        )
-
-    @_version.setter
-    @_deprecated("Version._version is private and will be removed soon")
-    def _version(self, value: _Version) -> None:
-        self._epoch = value.epoch
-        self._release = value.release
-        self._dev = value.dev
-        self._pre = value.pre
-        self._post = value.post
-        self._local = value.local
-        self._key_cache = None
-
-    def __repr__(self) -> str:
-        """A representation of the Version that shows all internal state.
-
-        >>> Version('1.0.0')
-        
-        """
-        return f""
-
-    def __str__(self) -> str:
-        """A string representation of the version that can be round-tripped.
-
-        >>> str(Version("1.0a5"))
-        '1.0a5'
-        """
-        # This is a hot function, so not calling self.base_version
-        version = ".".join(map(str, self.release))
-
-        # Epoch
-        if self.epoch:
-            version = f"{self.epoch}!{version}"
-
-        # Pre-release
-        if self.pre is not None:
-            version += "".join(map(str, self.pre))
-
-        # Post-release
-        if self.post is not None:
-            version += f".post{self.post}"
-
-        # Development release
-        if self.dev is not None:
-            version += f".dev{self.dev}"
-
-        # Local version segment
-        if self.local is not None:
-            version += f"+{self.local}"
-
-        return version
-
-    @property
-    def _str(self) -> str:
-        """Internal property for match_args"""
-        return str(self)
-
-    @property
-    def epoch(self) -> int:
-        """The epoch of the version.
-
-        >>> Version("2.0.0").epoch
-        0
-        >>> Version("1!2.0.0").epoch
-        1
-        """
-        return self._epoch
-
-    @property
-    def release(self) -> tuple[int, ...]:
-        """The components of the "release" segment of the version.
-
-        >>> Version("1.2.3").release
-        (1, 2, 3)
-        >>> Version("2.0.0").release
-        (2, 0, 0)
-        >>> Version("1!2.0.0.post0").release
-        (2, 0, 0)
-
-        Includes trailing zeroes but not the epoch or any pre-release / development /
-        post-release suffixes.
-        """
-        return self._release
-
-    @property
-    def pre(self) -> tuple[str, int] | None:
-        """The pre-release segment of the version.
-
-        >>> print(Version("1.2.3").pre)
-        None
-        >>> Version("1.2.3a1").pre
-        ('a', 1)
-        >>> Version("1.2.3b1").pre
-        ('b', 1)
-        >>> Version("1.2.3rc1").pre
-        ('rc', 1)
-        """
-        return self._pre
-
-    @property
-    def post(self) -> int | None:
-        """The post-release number of the version.
-
-        >>> print(Version("1.2.3").post)
-        None
-        >>> Version("1.2.3.post1").post
-        1
-        """
-        return self._post[1] if self._post else None
-
-    @property
-    def dev(self) -> int | None:
-        """The development number of the version.
-
-        >>> print(Version("1.2.3").dev)
-        None
-        >>> Version("1.2.3.dev1").dev
-        1
-        """
-        return self._dev[1] if self._dev else None
-
-    @property
-    def local(self) -> str | None:
-        """The local version segment of the version.
-
-        >>> print(Version("1.2.3").local)
-        None
-        >>> Version("1.2.3+abc").local
-        'abc'
-        """
-        if self._local:
-            return ".".join(str(x) for x in self._local)
-        else:
-            return None
-
-    @property
-    def public(self) -> str:
-        """The public portion of the version.
-
-        >>> Version("1.2.3").public
-        '1.2.3'
-        >>> Version("1.2.3+abc").public
-        '1.2.3'
-        >>> Version("1!1.2.3dev1+abc").public
-        '1!1.2.3.dev1'
-        """
-        return str(self).split("+", 1)[0]
-
-    @property
-    def base_version(self) -> str:
-        """The "base version" of the version.
-
-        >>> Version("1.2.3").base_version
-        '1.2.3'
-        >>> Version("1.2.3+abc").base_version
-        '1.2.3'
-        >>> Version("1!1.2.3dev1+abc").base_version
-        '1!1.2.3'
-
-        The "base version" is the public version of the project without any pre or post
-        release markers.
-        """
-        release_segment = ".".join(map(str, self.release))
-        return f"{self.epoch}!{release_segment}" if self.epoch else release_segment
-
-    @property
-    def is_prerelease(self) -> bool:
-        """Whether this version is a pre-release.
-
-        >>> Version("1.2.3").is_prerelease
-        False
-        >>> Version("1.2.3a1").is_prerelease
-        True
-        >>> Version("1.2.3b1").is_prerelease
-        True
-        >>> Version("1.2.3rc1").is_prerelease
-        True
-        >>> Version("1.2.3dev1").is_prerelease
-        True
-        """
-        return self.dev is not None or self.pre is not None
-
-    @property
-    def is_postrelease(self) -> bool:
-        """Whether this version is a post-release.
-
-        >>> Version("1.2.3").is_postrelease
-        False
-        >>> Version("1.2.3.post1").is_postrelease
-        True
-        """
-        return self.post is not None
-
-    @property
-    def is_devrelease(self) -> bool:
-        """Whether this version is a development release.
-
-        >>> Version("1.2.3").is_devrelease
-        False
-        >>> Version("1.2.3.dev1").is_devrelease
-        True
-        """
-        return self.dev is not None
-
-    @property
-    def major(self) -> int:
-        """The first item of :attr:`release` or ``0`` if unavailable.
-
-        >>> Version("1.2.3").major
-        1
-        """
-        return self.release[0] if len(self.release) >= 1 else 0
-
-    @property
-    def minor(self) -> int:
-        """The second item of :attr:`release` or ``0`` if unavailable.
-
-        >>> Version("1.2.3").minor
-        2
-        >>> Version("1").minor
-        0
-        """
-        return self.release[1] if len(self.release) >= 2 else 0
-
-    @property
-    def micro(self) -> int:
-        """The third item of :attr:`release` or ``0`` if unavailable.
-
-        >>> Version("1.2.3").micro
-        3
-        >>> Version("1").micro
-        0
-        """
-        return self.release[2] if len(self.release) >= 3 else 0
-
-
-class _TrimmedRelease(Version):
-    __slots__ = ()
-
-    def __init__(self, version: str | Version) -> None:
-        if isinstance(version, Version):
-            self._epoch = version._epoch
-            self._release = version._release
-            self._dev = version._dev
-            self._pre = version._pre
-            self._post = version._post
-            self._local = version._local
-            self._key_cache = version._key_cache
-            return
-        super().__init__(version)  # pragma: no cover
-
-    @property
-    def release(self) -> tuple[int, ...]:
-        """
-        Release segment without any trailing zeros.
-
-        >>> _TrimmedRelease('1.0.0').release
-        (1,)
-        >>> _TrimmedRelease('0.0').release
-        (0,)
-        """
-        # This leaves one 0.
-        rel = super().release
-        len_release = len(rel)
-        i = len_release
-        while i > 1 and rel[i - 1] == 0:
-            i -= 1
-        return rel if i == len_release else rel[:i]
-
-
-def _parse_letter_version(
-    letter: str | None, number: str | bytes | SupportsInt | None
-) -> tuple[str, int] | None:
-    if letter:
-        # We normalize any letters to their lower case form
-        letter = letter.lower()
-
-        # We consider some words to be alternate spellings of other words and
-        # in those cases we want to normalize the spellings to our preferred
-        # spelling.
-        letter = _LETTER_NORMALIZATION.get(letter, letter)
-
-        # We consider there to be an implicit 0 in a pre-release if there is
-        # not a numeral associated with it.
-        return letter, int(number or 0)
-
-    if number:
-        # We assume if we are given a number, but we are not given a letter
-        # then this is using the implicit post release syntax (e.g. 1.0-1)
-        return "post", int(number)
-
-    return None
-
-
-_local_version_separators = re.compile(r"[\._-]")
-
-
-def _parse_local_version(local: str | None) -> LocalType | None:
-    """
-    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
-    """
-    if local is not None:
-        return tuple(
-            part.lower() if not part.isdigit() else int(part)
-            for part in _local_version_separators.split(local)
-        )
-    return None
-
-
-def _cmpkey(
-    epoch: int,
-    release: tuple[int, ...],
-    pre: tuple[str, int] | None,
-    post: tuple[str, int] | None,
-    dev: tuple[str, int] | None,
-    local: LocalType | None,
-) -> CmpKey:
-    # When we compare a release version, we want to compare it with all of the
-    # trailing zeros removed. We will use this for our sorting key.
-    len_release = len(release)
-    i = len_release
-    while i and release[i - 1] == 0:
-        i -= 1
-    _release = release if i == len_release else release[:i]
-
-    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
-    # We'll do this by abusing the pre segment, but we _only_ want to do this
-    # if there is not a pre or a post segment. If we have one of those then
-    # the normal sorting rules will handle this case correctly.
-    if pre is None and post is None and dev is not None:
-        _pre: CmpPrePostDevType = NegativeInfinity
-    # Versions without a pre-release (except as noted above) should sort after
-    # those with one.
-    elif pre is None:
-        _pre = Infinity
-    else:
-        _pre = pre
-
-    # Versions without a post segment should sort before those with one.
-    if post is None:
-        _post: CmpPrePostDevType = NegativeInfinity
-
-    else:
-        _post = post
-
-    # Versions without a development segment should sort after those with one.
-    if dev is None:
-        _dev: CmpPrePostDevType = Infinity
-
-    else:
-        _dev = dev
-
-    if local is None:
-        # Versions without a local segment should sort before those with one.
-        _local: CmpLocalType = NegativeInfinity
-    else:
-        # Versions with a local segment need that segment parsed to implement
-        # the sorting rules in PEP440.
-        # - Alpha numeric segments sort before numeric segments
-        # - Alpha numeric segments sort lexicographically
-        # - Numeric segments sort numerically
-        # - Shorter versions sort before longer versions when the prefixes
-        #   match exactly
-        _local = tuple(
-            (i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
-        )
-
-    return epoch, _release, _pre, _post, _dev, _local
diff --git a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/INSTALLER
deleted file mode 100755
index a1b589e3..00000000
--- a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/INSTALLER
+++ /dev/null
@@ -1 +0,0 @@
-pip
diff --git a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/LICENSE b/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/LICENSE
deleted file mode 100755
index 1e65815c..00000000
--- a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/LICENSE
+++ /dev/null
@@ -1,54 +0,0 @@
-Copyright 2017- Paul Ganssle 
-Copyright 2017- dateutil contributors (see AUTHORS file)
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-The above license applies to all contributions after 2017-12-01, as well as
-all contributions that have been re-licensed (see AUTHORS file for the list of
-contributors who have re-licensed their code).
---------------------------------------------------------------------------------
-dateutil - Extensions to the standard Python datetime module.
-
-Copyright (c) 2003-2011 - Gustavo Niemeyer 
-Copyright (c) 2012-2014 - Tomi Pieviläinen 
-Copyright (c) 2014-2016 - Yaron de Leeuw 
-Copyright (c) 2015-     - Paul Ganssle 
-Copyright (c) 2015-     - dateutil contributors (see AUTHORS file)
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright notice,
-      this list of conditions and the following disclaimer in the documentation
-      and/or other materials provided with the distribution.
-    * Neither the name of the copyright holder nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The above BSD License Applies to all code, even that also covered by Apache 2.0.
\ No newline at end of file
diff --git a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/METADATA b/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/METADATA
deleted file mode 100755
index 577f2bf2..00000000
--- a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/METADATA
+++ /dev/null
@@ -1,204 +0,0 @@
-Metadata-Version: 2.1
-Name: python-dateutil
-Version: 2.9.0.post0
-Summary: Extensions to the standard Python datetime module
-Home-page: https://github.com/dateutil/dateutil
-Author: Gustavo Niemeyer
-Author-email: gustavo@niemeyer.net
-Maintainer: Paul Ganssle
-Maintainer-email: dateutil@python.org
-License: Dual License
-Project-URL: Documentation, https://dateutil.readthedocs.io/en/stable/
-Project-URL: Source, https://github.com/dateutil/dateutil
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: BSD License
-Classifier: License :: OSI Approved :: Apache Software License
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: 3.8
-Classifier: Programming Language :: Python :: 3.9
-Classifier: Programming Language :: Python :: 3.10
-Classifier: Programming Language :: Python :: 3.11
-Classifier: Programming Language :: Python :: 3.12
-Classifier: Topic :: Software Development :: Libraries
-Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,>=2.7
-Description-Content-Type: text/x-rst
-License-File: LICENSE
-Requires-Dist: six >=1.5
-
-dateutil - powerful extensions to datetime
-==========================================
-
-|pypi| |support| |licence|
-
-|gitter| |readthedocs|
-
-|travis| |appveyor| |pipelines| |coverage|
-
-.. |pypi| image:: https://img.shields.io/pypi/v/python-dateutil.svg?style=flat-square
-    :target: https://pypi.org/project/python-dateutil/
-    :alt: pypi version
-
-.. |support| image:: https://img.shields.io/pypi/pyversions/python-dateutil.svg?style=flat-square
-    :target: https://pypi.org/project/python-dateutil/
-    :alt: supported Python version
-
-.. |travis| image:: https://img.shields.io/travis/dateutil/dateutil/master.svg?style=flat-square&label=Travis%20Build
-    :target: https://travis-ci.org/dateutil/dateutil
-    :alt: travis build status
-
-.. |appveyor| image:: https://img.shields.io/appveyor/ci/dateutil/dateutil/master.svg?style=flat-square&logo=appveyor
-    :target: https://ci.appveyor.com/project/dateutil/dateutil
-    :alt: appveyor build status
-
-.. |pipelines| image:: https://dev.azure.com/pythondateutilazure/dateutil/_apis/build/status/dateutil.dateutil?branchName=master
-    :target: https://dev.azure.com/pythondateutilazure/dateutil/_build/latest?definitionId=1&branchName=master
-    :alt: azure pipelines build status
-
-.. |coverage| image:: https://codecov.io/gh/dateutil/dateutil/branch/master/graphs/badge.svg?branch=master
-    :target: https://codecov.io/gh/dateutil/dateutil?branch=master
-    :alt: Code coverage
-
-.. |gitter| image:: https://badges.gitter.im/dateutil/dateutil.svg
-   :alt: Join the chat at https://gitter.im/dateutil/dateutil
-   :target: https://gitter.im/dateutil/dateutil
-
-.. |licence| image:: https://img.shields.io/pypi/l/python-dateutil.svg?style=flat-square
-    :target: https://pypi.org/project/python-dateutil/
-    :alt: licence
-
-.. |readthedocs| image:: https://img.shields.io/readthedocs/dateutil/latest.svg?style=flat-square&label=Read%20the%20Docs
-   :alt: Read the documentation at https://dateutil.readthedocs.io/en/latest/
-   :target: https://dateutil.readthedocs.io/en/latest/
-
-The `dateutil` module provides powerful extensions to
-the standard `datetime` module, available in Python.
-
-Installation
-============
-`dateutil` can be installed from PyPI using `pip` (note that the package name is
-different from the importable name)::
-
-    pip install python-dateutil
-
-Download
-========
-dateutil is available on PyPI
-https://pypi.org/project/python-dateutil/
-
-The documentation is hosted at:
-https://dateutil.readthedocs.io/en/stable/
-
-Code
-====
-The code and issue tracker are hosted on GitHub:
-https://github.com/dateutil/dateutil/
-
-Features
-========
-
-* Computing of relative deltas (next month, next year,
-  next Monday, last week of month, etc);
-* Computing of relative deltas between two given
-  date and/or datetime objects;
-* Computing of dates based on very flexible recurrence rules,
-  using a superset of the `iCalendar `_
-  specification. Parsing of RFC strings is supported as well.
-* Generic parsing of dates in almost any string format;
-* Timezone (tzinfo) implementations for tzfile(5) format
-  files (/etc/localtime, /usr/share/zoneinfo, etc), TZ
-  environment string (in all known formats), iCalendar
-  format files, given ranges (with help from relative deltas),
-  local machine timezone, fixed offset timezone, UTC timezone,
-  and Windows registry-based time zones.
-* Internal up-to-date world timezone information based on
-  Olson's database.
-* Computing of Easter Sunday dates for any given year,
-  using Western, Orthodox or Julian algorithms;
-* A comprehensive test suite.
-
-Quick example
-=============
-Here's a snapshot, just to give an idea about the power of the
-package. For more examples, look at the documentation.
-
-Suppose you want to know how much time is left, in
-years/months/days/etc, before the next easter happening on a
-year with a Friday 13th in August, and you want to get today's
-date out of the "date" unix system command. Here is the code:
-
-.. code-block:: python3
-
-    >>> from dateutil.relativedelta import *
-    >>> from dateutil.easter import *
-    >>> from dateutil.rrule import *
-    >>> from dateutil.parser import *
-    >>> from datetime import *
-    >>> now = parse("Sat Oct 11 17:13:46 UTC 2003")
-    >>> today = now.date()
-    >>> year = rrule(YEARLY,dtstart=now,bymonth=8,bymonthday=13,byweekday=FR)[0].year
-    >>> rdelta = relativedelta(easter(year), today)
-    >>> print("Today is: %s" % today)
-    Today is: 2003-10-11
-    >>> print("Year with next Aug 13th on a Friday is: %s" % year)
-    Year with next Aug 13th on a Friday is: 2004
-    >>> print("How far is the Easter of that year: %s" % rdelta)
-    How far is the Easter of that year: relativedelta(months=+6)
-    >>> print("And the Easter of that year is: %s" % (today+rdelta))
-    And the Easter of that year is: 2004-04-11
-
-Being exactly 6 months ahead was **really** a coincidence :)
-
-Contributing
-============
-
-We welcome many types of contributions - bug reports, pull requests (code, infrastructure or documentation fixes). For more information about how to contribute to the project, see the ``CONTRIBUTING.md`` file in the repository.
-
-
-Author
-======
-The dateutil module was written by Gustavo Niemeyer 
-in 2003.
-
-It is maintained by:
-
-* Gustavo Niemeyer  2003-2011
-* Tomi Pieviläinen  2012-2014
-* Yaron de Leeuw  2014-2016
-* Paul Ganssle  2015-
-
-Starting with version 2.4.1 and running until 2.8.2, all source and binary
-distributions will be signed by a PGP key that has, at the very least, been
-signed by the key which made the previous release. A table of release signing
-keys can be found below:
-
-===========  ============================
-Releases     Signing key fingerprint
-===========  ============================
-2.4.1-2.8.2  `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_
-===========  ============================
-
-New releases *may* have signed tags, but binary and source distributions
-uploaded to PyPI will no longer have GPG signatures attached.
-
-Contact
-=======
-Our mailing list is available at `dateutil@python.org `_. As it is hosted by the PSF, it is subject to the `PSF code of
-conduct `_.
-
-License
-=======
-
-All contributions after December 1, 2017 released under dual license - either `Apache 2.0 License `_ or the `BSD 3-Clause License `_. Contributions before December 1, 2017 - except those those explicitly relicensed - are released only under the BSD 3-Clause License.
-
-
-.. _6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB:
-   https://pgp.mit.edu/pks/lookup?op=vindex&search=0xCD54FCE3D964BEFB
diff --git a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/RECORD b/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/RECORD
deleted file mode 100755
index 20958cfa..00000000
--- a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/RECORD
+++ /dev/null
@@ -1,27 +0,0 @@
-dateutil/__init__.py,sha256=Mqam67WO9IkTmUFyI66vS6IoSXTp9G388DadH2LCMLY,620
-dateutil/_common.py,sha256=77w0yytkrxlYbSn--lDVPUMabUXRR9I3lBv_vQRUqUY,932
-dateutil/_version.py,sha256=BV031OxDDAmy58neUg5yyqLkLaqIw7ibK9As3jiMib0,166
-dateutil/easter.py,sha256=dyBi-lKvimH1u_k6p7Z0JJK72QhqVtVBsqByvpEPKvc,2678
-dateutil/parser/__init__.py,sha256=wWk6GFuxTpjoggCGtgkceJoti4pVjl4_fHQXpNOaSYg,1766
-dateutil/parser/_parser.py,sha256=7klDdyicksQB_Xgl-3UAmBwzCYor1AIZqklIcT6dH_8,58796
-dateutil/parser/isoparser.py,sha256=8Fy999bnCd1frSdOYuOraWfJTtd5W7qQ51NwNuH_hXM,13233
-dateutil/relativedelta.py,sha256=IY_mglMjoZbYfrvloTY2ce02aiVjPIkiZfqgNTZRfuA,24903
-dateutil/rrule.py,sha256=KJzKlaCd1jEbu4A38ZltslaoAUh9nSbdbOFdjp70Kew,66557
-dateutil/tz/__init__.py,sha256=F-Mz13v6jYseklQf9Te9J6nzcLDmq47gORa61K35_FA,444
-dateutil/tz/_common.py,sha256=cgzDTANsOXvEc86cYF77EsliuSab8Puwpsl5-bX3_S4,12977
-dateutil/tz/_factories.py,sha256=unb6XQNXrPMveksTCU-Ag8jmVZs4SojoPUcAHpWnrvU,2569
-dateutil/tz/tz.py,sha256=EUnEdMfeThXiY6l4sh9yBabZ63_POzy01zSsh9thn1o,62855
-dateutil/tz/win.py,sha256=xJszWgSwE1xPx_HJj4ZkepyukC_hNy016WMcXhbRaB8,12935
-dateutil/tzwin.py,sha256=7Ar4vdQCnnM0mKR3MUjbIKsZrBVfHgdwsJZc_mGYRew,59
-dateutil/utils.py,sha256=dKCchEw8eObi0loGTx91unBxm_7UGlU3v_FjFMdqwYM,1965
-dateutil/zoneinfo/__init__.py,sha256=KYg0pthCMjcp5MXSEiBJn3nMjZeNZav7rlJw5-tz1S4,5889
-dateutil/zoneinfo/dateutil-zoneinfo.tar.gz,sha256=0-pS57bpaN4NiE3xKIGTWW-pW4A9tPkqGCeac5gARHU,156400
-dateutil/zoneinfo/rebuild.py,sha256=MiqYzCIHvNbMH-LdRYLv-4T0EIA7hDKt5GLR0IRTLdI,2392
-python_dateutil-2.9.0.post0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
-python_dateutil-2.9.0.post0.dist-info/LICENSE,sha256=ugD1Gg2SgjtaHN4n2LW50jIeZ-2NqbwWPv-W1eF-V34,2889
-python_dateutil-2.9.0.post0.dist-info/METADATA,sha256=qdQ22jIr6AgzL5jYgyWZjofLaTpniplp_rTPrXKabpM,8354
-python_dateutil-2.9.0.post0.dist-info/RECORD,,
-python_dateutil-2.9.0.post0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-python_dateutil-2.9.0.post0.dist-info/WHEEL,sha256=-G_t0oGuE7UD0DrSpVZnq1hHMBV9DD2XkS5v7XpmTnk,110
-python_dateutil-2.9.0.post0.dist-info/top_level.txt,sha256=4tjdWkhRZvF7LA_BYe_L9gB2w_p2a-z5y6ArjaRkot8,9
-python_dateutil-2.9.0.post0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
diff --git a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/REQUESTED
deleted file mode 100755
index e69de29b..00000000
diff --git a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/WHEEL
deleted file mode 100755
index 4724c457..00000000
--- a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/WHEEL
+++ /dev/null
@@ -1,6 +0,0 @@
-Wheel-Version: 1.0
-Generator: bdist_wheel (0.42.0)
-Root-Is-Purelib: true
-Tag: py2-none-any
-Tag: py3-none-any
-
diff --git a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/zip-safe b/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/zip-safe
deleted file mode 100755
index 8b137891..00000000
--- a/apps/bitwarden_event_logs/lib/python_dateutil-2.9.0.post0.dist-info/zip-safe
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/INSTALLER
deleted file mode 100755
index a1b589e3..00000000
--- a/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/INSTALLER
+++ /dev/null
@@ -1 +0,0 @@
-pip
diff --git a/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/METADATA b/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/METADATA
deleted file mode 100755
index b31773e3..00000000
--- a/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/METADATA
+++ /dev/null
@@ -1,133 +0,0 @@
-Metadata-Version: 2.4
-Name: requests
-Version: 2.32.5
-Summary: Python HTTP for Humans.
-Home-page: https://requests.readthedocs.io
-Author: Kenneth Reitz
-Author-email: me@kennethreitz.org
-License: Apache-2.0
-Project-URL: Documentation, https://requests.readthedocs.io
-Project-URL: Source, https://github.com/psf/requests
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Environment :: Web Environment
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: Apache Software License
-Classifier: Natural Language :: English
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.9
-Classifier: Programming Language :: Python :: 3.10
-Classifier: Programming Language :: Python :: 3.11
-Classifier: Programming Language :: Python :: 3.12
-Classifier: Programming Language :: Python :: 3.13
-Classifier: Programming Language :: Python :: 3.14
-Classifier: Programming Language :: Python :: 3 :: Only
-Classifier: Programming Language :: Python :: Implementation :: CPython
-Classifier: Programming Language :: Python :: Implementation :: PyPy
-Classifier: Topic :: Internet :: WWW/HTTP
-Classifier: Topic :: Software Development :: Libraries
-Requires-Python: >=3.9
-Description-Content-Type: text/markdown
-License-File: LICENSE
-Requires-Dist: charset_normalizer<4,>=2
-Requires-Dist: idna<4,>=2.5
-Requires-Dist: urllib3<3,>=1.21.1
-Requires-Dist: certifi>=2017.4.17
-Provides-Extra: security
-Provides-Extra: socks
-Requires-Dist: PySocks!=1.5.7,>=1.5.6; extra == "socks"
-Provides-Extra: use-chardet-on-py3
-Requires-Dist: chardet<6,>=3.0.2; extra == "use-chardet-on-py3"
-Dynamic: author
-Dynamic: author-email
-Dynamic: classifier
-Dynamic: description
-Dynamic: description-content-type
-Dynamic: home-page
-Dynamic: license
-Dynamic: license-file
-Dynamic: project-url
-Dynamic: provides-extra
-Dynamic: requires-dist
-Dynamic: requires-python
-Dynamic: summary
-
-# Requests
-
-**Requests** is a simple, yet elegant, HTTP library.
-
-```python
->>> import requests
->>> r = requests.get('https://httpbin.org/basic-auth/user/pass', auth=('user', 'pass'))
->>> r.status_code
-200
->>> r.headers['content-type']
-'application/json; charset=utf8'
->>> r.encoding
-'utf-8'
->>> r.text
-'{"authenticated": true, ...'
->>> r.json()
-{'authenticated': True, ...}
-```
-
-Requests allows you to send HTTP/1.1 requests extremely easily. There’s no need to manually add query strings to your URLs, or to form-encode your `PUT` & `POST` data — but nowadays, just use the `json` method!
-
-Requests is one of the most downloaded Python packages today, pulling in around `30M downloads / week`— according to GitHub, Requests is currently [depended upon](https://github.com/psf/requests/network/dependents?package_id=UGFja2FnZS01NzA4OTExNg%3D%3D) by `1,000,000+` repositories. You may certainly put your trust in this code.
-
-[![Downloads](https://static.pepy.tech/badge/requests/month)](https://pepy.tech/project/requests)
-[![Supported Versions](https://img.shields.io/pypi/pyversions/requests.svg)](https://pypi.org/project/requests)
-[![Contributors](https://img.shields.io/github/contributors/psf/requests.svg)](https://github.com/psf/requests/graphs/contributors)
-
-## Installing Requests and Supported Versions
-
-Requests is available on PyPI:
-
-```console
-$ python -m pip install requests
-```
-
-Requests officially supports Python 3.9+.
-
-## Supported Features & Best–Practices
-
-Requests is ready for the demands of building robust and reliable HTTP–speaking applications, for the needs of today.
-
-- Keep-Alive & Connection Pooling
-- International Domains and URLs
-- Sessions with Cookie Persistence
-- Browser-style TLS/SSL Verification
-- Basic & Digest Authentication
-- Familiar `dict`–like Cookies
-- Automatic Content Decompression and Decoding
-- Multi-part File Uploads
-- SOCKS Proxy Support
-- Connection Timeouts
-- Streaming Downloads
-- Automatic honoring of `.netrc`
-- Chunked HTTP Requests
-
-## API Reference and User Guide available on [Read the Docs](https://requests.readthedocs.io)
-
-[![Read the Docs](https://raw.githubusercontent.com/psf/requests/main/ext/ss.png)](https://requests.readthedocs.io)
-
-## Cloning the repository
-
-When cloning the Requests repository, you may need to add the `-c
-fetch.fsck.badTimezone=ignore` flag to avoid an error about a bad commit timestamp (see
-[this issue](https://github.com/psf/requests/issues/2690) for more background):
-
-```shell
-git clone -c fetch.fsck.badTimezone=ignore https://github.com/psf/requests.git
-```
-
-You can also apply this setting to your global Git config:
-
-```shell
-git config --global fetch.fsck.badTimezone ignore
-```
-
----
-
-[![Kenneth Reitz](https://raw.githubusercontent.com/psf/requests/main/ext/kr.png)](https://kennethreitz.org) [![Python Software Foundation](https://raw.githubusercontent.com/psf/requests/main/ext/psf.png)](https://www.python.org/psf)
diff --git a/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/RECORD b/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/RECORD
deleted file mode 100755
index c7e57418..00000000
--- a/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/RECORD
+++ /dev/null
@@ -1,25 +0,0 @@
-requests-2.32.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
-requests-2.32.5.dist-info/METADATA,sha256=ZbWgjagfSRVRPnYJZf8Ut1GPZbe7Pv4NqzZLvMTUDLA,4945
-requests-2.32.5.dist-info/RECORD,,
-requests-2.32.5.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-requests-2.32.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
-requests-2.32.5.dist-info/licenses/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
-requests-2.32.5.dist-info/top_level.txt,sha256=fMSVmHfb5rbGOo6xv-O_tUX6j-WyixssE-SnwcDRxNQ,9
-requests/__init__.py,sha256=4xaAERmPDIBPsa2PsjpU9r06yooK-2mZKHTZAhWRWts,5072
-requests/__version__.py,sha256=QKDceK8K_ujqwDDc3oYrR0odOBYgKVOQQ5vFap_G_cg,435
-requests/_internal_utils.py,sha256=nMQymr4hs32TqVo5AbCrmcJEhvPUh7xXlluyqwslLiQ,1495
-requests/adapters.py,sha256=8nX113gbb123aUtx2ETkAN_6IsYX-M2fRoLGluTEcRk,26285
-requests/api.py,sha256=_Zb9Oa7tzVIizTKwFrPjDEY9ejtm_OnSRERnADxGsQs,6449
-requests/auth.py,sha256=kF75tqnLctZ9Mf_hm9TZIj4cQWnN5uxRz8oWsx5wmR0,10186
-requests/certs.py,sha256=Z9Sb410Anv6jUFTyss0jFFhU6xst8ctELqfy8Ev23gw,429
-requests/compat.py,sha256=J7sIjR6XoDGp5JTVzOxkK5fSoUVUa_Pjc7iRZhAWGmI,2142
-requests/cookies.py,sha256=bNi-iqEj4NPZ00-ob-rHvzkvObzN3lEpgw3g6paS3Xw,18590
-requests/exceptions.py,sha256=jJPS1UWATs86ShVUaLorTiJb1SaGuoNEWgICJep-VkY,4260
-requests/help.py,sha256=gPX5d_H7Xd88aDABejhqGgl9B1VFRTt5BmiYvL3PzIQ,3875
-requests/hooks.py,sha256=CiuysiHA39V5UfcCBXFIx83IrDpuwfN9RcTUgv28ftQ,733
-requests/models.py,sha256=MjZdZ4k7tnw-1nz5PKShjmPmqyk0L6DciwnFngb_Vk4,35510
-requests/packages.py,sha256=_g0gZ681UyAlKHRjH6kanbaoxx2eAb6qzcXiODyTIoc,904
-requests/sessions.py,sha256=Cl1dpEnOfwrzzPbku-emepNeN4Rt_0_58Iy2x-JGTm8,30503
-requests/status_codes.py,sha256=iJUAeA25baTdw-6PfD0eF4qhpINDJRJI-yaMqxs4LEI,4322
-requests/structures.py,sha256=-IbmhVz06S-5aPSZuUthZ6-6D9XOjRuTXHOabY041XM,2912
-requests/utils.py,sha256=WqU86rZ3wvhC-tQjWcjtH_HEKZwWB3iWCZV6SW5DEdQ,33213
diff --git a/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/REQUESTED
deleted file mode 100755
index e69de29b..00000000
diff --git a/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/WHEEL
deleted file mode 100755
index e7fa31b6..00000000
--- a/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/WHEEL
+++ /dev/null
@@ -1,5 +0,0 @@
-Wheel-Version: 1.0
-Generator: setuptools (80.9.0)
-Root-Is-Purelib: true
-Tag: py3-none-any
-
diff --git a/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/licenses/LICENSE b/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/licenses/LICENSE
deleted file mode 100755
index 67db8588..00000000
--- a/apps/bitwarden_event_logs/lib/requests-2.32.5.dist-info/licenses/LICENSE
+++ /dev/null
@@ -1,175 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
diff --git a/apps/bitwarden_event_logs/lib/requests/__init__.py b/apps/bitwarden_event_logs/lib/requests/__init__.py
deleted file mode 100755
index 051cda13..00000000
--- a/apps/bitwarden_event_logs/lib/requests/__init__.py
+++ /dev/null
@@ -1,184 +0,0 @@
-#   __
-#  /__)  _  _     _   _ _/   _
-# / (   (- (/ (/ (- _)  /  _)
-#          /
-
-"""
-Requests HTTP Library
-~~~~~~~~~~~~~~~~~~~~~
-
-Requests is an HTTP library, written in Python, for human beings.
-Basic GET usage:
-
-   >>> import requests
-   >>> r = requests.get('https://www.python.org')
-   >>> r.status_code
-   200
-   >>> b'Python is a programming language' in r.content
-   True
-
-... or POST:
-
-   >>> payload = dict(key1='value1', key2='value2')
-   >>> r = requests.post('https://httpbin.org/post', data=payload)
-   >>> print(r.text)
-   {
-     ...
-     "form": {
-       "key1": "value1",
-       "key2": "value2"
-     },
-     ...
-   }
-
-The other HTTP methods are supported - see `requests.api`. Full documentation
-is at .
-
-:copyright: (c) 2017 by Kenneth Reitz.
-:license: Apache 2.0, see LICENSE for more details.
-"""
-
-import warnings
-
-import urllib3
-
-from .exceptions import RequestsDependencyWarning
-
-try:
-    from charset_normalizer import __version__ as charset_normalizer_version
-except ImportError:
-    charset_normalizer_version = None
-
-try:
-    from chardet import __version__ as chardet_version
-except ImportError:
-    chardet_version = None
-
-
-def check_compatibility(urllib3_version, chardet_version, charset_normalizer_version):
-    urllib3_version = urllib3_version.split(".")
-    assert urllib3_version != ["dev"]  # Verify urllib3 isn't installed from git.
-
-    # Sometimes, urllib3 only reports its version as 16.1.
-    if len(urllib3_version) == 2:
-        urllib3_version.append("0")
-
-    # Check urllib3 for compatibility.
-    major, minor, patch = urllib3_version  # noqa: F811
-    major, minor, patch = int(major), int(minor), int(patch)
-    # urllib3 >= 1.21.1
-    assert major >= 1
-    if major == 1:
-        assert minor >= 21
-
-    # Check charset_normalizer for compatibility.
-    if chardet_version:
-        major, minor, patch = chardet_version.split(".")[:3]
-        major, minor, patch = int(major), int(minor), int(patch)
-        # chardet_version >= 3.0.2, < 6.0.0
-        assert (3, 0, 2) <= (major, minor, patch) < (6, 0, 0)
-    elif charset_normalizer_version:
-        major, minor, patch = charset_normalizer_version.split(".")[:3]
-        major, minor, patch = int(major), int(minor), int(patch)
-        # charset_normalizer >= 2.0.0 < 4.0.0
-        assert (2, 0, 0) <= (major, minor, patch) < (4, 0, 0)
-    else:
-        warnings.warn(
-            "Unable to find acceptable character detection dependency "
-            "(chardet or charset_normalizer).",
-            RequestsDependencyWarning,
-        )
-
-
-def _check_cryptography(cryptography_version):
-    # cryptography < 1.3.4
-    try:
-        cryptography_version = list(map(int, cryptography_version.split(".")))
-    except ValueError:
-        return
-
-    if cryptography_version < [1, 3, 4]:
-        warning = "Old version of cryptography ({}) may cause slowdown.".format(
-            cryptography_version
-        )
-        warnings.warn(warning, RequestsDependencyWarning)
-
-
-# Check imported dependencies for compatibility.
-try:
-    check_compatibility(
-        urllib3.__version__, chardet_version, charset_normalizer_version
-    )
-except (AssertionError, ValueError):
-    warnings.warn(
-        "urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
-        "version!".format(
-            urllib3.__version__, chardet_version, charset_normalizer_version
-        ),
-        RequestsDependencyWarning,
-    )
-
-# Attempt to enable urllib3's fallback for SNI support
-# if the standard library doesn't support SNI or the
-# 'ssl' library isn't available.
-try:
-    try:
-        import ssl
-    except ImportError:
-        ssl = None
-
-    if not getattr(ssl, "HAS_SNI", False):
-        from urllib3.contrib import pyopenssl
-
-        pyopenssl.inject_into_urllib3()
-
-        # Check cryptography version
-        from cryptography import __version__ as cryptography_version
-
-        _check_cryptography(cryptography_version)
-except ImportError:
-    pass
-
-# urllib3's DependencyWarnings should be silenced.
-from urllib3.exceptions import DependencyWarning
-
-warnings.simplefilter("ignore", DependencyWarning)
-
-# Set default logging handler to avoid "No handler found" warnings.
-import logging
-from logging import NullHandler
-
-from . import packages, utils
-from .__version__ import (
-    __author__,
-    __author_email__,
-    __build__,
-    __cake__,
-    __copyright__,
-    __description__,
-    __license__,
-    __title__,
-    __url__,
-    __version__,
-)
-from .api import delete, get, head, options, patch, post, put, request
-from .exceptions import (
-    ConnectionError,
-    ConnectTimeout,
-    FileModeWarning,
-    HTTPError,
-    JSONDecodeError,
-    ReadTimeout,
-    RequestException,
-    Timeout,
-    TooManyRedirects,
-    URLRequired,
-)
-from .models import PreparedRequest, Request, Response
-from .sessions import Session, session
-from .status_codes import codes
-
-logging.getLogger(__name__).addHandler(NullHandler())
-
-# FileModeWarnings go off per the default.
-warnings.simplefilter("default", FileModeWarning, append=True)
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/__init__.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/__init__.cpython-39.pyc
deleted file mode 100755
index 3411266f..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/__init__.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/__version__.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/__version__.cpython-39.pyc
deleted file mode 100755
index f066b98e..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/__version__.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/_internal_utils.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/_internal_utils.cpython-39.pyc
deleted file mode 100755
index 9df0b629..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/_internal_utils.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/adapters.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/adapters.cpython-39.pyc
deleted file mode 100755
index 9a94f414..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/adapters.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/api.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/api.cpython-39.pyc
deleted file mode 100755
index 8f4f46a8..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/api.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/auth.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/auth.cpython-39.pyc
deleted file mode 100755
index e5d5eaca..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/auth.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/certs.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/certs.cpython-39.pyc
deleted file mode 100755
index 5840f2c7..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/certs.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/compat.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/compat.cpython-39.pyc
deleted file mode 100755
index 5e3415a5..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/compat.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/cookies.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/cookies.cpython-39.pyc
deleted file mode 100755
index 0dc4e591..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/cookies.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/exceptions.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/exceptions.cpython-39.pyc
deleted file mode 100755
index 6717503d..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/exceptions.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/hooks.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/hooks.cpython-39.pyc
deleted file mode 100755
index 36c29ddb..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/hooks.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/models.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/models.cpython-39.pyc
deleted file mode 100755
index b57b1482..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/models.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/packages.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/packages.cpython-39.pyc
deleted file mode 100755
index 78538c3a..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/packages.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/sessions.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/sessions.cpython-39.pyc
deleted file mode 100755
index 76511836..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/sessions.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/status_codes.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/status_codes.cpython-39.pyc
deleted file mode 100755
index c2b4c9d3..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/status_codes.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/structures.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/structures.cpython-39.pyc
deleted file mode 100755
index e7505041..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/structures.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__pycache__/utils.cpython-39.pyc b/apps/bitwarden_event_logs/lib/requests/__pycache__/utils.cpython-39.pyc
deleted file mode 100755
index 4373203c..00000000
Binary files a/apps/bitwarden_event_logs/lib/requests/__pycache__/utils.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/requests/__version__.py b/apps/bitwarden_event_logs/lib/requests/__version__.py
deleted file mode 100755
index effdd98c..00000000
--- a/apps/bitwarden_event_logs/lib/requests/__version__.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# .-. .-. .-. . . .-. .-. .-. .-.
-# |(  |-  |.| | | |-  `-.  |  `-.
-# ' ' `-' `-`.`-' `-' `-'  '  `-'
-
-__title__ = "requests"
-__description__ = "Python HTTP for Humans."
-__url__ = "https://requests.readthedocs.io"
-__version__ = "2.32.5"
-__build__ = 0x023205
-__author__ = "Kenneth Reitz"
-__author_email__ = "me@kennethreitz.org"
-__license__ = "Apache-2.0"
-__copyright__ = "Copyright Kenneth Reitz"
-__cake__ = "\u2728 \U0001f370 \u2728"
diff --git a/apps/bitwarden_event_logs/lib/requests/_internal_utils.py b/apps/bitwarden_event_logs/lib/requests/_internal_utils.py
deleted file mode 100755
index f2cf635e..00000000
--- a/apps/bitwarden_event_logs/lib/requests/_internal_utils.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""
-requests._internal_utils
-~~~~~~~~~~~~~~
-
-Provides utility functions that are consumed internally by Requests
-which depend on extremely few external helpers (such as compat)
-"""
-import re
-
-from .compat import builtin_str
-
-_VALID_HEADER_NAME_RE_BYTE = re.compile(rb"^[^:\s][^:\r\n]*$")
-_VALID_HEADER_NAME_RE_STR = re.compile(r"^[^:\s][^:\r\n]*$")
-_VALID_HEADER_VALUE_RE_BYTE = re.compile(rb"^\S[^\r\n]*$|^$")
-_VALID_HEADER_VALUE_RE_STR = re.compile(r"^\S[^\r\n]*$|^$")
-
-_HEADER_VALIDATORS_STR = (_VALID_HEADER_NAME_RE_STR, _VALID_HEADER_VALUE_RE_STR)
-_HEADER_VALIDATORS_BYTE = (_VALID_HEADER_NAME_RE_BYTE, _VALID_HEADER_VALUE_RE_BYTE)
-HEADER_VALIDATORS = {
-    bytes: _HEADER_VALIDATORS_BYTE,
-    str: _HEADER_VALIDATORS_STR,
-}
-
-
-def to_native_string(string, encoding="ascii"):
-    """Given a string object, regardless of type, returns a representation of
-    that string in the native string type, encoding and decoding where
-    necessary. This assumes ASCII unless told otherwise.
-    """
-    if isinstance(string, builtin_str):
-        out = string
-    else:
-        out = string.decode(encoding)
-
-    return out
-
-
-def unicode_is_ascii(u_string):
-    """Determine if unicode string only contains ASCII characters.
-
-    :param str u_string: unicode string to check. Must be unicode
-        and not Python 2 `str`.
-    :rtype: bool
-    """
-    assert isinstance(u_string, str)
-    try:
-        u_string.encode("ascii")
-        return True
-    except UnicodeEncodeError:
-        return False
diff --git a/apps/bitwarden_event_logs/lib/requests/adapters.py b/apps/bitwarden_event_logs/lib/requests/adapters.py
deleted file mode 100755
index 670c9276..00000000
--- a/apps/bitwarden_event_logs/lib/requests/adapters.py
+++ /dev/null
@@ -1,696 +0,0 @@
-"""
-requests.adapters
-~~~~~~~~~~~~~~~~~
-
-This module contains the transport adapters that Requests uses to define
-and maintain connections.
-"""
-
-import os.path
-import socket  # noqa: F401
-import typing
-import warnings
-
-from urllib3.exceptions import ClosedPoolError, ConnectTimeoutError
-from urllib3.exceptions import HTTPError as _HTTPError
-from urllib3.exceptions import InvalidHeader as _InvalidHeader
-from urllib3.exceptions import (
-    LocationValueError,
-    MaxRetryError,
-    NewConnectionError,
-    ProtocolError,
-)
-from urllib3.exceptions import ProxyError as _ProxyError
-from urllib3.exceptions import ReadTimeoutError, ResponseError
-from urllib3.exceptions import SSLError as _SSLError
-from urllib3.poolmanager import PoolManager, proxy_from_url
-from urllib3.util import Timeout as TimeoutSauce
-from urllib3.util import parse_url
-from urllib3.util.retry import Retry
-
-from .auth import _basic_auth_str
-from .compat import basestring, urlparse
-from .cookies import extract_cookies_to_jar
-from .exceptions import (
-    ConnectionError,
-    ConnectTimeout,
-    InvalidHeader,
-    InvalidProxyURL,
-    InvalidSchema,
-    InvalidURL,
-    ProxyError,
-    ReadTimeout,
-    RetryError,
-    SSLError,
-)
-from .models import Response
-from .structures import CaseInsensitiveDict
-from .utils import (
-    DEFAULT_CA_BUNDLE_PATH,
-    extract_zipped_paths,
-    get_auth_from_url,
-    get_encoding_from_headers,
-    prepend_scheme_if_needed,
-    select_proxy,
-    urldefragauth,
-)
-
-try:
-    from urllib3.contrib.socks import SOCKSProxyManager
-except ImportError:
-
-    def SOCKSProxyManager(*args, **kwargs):
-        raise InvalidSchema("Missing dependencies for SOCKS support.")
-
-
-if typing.TYPE_CHECKING:
-    from .models import PreparedRequest
-
-
-DEFAULT_POOLBLOCK = False
-DEFAULT_POOLSIZE = 10
-DEFAULT_RETRIES = 0
-DEFAULT_POOL_TIMEOUT = None
-
-
-def _urllib3_request_context(
-    request: "PreparedRequest",
-    verify: "bool | str | None",
-    client_cert: "typing.Tuple[str, str] | str | None",
-    poolmanager: "PoolManager",
-) -> "(typing.Dict[str, typing.Any], typing.Dict[str, typing.Any])":
-    host_params = {}
-    pool_kwargs = {}
-    parsed_request_url = urlparse(request.url)
-    scheme = parsed_request_url.scheme.lower()
-    port = parsed_request_url.port
-
-    cert_reqs = "CERT_REQUIRED"
-    if verify is False:
-        cert_reqs = "CERT_NONE"
-    elif isinstance(verify, str):
-        if not os.path.isdir(verify):
-            pool_kwargs["ca_certs"] = verify
-        else:
-            pool_kwargs["ca_cert_dir"] = verify
-    pool_kwargs["cert_reqs"] = cert_reqs
-    if client_cert is not None:
-        if isinstance(client_cert, tuple) and len(client_cert) == 2:
-            pool_kwargs["cert_file"] = client_cert[0]
-            pool_kwargs["key_file"] = client_cert[1]
-        else:
-            # According to our docs, we allow users to specify just the client
-            # cert path
-            pool_kwargs["cert_file"] = client_cert
-    host_params = {
-        "scheme": scheme,
-        "host": parsed_request_url.hostname,
-        "port": port,
-    }
-    return host_params, pool_kwargs
-
-
-class BaseAdapter:
-    """The Base Transport Adapter"""
-
-    def __init__(self):
-        super().__init__()
-
-    def send(
-        self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
-    ):
-        """Sends PreparedRequest object. Returns Response object.
-
-        :param request: The :class:`PreparedRequest ` being sent.
-        :param stream: (optional) Whether to stream the request content.
-        :param timeout: (optional) How long to wait for the server to send
-            data before giving up, as a float, or a :ref:`(connect timeout,
-            read timeout) ` tuple.
-        :type timeout: float or tuple
-        :param verify: (optional) Either a boolean, in which case it controls whether we verify
-            the server's TLS certificate, or a string, in which case it must be a path
-            to a CA bundle to use
-        :param cert: (optional) Any user-provided SSL certificate to be trusted.
-        :param proxies: (optional) The proxies dictionary to apply to the request.
-        """
-        raise NotImplementedError
-
-    def close(self):
-        """Cleans up adapter specific items."""
-        raise NotImplementedError
-
-
-class HTTPAdapter(BaseAdapter):
-    """The built-in HTTP Adapter for urllib3.
-
-    Provides a general-case interface for Requests sessions to contact HTTP and
-    HTTPS urls by implementing the Transport Adapter interface. This class will
-    usually be created by the :class:`Session ` class under the
-    covers.
-
-    :param pool_connections: The number of urllib3 connection pools to cache.
-    :param pool_maxsize: The maximum number of connections to save in the pool.
-    :param max_retries: The maximum number of retries each connection
-        should attempt. Note, this applies only to failed DNS lookups, socket
-        connections and connection timeouts, never to requests where data has
-        made it to the server. By default, Requests does not retry failed
-        connections. If you need granular control over the conditions under
-        which we retry a request, import urllib3's ``Retry`` class and pass
-        that instead.
-    :param pool_block: Whether the connection pool should block for connections.
-
-    Usage::
-
-      >>> import requests
-      >>> s = requests.Session()
-      >>> a = requests.adapters.HTTPAdapter(max_retries=3)
-      >>> s.mount('http://', a)
-    """
-
-    __attrs__ = [
-        "max_retries",
-        "config",
-        "_pool_connections",
-        "_pool_maxsize",
-        "_pool_block",
-    ]
-
-    def __init__(
-        self,
-        pool_connections=DEFAULT_POOLSIZE,
-        pool_maxsize=DEFAULT_POOLSIZE,
-        max_retries=DEFAULT_RETRIES,
-        pool_block=DEFAULT_POOLBLOCK,
-    ):
-        if max_retries == DEFAULT_RETRIES:
-            self.max_retries = Retry(0, read=False)
-        else:
-            self.max_retries = Retry.from_int(max_retries)
-        self.config = {}
-        self.proxy_manager = {}
-
-        super().__init__()
-
-        self._pool_connections = pool_connections
-        self._pool_maxsize = pool_maxsize
-        self._pool_block = pool_block
-
-        self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block)
-
-    def __getstate__(self):
-        return {attr: getattr(self, attr, None) for attr in self.__attrs__}
-
-    def __setstate__(self, state):
-        # Can't handle by adding 'proxy_manager' to self.__attrs__ because
-        # self.poolmanager uses a lambda function, which isn't pickleable.
-        self.proxy_manager = {}
-        self.config = {}
-
-        for attr, value in state.items():
-            setattr(self, attr, value)
-
-        self.init_poolmanager(
-            self._pool_connections, self._pool_maxsize, block=self._pool_block
-        )
-
-    def init_poolmanager(
-        self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs
-    ):
-        """Initializes a urllib3 PoolManager.
-
-        This method should not be called from user code, and is only
-        exposed for use when subclassing the
-        :class:`HTTPAdapter `.
-
-        :param connections: The number of urllib3 connection pools to cache.
-        :param maxsize: The maximum number of connections to save in the pool.
-        :param block: Block when no free connections are available.
-        :param pool_kwargs: Extra keyword arguments used to initialize the Pool Manager.
-        """
-        # save these values for pickling
-        self._pool_connections = connections
-        self._pool_maxsize = maxsize
-        self._pool_block = block
-
-        self.poolmanager = PoolManager(
-            num_pools=connections,
-            maxsize=maxsize,
-            block=block,
-            **pool_kwargs,
-        )
-
-    def proxy_manager_for(self, proxy, **proxy_kwargs):
-        """Return urllib3 ProxyManager for the given proxy.
-
-        This method should not be called from user code, and is only
-        exposed for use when subclassing the
-        :class:`HTTPAdapter `.
-
-        :param proxy: The proxy to return a urllib3 ProxyManager for.
-        :param proxy_kwargs: Extra keyword arguments used to configure the Proxy Manager.
-        :returns: ProxyManager
-        :rtype: urllib3.ProxyManager
-        """
-        if proxy in self.proxy_manager:
-            manager = self.proxy_manager[proxy]
-        elif proxy.lower().startswith("socks"):
-            username, password = get_auth_from_url(proxy)
-            manager = self.proxy_manager[proxy] = SOCKSProxyManager(
-                proxy,
-                username=username,
-                password=password,
-                num_pools=self._pool_connections,
-                maxsize=self._pool_maxsize,
-                block=self._pool_block,
-                **proxy_kwargs,
-            )
-        else:
-            proxy_headers = self.proxy_headers(proxy)
-            manager = self.proxy_manager[proxy] = proxy_from_url(
-                proxy,
-                proxy_headers=proxy_headers,
-                num_pools=self._pool_connections,
-                maxsize=self._pool_maxsize,
-                block=self._pool_block,
-                **proxy_kwargs,
-            )
-
-        return manager
-
-    def cert_verify(self, conn, url, verify, cert):
-        """Verify a SSL certificate. This method should not be called from user
-        code, and is only exposed for use when subclassing the
-        :class:`HTTPAdapter `.
-
-        :param conn: The urllib3 connection object associated with the cert.
-        :param url: The requested URL.
-        :param verify: Either a boolean, in which case it controls whether we verify
-            the server's TLS certificate, or a string, in which case it must be a path
-            to a CA bundle to use
-        :param cert: The SSL certificate to verify.
-        """
-        if url.lower().startswith("https") and verify:
-            cert_loc = None
-
-            # Allow self-specified cert location.
-            if verify is not True:
-                cert_loc = verify
-
-            if not cert_loc:
-                cert_loc = extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH)
-
-            if not cert_loc or not os.path.exists(cert_loc):
-                raise OSError(
-                    f"Could not find a suitable TLS CA certificate bundle, "
-                    f"invalid path: {cert_loc}"
-                )
-
-            conn.cert_reqs = "CERT_REQUIRED"
-
-            if not os.path.isdir(cert_loc):
-                conn.ca_certs = cert_loc
-            else:
-                conn.ca_cert_dir = cert_loc
-        else:
-            conn.cert_reqs = "CERT_NONE"
-            conn.ca_certs = None
-            conn.ca_cert_dir = None
-
-        if cert:
-            if not isinstance(cert, basestring):
-                conn.cert_file = cert[0]
-                conn.key_file = cert[1]
-            else:
-                conn.cert_file = cert
-                conn.key_file = None
-            if conn.cert_file and not os.path.exists(conn.cert_file):
-                raise OSError(
-                    f"Could not find the TLS certificate file, "
-                    f"invalid path: {conn.cert_file}"
-                )
-            if conn.key_file and not os.path.exists(conn.key_file):
-                raise OSError(
-                    f"Could not find the TLS key file, invalid path: {conn.key_file}"
-                )
-
-    def build_response(self, req, resp):
-        """Builds a :class:`Response ` object from a urllib3
-        response. This should not be called from user code, and is only exposed
-        for use when subclassing the
-        :class:`HTTPAdapter `
-
-        :param req: The :class:`PreparedRequest ` used to generate the response.
-        :param resp: The urllib3 response object.
-        :rtype: requests.Response
-        """
-        response = Response()
-
-        # Fallback to None if there's no status_code, for whatever reason.
-        response.status_code = getattr(resp, "status", None)
-
-        # Make headers case-insensitive.
-        response.headers = CaseInsensitiveDict(getattr(resp, "headers", {}))
-
-        # Set encoding.
-        response.encoding = get_encoding_from_headers(response.headers)
-        response.raw = resp
-        response.reason = response.raw.reason
-
-        if isinstance(req.url, bytes):
-            response.url = req.url.decode("utf-8")
-        else:
-            response.url = req.url
-
-        # Add new cookies from the server.
-        extract_cookies_to_jar(response.cookies, req, resp)
-
-        # Give the Response some context.
-        response.request = req
-        response.connection = self
-
-        return response
-
-    def build_connection_pool_key_attributes(self, request, verify, cert=None):
-        """Build the PoolKey attributes used by urllib3 to return a connection.
-
-        This looks at the PreparedRequest, the user-specified verify value,
-        and the value of the cert parameter to determine what PoolKey values
-        to use to select a connection from a given urllib3 Connection Pool.
-
-        The SSL related pool key arguments are not consistently set. As of
-        this writing, use the following to determine what keys may be in that
-        dictionary:
-
-        * If ``verify`` is ``True``, ``"ssl_context"`` will be set and will be the
-          default Requests SSL Context
-        * If ``verify`` is ``False``, ``"ssl_context"`` will not be set but
-          ``"cert_reqs"`` will be set
-        * If ``verify`` is a string, (i.e., it is a user-specified trust bundle)
-          ``"ca_certs"`` will be set if the string is not a directory recognized
-          by :py:func:`os.path.isdir`, otherwise ``"ca_cert_dir"`` will be
-          set.
-        * If ``"cert"`` is specified, ``"cert_file"`` will always be set. If
-          ``"cert"`` is a tuple with a second item, ``"key_file"`` will also
-          be present
-
-        To override these settings, one may subclass this class, call this
-        method and use the above logic to change parameters as desired. For
-        example, if one wishes to use a custom :py:class:`ssl.SSLContext` one
-        must both set ``"ssl_context"`` and based on what else they require,
-        alter the other keys to ensure the desired behaviour.
-
-        :param request:
-            The PreparedReqest being sent over the connection.
-        :type request:
-            :class:`~requests.models.PreparedRequest`
-        :param verify:
-            Either a boolean, in which case it controls whether
-            we verify the server's TLS certificate, or a string, in which case it
-            must be a path to a CA bundle to use.
-        :param cert:
-            (optional) Any user-provided SSL certificate for client
-            authentication (a.k.a., mTLS). This may be a string (i.e., just
-            the path to a file which holds both certificate and key) or a
-            tuple of length 2 with the certificate file path and key file
-            path.
-        :returns:
-            A tuple of two dictionaries. The first is the "host parameters"
-            portion of the Pool Key including scheme, hostname, and port. The
-            second is a dictionary of SSLContext related parameters.
-        """
-        return _urllib3_request_context(request, verify, cert, self.poolmanager)
-
-    def get_connection_with_tls_context(self, request, verify, proxies=None, cert=None):
-        """Returns a urllib3 connection for the given request and TLS settings.
-        This should not be called from user code, and is only exposed for use
-        when subclassing the :class:`HTTPAdapter `.
-
-        :param request:
-            The :class:`PreparedRequest ` object to be sent
-            over the connection.
-        :param verify:
-            Either a boolean, in which case it controls whether we verify the
-            server's TLS certificate, or a string, in which case it must be a
-            path to a CA bundle to use.
-        :param proxies:
-            (optional) The proxies dictionary to apply to the request.
-        :param cert:
-            (optional) Any user-provided SSL certificate to be used for client
-            authentication (a.k.a., mTLS).
-        :rtype:
-            urllib3.ConnectionPool
-        """
-        proxy = select_proxy(request.url, proxies)
-        try:
-            host_params, pool_kwargs = self.build_connection_pool_key_attributes(
-                request,
-                verify,
-                cert,
-            )
-        except ValueError as e:
-            raise InvalidURL(e, request=request)
-        if proxy:
-            proxy = prepend_scheme_if_needed(proxy, "http")
-            proxy_url = parse_url(proxy)
-            if not proxy_url.host:
-                raise InvalidProxyURL(
-                    "Please check proxy URL. It is malformed "
-                    "and could be missing the host."
-                )
-            proxy_manager = self.proxy_manager_for(proxy)
-            conn = proxy_manager.connection_from_host(
-                **host_params, pool_kwargs=pool_kwargs
-            )
-        else:
-            # Only scheme should be lower case
-            conn = self.poolmanager.connection_from_host(
-                **host_params, pool_kwargs=pool_kwargs
-            )
-
-        return conn
-
-    def get_connection(self, url, proxies=None):
-        """DEPRECATED: Users should move to `get_connection_with_tls_context`
-        for all subclasses of HTTPAdapter using Requests>=2.32.2.
-
-        Returns a urllib3 connection for the given URL. This should not be
-        called from user code, and is only exposed for use when subclassing the
-        :class:`HTTPAdapter `.
-
-        :param url: The URL to connect to.
-        :param proxies: (optional) A Requests-style dictionary of proxies used on this request.
-        :rtype: urllib3.ConnectionPool
-        """
-        warnings.warn(
-            (
-                "`get_connection` has been deprecated in favor of "
-                "`get_connection_with_tls_context`. Custom HTTPAdapter subclasses "
-                "will need to migrate for Requests>=2.32.2. Please see "
-                "https://github.com/psf/requests/pull/6710 for more details."
-            ),
-            DeprecationWarning,
-        )
-        proxy = select_proxy(url, proxies)
-
-        if proxy:
-            proxy = prepend_scheme_if_needed(proxy, "http")
-            proxy_url = parse_url(proxy)
-            if not proxy_url.host:
-                raise InvalidProxyURL(
-                    "Please check proxy URL. It is malformed "
-                    "and could be missing the host."
-                )
-            proxy_manager = self.proxy_manager_for(proxy)
-            conn = proxy_manager.connection_from_url(url)
-        else:
-            # Only scheme should be lower case
-            parsed = urlparse(url)
-            url = parsed.geturl()
-            conn = self.poolmanager.connection_from_url(url)
-
-        return conn
-
-    def close(self):
-        """Disposes of any internal state.
-
-        Currently, this closes the PoolManager and any active ProxyManager,
-        which closes any pooled connections.
-        """
-        self.poolmanager.clear()
-        for proxy in self.proxy_manager.values():
-            proxy.clear()
-
-    def request_url(self, request, proxies):
-        """Obtain the url to use when making the final request.
-
-        If the message is being sent through a HTTP proxy, the full URL has to
-        be used. Otherwise, we should only use the path portion of the URL.
-
-        This should not be called from user code, and is only exposed for use
-        when subclassing the
-        :class:`HTTPAdapter `.
-
-        :param request: The :class:`PreparedRequest ` being sent.
-        :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs.
-        :rtype: str
-        """
-        proxy = select_proxy(request.url, proxies)
-        scheme = urlparse(request.url).scheme
-
-        is_proxied_http_request = proxy and scheme != "https"
-        using_socks_proxy = False
-        if proxy:
-            proxy_scheme = urlparse(proxy).scheme.lower()
-            using_socks_proxy = proxy_scheme.startswith("socks")
-
-        url = request.path_url
-        if url.startswith("//"):  # Don't confuse urllib3
-            url = f"/{url.lstrip('/')}"
-
-        if is_proxied_http_request and not using_socks_proxy:
-            url = urldefragauth(request.url)
-
-        return url
-
-    def add_headers(self, request, **kwargs):
-        """Add any headers needed by the connection. As of v2.0 this does
-        nothing by default, but is left for overriding by users that subclass
-        the :class:`HTTPAdapter `.
-
-        This should not be called from user code, and is only exposed for use
-        when subclassing the
-        :class:`HTTPAdapter `.
-
-        :param request: The :class:`PreparedRequest ` to add headers to.
-        :param kwargs: The keyword arguments from the call to send().
-        """
-        pass
-
-    def proxy_headers(self, proxy):
-        """Returns a dictionary of the headers to add to any request sent
-        through a proxy. This works with urllib3 magic to ensure that they are
-        correctly sent to the proxy, rather than in a tunnelled request if
-        CONNECT is being used.
-
-        This should not be called from user code, and is only exposed for use
-        when subclassing the
-        :class:`HTTPAdapter `.
-
-        :param proxy: The url of the proxy being used for this request.
-        :rtype: dict
-        """
-        headers = {}
-        username, password = get_auth_from_url(proxy)
-
-        if username:
-            headers["Proxy-Authorization"] = _basic_auth_str(username, password)
-
-        return headers
-
-    def send(
-        self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
-    ):
-        """Sends PreparedRequest object. Returns Response object.
-
-        :param request: The :class:`PreparedRequest ` being sent.
-        :param stream: (optional) Whether to stream the request content.
-        :param timeout: (optional) How long to wait for the server to send
-            data before giving up, as a float, or a :ref:`(connect timeout,
-            read timeout) ` tuple.
-        :type timeout: float or tuple or urllib3 Timeout object
-        :param verify: (optional) Either a boolean, in which case it controls whether
-            we verify the server's TLS certificate, or a string, in which case it
-            must be a path to a CA bundle to use
-        :param cert: (optional) Any user-provided SSL certificate to be trusted.
-        :param proxies: (optional) The proxies dictionary to apply to the request.
-        :rtype: requests.Response
-        """
-
-        try:
-            conn = self.get_connection_with_tls_context(
-                request, verify, proxies=proxies, cert=cert
-            )
-        except LocationValueError as e:
-            raise InvalidURL(e, request=request)
-
-        self.cert_verify(conn, request.url, verify, cert)
-        url = self.request_url(request, proxies)
-        self.add_headers(
-            request,
-            stream=stream,
-            timeout=timeout,
-            verify=verify,
-            cert=cert,
-            proxies=proxies,
-        )
-
-        chunked = not (request.body is None or "Content-Length" in request.headers)
-
-        if isinstance(timeout, tuple):
-            try:
-                connect, read = timeout
-                timeout = TimeoutSauce(connect=connect, read=read)
-            except ValueError:
-                raise ValueError(
-                    f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
-                    f"or a single float to set both timeouts to the same value."
-                )
-        elif isinstance(timeout, TimeoutSauce):
-            pass
-        else:
-            timeout = TimeoutSauce(connect=timeout, read=timeout)
-
-        try:
-            resp = conn.urlopen(
-                method=request.method,
-                url=url,
-                body=request.body,
-                headers=request.headers,
-                redirect=False,
-                assert_same_host=False,
-                preload_content=False,
-                decode_content=False,
-                retries=self.max_retries,
-                timeout=timeout,
-                chunked=chunked,
-            )
-
-        except (ProtocolError, OSError) as err:
-            raise ConnectionError(err, request=request)
-
-        except MaxRetryError as e:
-            if isinstance(e.reason, ConnectTimeoutError):
-                # TODO: Remove this in 3.0.0: see #2811
-                if not isinstance(e.reason, NewConnectionError):
-                    raise ConnectTimeout(e, request=request)
-
-            if isinstance(e.reason, ResponseError):
-                raise RetryError(e, request=request)
-
-            if isinstance(e.reason, _ProxyError):
-                raise ProxyError(e, request=request)
-
-            if isinstance(e.reason, _SSLError):
-                # This branch is for urllib3 v1.22 and later.
-                raise SSLError(e, request=request)
-
-            raise ConnectionError(e, request=request)
-
-        except ClosedPoolError as e:
-            raise ConnectionError(e, request=request)
-
-        except _ProxyError as e:
-            raise ProxyError(e)
-
-        except (_SSLError, _HTTPError) as e:
-            if isinstance(e, _SSLError):
-                # This branch is for urllib3 versions earlier than v1.22
-                raise SSLError(e, request=request)
-            elif isinstance(e, ReadTimeoutError):
-                raise ReadTimeout(e, request=request)
-            elif isinstance(e, _InvalidHeader):
-                raise InvalidHeader(e, request=request)
-            else:
-                raise
-
-        return self.build_response(request, resp)
diff --git a/apps/bitwarden_event_logs/lib/requests/api.py b/apps/bitwarden_event_logs/lib/requests/api.py
deleted file mode 100755
index 59607445..00000000
--- a/apps/bitwarden_event_logs/lib/requests/api.py
+++ /dev/null
@@ -1,157 +0,0 @@
-"""
-requests.api
-~~~~~~~~~~~~
-
-This module implements the Requests API.
-
-:copyright: (c) 2012 by Kenneth Reitz.
-:license: Apache2, see LICENSE for more details.
-"""
-
-from . import sessions
-
-
-def request(method, url, **kwargs):
-    """Constructs and sends a :class:`Request `.
-
-    :param method: method for the new :class:`Request` object: ``GET``, ``OPTIONS``, ``HEAD``, ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
-    :param url: URL for the new :class:`Request` object.
-    :param params: (optional) Dictionary, list of tuples or bytes to send
-        in the query string for the :class:`Request`.
-    :param data: (optional) Dictionary, list of tuples, bytes, or file-like
-        object to send in the body of the :class:`Request`.
-    :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
-    :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
-    :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
-    :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.
-        ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``
-        or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content_type'`` is a string
-        defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers
-        to add for the file.
-    :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
-    :param timeout: (optional) How many seconds to wait for the server to send data
-        before giving up, as a float, or a :ref:`(connect timeout, read
-        timeout) ` tuple.
-    :type timeout: float or tuple
-    :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.
-    :type allow_redirects: bool
-    :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
-    :param verify: (optional) Either a boolean, in which case it controls whether we verify
-            the server's TLS certificate, or a string, in which case it must be a path
-            to a CA bundle to use. Defaults to ``True``.
-    :param stream: (optional) if ``False``, the response content will be immediately downloaded.
-    :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
-    :return: :class:`Response ` object
-    :rtype: requests.Response
-
-    Usage::
-
-      >>> import requests
-      >>> req = requests.request('GET', 'https://httpbin.org/get')
-      >>> req
-      
-    """
-
-    # By using the 'with' statement we are sure the session is closed, thus we
-    # avoid leaving sockets open which can trigger a ResourceWarning in some
-    # cases, and look like a memory leak in others.
-    with sessions.Session() as session:
-        return session.request(method=method, url=url, **kwargs)
-
-
-def get(url, params=None, **kwargs):
-    r"""Sends a GET request.
-
-    :param url: URL for the new :class:`Request` object.
-    :param params: (optional) Dictionary, list of tuples or bytes to send
-        in the query string for the :class:`Request`.
-    :param \*\*kwargs: Optional arguments that ``request`` takes.
-    :return: :class:`Response ` object
-    :rtype: requests.Response
-    """
-
-    return request("get", url, params=params, **kwargs)
-
-
-def options(url, **kwargs):
-    r"""Sends an OPTIONS request.
-
-    :param url: URL for the new :class:`Request` object.
-    :param \*\*kwargs: Optional arguments that ``request`` takes.
-    :return: :class:`Response ` object
-    :rtype: requests.Response
-    """
-
-    return request("options", url, **kwargs)
-
-
-def head(url, **kwargs):
-    r"""Sends a HEAD request.
-
-    :param url: URL for the new :class:`Request` object.
-    :param \*\*kwargs: Optional arguments that ``request`` takes. If
-        `allow_redirects` is not provided, it will be set to `False` (as
-        opposed to the default :meth:`request` behavior).
-    :return: :class:`Response ` object
-    :rtype: requests.Response
-    """
-
-    kwargs.setdefault("allow_redirects", False)
-    return request("head", url, **kwargs)
-
-
-def post(url, data=None, json=None, **kwargs):
-    r"""Sends a POST request.
-
-    :param url: URL for the new :class:`Request` object.
-    :param data: (optional) Dictionary, list of tuples, bytes, or file-like
-        object to send in the body of the :class:`Request`.
-    :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
-    :param \*\*kwargs: Optional arguments that ``request`` takes.
-    :return: :class:`Response ` object
-    :rtype: requests.Response
-    """
-
-    return request("post", url, data=data, json=json, **kwargs)
-
-
-def put(url, data=None, **kwargs):
-    r"""Sends a PUT request.
-
-    :param url: URL for the new :class:`Request` object.
-    :param data: (optional) Dictionary, list of tuples, bytes, or file-like
-        object to send in the body of the :class:`Request`.
-    :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
-    :param \*\*kwargs: Optional arguments that ``request`` takes.
-    :return: :class:`Response ` object
-    :rtype: requests.Response
-    """
-
-    return request("put", url, data=data, **kwargs)
-
-
-def patch(url, data=None, **kwargs):
-    r"""Sends a PATCH request.
-
-    :param url: URL for the new :class:`Request` object.
-    :param data: (optional) Dictionary, list of tuples, bytes, or file-like
-        object to send in the body of the :class:`Request`.
-    :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
-    :param \*\*kwargs: Optional arguments that ``request`` takes.
-    :return: :class:`Response ` object
-    :rtype: requests.Response
-    """
-
-    return request("patch", url, data=data, **kwargs)
-
-
-def delete(url, **kwargs):
-    r"""Sends a DELETE request.
-
-    :param url: URL for the new :class:`Request` object.
-    :param \*\*kwargs: Optional arguments that ``request`` takes.
-    :return: :class:`Response ` object
-    :rtype: requests.Response
-    """
-
-    return request("delete", url, **kwargs)
diff --git a/apps/bitwarden_event_logs/lib/requests/auth.py b/apps/bitwarden_event_logs/lib/requests/auth.py
deleted file mode 100755
index 4a7ce6dc..00000000
--- a/apps/bitwarden_event_logs/lib/requests/auth.py
+++ /dev/null
@@ -1,314 +0,0 @@
-"""
-requests.auth
-~~~~~~~~~~~~~
-
-This module contains the authentication handlers for Requests.
-"""
-
-import hashlib
-import os
-import re
-import threading
-import time
-import warnings
-from base64 import b64encode
-
-from ._internal_utils import to_native_string
-from .compat import basestring, str, urlparse
-from .cookies import extract_cookies_to_jar
-from .utils import parse_dict_header
-
-CONTENT_TYPE_FORM_URLENCODED = "application/x-www-form-urlencoded"
-CONTENT_TYPE_MULTI_PART = "multipart/form-data"
-
-
-def _basic_auth_str(username, password):
-    """Returns a Basic Auth string."""
-
-    # "I want us to put a big-ol' comment on top of it that
-    # says that this behaviour is dumb but we need to preserve
-    # it because people are relying on it."
-    #    - Lukasa
-    #
-    # These are here solely to maintain backwards compatibility
-    # for things like ints. This will be removed in 3.0.0.
-    if not isinstance(username, basestring):
-        warnings.warn(
-            "Non-string usernames will no longer be supported in Requests "
-            "3.0.0. Please convert the object you've passed in ({!r}) to "
-            "a string or bytes object in the near future to avoid "
-            "problems.".format(username),
-            category=DeprecationWarning,
-        )
-        username = str(username)
-
-    if not isinstance(password, basestring):
-        warnings.warn(
-            "Non-string passwords will no longer be supported in Requests "
-            "3.0.0. Please convert the object you've passed in ({!r}) to "
-            "a string or bytes object in the near future to avoid "
-            "problems.".format(type(password)),
-            category=DeprecationWarning,
-        )
-        password = str(password)
-    # -- End Removal --
-
-    if isinstance(username, str):
-        username = username.encode("latin1")
-
-    if isinstance(password, str):
-        password = password.encode("latin1")
-
-    authstr = "Basic " + to_native_string(
-        b64encode(b":".join((username, password))).strip()
-    )
-
-    return authstr
-
-
-class AuthBase:
-    """Base class that all auth implementations derive from"""
-
-    def __call__(self, r):
-        raise NotImplementedError("Auth hooks must be callable.")
-
-
-class HTTPBasicAuth(AuthBase):
-    """Attaches HTTP Basic Authentication to the given Request object."""
-
-    def __init__(self, username, password):
-        self.username = username
-        self.password = password
-
-    def __eq__(self, other):
-        return all(
-            [
-                self.username == getattr(other, "username", None),
-                self.password == getattr(other, "password", None),
-            ]
-        )
-
-    def __ne__(self, other):
-        return not self == other
-
-    def __call__(self, r):
-        r.headers["Authorization"] = _basic_auth_str(self.username, self.password)
-        return r
-
-
-class HTTPProxyAuth(HTTPBasicAuth):
-    """Attaches HTTP Proxy Authentication to a given Request object."""
-
-    def __call__(self, r):
-        r.headers["Proxy-Authorization"] = _basic_auth_str(self.username, self.password)
-        return r
-
-
-class HTTPDigestAuth(AuthBase):
-    """Attaches HTTP Digest Authentication to the given Request object."""
-
-    def __init__(self, username, password):
-        self.username = username
-        self.password = password
-        # Keep state in per-thread local storage
-        self._thread_local = threading.local()
-
-    def init_per_thread_state(self):
-        # Ensure state is initialized just once per-thread
-        if not hasattr(self._thread_local, "init"):
-            self._thread_local.init = True
-            self._thread_local.last_nonce = ""
-            self._thread_local.nonce_count = 0
-            self._thread_local.chal = {}
-            self._thread_local.pos = None
-            self._thread_local.num_401_calls = None
-
-    def build_digest_header(self, method, url):
-        """
-        :rtype: str
-        """
-
-        realm = self._thread_local.chal["realm"]
-        nonce = self._thread_local.chal["nonce"]
-        qop = self._thread_local.chal.get("qop")
-        algorithm = self._thread_local.chal.get("algorithm")
-        opaque = self._thread_local.chal.get("opaque")
-        hash_utf8 = None
-
-        if algorithm is None:
-            _algorithm = "MD5"
-        else:
-            _algorithm = algorithm.upper()
-        # lambdas assume digest modules are imported at the top level
-        if _algorithm == "MD5" or _algorithm == "MD5-SESS":
-
-            def md5_utf8(x):
-                if isinstance(x, str):
-                    x = x.encode("utf-8")
-                return hashlib.md5(x).hexdigest()
-
-            hash_utf8 = md5_utf8
-        elif _algorithm == "SHA":
-
-            def sha_utf8(x):
-                if isinstance(x, str):
-                    x = x.encode("utf-8")
-                return hashlib.sha1(x).hexdigest()
-
-            hash_utf8 = sha_utf8
-        elif _algorithm == "SHA-256":
-
-            def sha256_utf8(x):
-                if isinstance(x, str):
-                    x = x.encode("utf-8")
-                return hashlib.sha256(x).hexdigest()
-
-            hash_utf8 = sha256_utf8
-        elif _algorithm == "SHA-512":
-
-            def sha512_utf8(x):
-                if isinstance(x, str):
-                    x = x.encode("utf-8")
-                return hashlib.sha512(x).hexdigest()
-
-            hash_utf8 = sha512_utf8
-
-        KD = lambda s, d: hash_utf8(f"{s}:{d}")  # noqa:E731
-
-        if hash_utf8 is None:
-            return None
-
-        # XXX not implemented yet
-        entdig = None
-        p_parsed = urlparse(url)
-        #: path is request-uri defined in RFC 2616 which should not be empty
-        path = p_parsed.path or "/"
-        if p_parsed.query:
-            path += f"?{p_parsed.query}"
-
-        A1 = f"{self.username}:{realm}:{self.password}"
-        A2 = f"{method}:{path}"
-
-        HA1 = hash_utf8(A1)
-        HA2 = hash_utf8(A2)
-
-        if nonce == self._thread_local.last_nonce:
-            self._thread_local.nonce_count += 1
-        else:
-            self._thread_local.nonce_count = 1
-        ncvalue = f"{self._thread_local.nonce_count:08x}"
-        s = str(self._thread_local.nonce_count).encode("utf-8")
-        s += nonce.encode("utf-8")
-        s += time.ctime().encode("utf-8")
-        s += os.urandom(8)
-
-        cnonce = hashlib.sha1(s).hexdigest()[:16]
-        if _algorithm == "MD5-SESS":
-            HA1 = hash_utf8(f"{HA1}:{nonce}:{cnonce}")
-
-        if not qop:
-            respdig = KD(HA1, f"{nonce}:{HA2}")
-        elif qop == "auth" or "auth" in qop.split(","):
-            noncebit = f"{nonce}:{ncvalue}:{cnonce}:auth:{HA2}"
-            respdig = KD(HA1, noncebit)
-        else:
-            # XXX handle auth-int.
-            return None
-
-        self._thread_local.last_nonce = nonce
-
-        # XXX should the partial digests be encoded too?
-        base = (
-            f'username="{self.username}", realm="{realm}", nonce="{nonce}", '
-            f'uri="{path}", response="{respdig}"'
-        )
-        if opaque:
-            base += f', opaque="{opaque}"'
-        if algorithm:
-            base += f', algorithm="{algorithm}"'
-        if entdig:
-            base += f', digest="{entdig}"'
-        if qop:
-            base += f', qop="auth", nc={ncvalue}, cnonce="{cnonce}"'
-
-        return f"Digest {base}"
-
-    def handle_redirect(self, r, **kwargs):
-        """Reset num_401_calls counter on redirects."""
-        if r.is_redirect:
-            self._thread_local.num_401_calls = 1
-
-    def handle_401(self, r, **kwargs):
-        """
-        Takes the given response and tries digest-auth, if needed.
-
-        :rtype: requests.Response
-        """
-
-        # If response is not 4xx, do not auth
-        # See https://github.com/psf/requests/issues/3772
-        if not 400 <= r.status_code < 500:
-            self._thread_local.num_401_calls = 1
-            return r
-
-        if self._thread_local.pos is not None:
-            # Rewind the file position indicator of the body to where
-            # it was to resend the request.
-            r.request.body.seek(self._thread_local.pos)
-        s_auth = r.headers.get("www-authenticate", "")
-
-        if "digest" in s_auth.lower() and self._thread_local.num_401_calls < 2:
-            self._thread_local.num_401_calls += 1
-            pat = re.compile(r"digest ", flags=re.IGNORECASE)
-            self._thread_local.chal = parse_dict_header(pat.sub("", s_auth, count=1))
-
-            # Consume content and release the original connection
-            # to allow our new request to reuse the same one.
-            r.content
-            r.close()
-            prep = r.request.copy()
-            extract_cookies_to_jar(prep._cookies, r.request, r.raw)
-            prep.prepare_cookies(prep._cookies)
-
-            prep.headers["Authorization"] = self.build_digest_header(
-                prep.method, prep.url
-            )
-            _r = r.connection.send(prep, **kwargs)
-            _r.history.append(r)
-            _r.request = prep
-
-            return _r
-
-        self._thread_local.num_401_calls = 1
-        return r
-
-    def __call__(self, r):
-        # Initialize per-thread state, if needed
-        self.init_per_thread_state()
-        # If we have a saved nonce, skip the 401
-        if self._thread_local.last_nonce:
-            r.headers["Authorization"] = self.build_digest_header(r.method, r.url)
-        try:
-            self._thread_local.pos = r.body.tell()
-        except AttributeError:
-            # In the case of HTTPDigestAuth being reused and the body of
-            # the previous request was a file-like object, pos has the
-            # file position of the previous body. Ensure it's set to
-            # None.
-            self._thread_local.pos = None
-        r.register_hook("response", self.handle_401)
-        r.register_hook("response", self.handle_redirect)
-        self._thread_local.num_401_calls = 1
-
-        return r
-
-    def __eq__(self, other):
-        return all(
-            [
-                self.username == getattr(other, "username", None),
-                self.password == getattr(other, "password", None),
-            ]
-        )
-
-    def __ne__(self, other):
-        return not self == other
diff --git a/apps/bitwarden_event_logs/lib/requests/certs.py b/apps/bitwarden_event_logs/lib/requests/certs.py
deleted file mode 100755
index be422c3e..00000000
--- a/apps/bitwarden_event_logs/lib/requests/certs.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env python
-
-"""
-requests.certs
-~~~~~~~~~~~~~~
-
-This module returns the preferred default CA certificate bundle. There is
-only one — the one from the certifi package.
-
-If you are packaging Requests, e.g., for a Linux distribution or a managed
-environment, you can change the definition of where() to return a separately
-packaged CA bundle.
-"""
-from certifi import where
-
-if __name__ == "__main__":
-    print(where())
diff --git a/apps/bitwarden_event_logs/lib/requests/compat.py b/apps/bitwarden_event_logs/lib/requests/compat.py
deleted file mode 100755
index 7f9d7543..00000000
--- a/apps/bitwarden_event_logs/lib/requests/compat.py
+++ /dev/null
@@ -1,106 +0,0 @@
-"""
-requests.compat
-~~~~~~~~~~~~~~~
-
-This module previously handled import compatibility issues
-between Python 2 and Python 3. It remains for backwards
-compatibility until the next major version.
-"""
-
-import importlib
-import sys
-
-# -------
-# urllib3
-# -------
-from urllib3 import __version__ as urllib3_version
-
-# Detect which major version of urllib3 is being used.
-try:
-    is_urllib3_1 = int(urllib3_version.split(".")[0]) == 1
-except (TypeError, AttributeError):
-    # If we can't discern a version, prefer old functionality.
-    is_urllib3_1 = True
-
-# -------------------
-# Character Detection
-# -------------------
-
-
-def _resolve_char_detection():
-    """Find supported character detection libraries."""
-    chardet = None
-    for lib in ("chardet", "charset_normalizer"):
-        if chardet is None:
-            try:
-                chardet = importlib.import_module(lib)
-            except ImportError:
-                pass
-    return chardet
-
-
-chardet = _resolve_char_detection()
-
-# -------
-# Pythons
-# -------
-
-# Syntax sugar.
-_ver = sys.version_info
-
-#: Python 2.x?
-is_py2 = _ver[0] == 2
-
-#: Python 3.x?
-is_py3 = _ver[0] == 3
-
-# json/simplejson module import resolution
-has_simplejson = False
-try:
-    import simplejson as json
-
-    has_simplejson = True
-except ImportError:
-    import json
-
-if has_simplejson:
-    from simplejson import JSONDecodeError
-else:
-    from json import JSONDecodeError
-
-# Keep OrderedDict for backwards compatibility.
-from collections import OrderedDict
-from collections.abc import Callable, Mapping, MutableMapping
-from http import cookiejar as cookielib
-from http.cookies import Morsel
-from io import StringIO
-
-# --------------
-# Legacy Imports
-# --------------
-from urllib.parse import (
-    quote,
-    quote_plus,
-    unquote,
-    unquote_plus,
-    urldefrag,
-    urlencode,
-    urljoin,
-    urlparse,
-    urlsplit,
-    urlunparse,
-)
-from urllib.request import (
-    getproxies,
-    getproxies_environment,
-    parse_http_list,
-    proxy_bypass,
-    proxy_bypass_environment,
-)
-
-builtin_str = str
-str = str
-bytes = bytes
-basestring = (str, bytes)
-numeric_types = (int, float)
-integer_types = (int,)
diff --git a/apps/bitwarden_event_logs/lib/requests/cookies.py b/apps/bitwarden_event_logs/lib/requests/cookies.py
deleted file mode 100755
index f69d0cda..00000000
--- a/apps/bitwarden_event_logs/lib/requests/cookies.py
+++ /dev/null
@@ -1,561 +0,0 @@
-"""
-requests.cookies
-~~~~~~~~~~~~~~~~
-
-Compatibility code to be able to use `http.cookiejar.CookieJar` with requests.
-
-requests.utils imports from here, so be careful with imports.
-"""
-
-import calendar
-import copy
-import time
-
-from ._internal_utils import to_native_string
-from .compat import Morsel, MutableMapping, cookielib, urlparse, urlunparse
-
-try:
-    import threading
-except ImportError:
-    import dummy_threading as threading
-
-
-class MockRequest:
-    """Wraps a `requests.Request` to mimic a `urllib2.Request`.
-
-    The code in `http.cookiejar.CookieJar` expects this interface in order to correctly
-    manage cookie policies, i.e., determine whether a cookie can be set, given the
-    domains of the request and the cookie.
-
-    The original request object is read-only. The client is responsible for collecting
-    the new headers via `get_new_headers()` and interpreting them appropriately. You
-    probably want `get_cookie_header`, defined below.
-    """
-
-    def __init__(self, request):
-        self._r = request
-        self._new_headers = {}
-        self.type = urlparse(self._r.url).scheme
-
-    def get_type(self):
-        return self.type
-
-    def get_host(self):
-        return urlparse(self._r.url).netloc
-
-    def get_origin_req_host(self):
-        return self.get_host()
-
-    def get_full_url(self):
-        # Only return the response's URL if the user hadn't set the Host
-        # header
-        if not self._r.headers.get("Host"):
-            return self._r.url
-        # If they did set it, retrieve it and reconstruct the expected domain
-        host = to_native_string(self._r.headers["Host"], encoding="utf-8")
-        parsed = urlparse(self._r.url)
-        # Reconstruct the URL as we expect it
-        return urlunparse(
-            [
-                parsed.scheme,
-                host,
-                parsed.path,
-                parsed.params,
-                parsed.query,
-                parsed.fragment,
-            ]
-        )
-
-    def is_unverifiable(self):
-        return True
-
-    def has_header(self, name):
-        return name in self._r.headers or name in self._new_headers
-
-    def get_header(self, name, default=None):
-        return self._r.headers.get(name, self._new_headers.get(name, default))
-
-    def add_header(self, key, val):
-        """cookiejar has no legitimate use for this method; add it back if you find one."""
-        raise NotImplementedError(
-            "Cookie headers should be added with add_unredirected_header()"
-        )
-
-    def add_unredirected_header(self, name, value):
-        self._new_headers[name] = value
-
-    def get_new_headers(self):
-        return self._new_headers
-
-    @property
-    def unverifiable(self):
-        return self.is_unverifiable()
-
-    @property
-    def origin_req_host(self):
-        return self.get_origin_req_host()
-
-    @property
-    def host(self):
-        return self.get_host()
-
-
-class MockResponse:
-    """Wraps a `httplib.HTTPMessage` to mimic a `urllib.addinfourl`.
-
-    ...what? Basically, expose the parsed HTTP headers from the server response
-    the way `http.cookiejar` expects to see them.
-    """
-
-    def __init__(self, headers):
-        """Make a MockResponse for `cookiejar` to read.
-
-        :param headers: a httplib.HTTPMessage or analogous carrying the headers
-        """
-        self._headers = headers
-
-    def info(self):
-        return self._headers
-
-    def getheaders(self, name):
-        self._headers.getheaders(name)
-
-
-def extract_cookies_to_jar(jar, request, response):
-    """Extract the cookies from the response into a CookieJar.
-
-    :param jar: http.cookiejar.CookieJar (not necessarily a RequestsCookieJar)
-    :param request: our own requests.Request object
-    :param response: urllib3.HTTPResponse object
-    """
-    if not (hasattr(response, "_original_response") and response._original_response):
-        return
-    # the _original_response field is the wrapped httplib.HTTPResponse object,
-    req = MockRequest(request)
-    # pull out the HTTPMessage with the headers and put it in the mock:
-    res = MockResponse(response._original_response.msg)
-    jar.extract_cookies(res, req)
-
-
-def get_cookie_header(jar, request):
-    """
-    Produce an appropriate Cookie header string to be sent with `request`, or None.
-
-    :rtype: str
-    """
-    r = MockRequest(request)
-    jar.add_cookie_header(r)
-    return r.get_new_headers().get("Cookie")
-
-
-def remove_cookie_by_name(cookiejar, name, domain=None, path=None):
-    """Unsets a cookie by name, by default over all domains and paths.
-
-    Wraps CookieJar.clear(), is O(n).
-    """
-    clearables = []
-    for cookie in cookiejar:
-        if cookie.name != name:
-            continue
-        if domain is not None and domain != cookie.domain:
-            continue
-        if path is not None and path != cookie.path:
-            continue
-        clearables.append((cookie.domain, cookie.path, cookie.name))
-
-    for domain, path, name in clearables:
-        cookiejar.clear(domain, path, name)
-
-
-class CookieConflictError(RuntimeError):
-    """There are two cookies that meet the criteria specified in the cookie jar.
-    Use .get and .set and include domain and path args in order to be more specific.
-    """
-
-
-class RequestsCookieJar(cookielib.CookieJar, MutableMapping):
-    """Compatibility class; is a http.cookiejar.CookieJar, but exposes a dict
-    interface.
-
-    This is the CookieJar we create by default for requests and sessions that
-    don't specify one, since some clients may expect response.cookies and
-    session.cookies to support dict operations.
-
-    Requests does not use the dict interface internally; it's just for
-    compatibility with external client code. All requests code should work
-    out of the box with externally provided instances of ``CookieJar``, e.g.
-    ``LWPCookieJar`` and ``FileCookieJar``.
-
-    Unlike a regular CookieJar, this class is pickleable.
-
-    .. warning:: dictionary operations that are normally O(1) may be O(n).
-    """
-
-    def get(self, name, default=None, domain=None, path=None):
-        """Dict-like get() that also supports optional domain and path args in
-        order to resolve naming collisions from using one cookie jar over
-        multiple domains.
-
-        .. warning:: operation is O(n), not O(1).
-        """
-        try:
-            return self._find_no_duplicates(name, domain, path)
-        except KeyError:
-            return default
-
-    def set(self, name, value, **kwargs):
-        """Dict-like set() that also supports optional domain and path args in
-        order to resolve naming collisions from using one cookie jar over
-        multiple domains.
-        """
-        # support client code that unsets cookies by assignment of a None value:
-        if value is None:
-            remove_cookie_by_name(
-                self, name, domain=kwargs.get("domain"), path=kwargs.get("path")
-            )
-            return
-
-        if isinstance(value, Morsel):
-            c = morsel_to_cookie(value)
-        else:
-            c = create_cookie(name, value, **kwargs)
-        self.set_cookie(c)
-        return c
-
-    def iterkeys(self):
-        """Dict-like iterkeys() that returns an iterator of names of cookies
-        from the jar.
-
-        .. seealso:: itervalues() and iteritems().
-        """
-        for cookie in iter(self):
-            yield cookie.name
-
-    def keys(self):
-        """Dict-like keys() that returns a list of names of cookies from the
-        jar.
-
-        .. seealso:: values() and items().
-        """
-        return list(self.iterkeys())
-
-    def itervalues(self):
-        """Dict-like itervalues() that returns an iterator of values of cookies
-        from the jar.
-
-        .. seealso:: iterkeys() and iteritems().
-        """
-        for cookie in iter(self):
-            yield cookie.value
-
-    def values(self):
-        """Dict-like values() that returns a list of values of cookies from the
-        jar.
-
-        .. seealso:: keys() and items().
-        """
-        return list(self.itervalues())
-
-    def iteritems(self):
-        """Dict-like iteritems() that returns an iterator of name-value tuples
-        from the jar.
-
-        .. seealso:: iterkeys() and itervalues().
-        """
-        for cookie in iter(self):
-            yield cookie.name, cookie.value
-
-    def items(self):
-        """Dict-like items() that returns a list of name-value tuples from the
-        jar. Allows client-code to call ``dict(RequestsCookieJar)`` and get a
-        vanilla python dict of key value pairs.
-
-        .. seealso:: keys() and values().
-        """
-        return list(self.iteritems())
-
-    def list_domains(self):
-        """Utility method to list all the domains in the jar."""
-        domains = []
-        for cookie in iter(self):
-            if cookie.domain not in domains:
-                domains.append(cookie.domain)
-        return domains
-
-    def list_paths(self):
-        """Utility method to list all the paths in the jar."""
-        paths = []
-        for cookie in iter(self):
-            if cookie.path not in paths:
-                paths.append(cookie.path)
-        return paths
-
-    def multiple_domains(self):
-        """Returns True if there are multiple domains in the jar.
-        Returns False otherwise.
-
-        :rtype: bool
-        """
-        domains = []
-        for cookie in iter(self):
-            if cookie.domain is not None and cookie.domain in domains:
-                return True
-            domains.append(cookie.domain)
-        return False  # there is only one domain in jar
-
-    def get_dict(self, domain=None, path=None):
-        """Takes as an argument an optional domain and path and returns a plain
-        old Python dict of name-value pairs of cookies that meet the
-        requirements.
-
-        :rtype: dict
-        """
-        dictionary = {}
-        for cookie in iter(self):
-            if (domain is None or cookie.domain == domain) and (
-                path is None or cookie.path == path
-            ):
-                dictionary[cookie.name] = cookie.value
-        return dictionary
-
-    def __contains__(self, name):
-        try:
-            return super().__contains__(name)
-        except CookieConflictError:
-            return True
-
-    def __getitem__(self, name):
-        """Dict-like __getitem__() for compatibility with client code. Throws
-        exception if there are more than one cookie with name. In that case,
-        use the more explicit get() method instead.
-
-        .. warning:: operation is O(n), not O(1).
-        """
-        return self._find_no_duplicates(name)
-
-    def __setitem__(self, name, value):
-        """Dict-like __setitem__ for compatibility with client code. Throws
-        exception if there is already a cookie of that name in the jar. In that
-        case, use the more explicit set() method instead.
-        """
-        self.set(name, value)
-
-    def __delitem__(self, name):
-        """Deletes a cookie given a name. Wraps ``http.cookiejar.CookieJar``'s
-        ``remove_cookie_by_name()``.
-        """
-        remove_cookie_by_name(self, name)
-
-    def set_cookie(self, cookie, *args, **kwargs):
-        if (
-            hasattr(cookie.value, "startswith")
-            and cookie.value.startswith('"')
-            and cookie.value.endswith('"')
-        ):
-            cookie.value = cookie.value.replace('\\"', "")
-        return super().set_cookie(cookie, *args, **kwargs)
-
-    def update(self, other):
-        """Updates this jar with cookies from another CookieJar or dict-like"""
-        if isinstance(other, cookielib.CookieJar):
-            for cookie in other:
-                self.set_cookie(copy.copy(cookie))
-        else:
-            super().update(other)
-
-    def _find(self, name, domain=None, path=None):
-        """Requests uses this method internally to get cookie values.
-
-        If there are conflicting cookies, _find arbitrarily chooses one.
-        See _find_no_duplicates if you want an exception thrown if there are
-        conflicting cookies.
-
-        :param name: a string containing name of cookie
-        :param domain: (optional) string containing domain of cookie
-        :param path: (optional) string containing path of cookie
-        :return: cookie.value
-        """
-        for cookie in iter(self):
-            if cookie.name == name:
-                if domain is None or cookie.domain == domain:
-                    if path is None or cookie.path == path:
-                        return cookie.value
-
-        raise KeyError(f"name={name!r}, domain={domain!r}, path={path!r}")
-
-    def _find_no_duplicates(self, name, domain=None, path=None):
-        """Both ``__get_item__`` and ``get`` call this function: it's never
-        used elsewhere in Requests.
-
-        :param name: a string containing name of cookie
-        :param domain: (optional) string containing domain of cookie
-        :param path: (optional) string containing path of cookie
-        :raises KeyError: if cookie is not found
-        :raises CookieConflictError: if there are multiple cookies
-            that match name and optionally domain and path
-        :return: cookie.value
-        """
-        toReturn = None
-        for cookie in iter(self):
-            if cookie.name == name:
-                if domain is None or cookie.domain == domain:
-                    if path is None or cookie.path == path:
-                        if toReturn is not None:
-                            # if there are multiple cookies that meet passed in criteria
-                            raise CookieConflictError(
-                                f"There are multiple cookies with name, {name!r}"
-                            )
-                        # we will eventually return this as long as no cookie conflict
-                        toReturn = cookie.value
-
-        if toReturn:
-            return toReturn
-        raise KeyError(f"name={name!r}, domain={domain!r}, path={path!r}")
-
-    def __getstate__(self):
-        """Unlike a normal CookieJar, this class is pickleable."""
-        state = self.__dict__.copy()
-        # remove the unpickleable RLock object
-        state.pop("_cookies_lock")
-        return state
-
-    def __setstate__(self, state):
-        """Unlike a normal CookieJar, this class is pickleable."""
-        self.__dict__.update(state)
-        if "_cookies_lock" not in self.__dict__:
-            self._cookies_lock = threading.RLock()
-
-    def copy(self):
-        """Return a copy of this RequestsCookieJar."""
-        new_cj = RequestsCookieJar()
-        new_cj.set_policy(self.get_policy())
-        new_cj.update(self)
-        return new_cj
-
-    def get_policy(self):
-        """Return the CookiePolicy instance used."""
-        return self._policy
-
-
-def _copy_cookie_jar(jar):
-    if jar is None:
-        return None
-
-    if hasattr(jar, "copy"):
-        # We're dealing with an instance of RequestsCookieJar
-        return jar.copy()
-    # We're dealing with a generic CookieJar instance
-    new_jar = copy.copy(jar)
-    new_jar.clear()
-    for cookie in jar:
-        new_jar.set_cookie(copy.copy(cookie))
-    return new_jar
-
-
-def create_cookie(name, value, **kwargs):
-    """Make a cookie from underspecified parameters.
-
-    By default, the pair of `name` and `value` will be set for the domain ''
-    and sent on every request (this is sometimes called a "supercookie").
-    """
-    result = {
-        "version": 0,
-        "name": name,
-        "value": value,
-        "port": None,
-        "domain": "",
-        "path": "/",
-        "secure": False,
-        "expires": None,
-        "discard": True,
-        "comment": None,
-        "comment_url": None,
-        "rest": {"HttpOnly": None},
-        "rfc2109": False,
-    }
-
-    badargs = set(kwargs) - set(result)
-    if badargs:
-        raise TypeError(
-            f"create_cookie() got unexpected keyword arguments: {list(badargs)}"
-        )
-
-    result.update(kwargs)
-    result["port_specified"] = bool(result["port"])
-    result["domain_specified"] = bool(result["domain"])
-    result["domain_initial_dot"] = result["domain"].startswith(".")
-    result["path_specified"] = bool(result["path"])
-
-    return cookielib.Cookie(**result)
-
-
-def morsel_to_cookie(morsel):
-    """Convert a Morsel object into a Cookie containing the one k/v pair."""
-
-    expires = None
-    if morsel["max-age"]:
-        try:
-            expires = int(time.time() + int(morsel["max-age"]))
-        except ValueError:
-            raise TypeError(f"max-age: {morsel['max-age']} must be integer")
-    elif morsel["expires"]:
-        time_template = "%a, %d-%b-%Y %H:%M:%S GMT"
-        expires = calendar.timegm(time.strptime(morsel["expires"], time_template))
-    return create_cookie(
-        comment=morsel["comment"],
-        comment_url=bool(morsel["comment"]),
-        discard=False,
-        domain=morsel["domain"],
-        expires=expires,
-        name=morsel.key,
-        path=morsel["path"],
-        port=None,
-        rest={"HttpOnly": morsel["httponly"]},
-        rfc2109=False,
-        secure=bool(morsel["secure"]),
-        value=morsel.value,
-        version=morsel["version"] or 0,
-    )
-
-
-def cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True):
-    """Returns a CookieJar from a key/value dictionary.
-
-    :param cookie_dict: Dict of key/values to insert into CookieJar.
-    :param cookiejar: (optional) A cookiejar to add the cookies to.
-    :param overwrite: (optional) If False, will not replace cookies
-        already in the jar with new ones.
-    :rtype: CookieJar
-    """
-    if cookiejar is None:
-        cookiejar = RequestsCookieJar()
-
-    if cookie_dict is not None:
-        names_from_jar = [cookie.name for cookie in cookiejar]
-        for name in cookie_dict:
-            if overwrite or (name not in names_from_jar):
-                cookiejar.set_cookie(create_cookie(name, cookie_dict[name]))
-
-    return cookiejar
-
-
-def merge_cookies(cookiejar, cookies):
-    """Add cookies to cookiejar and returns a merged CookieJar.
-
-    :param cookiejar: CookieJar object to add the cookies to.
-    :param cookies: Dictionary or CookieJar object to be added.
-    :rtype: CookieJar
-    """
-    if not isinstance(cookiejar, cookielib.CookieJar):
-        raise ValueError("You can only merge into CookieJar")
-
-    if isinstance(cookies, dict):
-        cookiejar = cookiejar_from_dict(cookies, cookiejar=cookiejar, overwrite=False)
-    elif isinstance(cookies, cookielib.CookieJar):
-        try:
-            cookiejar.update(cookies)
-        except AttributeError:
-            for cookie_in_jar in cookies:
-                cookiejar.set_cookie(cookie_in_jar)
-
-    return cookiejar
diff --git a/apps/bitwarden_event_logs/lib/requests/exceptions.py b/apps/bitwarden_event_logs/lib/requests/exceptions.py
deleted file mode 100755
index 83986b48..00000000
--- a/apps/bitwarden_event_logs/lib/requests/exceptions.py
+++ /dev/null
@@ -1,151 +0,0 @@
-"""
-requests.exceptions
-~~~~~~~~~~~~~~~~~~~
-
-This module contains the set of Requests' exceptions.
-"""
-from urllib3.exceptions import HTTPError as BaseHTTPError
-
-from .compat import JSONDecodeError as CompatJSONDecodeError
-
-
-class RequestException(IOError):
-    """There was an ambiguous exception that occurred while handling your
-    request.
-    """
-
-    def __init__(self, *args, **kwargs):
-        """Initialize RequestException with `request` and `response` objects."""
-        response = kwargs.pop("response", None)
-        self.response = response
-        self.request = kwargs.pop("request", None)
-        if response is not None and not self.request and hasattr(response, "request"):
-            self.request = self.response.request
-        super().__init__(*args, **kwargs)
-
-
-class InvalidJSONError(RequestException):
-    """A JSON error occurred."""
-
-
-class JSONDecodeError(InvalidJSONError, CompatJSONDecodeError):
-    """Couldn't decode the text into json"""
-
-    def __init__(self, *args, **kwargs):
-        """
-        Construct the JSONDecodeError instance first with all
-        args. Then use it's args to construct the IOError so that
-        the json specific args aren't used as IOError specific args
-        and the error message from JSONDecodeError is preserved.
-        """
-        CompatJSONDecodeError.__init__(self, *args)
-        InvalidJSONError.__init__(self, *self.args, **kwargs)
-
-    def __reduce__(self):
-        """
-        The __reduce__ method called when pickling the object must
-        be the one from the JSONDecodeError (be it json/simplejson)
-        as it expects all the arguments for instantiation, not just
-        one like the IOError, and the MRO would by default call the
-        __reduce__ method from the IOError due to the inheritance order.
-        """
-        return CompatJSONDecodeError.__reduce__(self)
-
-
-class HTTPError(RequestException):
-    """An HTTP error occurred."""
-
-
-class ConnectionError(RequestException):
-    """A Connection error occurred."""
-
-
-class ProxyError(ConnectionError):
-    """A proxy error occurred."""
-
-
-class SSLError(ConnectionError):
-    """An SSL error occurred."""
-
-
-class Timeout(RequestException):
-    """The request timed out.
-
-    Catching this error will catch both
-    :exc:`~requests.exceptions.ConnectTimeout` and
-    :exc:`~requests.exceptions.ReadTimeout` errors.
-    """
-
-
-class ConnectTimeout(ConnectionError, Timeout):
-    """The request timed out while trying to connect to the remote server.
-
-    Requests that produced this error are safe to retry.
-    """
-
-
-class ReadTimeout(Timeout):
-    """The server did not send any data in the allotted amount of time."""
-
-
-class URLRequired(RequestException):
-    """A valid URL is required to make a request."""
-
-
-class TooManyRedirects(RequestException):
-    """Too many redirects."""
-
-
-class MissingSchema(RequestException, ValueError):
-    """The URL scheme (e.g. http or https) is missing."""
-
-
-class InvalidSchema(RequestException, ValueError):
-    """The URL scheme provided is either invalid or unsupported."""
-
-
-class InvalidURL(RequestException, ValueError):
-    """The URL provided was somehow invalid."""
-
-
-class InvalidHeader(RequestException, ValueError):
-    """The header value provided was somehow invalid."""
-
-
-class InvalidProxyURL(InvalidURL):
-    """The proxy URL provided is invalid."""
-
-
-class ChunkedEncodingError(RequestException):
-    """The server declared chunked encoding but sent an invalid chunk."""
-
-
-class ContentDecodingError(RequestException, BaseHTTPError):
-    """Failed to decode response content."""
-
-
-class StreamConsumedError(RequestException, TypeError):
-    """The content for this response was already consumed."""
-
-
-class RetryError(RequestException):
-    """Custom retries logic failed"""
-
-
-class UnrewindableBodyError(RequestException):
-    """Requests encountered an error when trying to rewind a body."""
-
-
-# Warnings
-
-
-class RequestsWarning(Warning):
-    """Base warning for Requests."""
-
-
-class FileModeWarning(RequestsWarning, DeprecationWarning):
-    """A file was opened in text mode, but Requests determined its binary length."""
-
-
-class RequestsDependencyWarning(RequestsWarning):
-    """An imported dependency doesn't match the expected version range."""
diff --git a/apps/bitwarden_event_logs/lib/requests/help.py b/apps/bitwarden_event_logs/lib/requests/help.py
deleted file mode 100755
index 8fbcd656..00000000
--- a/apps/bitwarden_event_logs/lib/requests/help.py
+++ /dev/null
@@ -1,134 +0,0 @@
-"""Module containing bug report helper(s)."""
-
-import json
-import platform
-import ssl
-import sys
-
-import idna
-import urllib3
-
-from . import __version__ as requests_version
-
-try:
-    import charset_normalizer
-except ImportError:
-    charset_normalizer = None
-
-try:
-    import chardet
-except ImportError:
-    chardet = None
-
-try:
-    from urllib3.contrib import pyopenssl
-except ImportError:
-    pyopenssl = None
-    OpenSSL = None
-    cryptography = None
-else:
-    import cryptography
-    import OpenSSL
-
-
-def _implementation():
-    """Return a dict with the Python implementation and version.
-
-    Provide both the name and the version of the Python implementation
-    currently running. For example, on CPython 3.10.3 it will return
-    {'name': 'CPython', 'version': '3.10.3'}.
-
-    This function works best on CPython and PyPy: in particular, it probably
-    doesn't work for Jython or IronPython. Future investigation should be done
-    to work out the correct shape of the code for those platforms.
-    """
-    implementation = platform.python_implementation()
-
-    if implementation == "CPython":
-        implementation_version = platform.python_version()
-    elif implementation == "PyPy":
-        implementation_version = "{}.{}.{}".format(
-            sys.pypy_version_info.major,
-            sys.pypy_version_info.minor,
-            sys.pypy_version_info.micro,
-        )
-        if sys.pypy_version_info.releaselevel != "final":
-            implementation_version = "".join(
-                [implementation_version, sys.pypy_version_info.releaselevel]
-            )
-    elif implementation == "Jython":
-        implementation_version = platform.python_version()  # Complete Guess
-    elif implementation == "IronPython":
-        implementation_version = platform.python_version()  # Complete Guess
-    else:
-        implementation_version = "Unknown"
-
-    return {"name": implementation, "version": implementation_version}
-
-
-def info():
-    """Generate information for a bug report."""
-    try:
-        platform_info = {
-            "system": platform.system(),
-            "release": platform.release(),
-        }
-    except OSError:
-        platform_info = {
-            "system": "Unknown",
-            "release": "Unknown",
-        }
-
-    implementation_info = _implementation()
-    urllib3_info = {"version": urllib3.__version__}
-    charset_normalizer_info = {"version": None}
-    chardet_info = {"version": None}
-    if charset_normalizer:
-        charset_normalizer_info = {"version": charset_normalizer.__version__}
-    if chardet:
-        chardet_info = {"version": chardet.__version__}
-
-    pyopenssl_info = {
-        "version": None,
-        "openssl_version": "",
-    }
-    if OpenSSL:
-        pyopenssl_info = {
-            "version": OpenSSL.__version__,
-            "openssl_version": f"{OpenSSL.SSL.OPENSSL_VERSION_NUMBER:x}",
-        }
-    cryptography_info = {
-        "version": getattr(cryptography, "__version__", ""),
-    }
-    idna_info = {
-        "version": getattr(idna, "__version__", ""),
-    }
-
-    system_ssl = ssl.OPENSSL_VERSION_NUMBER
-    system_ssl_info = {"version": f"{system_ssl:x}" if system_ssl is not None else ""}
-
-    return {
-        "platform": platform_info,
-        "implementation": implementation_info,
-        "system_ssl": system_ssl_info,
-        "using_pyopenssl": pyopenssl is not None,
-        "using_charset_normalizer": chardet is None,
-        "pyOpenSSL": pyopenssl_info,
-        "urllib3": urllib3_info,
-        "chardet": chardet_info,
-        "charset_normalizer": charset_normalizer_info,
-        "cryptography": cryptography_info,
-        "idna": idna_info,
-        "requests": {
-            "version": requests_version,
-        },
-    }
-
-
-def main():
-    """Pretty-print the bug information as JSON."""
-    print(json.dumps(info(), sort_keys=True, indent=2))
-
-
-if __name__ == "__main__":
-    main()
diff --git a/apps/bitwarden_event_logs/lib/requests/hooks.py b/apps/bitwarden_event_logs/lib/requests/hooks.py
deleted file mode 100755
index d181ba2e..00000000
--- a/apps/bitwarden_event_logs/lib/requests/hooks.py
+++ /dev/null
@@ -1,33 +0,0 @@
-"""
-requests.hooks
-~~~~~~~~~~~~~~
-
-This module provides the capabilities for the Requests hooks system.
-
-Available hooks:
-
-``response``:
-    The response generated from a Request.
-"""
-HOOKS = ["response"]
-
-
-def default_hooks():
-    return {event: [] for event in HOOKS}
-
-
-# TODO: response is the only one
-
-
-def dispatch_hook(key, hooks, hook_data, **kwargs):
-    """Dispatches a hook dictionary on a given piece of data."""
-    hooks = hooks or {}
-    hooks = hooks.get(key)
-    if hooks:
-        if hasattr(hooks, "__call__"):
-            hooks = [hooks]
-        for hook in hooks:
-            _hook_data = hook(hook_data, **kwargs)
-            if _hook_data is not None:
-                hook_data = _hook_data
-    return hook_data
diff --git a/apps/bitwarden_event_logs/lib/requests/models.py b/apps/bitwarden_event_logs/lib/requests/models.py
deleted file mode 100755
index c4b25fa0..00000000
--- a/apps/bitwarden_event_logs/lib/requests/models.py
+++ /dev/null
@@ -1,1039 +0,0 @@
-"""
-requests.models
-~~~~~~~~~~~~~~~
-
-This module contains the primary objects that power Requests.
-"""
-
-import datetime
-
-# Import encoding now, to avoid implicit import later.
-# Implicit import within threads may cause LookupError when standard library is in a ZIP,
-# such as in Embedded Python. See https://github.com/psf/requests/issues/3578.
-import encodings.idna  # noqa: F401
-from io import UnsupportedOperation
-
-from urllib3.exceptions import (
-    DecodeError,
-    LocationParseError,
-    ProtocolError,
-    ReadTimeoutError,
-    SSLError,
-)
-from urllib3.fields import RequestField
-from urllib3.filepost import encode_multipart_formdata
-from urllib3.util import parse_url
-
-from ._internal_utils import to_native_string, unicode_is_ascii
-from .auth import HTTPBasicAuth
-from .compat import (
-    Callable,
-    JSONDecodeError,
-    Mapping,
-    basestring,
-    builtin_str,
-    chardet,
-    cookielib,
-)
-from .compat import json as complexjson
-from .compat import urlencode, urlsplit, urlunparse
-from .cookies import _copy_cookie_jar, cookiejar_from_dict, get_cookie_header
-from .exceptions import (
-    ChunkedEncodingError,
-    ConnectionError,
-    ContentDecodingError,
-    HTTPError,
-    InvalidJSONError,
-    InvalidURL,
-)
-from .exceptions import JSONDecodeError as RequestsJSONDecodeError
-from .exceptions import MissingSchema
-from .exceptions import SSLError as RequestsSSLError
-from .exceptions import StreamConsumedError
-from .hooks import default_hooks
-from .status_codes import codes
-from .structures import CaseInsensitiveDict
-from .utils import (
-    check_header_validity,
-    get_auth_from_url,
-    guess_filename,
-    guess_json_utf,
-    iter_slices,
-    parse_header_links,
-    requote_uri,
-    stream_decode_response_unicode,
-    super_len,
-    to_key_val_list,
-)
-
-#: The set of HTTP status codes that indicate an automatically
-#: processable redirect.
-REDIRECT_STATI = (
-    codes.moved,  # 301
-    codes.found,  # 302
-    codes.other,  # 303
-    codes.temporary_redirect,  # 307
-    codes.permanent_redirect,  # 308
-)
-
-DEFAULT_REDIRECT_LIMIT = 30
-CONTENT_CHUNK_SIZE = 10 * 1024
-ITER_CHUNK_SIZE = 512
-
-
-class RequestEncodingMixin:
-    @property
-    def path_url(self):
-        """Build the path URL to use."""
-
-        url = []
-
-        p = urlsplit(self.url)
-
-        path = p.path
-        if not path:
-            path = "/"
-
-        url.append(path)
-
-        query = p.query
-        if query:
-            url.append("?")
-            url.append(query)
-
-        return "".join(url)
-
-    @staticmethod
-    def _encode_params(data):
-        """Encode parameters in a piece of data.
-
-        Will successfully encode parameters when passed as a dict or a list of
-        2-tuples. Order is retained if data is a list of 2-tuples but arbitrary
-        if parameters are supplied as a dict.
-        """
-
-        if isinstance(data, (str, bytes)):
-            return data
-        elif hasattr(data, "read"):
-            return data
-        elif hasattr(data, "__iter__"):
-            result = []
-            for k, vs in to_key_val_list(data):
-                if isinstance(vs, basestring) or not hasattr(vs, "__iter__"):
-                    vs = [vs]
-                for v in vs:
-                    if v is not None:
-                        result.append(
-                            (
-                                k.encode("utf-8") if isinstance(k, str) else k,
-                                v.encode("utf-8") if isinstance(v, str) else v,
-                            )
-                        )
-            return urlencode(result, doseq=True)
-        else:
-            return data
-
-    @staticmethod
-    def _encode_files(files, data):
-        """Build the body for a multipart/form-data request.
-
-        Will successfully encode files when passed as a dict or a list of
-        tuples. Order is retained if data is a list of tuples but arbitrary
-        if parameters are supplied as a dict.
-        The tuples may be 2-tuples (filename, fileobj), 3-tuples (filename, fileobj, contentype)
-        or 4-tuples (filename, fileobj, contentype, custom_headers).
-        """
-        if not files:
-            raise ValueError("Files must be provided.")
-        elif isinstance(data, basestring):
-            raise ValueError("Data must not be a string.")
-
-        new_fields = []
-        fields = to_key_val_list(data or {})
-        files = to_key_val_list(files or {})
-
-        for field, val in fields:
-            if isinstance(val, basestring) or not hasattr(val, "__iter__"):
-                val = [val]
-            for v in val:
-                if v is not None:
-                    # Don't call str() on bytestrings: in Py3 it all goes wrong.
-                    if not isinstance(v, bytes):
-                        v = str(v)
-
-                    new_fields.append(
-                        (
-                            field.decode("utf-8")
-                            if isinstance(field, bytes)
-                            else field,
-                            v.encode("utf-8") if isinstance(v, str) else v,
-                        )
-                    )
-
-        for k, v in files:
-            # support for explicit filename
-            ft = None
-            fh = None
-            if isinstance(v, (tuple, list)):
-                if len(v) == 2:
-                    fn, fp = v
-                elif len(v) == 3:
-                    fn, fp, ft = v
-                else:
-                    fn, fp, ft, fh = v
-            else:
-                fn = guess_filename(v) or k
-                fp = v
-
-            if isinstance(fp, (str, bytes, bytearray)):
-                fdata = fp
-            elif hasattr(fp, "read"):
-                fdata = fp.read()
-            elif fp is None:
-                continue
-            else:
-                fdata = fp
-
-            rf = RequestField(name=k, data=fdata, filename=fn, headers=fh)
-            rf.make_multipart(content_type=ft)
-            new_fields.append(rf)
-
-        body, content_type = encode_multipart_formdata(new_fields)
-
-        return body, content_type
-
-
-class RequestHooksMixin:
-    def register_hook(self, event, hook):
-        """Properly register a hook."""
-
-        if event not in self.hooks:
-            raise ValueError(f'Unsupported event specified, with event name "{event}"')
-
-        if isinstance(hook, Callable):
-            self.hooks[event].append(hook)
-        elif hasattr(hook, "__iter__"):
-            self.hooks[event].extend(h for h in hook if isinstance(h, Callable))
-
-    def deregister_hook(self, event, hook):
-        """Deregister a previously registered hook.
-        Returns True if the hook existed, False if not.
-        """
-
-        try:
-            self.hooks[event].remove(hook)
-            return True
-        except ValueError:
-            return False
-
-
-class Request(RequestHooksMixin):
-    """A user-created :class:`Request ` object.
-
-    Used to prepare a :class:`PreparedRequest `, which is sent to the server.
-
-    :param method: HTTP method to use.
-    :param url: URL to send.
-    :param headers: dictionary of headers to send.
-    :param files: dictionary of {filename: fileobject} files to multipart upload.
-    :param data: the body to attach to the request. If a dictionary or
-        list of tuples ``[(key, value)]`` is provided, form-encoding will
-        take place.
-    :param json: json for the body to attach to the request (if files or data is not specified).
-    :param params: URL parameters to append to the URL. If a dictionary or
-        list of tuples ``[(key, value)]`` is provided, form-encoding will
-        take place.
-    :param auth: Auth handler or (user, pass) tuple.
-    :param cookies: dictionary or CookieJar of cookies to attach to this request.
-    :param hooks: dictionary of callback hooks, for internal usage.
-
-    Usage::
-
-      >>> import requests
-      >>> req = requests.Request('GET', 'https://httpbin.org/get')
-      >>> req.prepare()
-      
-    """
-
-    def __init__(
-        self,
-        method=None,
-        url=None,
-        headers=None,
-        files=None,
-        data=None,
-        params=None,
-        auth=None,
-        cookies=None,
-        hooks=None,
-        json=None,
-    ):
-        # Default empty dicts for dict params.
-        data = [] if data is None else data
-        files = [] if files is None else files
-        headers = {} if headers is None else headers
-        params = {} if params is None else params
-        hooks = {} if hooks is None else hooks
-
-        self.hooks = default_hooks()
-        for k, v in list(hooks.items()):
-            self.register_hook(event=k, hook=v)
-
-        self.method = method
-        self.url = url
-        self.headers = headers
-        self.files = files
-        self.data = data
-        self.json = json
-        self.params = params
-        self.auth = auth
-        self.cookies = cookies
-
-    def __repr__(self):
-        return f""
-
-    def prepare(self):
-        """Constructs a :class:`PreparedRequest ` for transmission and returns it."""
-        p = PreparedRequest()
-        p.prepare(
-            method=self.method,
-            url=self.url,
-            headers=self.headers,
-            files=self.files,
-            data=self.data,
-            json=self.json,
-            params=self.params,
-            auth=self.auth,
-            cookies=self.cookies,
-            hooks=self.hooks,
-        )
-        return p
-
-
-class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
-    """The fully mutable :class:`PreparedRequest ` object,
-    containing the exact bytes that will be sent to the server.
-
-    Instances are generated from a :class:`Request ` object, and
-    should not be instantiated manually; doing so may produce undesirable
-    effects.
-
-    Usage::
-
-      >>> import requests
-      >>> req = requests.Request('GET', 'https://httpbin.org/get')
-      >>> r = req.prepare()
-      >>> r
-      
-
-      >>> s = requests.Session()
-      >>> s.send(r)
-      
-    """
-
-    def __init__(self):
-        #: HTTP verb to send to the server.
-        self.method = None
-        #: HTTP URL to send the request to.
-        self.url = None
-        #: dictionary of HTTP headers.
-        self.headers = None
-        # The `CookieJar` used to create the Cookie header will be stored here
-        # after prepare_cookies is called
-        self._cookies = None
-        #: request body to send to the server.
-        self.body = None
-        #: dictionary of callback hooks, for internal usage.
-        self.hooks = default_hooks()
-        #: integer denoting starting position of a readable file-like body.
-        self._body_position = None
-
-    def prepare(
-        self,
-        method=None,
-        url=None,
-        headers=None,
-        files=None,
-        data=None,
-        params=None,
-        auth=None,
-        cookies=None,
-        hooks=None,
-        json=None,
-    ):
-        """Prepares the entire request with the given parameters."""
-
-        self.prepare_method(method)
-        self.prepare_url(url, params)
-        self.prepare_headers(headers)
-        self.prepare_cookies(cookies)
-        self.prepare_body(data, files, json)
-        self.prepare_auth(auth, url)
-
-        # Note that prepare_auth must be last to enable authentication schemes
-        # such as OAuth to work on a fully prepared request.
-
-        # This MUST go after prepare_auth. Authenticators could add a hook
-        self.prepare_hooks(hooks)
-
-    def __repr__(self):
-        return f""
-
-    def copy(self):
-        p = PreparedRequest()
-        p.method = self.method
-        p.url = self.url
-        p.headers = self.headers.copy() if self.headers is not None else None
-        p._cookies = _copy_cookie_jar(self._cookies)
-        p.body = self.body
-        p.hooks = self.hooks
-        p._body_position = self._body_position
-        return p
-
-    def prepare_method(self, method):
-        """Prepares the given HTTP method."""
-        self.method = method
-        if self.method is not None:
-            self.method = to_native_string(self.method.upper())
-
-    @staticmethod
-    def _get_idna_encoded_host(host):
-        import idna
-
-        try:
-            host = idna.encode(host, uts46=True).decode("utf-8")
-        except idna.IDNAError:
-            raise UnicodeError
-        return host
-
-    def prepare_url(self, url, params):
-        """Prepares the given HTTP URL."""
-        #: Accept objects that have string representations.
-        #: We're unable to blindly call unicode/str functions
-        #: as this will include the bytestring indicator (b'')
-        #: on python 3.x.
-        #: https://github.com/psf/requests/pull/2238
-        if isinstance(url, bytes):
-            url = url.decode("utf8")
-        else:
-            url = str(url)
-
-        # Remove leading whitespaces from url
-        url = url.lstrip()
-
-        # Don't do any URL preparation for non-HTTP schemes like `mailto`,
-        # `data` etc to work around exceptions from `url_parse`, which
-        # handles RFC 3986 only.
-        if ":" in url and not url.lower().startswith("http"):
-            self.url = url
-            return
-
-        # Support for unicode domain names and paths.
-        try:
-            scheme, auth, host, port, path, query, fragment = parse_url(url)
-        except LocationParseError as e:
-            raise InvalidURL(*e.args)
-
-        if not scheme:
-            raise MissingSchema(
-                f"Invalid URL {url!r}: No scheme supplied. "
-                f"Perhaps you meant https://{url}?"
-            )
-
-        if not host:
-            raise InvalidURL(f"Invalid URL {url!r}: No host supplied")
-
-        # In general, we want to try IDNA encoding the hostname if the string contains
-        # non-ASCII characters. This allows users to automatically get the correct IDNA
-        # behaviour. For strings containing only ASCII characters, we need to also verify
-        # it doesn't start with a wildcard (*), before allowing the unencoded hostname.
-        if not unicode_is_ascii(host):
-            try:
-                host = self._get_idna_encoded_host(host)
-            except UnicodeError:
-                raise InvalidURL("URL has an invalid label.")
-        elif host.startswith(("*", ".")):
-            raise InvalidURL("URL has an invalid label.")
-
-        # Carefully reconstruct the network location
-        netloc = auth or ""
-        if netloc:
-            netloc += "@"
-        netloc += host
-        if port:
-            netloc += f":{port}"
-
-        # Bare domains aren't valid URLs.
-        if not path:
-            path = "/"
-
-        if isinstance(params, (str, bytes)):
-            params = to_native_string(params)
-
-        enc_params = self._encode_params(params)
-        if enc_params:
-            if query:
-                query = f"{query}&{enc_params}"
-            else:
-                query = enc_params
-
-        url = requote_uri(urlunparse([scheme, netloc, path, None, query, fragment]))
-        self.url = url
-
-    def prepare_headers(self, headers):
-        """Prepares the given HTTP headers."""
-
-        self.headers = CaseInsensitiveDict()
-        if headers:
-            for header in headers.items():
-                # Raise exception on invalid header value.
-                check_header_validity(header)
-                name, value = header
-                self.headers[to_native_string(name)] = value
-
-    def prepare_body(self, data, files, json=None):
-        """Prepares the given HTTP body data."""
-
-        # Check if file, fo, generator, iterator.
-        # If not, run through normal process.
-
-        # Nottin' on you.
-        body = None
-        content_type = None
-
-        if not data and json is not None:
-            # urllib3 requires a bytes-like body. Python 2's json.dumps
-            # provides this natively, but Python 3 gives a Unicode string.
-            content_type = "application/json"
-
-            try:
-                body = complexjson.dumps(json, allow_nan=False)
-            except ValueError as ve:
-                raise InvalidJSONError(ve, request=self)
-
-            if not isinstance(body, bytes):
-                body = body.encode("utf-8")
-
-        is_stream = all(
-            [
-                hasattr(data, "__iter__"),
-                not isinstance(data, (basestring, list, tuple, Mapping)),
-            ]
-        )
-
-        if is_stream:
-            try:
-                length = super_len(data)
-            except (TypeError, AttributeError, UnsupportedOperation):
-                length = None
-
-            body = data
-
-            if getattr(body, "tell", None) is not None:
-                # Record the current file position before reading.
-                # This will allow us to rewind a file in the event
-                # of a redirect.
-                try:
-                    self._body_position = body.tell()
-                except OSError:
-                    # This differentiates from None, allowing us to catch
-                    # a failed `tell()` later when trying to rewind the body
-                    self._body_position = object()
-
-            if files:
-                raise NotImplementedError(
-                    "Streamed bodies and files are mutually exclusive."
-                )
-
-            if length:
-                self.headers["Content-Length"] = builtin_str(length)
-            else:
-                self.headers["Transfer-Encoding"] = "chunked"
-        else:
-            # Multi-part file uploads.
-            if files:
-                (body, content_type) = self._encode_files(files, data)
-            else:
-                if data:
-                    body = self._encode_params(data)
-                    if isinstance(data, basestring) or hasattr(data, "read"):
-                        content_type = None
-                    else:
-                        content_type = "application/x-www-form-urlencoded"
-
-            self.prepare_content_length(body)
-
-            # Add content-type if it wasn't explicitly provided.
-            if content_type and ("content-type" not in self.headers):
-                self.headers["Content-Type"] = content_type
-
-        self.body = body
-
-    def prepare_content_length(self, body):
-        """Prepare Content-Length header based on request method and body"""
-        if body is not None:
-            length = super_len(body)
-            if length:
-                # If length exists, set it. Otherwise, we fallback
-                # to Transfer-Encoding: chunked.
-                self.headers["Content-Length"] = builtin_str(length)
-        elif (
-            self.method not in ("GET", "HEAD")
-            and self.headers.get("Content-Length") is None
-        ):
-            # Set Content-Length to 0 for methods that can have a body
-            # but don't provide one. (i.e. not GET or HEAD)
-            self.headers["Content-Length"] = "0"
-
-    def prepare_auth(self, auth, url=""):
-        """Prepares the given HTTP auth data."""
-
-        # If no Auth is explicitly provided, extract it from the URL first.
-        if auth is None:
-            url_auth = get_auth_from_url(self.url)
-            auth = url_auth if any(url_auth) else None
-
-        if auth:
-            if isinstance(auth, tuple) and len(auth) == 2:
-                # special-case basic HTTP auth
-                auth = HTTPBasicAuth(*auth)
-
-            # Allow auth to make its changes.
-            r = auth(self)
-
-            # Update self to reflect the auth changes.
-            self.__dict__.update(r.__dict__)
-
-            # Recompute Content-Length
-            self.prepare_content_length(self.body)
-
-    def prepare_cookies(self, cookies):
-        """Prepares the given HTTP cookie data.
-
-        This function eventually generates a ``Cookie`` header from the
-        given cookies using cookielib. Due to cookielib's design, the header
-        will not be regenerated if it already exists, meaning this function
-        can only be called once for the life of the
-        :class:`PreparedRequest ` object. Any subsequent calls
-        to ``prepare_cookies`` will have no actual effect, unless the "Cookie"
-        header is removed beforehand.
-        """
-        if isinstance(cookies, cookielib.CookieJar):
-            self._cookies = cookies
-        else:
-            self._cookies = cookiejar_from_dict(cookies)
-
-        cookie_header = get_cookie_header(self._cookies, self)
-        if cookie_header is not None:
-            self.headers["Cookie"] = cookie_header
-
-    def prepare_hooks(self, hooks):
-        """Prepares the given hooks."""
-        # hooks can be passed as None to the prepare method and to this
-        # method. To prevent iterating over None, simply use an empty list
-        # if hooks is False-y
-        hooks = hooks or []
-        for event in hooks:
-            self.register_hook(event, hooks[event])
-
-
-class Response:
-    """The :class:`Response ` object, which contains a
-    server's response to an HTTP request.
-    """
-
-    __attrs__ = [
-        "_content",
-        "status_code",
-        "headers",
-        "url",
-        "history",
-        "encoding",
-        "reason",
-        "cookies",
-        "elapsed",
-        "request",
-    ]
-
-    def __init__(self):
-        self._content = False
-        self._content_consumed = False
-        self._next = None
-
-        #: Integer Code of responded HTTP Status, e.g. 404 or 200.
-        self.status_code = None
-
-        #: Case-insensitive Dictionary of Response Headers.
-        #: For example, ``headers['content-encoding']`` will return the
-        #: value of a ``'Content-Encoding'`` response header.
-        self.headers = CaseInsensitiveDict()
-
-        #: File-like object representation of response (for advanced usage).
-        #: Use of ``raw`` requires that ``stream=True`` be set on the request.
-        #: This requirement does not apply for use internally to Requests.
-        self.raw = None
-
-        #: Final URL location of Response.
-        self.url = None
-
-        #: Encoding to decode with when accessing r.text.
-        self.encoding = None
-
-        #: A list of :class:`Response ` objects from
-        #: the history of the Request. Any redirect responses will end
-        #: up here. The list is sorted from the oldest to the most recent request.
-        self.history = []
-
-        #: Textual reason of responded HTTP Status, e.g. "Not Found" or "OK".
-        self.reason = None
-
-        #: A CookieJar of Cookies the server sent back.
-        self.cookies = cookiejar_from_dict({})
-
-        #: The amount of time elapsed between sending the request
-        #: and the arrival of the response (as a timedelta).
-        #: This property specifically measures the time taken between sending
-        #: the first byte of the request and finishing parsing the headers. It
-        #: is therefore unaffected by consuming the response content or the
-        #: value of the ``stream`` keyword argument.
-        self.elapsed = datetime.timedelta(0)
-
-        #: The :class:`PreparedRequest ` object to which this
-        #: is a response.
-        self.request = None
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, *args):
-        self.close()
-
-    def __getstate__(self):
-        # Consume everything; accessing the content attribute makes
-        # sure the content has been fully read.
-        if not self._content_consumed:
-            self.content
-
-        return {attr: getattr(self, attr, None) for attr in self.__attrs__}
-
-    def __setstate__(self, state):
-        for name, value in state.items():
-            setattr(self, name, value)
-
-        # pickled objects do not have .raw
-        setattr(self, "_content_consumed", True)
-        setattr(self, "raw", None)
-
-    def __repr__(self):
-        return f""
-
-    def __bool__(self):
-        """Returns True if :attr:`status_code` is less than 400.
-
-        This attribute checks if the status code of the response is between
-        400 and 600 to see if there was a client error or a server error. If
-        the status code, is between 200 and 400, this will return True. This
-        is **not** a check to see if the response code is ``200 OK``.
-        """
-        return self.ok
-
-    def __nonzero__(self):
-        """Returns True if :attr:`status_code` is less than 400.
-
-        This attribute checks if the status code of the response is between
-        400 and 600 to see if there was a client error or a server error. If
-        the status code, is between 200 and 400, this will return True. This
-        is **not** a check to see if the response code is ``200 OK``.
-        """
-        return self.ok
-
-    def __iter__(self):
-        """Allows you to use a response as an iterator."""
-        return self.iter_content(128)
-
-    @property
-    def ok(self):
-        """Returns True if :attr:`status_code` is less than 400, False if not.
-
-        This attribute checks if the status code of the response is between
-        400 and 600 to see if there was a client error or a server error. If
-        the status code is between 200 and 400, this will return True. This
-        is **not** a check to see if the response code is ``200 OK``.
-        """
-        try:
-            self.raise_for_status()
-        except HTTPError:
-            return False
-        return True
-
-    @property
-    def is_redirect(self):
-        """True if this Response is a well-formed HTTP redirect that could have
-        been processed automatically (by :meth:`Session.resolve_redirects`).
-        """
-        return "location" in self.headers and self.status_code in REDIRECT_STATI
-
-    @property
-    def is_permanent_redirect(self):
-        """True if this Response one of the permanent versions of redirect."""
-        return "location" in self.headers and self.status_code in (
-            codes.moved_permanently,
-            codes.permanent_redirect,
-        )
-
-    @property
-    def next(self):
-        """Returns a PreparedRequest for the next request in a redirect chain, if there is one."""
-        return self._next
-
-    @property
-    def apparent_encoding(self):
-        """The apparent encoding, provided by the charset_normalizer or chardet libraries."""
-        if chardet is not None:
-            return chardet.detect(self.content)["encoding"]
-        else:
-            # If no character detection library is available, we'll fall back
-            # to a standard Python utf-8 str.
-            return "utf-8"
-
-    def iter_content(self, chunk_size=1, decode_unicode=False):
-        """Iterates over the response data.  When stream=True is set on the
-        request, this avoids reading the content at once into memory for
-        large responses.  The chunk size is the number of bytes it should
-        read into memory.  This is not necessarily the length of each item
-        returned as decoding can take place.
-
-        chunk_size must be of type int or None. A value of None will
-        function differently depending on the value of `stream`.
-        stream=True will read data as it arrives in whatever size the
-        chunks are received. If stream=False, data is returned as
-        a single chunk.
-
-        If decode_unicode is True, content will be decoded using the best
-        available encoding based on the response.
-        """
-
-        def generate():
-            # Special case for urllib3.
-            if hasattr(self.raw, "stream"):
-                try:
-                    yield from self.raw.stream(chunk_size, decode_content=True)
-                except ProtocolError as e:
-                    raise ChunkedEncodingError(e)
-                except DecodeError as e:
-                    raise ContentDecodingError(e)
-                except ReadTimeoutError as e:
-                    raise ConnectionError(e)
-                except SSLError as e:
-                    raise RequestsSSLError(e)
-            else:
-                # Standard file-like object.
-                while True:
-                    chunk = self.raw.read(chunk_size)
-                    if not chunk:
-                        break
-                    yield chunk
-
-            self._content_consumed = True
-
-        if self._content_consumed and isinstance(self._content, bool):
-            raise StreamConsumedError()
-        elif chunk_size is not None and not isinstance(chunk_size, int):
-            raise TypeError(
-                f"chunk_size must be an int, it is instead a {type(chunk_size)}."
-            )
-        # simulate reading small chunks of the content
-        reused_chunks = iter_slices(self._content, chunk_size)
-
-        stream_chunks = generate()
-
-        chunks = reused_chunks if self._content_consumed else stream_chunks
-
-        if decode_unicode:
-            chunks = stream_decode_response_unicode(chunks, self)
-
-        return chunks
-
-    def iter_lines(
-        self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=False, delimiter=None
-    ):
-        """Iterates over the response data, one line at a time.  When
-        stream=True is set on the request, this avoids reading the
-        content at once into memory for large responses.
-
-        .. note:: This method is not reentrant safe.
-        """
-
-        pending = None
-
-        for chunk in self.iter_content(
-            chunk_size=chunk_size, decode_unicode=decode_unicode
-        ):
-            if pending is not None:
-                chunk = pending + chunk
-
-            if delimiter:
-                lines = chunk.split(delimiter)
-            else:
-                lines = chunk.splitlines()
-
-            if lines and lines[-1] and chunk and lines[-1][-1] == chunk[-1]:
-                pending = lines.pop()
-            else:
-                pending = None
-
-            yield from lines
-
-        if pending is not None:
-            yield pending
-
-    @property
-    def content(self):
-        """Content of the response, in bytes."""
-
-        if self._content is False:
-            # Read the contents.
-            if self._content_consumed:
-                raise RuntimeError("The content for this response was already consumed")
-
-            if self.status_code == 0 or self.raw is None:
-                self._content = None
-            else:
-                self._content = b"".join(self.iter_content(CONTENT_CHUNK_SIZE)) or b""
-
-        self._content_consumed = True
-        # don't need to release the connection; that's been handled by urllib3
-        # since we exhausted the data.
-        return self._content
-
-    @property
-    def text(self):
-        """Content of the response, in unicode.
-
-        If Response.encoding is None, encoding will be guessed using
-        ``charset_normalizer`` or ``chardet``.
-
-        The encoding of the response content is determined based solely on HTTP
-        headers, following RFC 2616 to the letter. If you can take advantage of
-        non-HTTP knowledge to make a better guess at the encoding, you should
-        set ``r.encoding`` appropriately before accessing this property.
-        """
-
-        # Try charset from content-type
-        content = None
-        encoding = self.encoding
-
-        if not self.content:
-            return ""
-
-        # Fallback to auto-detected encoding.
-        if self.encoding is None:
-            encoding = self.apparent_encoding
-
-        # Decode unicode from given encoding.
-        try:
-            content = str(self.content, encoding, errors="replace")
-        except (LookupError, TypeError):
-            # A LookupError is raised if the encoding was not found which could
-            # indicate a misspelling or similar mistake.
-            #
-            # A TypeError can be raised if encoding is None
-            #
-            # So we try blindly encoding.
-            content = str(self.content, errors="replace")
-
-        return content
-
-    def json(self, **kwargs):
-        r"""Decodes the JSON response body (if any) as a Python object.
-
-        This may return a dictionary, list, etc. depending on what is in the response.
-
-        :param \*\*kwargs: Optional arguments that ``json.loads`` takes.
-        :raises requests.exceptions.JSONDecodeError: If the response body does not
-            contain valid json.
-        """
-
-        if not self.encoding and self.content and len(self.content) > 3:
-            # No encoding set. JSON RFC 4627 section 3 states we should expect
-            # UTF-8, -16 or -32. Detect which one to use; If the detection or
-            # decoding fails, fall back to `self.text` (using charset_normalizer to make
-            # a best guess).
-            encoding = guess_json_utf(self.content)
-            if encoding is not None:
-                try:
-                    return complexjson.loads(self.content.decode(encoding), **kwargs)
-                except UnicodeDecodeError:
-                    # Wrong UTF codec detected; usually because it's not UTF-8
-                    # but some other 8-bit codec.  This is an RFC violation,
-                    # and the server didn't bother to tell us what codec *was*
-                    # used.
-                    pass
-                except JSONDecodeError as e:
-                    raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
-
-        try:
-            return complexjson.loads(self.text, **kwargs)
-        except JSONDecodeError as e:
-            # Catch JSON-related errors and raise as requests.JSONDecodeError
-            # This aliases json.JSONDecodeError and simplejson.JSONDecodeError
-            raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
-
-    @property
-    def links(self):
-        """Returns the parsed header links of the response, if any."""
-
-        header = self.headers.get("link")
-
-        resolved_links = {}
-
-        if header:
-            links = parse_header_links(header)
-
-            for link in links:
-                key = link.get("rel") or link.get("url")
-                resolved_links[key] = link
-
-        return resolved_links
-
-    def raise_for_status(self):
-        """Raises :class:`HTTPError`, if one occurred."""
-
-        http_error_msg = ""
-        if isinstance(self.reason, bytes):
-            # We attempt to decode utf-8 first because some servers
-            # choose to localize their reason strings. If the string
-            # isn't utf-8, we fall back to iso-8859-1 for all other
-            # encodings. (See PR #3538)
-            try:
-                reason = self.reason.decode("utf-8")
-            except UnicodeDecodeError:
-                reason = self.reason.decode("iso-8859-1")
-        else:
-            reason = self.reason
-
-        if 400 <= self.status_code < 500:
-            http_error_msg = (
-                f"{self.status_code} Client Error: {reason} for url: {self.url}"
-            )
-
-        elif 500 <= self.status_code < 600:
-            http_error_msg = (
-                f"{self.status_code} Server Error: {reason} for url: {self.url}"
-            )
-
-        if http_error_msg:
-            raise HTTPError(http_error_msg, response=self)
-
-    def close(self):
-        """Releases the connection back to the pool. Once this method has been
-        called the underlying ``raw`` object must not be accessed again.
-
-        *Note: Should not normally need to be called explicitly.*
-        """
-        if not self._content_consumed:
-            self.raw.close()
-
-        release_conn = getattr(self.raw, "release_conn", None)
-        if release_conn is not None:
-            release_conn()
diff --git a/apps/bitwarden_event_logs/lib/requests/packages.py b/apps/bitwarden_event_logs/lib/requests/packages.py
deleted file mode 100755
index 5ab3d8e2..00000000
--- a/apps/bitwarden_event_logs/lib/requests/packages.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import sys
-
-from .compat import chardet
-
-# This code exists for backwards compatibility reasons.
-# I don't like it either. Just look the other way. :)
-
-for package in ("urllib3", "idna"):
-    locals()[package] = __import__(package)
-    # This traversal is apparently necessary such that the identities are
-    # preserved (requests.packages.urllib3.* is urllib3.*)
-    for mod in list(sys.modules):
-        if mod == package or mod.startswith(f"{package}."):
-            sys.modules[f"requests.packages.{mod}"] = sys.modules[mod]
-
-if chardet is not None:
-    target = chardet.__name__
-    for mod in list(sys.modules):
-        if mod == target or mod.startswith(f"{target}."):
-            imported_mod = sys.modules[mod]
-            sys.modules[f"requests.packages.{mod}"] = imported_mod
-            mod = mod.replace(target, "chardet")
-            sys.modules[f"requests.packages.{mod}"] = imported_mod
diff --git a/apps/bitwarden_event_logs/lib/requests/sessions.py b/apps/bitwarden_event_logs/lib/requests/sessions.py
deleted file mode 100755
index 731550de..00000000
--- a/apps/bitwarden_event_logs/lib/requests/sessions.py
+++ /dev/null
@@ -1,831 +0,0 @@
-"""
-requests.sessions
-~~~~~~~~~~~~~~~~~
-
-This module provides a Session object to manage and persist settings across
-requests (cookies, auth, proxies).
-"""
-import os
-import sys
-import time
-from collections import OrderedDict
-from datetime import timedelta
-
-from ._internal_utils import to_native_string
-from .adapters import HTTPAdapter
-from .auth import _basic_auth_str
-from .compat import Mapping, cookielib, urljoin, urlparse
-from .cookies import (
-    RequestsCookieJar,
-    cookiejar_from_dict,
-    extract_cookies_to_jar,
-    merge_cookies,
-)
-from .exceptions import (
-    ChunkedEncodingError,
-    ContentDecodingError,
-    InvalidSchema,
-    TooManyRedirects,
-)
-from .hooks import default_hooks, dispatch_hook
-
-# formerly defined here, reexposed here for backward compatibility
-from .models import (  # noqa: F401
-    DEFAULT_REDIRECT_LIMIT,
-    REDIRECT_STATI,
-    PreparedRequest,
-    Request,
-)
-from .status_codes import codes
-from .structures import CaseInsensitiveDict
-from .utils import (  # noqa: F401
-    DEFAULT_PORTS,
-    default_headers,
-    get_auth_from_url,
-    get_environ_proxies,
-    get_netrc_auth,
-    requote_uri,
-    resolve_proxies,
-    rewind_body,
-    should_bypass_proxies,
-    to_key_val_list,
-)
-
-# Preferred clock, based on which one is more accurate on a given system.
-if sys.platform == "win32":
-    preferred_clock = time.perf_counter
-else:
-    preferred_clock = time.time
-
-
-def merge_setting(request_setting, session_setting, dict_class=OrderedDict):
-    """Determines appropriate setting for a given request, taking into account
-    the explicit setting on that request, and the setting in the session. If a
-    setting is a dictionary, they will be merged together using `dict_class`
-    """
-
-    if session_setting is None:
-        return request_setting
-
-    if request_setting is None:
-        return session_setting
-
-    # Bypass if not a dictionary (e.g. verify)
-    if not (
-        isinstance(session_setting, Mapping) and isinstance(request_setting, Mapping)
-    ):
-        return request_setting
-
-    merged_setting = dict_class(to_key_val_list(session_setting))
-    merged_setting.update(to_key_val_list(request_setting))
-
-    # Remove keys that are set to None. Extract keys first to avoid altering
-    # the dictionary during iteration.
-    none_keys = [k for (k, v) in merged_setting.items() if v is None]
-    for key in none_keys:
-        del merged_setting[key]
-
-    return merged_setting
-
-
-def merge_hooks(request_hooks, session_hooks, dict_class=OrderedDict):
-    """Properly merges both requests and session hooks.
-
-    This is necessary because when request_hooks == {'response': []}, the
-    merge breaks Session hooks entirely.
-    """
-    if session_hooks is None or session_hooks.get("response") == []:
-        return request_hooks
-
-    if request_hooks is None or request_hooks.get("response") == []:
-        return session_hooks
-
-    return merge_setting(request_hooks, session_hooks, dict_class)
-
-
-class SessionRedirectMixin:
-    def get_redirect_target(self, resp):
-        """Receives a Response. Returns a redirect URI or ``None``"""
-        # Due to the nature of how requests processes redirects this method will
-        # be called at least once upon the original response and at least twice
-        # on each subsequent redirect response (if any).
-        # If a custom mixin is used to handle this logic, it may be advantageous
-        # to cache the redirect location onto the response object as a private
-        # attribute.
-        if resp.is_redirect:
-            location = resp.headers["location"]
-            # Currently the underlying http module on py3 decode headers
-            # in latin1, but empirical evidence suggests that latin1 is very
-            # rarely used with non-ASCII characters in HTTP headers.
-            # It is more likely to get UTF8 header rather than latin1.
-            # This causes incorrect handling of UTF8 encoded location headers.
-            # To solve this, we re-encode the location in latin1.
-            location = location.encode("latin1")
-            return to_native_string(location, "utf8")
-        return None
-
-    def should_strip_auth(self, old_url, new_url):
-        """Decide whether Authorization header should be removed when redirecting"""
-        old_parsed = urlparse(old_url)
-        new_parsed = urlparse(new_url)
-        if old_parsed.hostname != new_parsed.hostname:
-            return True
-        # Special case: allow http -> https redirect when using the standard
-        # ports. This isn't specified by RFC 7235, but is kept to avoid
-        # breaking backwards compatibility with older versions of requests
-        # that allowed any redirects on the same host.
-        if (
-            old_parsed.scheme == "http"
-            and old_parsed.port in (80, None)
-            and new_parsed.scheme == "https"
-            and new_parsed.port in (443, None)
-        ):
-            return False
-
-        # Handle default port usage corresponding to scheme.
-        changed_port = old_parsed.port != new_parsed.port
-        changed_scheme = old_parsed.scheme != new_parsed.scheme
-        default_port = (DEFAULT_PORTS.get(old_parsed.scheme, None), None)
-        if (
-            not changed_scheme
-            and old_parsed.port in default_port
-            and new_parsed.port in default_port
-        ):
-            return False
-
-        # Standard case: root URI must match
-        return changed_port or changed_scheme
-
-    def resolve_redirects(
-        self,
-        resp,
-        req,
-        stream=False,
-        timeout=None,
-        verify=True,
-        cert=None,
-        proxies=None,
-        yield_requests=False,
-        **adapter_kwargs,
-    ):
-        """Receives a Response. Returns a generator of Responses or Requests."""
-
-        hist = []  # keep track of history
-
-        url = self.get_redirect_target(resp)
-        previous_fragment = urlparse(req.url).fragment
-        while url:
-            prepared_request = req.copy()
-
-            # Update history and keep track of redirects.
-            # resp.history must ignore the original request in this loop
-            hist.append(resp)
-            resp.history = hist[1:]
-
-            try:
-                resp.content  # Consume socket so it can be released
-            except (ChunkedEncodingError, ContentDecodingError, RuntimeError):
-                resp.raw.read(decode_content=False)
-
-            if len(resp.history) >= self.max_redirects:
-                raise TooManyRedirects(
-                    f"Exceeded {self.max_redirects} redirects.", response=resp
-                )
-
-            # Release the connection back into the pool.
-            resp.close()
-
-            # Handle redirection without scheme (see: RFC 1808 Section 4)
-            if url.startswith("//"):
-                parsed_rurl = urlparse(resp.url)
-                url = ":".join([to_native_string(parsed_rurl.scheme), url])
-
-            # Normalize url case and attach previous fragment if needed (RFC 7231 7.1.2)
-            parsed = urlparse(url)
-            if parsed.fragment == "" and previous_fragment:
-                parsed = parsed._replace(fragment=previous_fragment)
-            elif parsed.fragment:
-                previous_fragment = parsed.fragment
-            url = parsed.geturl()
-
-            # Facilitate relative 'location' headers, as allowed by RFC 7231.
-            # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource')
-            # Compliant with RFC3986, we percent encode the url.
-            if not parsed.netloc:
-                url = urljoin(resp.url, requote_uri(url))
-            else:
-                url = requote_uri(url)
-
-            prepared_request.url = to_native_string(url)
-
-            self.rebuild_method(prepared_request, resp)
-
-            # https://github.com/psf/requests/issues/1084
-            if resp.status_code not in (
-                codes.temporary_redirect,
-                codes.permanent_redirect,
-            ):
-                # https://github.com/psf/requests/issues/3490
-                purged_headers = ("Content-Length", "Content-Type", "Transfer-Encoding")
-                for header in purged_headers:
-                    prepared_request.headers.pop(header, None)
-                prepared_request.body = None
-
-            headers = prepared_request.headers
-            headers.pop("Cookie", None)
-
-            # Extract any cookies sent on the response to the cookiejar
-            # in the new request. Because we've mutated our copied prepared
-            # request, use the old one that we haven't yet touched.
-            extract_cookies_to_jar(prepared_request._cookies, req, resp.raw)
-            merge_cookies(prepared_request._cookies, self.cookies)
-            prepared_request.prepare_cookies(prepared_request._cookies)
-
-            # Rebuild auth and proxy information.
-            proxies = self.rebuild_proxies(prepared_request, proxies)
-            self.rebuild_auth(prepared_request, resp)
-
-            # A failed tell() sets `_body_position` to `object()`. This non-None
-            # value ensures `rewindable` will be True, allowing us to raise an
-            # UnrewindableBodyError, instead of hanging the connection.
-            rewindable = prepared_request._body_position is not None and (
-                "Content-Length" in headers or "Transfer-Encoding" in headers
-            )
-
-            # Attempt to rewind consumed file-like object.
-            if rewindable:
-                rewind_body(prepared_request)
-
-            # Override the original request.
-            req = prepared_request
-
-            if yield_requests:
-                yield req
-            else:
-                resp = self.send(
-                    req,
-                    stream=stream,
-                    timeout=timeout,
-                    verify=verify,
-                    cert=cert,
-                    proxies=proxies,
-                    allow_redirects=False,
-                    **adapter_kwargs,
-                )
-
-                extract_cookies_to_jar(self.cookies, prepared_request, resp.raw)
-
-                # extract redirect url, if any, for the next loop
-                url = self.get_redirect_target(resp)
-                yield resp
-
-    def rebuild_auth(self, prepared_request, response):
-        """When being redirected we may want to strip authentication from the
-        request to avoid leaking credentials. This method intelligently removes
-        and reapplies authentication where possible to avoid credential loss.
-        """
-        headers = prepared_request.headers
-        url = prepared_request.url
-
-        if "Authorization" in headers and self.should_strip_auth(
-            response.request.url, url
-        ):
-            # If we get redirected to a new host, we should strip out any
-            # authentication headers.
-            del headers["Authorization"]
-
-        # .netrc might have more auth for us on our new host.
-        new_auth = get_netrc_auth(url) if self.trust_env else None
-        if new_auth is not None:
-            prepared_request.prepare_auth(new_auth)
-
-    def rebuild_proxies(self, prepared_request, proxies):
-        """This method re-evaluates the proxy configuration by considering the
-        environment variables. If we are redirected to a URL covered by
-        NO_PROXY, we strip the proxy configuration. Otherwise, we set missing
-        proxy keys for this URL (in case they were stripped by a previous
-        redirect).
-
-        This method also replaces the Proxy-Authorization header where
-        necessary.
-
-        :rtype: dict
-        """
-        headers = prepared_request.headers
-        scheme = urlparse(prepared_request.url).scheme
-        new_proxies = resolve_proxies(prepared_request, proxies, self.trust_env)
-
-        if "Proxy-Authorization" in headers:
-            del headers["Proxy-Authorization"]
-
-        try:
-            username, password = get_auth_from_url(new_proxies[scheme])
-        except KeyError:
-            username, password = None, None
-
-        # urllib3 handles proxy authorization for us in the standard adapter.
-        # Avoid appending this to TLS tunneled requests where it may be leaked.
-        if not scheme.startswith("https") and username and password:
-            headers["Proxy-Authorization"] = _basic_auth_str(username, password)
-
-        return new_proxies
-
-    def rebuild_method(self, prepared_request, response):
-        """When being redirected we may want to change the method of the request
-        based on certain specs or browser behavior.
-        """
-        method = prepared_request.method
-
-        # https://tools.ietf.org/html/rfc7231#section-6.4.4
-        if response.status_code == codes.see_other and method != "HEAD":
-            method = "GET"
-
-        # Do what the browsers do, despite standards...
-        # First, turn 302s into GETs.
-        if response.status_code == codes.found and method != "HEAD":
-            method = "GET"
-
-        # Second, if a POST is responded to with a 301, turn it into a GET.
-        # This bizarre behaviour is explained in Issue 1704.
-        if response.status_code == codes.moved and method == "POST":
-            method = "GET"
-
-        prepared_request.method = method
-
-
-class Session(SessionRedirectMixin):
-    """A Requests session.
-
-    Provides cookie persistence, connection-pooling, and configuration.
-
-    Basic Usage::
-
-      >>> import requests
-      >>> s = requests.Session()
-      >>> s.get('https://httpbin.org/get')
-      
-
-    Or as a context manager::
-
-      >>> with requests.Session() as s:
-      ...     s.get('https://httpbin.org/get')
-      
-    """
-
-    __attrs__ = [
-        "headers",
-        "cookies",
-        "auth",
-        "proxies",
-        "hooks",
-        "params",
-        "verify",
-        "cert",
-        "adapters",
-        "stream",
-        "trust_env",
-        "max_redirects",
-    ]
-
-    def __init__(self):
-        #: A case-insensitive dictionary of headers to be sent on each
-        #: :class:`Request ` sent from this
-        #: :class:`Session `.
-        self.headers = default_headers()
-
-        #: Default Authentication tuple or object to attach to
-        #: :class:`Request `.
-        self.auth = None
-
-        #: Dictionary mapping protocol or protocol and host to the URL of the proxy
-        #: (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) to
-        #: be used on each :class:`Request `.
-        self.proxies = {}
-
-        #: Event-handling hooks.
-        self.hooks = default_hooks()
-
-        #: Dictionary of querystring data to attach to each
-        #: :class:`Request `. The dictionary values may be lists for
-        #: representing multivalued query parameters.
-        self.params = {}
-
-        #: Stream response content default.
-        self.stream = False
-
-        #: SSL Verification default.
-        #: Defaults to `True`, requiring requests to verify the TLS certificate at the
-        #: remote end.
-        #: If verify is set to `False`, requests will accept any TLS certificate
-        #: presented by the server, and will ignore hostname mismatches and/or
-        #: expired certificates, which will make your application vulnerable to
-        #: man-in-the-middle (MitM) attacks.
-        #: Only set this to `False` for testing.
-        self.verify = True
-
-        #: SSL client certificate default, if String, path to ssl client
-        #: cert file (.pem). If Tuple, ('cert', 'key') pair.
-        self.cert = None
-
-        #: Maximum number of redirects allowed. If the request exceeds this
-        #: limit, a :class:`TooManyRedirects` exception is raised.
-        #: This defaults to requests.models.DEFAULT_REDIRECT_LIMIT, which is
-        #: 30.
-        self.max_redirects = DEFAULT_REDIRECT_LIMIT
-
-        #: Trust environment settings for proxy configuration, default
-        #: authentication and similar.
-        self.trust_env = True
-
-        #: A CookieJar containing all currently outstanding cookies set on this
-        #: session. By default it is a
-        #: :class:`RequestsCookieJar `, but
-        #: may be any other ``cookielib.CookieJar`` compatible object.
-        self.cookies = cookiejar_from_dict({})
-
-        # Default connection adapters.
-        self.adapters = OrderedDict()
-        self.mount("https://", HTTPAdapter())
-        self.mount("http://", HTTPAdapter())
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, *args):
-        self.close()
-
-    def prepare_request(self, request):
-        """Constructs a :class:`PreparedRequest ` for
-        transmission and returns it. The :class:`PreparedRequest` has settings
-        merged from the :class:`Request ` instance and those of the
-        :class:`Session`.
-
-        :param request: :class:`Request` instance to prepare with this
-            session's settings.
-        :rtype: requests.PreparedRequest
-        """
-        cookies = request.cookies or {}
-
-        # Bootstrap CookieJar.
-        if not isinstance(cookies, cookielib.CookieJar):
-            cookies = cookiejar_from_dict(cookies)
-
-        # Merge with session cookies
-        merged_cookies = merge_cookies(
-            merge_cookies(RequestsCookieJar(), self.cookies), cookies
-        )
-
-        # Set environment's basic authentication if not explicitly set.
-        auth = request.auth
-        if self.trust_env and not auth and not self.auth:
-            auth = get_netrc_auth(request.url)
-
-        p = PreparedRequest()
-        p.prepare(
-            method=request.method.upper(),
-            url=request.url,
-            files=request.files,
-            data=request.data,
-            json=request.json,
-            headers=merge_setting(
-                request.headers, self.headers, dict_class=CaseInsensitiveDict
-            ),
-            params=merge_setting(request.params, self.params),
-            auth=merge_setting(auth, self.auth),
-            cookies=merged_cookies,
-            hooks=merge_hooks(request.hooks, self.hooks),
-        )
-        return p
-
-    def request(
-        self,
-        method,
-        url,
-        params=None,
-        data=None,
-        headers=None,
-        cookies=None,
-        files=None,
-        auth=None,
-        timeout=None,
-        allow_redirects=True,
-        proxies=None,
-        hooks=None,
-        stream=None,
-        verify=None,
-        cert=None,
-        json=None,
-    ):
-        """Constructs a :class:`Request `, prepares it and sends it.
-        Returns :class:`Response ` object.
-
-        :param method: method for the new :class:`Request` object.
-        :param url: URL for the new :class:`Request` object.
-        :param params: (optional) Dictionary or bytes to be sent in the query
-            string for the :class:`Request`.
-        :param data: (optional) Dictionary, list of tuples, bytes, or file-like
-            object to send in the body of the :class:`Request`.
-        :param json: (optional) json to send in the body of the
-            :class:`Request`.
-        :param headers: (optional) Dictionary of HTTP Headers to send with the
-            :class:`Request`.
-        :param cookies: (optional) Dict or CookieJar object to send with the
-            :class:`Request`.
-        :param files: (optional) Dictionary of ``'filename': file-like-objects``
-            for multipart encoding upload.
-        :param auth: (optional) Auth tuple or callable to enable
-            Basic/Digest/Custom HTTP Auth.
-        :param timeout: (optional) How many seconds to wait for the server to send
-            data before giving up, as a float, or a :ref:`(connect timeout,
-            read timeout) ` tuple.
-        :type timeout: float or tuple
-        :param allow_redirects: (optional) Set to True by default.
-        :type allow_redirects: bool
-        :param proxies: (optional) Dictionary mapping protocol or protocol and
-            hostname to the URL of the proxy.
-        :param hooks: (optional) Dictionary mapping hook name to one event or
-            list of events, event must be callable.
-        :param stream: (optional) whether to immediately download the response
-            content. Defaults to ``False``.
-        :param verify: (optional) Either a boolean, in which case it controls whether we verify
-            the server's TLS certificate, or a string, in which case it must be a path
-            to a CA bundle to use. Defaults to ``True``. When set to
-            ``False``, requests will accept any TLS certificate presented by
-            the server, and will ignore hostname mismatches and/or expired
-            certificates, which will make your application vulnerable to
-            man-in-the-middle (MitM) attacks. Setting verify to ``False``
-            may be useful during local development or testing.
-        :param cert: (optional) if String, path to ssl client cert file (.pem).
-            If Tuple, ('cert', 'key') pair.
-        :rtype: requests.Response
-        """
-        # Create the Request.
-        req = Request(
-            method=method.upper(),
-            url=url,
-            headers=headers,
-            files=files,
-            data=data or {},
-            json=json,
-            params=params or {},
-            auth=auth,
-            cookies=cookies,
-            hooks=hooks,
-        )
-        prep = self.prepare_request(req)
-
-        proxies = proxies or {}
-
-        settings = self.merge_environment_settings(
-            prep.url, proxies, stream, verify, cert
-        )
-
-        # Send the request.
-        send_kwargs = {
-            "timeout": timeout,
-            "allow_redirects": allow_redirects,
-        }
-        send_kwargs.update(settings)
-        resp = self.send(prep, **send_kwargs)
-
-        return resp
-
-    def get(self, url, **kwargs):
-        r"""Sends a GET request. Returns :class:`Response` object.
-
-        :param url: URL for the new :class:`Request` object.
-        :param \*\*kwargs: Optional arguments that ``request`` takes.
-        :rtype: requests.Response
-        """
-
-        kwargs.setdefault("allow_redirects", True)
-        return self.request("GET", url, **kwargs)
-
-    def options(self, url, **kwargs):
-        r"""Sends a OPTIONS request. Returns :class:`Response` object.
-
-        :param url: URL for the new :class:`Request` object.
-        :param \*\*kwargs: Optional arguments that ``request`` takes.
-        :rtype: requests.Response
-        """
-
-        kwargs.setdefault("allow_redirects", True)
-        return self.request("OPTIONS", url, **kwargs)
-
-    def head(self, url, **kwargs):
-        r"""Sends a HEAD request. Returns :class:`Response` object.
-
-        :param url: URL for the new :class:`Request` object.
-        :param \*\*kwargs: Optional arguments that ``request`` takes.
-        :rtype: requests.Response
-        """
-
-        kwargs.setdefault("allow_redirects", False)
-        return self.request("HEAD", url, **kwargs)
-
-    def post(self, url, data=None, json=None, **kwargs):
-        r"""Sends a POST request. Returns :class:`Response` object.
-
-        :param url: URL for the new :class:`Request` object.
-        :param data: (optional) Dictionary, list of tuples, bytes, or file-like
-            object to send in the body of the :class:`Request`.
-        :param json: (optional) json to send in the body of the :class:`Request`.
-        :param \*\*kwargs: Optional arguments that ``request`` takes.
-        :rtype: requests.Response
-        """
-
-        return self.request("POST", url, data=data, json=json, **kwargs)
-
-    def put(self, url, data=None, **kwargs):
-        r"""Sends a PUT request. Returns :class:`Response` object.
-
-        :param url: URL for the new :class:`Request` object.
-        :param data: (optional) Dictionary, list of tuples, bytes, or file-like
-            object to send in the body of the :class:`Request`.
-        :param \*\*kwargs: Optional arguments that ``request`` takes.
-        :rtype: requests.Response
-        """
-
-        return self.request("PUT", url, data=data, **kwargs)
-
-    def patch(self, url, data=None, **kwargs):
-        r"""Sends a PATCH request. Returns :class:`Response` object.
-
-        :param url: URL for the new :class:`Request` object.
-        :param data: (optional) Dictionary, list of tuples, bytes, or file-like
-            object to send in the body of the :class:`Request`.
-        :param \*\*kwargs: Optional arguments that ``request`` takes.
-        :rtype: requests.Response
-        """
-
-        return self.request("PATCH", url, data=data, **kwargs)
-
-    def delete(self, url, **kwargs):
-        r"""Sends a DELETE request. Returns :class:`Response` object.
-
-        :param url: URL for the new :class:`Request` object.
-        :param \*\*kwargs: Optional arguments that ``request`` takes.
-        :rtype: requests.Response
-        """
-
-        return self.request("DELETE", url, **kwargs)
-
-    def send(self, request, **kwargs):
-        """Send a given PreparedRequest.
-
-        :rtype: requests.Response
-        """
-        # Set defaults that the hooks can utilize to ensure they always have
-        # the correct parameters to reproduce the previous request.
-        kwargs.setdefault("stream", self.stream)
-        kwargs.setdefault("verify", self.verify)
-        kwargs.setdefault("cert", self.cert)
-        if "proxies" not in kwargs:
-            kwargs["proxies"] = resolve_proxies(request, self.proxies, self.trust_env)
-
-        # It's possible that users might accidentally send a Request object.
-        # Guard against that specific failure case.
-        if isinstance(request, Request):
-            raise ValueError("You can only send PreparedRequests.")
-
-        # Set up variables needed for resolve_redirects and dispatching of hooks
-        allow_redirects = kwargs.pop("allow_redirects", True)
-        stream = kwargs.get("stream")
-        hooks = request.hooks
-
-        # Get the appropriate adapter to use
-        adapter = self.get_adapter(url=request.url)
-
-        # Start time (approximately) of the request
-        start = preferred_clock()
-
-        # Send the request
-        r = adapter.send(request, **kwargs)
-
-        # Total elapsed time of the request (approximately)
-        elapsed = preferred_clock() - start
-        r.elapsed = timedelta(seconds=elapsed)
-
-        # Response manipulation hooks
-        r = dispatch_hook("response", hooks, r, **kwargs)
-
-        # Persist cookies
-        if r.history:
-            # If the hooks create history then we want those cookies too
-            for resp in r.history:
-                extract_cookies_to_jar(self.cookies, resp.request, resp.raw)
-
-        extract_cookies_to_jar(self.cookies, request, r.raw)
-
-        # Resolve redirects if allowed.
-        if allow_redirects:
-            # Redirect resolving generator.
-            gen = self.resolve_redirects(r, request, **kwargs)
-            history = [resp for resp in gen]
-        else:
-            history = []
-
-        # Shuffle things around if there's history.
-        if history:
-            # Insert the first (original) request at the start
-            history.insert(0, r)
-            # Get the last request made
-            r = history.pop()
-            r.history = history
-
-        # If redirects aren't being followed, store the response on the Request for Response.next().
-        if not allow_redirects:
-            try:
-                r._next = next(
-                    self.resolve_redirects(r, request, yield_requests=True, **kwargs)
-                )
-            except StopIteration:
-                pass
-
-        if not stream:
-            r.content
-
-        return r
-
-    def merge_environment_settings(self, url, proxies, stream, verify, cert):
-        """
-        Check the environment and merge it with some settings.
-
-        :rtype: dict
-        """
-        # Gather clues from the surrounding environment.
-        if self.trust_env:
-            # Set environment's proxies.
-            no_proxy = proxies.get("no_proxy") if proxies is not None else None
-            env_proxies = get_environ_proxies(url, no_proxy=no_proxy)
-            for k, v in env_proxies.items():
-                proxies.setdefault(k, v)
-
-            # Look for requests environment configuration
-            # and be compatible with cURL.
-            if verify is True or verify is None:
-                verify = (
-                    os.environ.get("REQUESTS_CA_BUNDLE")
-                    or os.environ.get("CURL_CA_BUNDLE")
-                    or verify
-                )
-
-        # Merge all the kwargs.
-        proxies = merge_setting(proxies, self.proxies)
-        stream = merge_setting(stream, self.stream)
-        verify = merge_setting(verify, self.verify)
-        cert = merge_setting(cert, self.cert)
-
-        return {"proxies": proxies, "stream": stream, "verify": verify, "cert": cert}
-
-    def get_adapter(self, url):
-        """
-        Returns the appropriate connection adapter for the given URL.
-
-        :rtype: requests.adapters.BaseAdapter
-        """
-        for prefix, adapter in self.adapters.items():
-            if url.lower().startswith(prefix.lower()):
-                return adapter
-
-        # Nothing matches :-/
-        raise InvalidSchema(f"No connection adapters were found for {url!r}")
-
-    def close(self):
-        """Closes all adapters and as such the session"""
-        for v in self.adapters.values():
-            v.close()
-
-    def mount(self, prefix, adapter):
-        """Registers a connection adapter to a prefix.
-
-        Adapters are sorted in descending order by prefix length.
-        """
-        self.adapters[prefix] = adapter
-        keys_to_move = [k for k in self.adapters if len(k) < len(prefix)]
-
-        for key in keys_to_move:
-            self.adapters[key] = self.adapters.pop(key)
-
-    def __getstate__(self):
-        state = {attr: getattr(self, attr, None) for attr in self.__attrs__}
-        return state
-
-    def __setstate__(self, state):
-        for attr, value in state.items():
-            setattr(self, attr, value)
-
-
-def session():
-    """
-    Returns a :class:`Session` for context-management.
-
-    .. deprecated:: 1.0.0
-
-        This method has been deprecated since version 1.0.0 and is only kept for
-        backwards compatibility. New code should use :class:`~requests.sessions.Session`
-        to create a session. This may be removed at a future date.
-
-    :rtype: Session
-    """
-    return Session()
diff --git a/apps/bitwarden_event_logs/lib/requests/status_codes.py b/apps/bitwarden_event_logs/lib/requests/status_codes.py
deleted file mode 100755
index c7945a2f..00000000
--- a/apps/bitwarden_event_logs/lib/requests/status_codes.py
+++ /dev/null
@@ -1,128 +0,0 @@
-r"""
-The ``codes`` object defines a mapping from common names for HTTP statuses
-to their numerical codes, accessible either as attributes or as dictionary
-items.
-
-Example::
-
-    >>> import requests
-    >>> requests.codes['temporary_redirect']
-    307
-    >>> requests.codes.teapot
-    418
-    >>> requests.codes['\o/']
-    200
-
-Some codes have multiple names, and both upper- and lower-case versions of
-the names are allowed. For example, ``codes.ok``, ``codes.OK``, and
-``codes.okay`` all correspond to the HTTP status code 200.
-"""
-
-from .structures import LookupDict
-
-_codes = {
-    # Informational.
-    100: ("continue",),
-    101: ("switching_protocols",),
-    102: ("processing", "early-hints"),
-    103: ("checkpoint",),
-    122: ("uri_too_long", "request_uri_too_long"),
-    200: ("ok", "okay", "all_ok", "all_okay", "all_good", "\\o/", "✓"),
-    201: ("created",),
-    202: ("accepted",),
-    203: ("non_authoritative_info", "non_authoritative_information"),
-    204: ("no_content",),
-    205: ("reset_content", "reset"),
-    206: ("partial_content", "partial"),
-    207: ("multi_status", "multiple_status", "multi_stati", "multiple_stati"),
-    208: ("already_reported",),
-    226: ("im_used",),
-    # Redirection.
-    300: ("multiple_choices",),
-    301: ("moved_permanently", "moved", "\\o-"),
-    302: ("found",),
-    303: ("see_other", "other"),
-    304: ("not_modified",),
-    305: ("use_proxy",),
-    306: ("switch_proxy",),
-    307: ("temporary_redirect", "temporary_moved", "temporary"),
-    308: (
-        "permanent_redirect",
-        "resume_incomplete",
-        "resume",
-    ),  # "resume" and "resume_incomplete" to be removed in 3.0
-    # Client Error.
-    400: ("bad_request", "bad"),
-    401: ("unauthorized",),
-    402: ("payment_required", "payment"),
-    403: ("forbidden",),
-    404: ("not_found", "-o-"),
-    405: ("method_not_allowed", "not_allowed"),
-    406: ("not_acceptable",),
-    407: ("proxy_authentication_required", "proxy_auth", "proxy_authentication"),
-    408: ("request_timeout", "timeout"),
-    409: ("conflict",),
-    410: ("gone",),
-    411: ("length_required",),
-    412: ("precondition_failed", "precondition"),
-    413: ("request_entity_too_large", "content_too_large"),
-    414: ("request_uri_too_large", "uri_too_long"),
-    415: ("unsupported_media_type", "unsupported_media", "media_type"),
-    416: (
-        "requested_range_not_satisfiable",
-        "requested_range",
-        "range_not_satisfiable",
-    ),
-    417: ("expectation_failed",),
-    418: ("im_a_teapot", "teapot", "i_am_a_teapot"),
-    421: ("misdirected_request",),
-    422: ("unprocessable_entity", "unprocessable", "unprocessable_content"),
-    423: ("locked",),
-    424: ("failed_dependency", "dependency"),
-    425: ("unordered_collection", "unordered", "too_early"),
-    426: ("upgrade_required", "upgrade"),
-    428: ("precondition_required", "precondition"),
-    429: ("too_many_requests", "too_many"),
-    431: ("header_fields_too_large", "fields_too_large"),
-    444: ("no_response", "none"),
-    449: ("retry_with", "retry"),
-    450: ("blocked_by_windows_parental_controls", "parental_controls"),
-    451: ("unavailable_for_legal_reasons", "legal_reasons"),
-    499: ("client_closed_request",),
-    # Server Error.
-    500: ("internal_server_error", "server_error", "/o\\", "✗"),
-    501: ("not_implemented",),
-    502: ("bad_gateway",),
-    503: ("service_unavailable", "unavailable"),
-    504: ("gateway_timeout",),
-    505: ("http_version_not_supported", "http_version"),
-    506: ("variant_also_negotiates",),
-    507: ("insufficient_storage",),
-    509: ("bandwidth_limit_exceeded", "bandwidth"),
-    510: ("not_extended",),
-    511: ("network_authentication_required", "network_auth", "network_authentication"),
-}
-
-codes = LookupDict(name="status_codes")
-
-
-def _init():
-    for code, titles in _codes.items():
-        for title in titles:
-            setattr(codes, title, code)
-            if not title.startswith(("\\", "/")):
-                setattr(codes, title.upper(), code)
-
-    def doc(code):
-        names = ", ".join(f"``{n}``" for n in _codes[code])
-        return "* %d: %s" % (code, names)
-
-    global __doc__
-    __doc__ = (
-        __doc__ + "\n" + "\n".join(doc(code) for code in sorted(_codes))
-        if __doc__ is not None
-        else None
-    )
-
-
-_init()
diff --git a/apps/bitwarden_event_logs/lib/requests/structures.py b/apps/bitwarden_event_logs/lib/requests/structures.py
deleted file mode 100755
index 188e13e4..00000000
--- a/apps/bitwarden_event_logs/lib/requests/structures.py
+++ /dev/null
@@ -1,99 +0,0 @@
-"""
-requests.structures
-~~~~~~~~~~~~~~~~~~~
-
-Data structures that power Requests.
-"""
-
-from collections import OrderedDict
-
-from .compat import Mapping, MutableMapping
-
-
-class CaseInsensitiveDict(MutableMapping):
-    """A case-insensitive ``dict``-like object.
-
-    Implements all methods and operations of
-    ``MutableMapping`` as well as dict's ``copy``. Also
-    provides ``lower_items``.
-
-    All keys are expected to be strings. The structure remembers the
-    case of the last key to be set, and ``iter(instance)``,
-    ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()``
-    will contain case-sensitive keys. However, querying and contains
-    testing is case insensitive::
-
-        cid = CaseInsensitiveDict()
-        cid['Accept'] = 'application/json'
-        cid['aCCEPT'] == 'application/json'  # True
-        list(cid) == ['Accept']  # True
-
-    For example, ``headers['content-encoding']`` will return the
-    value of a ``'Content-Encoding'`` response header, regardless
-    of how the header name was originally stored.
-
-    If the constructor, ``.update``, or equality comparison
-    operations are given keys that have equal ``.lower()``s, the
-    behavior is undefined.
-    """
-
-    def __init__(self, data=None, **kwargs):
-        self._store = OrderedDict()
-        if data is None:
-            data = {}
-        self.update(data, **kwargs)
-
-    def __setitem__(self, key, value):
-        # Use the lowercased key for lookups, but store the actual
-        # key alongside the value.
-        self._store[key.lower()] = (key, value)
-
-    def __getitem__(self, key):
-        return self._store[key.lower()][1]
-
-    def __delitem__(self, key):
-        del self._store[key.lower()]
-
-    def __iter__(self):
-        return (casedkey for casedkey, mappedvalue in self._store.values())
-
-    def __len__(self):
-        return len(self._store)
-
-    def lower_items(self):
-        """Like iteritems(), but with all lowercase keys."""
-        return ((lowerkey, keyval[1]) for (lowerkey, keyval) in self._store.items())
-
-    def __eq__(self, other):
-        if isinstance(other, Mapping):
-            other = CaseInsensitiveDict(other)
-        else:
-            return NotImplemented
-        # Compare insensitively
-        return dict(self.lower_items()) == dict(other.lower_items())
-
-    # Copy is required
-    def copy(self):
-        return CaseInsensitiveDict(self._store.values())
-
-    def __repr__(self):
-        return str(dict(self.items()))
-
-
-class LookupDict(dict):
-    """Dictionary lookup object."""
-
-    def __init__(self, name=None):
-        self.name = name
-        super().__init__()
-
-    def __repr__(self):
-        return f""
-
-    def __getitem__(self, key):
-        # We allow fall-through here, so values default to None
-
-        return self.__dict__.get(key, None)
-
-    def get(self, key, default=None):
-        return self.__dict__.get(key, default)
diff --git a/apps/bitwarden_event_logs/lib/requests/utils.py b/apps/bitwarden_event_logs/lib/requests/utils.py
deleted file mode 100755
index 8ab55852..00000000
--- a/apps/bitwarden_event_logs/lib/requests/utils.py
+++ /dev/null
@@ -1,1086 +0,0 @@
-"""
-requests.utils
-~~~~~~~~~~~~~~
-
-This module provides utility functions that are used within Requests
-that are also useful for external consumption.
-"""
-
-import codecs
-import contextlib
-import io
-import os
-import re
-import socket
-import struct
-import sys
-import tempfile
-import warnings
-import zipfile
-from collections import OrderedDict
-
-from urllib3.util import make_headers, parse_url
-
-from . import certs
-from .__version__ import __version__
-
-# to_native_string is unused here, but imported here for backwards compatibility
-from ._internal_utils import (  # noqa: F401
-    _HEADER_VALIDATORS_BYTE,
-    _HEADER_VALIDATORS_STR,
-    HEADER_VALIDATORS,
-    to_native_string,
-)
-from .compat import (
-    Mapping,
-    basestring,
-    bytes,
-    getproxies,
-    getproxies_environment,
-    integer_types,
-    is_urllib3_1,
-)
-from .compat import parse_http_list as _parse_list_header
-from .compat import (
-    proxy_bypass,
-    proxy_bypass_environment,
-    quote,
-    str,
-    unquote,
-    urlparse,
-    urlunparse,
-)
-from .cookies import cookiejar_from_dict
-from .exceptions import (
-    FileModeWarning,
-    InvalidHeader,
-    InvalidURL,
-    UnrewindableBodyError,
-)
-from .structures import CaseInsensitiveDict
-
-NETRC_FILES = (".netrc", "_netrc")
-
-DEFAULT_CA_BUNDLE_PATH = certs.where()
-
-DEFAULT_PORTS = {"http": 80, "https": 443}
-
-# Ensure that ', ' is used to preserve previous delimiter behavior.
-DEFAULT_ACCEPT_ENCODING = ", ".join(
-    re.split(r",\s*", make_headers(accept_encoding=True)["accept-encoding"])
-)
-
-
-if sys.platform == "win32":
-    # provide a proxy_bypass version on Windows without DNS lookups
-
-    def proxy_bypass_registry(host):
-        try:
-            import winreg
-        except ImportError:
-            return False
-
-        try:
-            internetSettings = winreg.OpenKey(
-                winreg.HKEY_CURRENT_USER,
-                r"Software\Microsoft\Windows\CurrentVersion\Internet Settings",
-            )
-            # ProxyEnable could be REG_SZ or REG_DWORD, normalizing it
-            proxyEnable = int(winreg.QueryValueEx(internetSettings, "ProxyEnable")[0])
-            # ProxyOverride is almost always a string
-            proxyOverride = winreg.QueryValueEx(internetSettings, "ProxyOverride")[0]
-        except (OSError, ValueError):
-            return False
-        if not proxyEnable or not proxyOverride:
-            return False
-
-        # make a check value list from the registry entry: replace the
-        # '' string by the localhost entry and the corresponding
-        # canonical entry.
-        proxyOverride = proxyOverride.split(";")
-        # filter out empty strings to avoid re.match return true in the following code.
-        proxyOverride = filter(None, proxyOverride)
-        # now check if we match one of the registry values.
-        for test in proxyOverride:
-            if test == "":
-                if "." not in host:
-                    return True
-            test = test.replace(".", r"\.")  # mask dots
-            test = test.replace("*", r".*")  # change glob sequence
-            test = test.replace("?", r".")  # change glob char
-            if re.match(test, host, re.I):
-                return True
-        return False
-
-    def proxy_bypass(host):  # noqa
-        """Return True, if the host should be bypassed.
-
-        Checks proxy settings gathered from the environment, if specified,
-        or the registry.
-        """
-        if getproxies_environment():
-            return proxy_bypass_environment(host)
-        else:
-            return proxy_bypass_registry(host)
-
-
-def dict_to_sequence(d):
-    """Returns an internal sequence dictionary update."""
-
-    if hasattr(d, "items"):
-        d = d.items()
-
-    return d
-
-
-def super_len(o):
-    total_length = None
-    current_position = 0
-
-    if not is_urllib3_1 and isinstance(o, str):
-        # urllib3 2.x+ treats all strings as utf-8 instead
-        # of latin-1 (iso-8859-1) like http.client.
-        o = o.encode("utf-8")
-
-    if hasattr(o, "__len__"):
-        total_length = len(o)
-
-    elif hasattr(o, "len"):
-        total_length = o.len
-
-    elif hasattr(o, "fileno"):
-        try:
-            fileno = o.fileno()
-        except (io.UnsupportedOperation, AttributeError):
-            # AttributeError is a surprising exception, seeing as how we've just checked
-            # that `hasattr(o, 'fileno')`.  It happens for objects obtained via
-            # `Tarfile.extractfile()`, per issue 5229.
-            pass
-        else:
-            total_length = os.fstat(fileno).st_size
-
-            # Having used fstat to determine the file length, we need to
-            # confirm that this file was opened up in binary mode.
-            if "b" not in o.mode:
-                warnings.warn(
-                    (
-                        "Requests has determined the content-length for this "
-                        "request using the binary size of the file: however, the "
-                        "file has been opened in text mode (i.e. without the 'b' "
-                        "flag in the mode). This may lead to an incorrect "
-                        "content-length. In Requests 3.0, support will be removed "
-                        "for files in text mode."
-                    ),
-                    FileModeWarning,
-                )
-
-    if hasattr(o, "tell"):
-        try:
-            current_position = o.tell()
-        except OSError:
-            # This can happen in some weird situations, such as when the file
-            # is actually a special file descriptor like stdin. In this
-            # instance, we don't know what the length is, so set it to zero and
-            # let requests chunk it instead.
-            if total_length is not None:
-                current_position = total_length
-        else:
-            if hasattr(o, "seek") and total_length is None:
-                # StringIO and BytesIO have seek but no usable fileno
-                try:
-                    # seek to end of file
-                    o.seek(0, 2)
-                    total_length = o.tell()
-
-                    # seek back to current position to support
-                    # partially read file-like objects
-                    o.seek(current_position or 0)
-                except OSError:
-                    total_length = 0
-
-    if total_length is None:
-        total_length = 0
-
-    return max(0, total_length - current_position)
-
-
-def get_netrc_auth(url, raise_errors=False):
-    """Returns the Requests tuple auth for a given url from netrc."""
-
-    netrc_file = os.environ.get("NETRC")
-    if netrc_file is not None:
-        netrc_locations = (netrc_file,)
-    else:
-        netrc_locations = (f"~/{f}" for f in NETRC_FILES)
-
-    try:
-        from netrc import NetrcParseError, netrc
-
-        netrc_path = None
-
-        for f in netrc_locations:
-            loc = os.path.expanduser(f)
-            if os.path.exists(loc):
-                netrc_path = loc
-                break
-
-        # Abort early if there isn't one.
-        if netrc_path is None:
-            return
-
-        ri = urlparse(url)
-        host = ri.hostname
-
-        try:
-            _netrc = netrc(netrc_path).authenticators(host)
-            if _netrc:
-                # Return with login / password
-                login_i = 0 if _netrc[0] else 1
-                return (_netrc[login_i], _netrc[2])
-        except (NetrcParseError, OSError):
-            # If there was a parsing error or a permissions issue reading the file,
-            # we'll just skip netrc auth unless explicitly asked to raise errors.
-            if raise_errors:
-                raise
-
-    # App Engine hackiness.
-    except (ImportError, AttributeError):
-        pass
-
-
-def guess_filename(obj):
-    """Tries to guess the filename of the given object."""
-    name = getattr(obj, "name", None)
-    if name and isinstance(name, basestring) and name[0] != "<" and name[-1] != ">":
-        return os.path.basename(name)
-
-
-def extract_zipped_paths(path):
-    """Replace nonexistent paths that look like they refer to a member of a zip
-    archive with the location of an extracted copy of the target, or else
-    just return the provided path unchanged.
-    """
-    if os.path.exists(path):
-        # this is already a valid path, no need to do anything further
-        return path
-
-    # find the first valid part of the provided path and treat that as a zip archive
-    # assume the rest of the path is the name of a member in the archive
-    archive, member = os.path.split(path)
-    while archive and not os.path.exists(archive):
-        archive, prefix = os.path.split(archive)
-        if not prefix:
-            # If we don't check for an empty prefix after the split (in other words, archive remains unchanged after the split),
-            # we _can_ end up in an infinite loop on a rare corner case affecting a small number of users
-            break
-        member = "/".join([prefix, member])
-
-    if not zipfile.is_zipfile(archive):
-        return path
-
-    zip_file = zipfile.ZipFile(archive)
-    if member not in zip_file.namelist():
-        return path
-
-    # we have a valid zip archive and a valid member of that archive
-    tmp = tempfile.gettempdir()
-    extracted_path = os.path.join(tmp, member.split("/")[-1])
-    if not os.path.exists(extracted_path):
-        # use read + write to avoid the creating nested folders, we only want the file, avoids mkdir racing condition
-        with atomic_open(extracted_path) as file_handler:
-            file_handler.write(zip_file.read(member))
-    return extracted_path
-
-
-@contextlib.contextmanager
-def atomic_open(filename):
-    """Write a file to the disk in an atomic fashion"""
-    tmp_descriptor, tmp_name = tempfile.mkstemp(dir=os.path.dirname(filename))
-    try:
-        with os.fdopen(tmp_descriptor, "wb") as tmp_handler:
-            yield tmp_handler
-        os.replace(tmp_name, filename)
-    except BaseException:
-        os.remove(tmp_name)
-        raise
-
-
-def from_key_val_list(value):
-    """Take an object and test to see if it can be represented as a
-    dictionary. Unless it can not be represented as such, return an
-    OrderedDict, e.g.,
-
-    ::
-
-        >>> from_key_val_list([('key', 'val')])
-        OrderedDict([('key', 'val')])
-        >>> from_key_val_list('string')
-        Traceback (most recent call last):
-        ...
-        ValueError: cannot encode objects that are not 2-tuples
-        >>> from_key_val_list({'key': 'val'})
-        OrderedDict([('key', 'val')])
-
-    :rtype: OrderedDict
-    """
-    if value is None:
-        return None
-
-    if isinstance(value, (str, bytes, bool, int)):
-        raise ValueError("cannot encode objects that are not 2-tuples")
-
-    return OrderedDict(value)
-
-
-def to_key_val_list(value):
-    """Take an object and test to see if it can be represented as a
-    dictionary. If it can be, return a list of tuples, e.g.,
-
-    ::
-
-        >>> to_key_val_list([('key', 'val')])
-        [('key', 'val')]
-        >>> to_key_val_list({'key': 'val'})
-        [('key', 'val')]
-        >>> to_key_val_list('string')
-        Traceback (most recent call last):
-        ...
-        ValueError: cannot encode objects that are not 2-tuples
-
-    :rtype: list
-    """
-    if value is None:
-        return None
-
-    if isinstance(value, (str, bytes, bool, int)):
-        raise ValueError("cannot encode objects that are not 2-tuples")
-
-    if isinstance(value, Mapping):
-        value = value.items()
-
-    return list(value)
-
-
-# From mitsuhiko/werkzeug (used with permission).
-def parse_list_header(value):
-    """Parse lists as described by RFC 2068 Section 2.
-
-    In particular, parse comma-separated lists where the elements of
-    the list may include quoted-strings.  A quoted-string could
-    contain a comma.  A non-quoted string could have quotes in the
-    middle.  Quotes are removed automatically after parsing.
-
-    It basically works like :func:`parse_set_header` just that items
-    may appear multiple times and case sensitivity is preserved.
-
-    The return value is a standard :class:`list`:
-
-    >>> parse_list_header('token, "quoted value"')
-    ['token', 'quoted value']
-
-    To create a header from the :class:`list` again, use the
-    :func:`dump_header` function.
-
-    :param value: a string with a list header.
-    :return: :class:`list`
-    :rtype: list
-    """
-    result = []
-    for item in _parse_list_header(value):
-        if item[:1] == item[-1:] == '"':
-            item = unquote_header_value(item[1:-1])
-        result.append(item)
-    return result
-
-
-# From mitsuhiko/werkzeug (used with permission).
-def parse_dict_header(value):
-    """Parse lists of key, value pairs as described by RFC 2068 Section 2 and
-    convert them into a python dict:
-
-    >>> d = parse_dict_header('foo="is a fish", bar="as well"')
-    >>> type(d) is dict
-    True
-    >>> sorted(d.items())
-    [('bar', 'as well'), ('foo', 'is a fish')]
-
-    If there is no value for a key it will be `None`:
-
-    >>> parse_dict_header('key_without_value')
-    {'key_without_value': None}
-
-    To create a header from the :class:`dict` again, use the
-    :func:`dump_header` function.
-
-    :param value: a string with a dict header.
-    :return: :class:`dict`
-    :rtype: dict
-    """
-    result = {}
-    for item in _parse_list_header(value):
-        if "=" not in item:
-            result[item] = None
-            continue
-        name, value = item.split("=", 1)
-        if value[:1] == value[-1:] == '"':
-            value = unquote_header_value(value[1:-1])
-        result[name] = value
-    return result
-
-
-# From mitsuhiko/werkzeug (used with permission).
-def unquote_header_value(value, is_filename=False):
-    r"""Unquotes a header value.  (Reversal of :func:`quote_header_value`).
-    This does not use the real unquoting but what browsers are actually
-    using for quoting.
-
-    :param value: the header value to unquote.
-    :rtype: str
-    """
-    if value and value[0] == value[-1] == '"':
-        # this is not the real unquoting, but fixing this so that the
-        # RFC is met will result in bugs with internet explorer and
-        # probably some other browsers as well.  IE for example is
-        # uploading files with "C:\foo\bar.txt" as filename
-        value = value[1:-1]
-
-        # if this is a filename and the starting characters look like
-        # a UNC path, then just return the value without quotes.  Using the
-        # replace sequence below on a UNC path has the effect of turning
-        # the leading double slash into a single slash and then
-        # _fix_ie_filename() doesn't work correctly.  See #458.
-        if not is_filename or value[:2] != "\\\\":
-            return value.replace("\\\\", "\\").replace('\\"', '"')
-    return value
-
-
-def dict_from_cookiejar(cj):
-    """Returns a key/value dictionary from a CookieJar.
-
-    :param cj: CookieJar object to extract cookies from.
-    :rtype: dict
-    """
-
-    cookie_dict = {cookie.name: cookie.value for cookie in cj}
-    return cookie_dict
-
-
-def add_dict_to_cookiejar(cj, cookie_dict):
-    """Returns a CookieJar from a key/value dictionary.
-
-    :param cj: CookieJar to insert cookies into.
-    :param cookie_dict: Dict of key/values to insert into CookieJar.
-    :rtype: CookieJar
-    """
-
-    return cookiejar_from_dict(cookie_dict, cj)
-
-
-def get_encodings_from_content(content):
-    """Returns encodings from given content string.
-
-    :param content: bytestring to extract encodings from.
-    """
-    warnings.warn(
-        (
-            "In requests 3.0, get_encodings_from_content will be removed. For "
-            "more information, please see the discussion on issue #2266. (This"
-            " warning should only appear once.)"
-        ),
-        DeprecationWarning,
-    )
-
-    charset_re = re.compile(r']', flags=re.I)
-    pragma_re = re.compile(r']', flags=re.I)
-    xml_re = re.compile(r'^<\?xml.*?encoding=["\']*(.+?)["\'>]')
-
-    return (
-        charset_re.findall(content)
-        + pragma_re.findall(content)
-        + xml_re.findall(content)
-    )
-
-
-def _parse_content_type_header(header):
-    """Returns content type and parameters from given header
-
-    :param header: string
-    :return: tuple containing content type and dictionary of
-         parameters
-    """
-
-    tokens = header.split(";")
-    content_type, params = tokens[0].strip(), tokens[1:]
-    params_dict = {}
-    items_to_strip = "\"' "
-
-    for param in params:
-        param = param.strip()
-        if param:
-            key, value = param, True
-            index_of_equals = param.find("=")
-            if index_of_equals != -1:
-                key = param[:index_of_equals].strip(items_to_strip)
-                value = param[index_of_equals + 1 :].strip(items_to_strip)
-            params_dict[key.lower()] = value
-    return content_type, params_dict
-
-
-def get_encoding_from_headers(headers):
-    """Returns encodings from given HTTP Header Dict.
-
-    :param headers: dictionary to extract encoding from.
-    :rtype: str
-    """
-
-    content_type = headers.get("content-type")
-
-    if not content_type:
-        return None
-
-    content_type, params = _parse_content_type_header(content_type)
-
-    if "charset" in params:
-        return params["charset"].strip("'\"")
-
-    if "text" in content_type:
-        return "ISO-8859-1"
-
-    if "application/json" in content_type:
-        # Assume UTF-8 based on RFC 4627: https://www.ietf.org/rfc/rfc4627.txt since the charset was unset
-        return "utf-8"
-
-
-def stream_decode_response_unicode(iterator, r):
-    """Stream decodes an iterator."""
-
-    if r.encoding is None:
-        yield from iterator
-        return
-
-    decoder = codecs.getincrementaldecoder(r.encoding)(errors="replace")
-    for chunk in iterator:
-        rv = decoder.decode(chunk)
-        if rv:
-            yield rv
-    rv = decoder.decode(b"", final=True)
-    if rv:
-        yield rv
-
-
-def iter_slices(string, slice_length):
-    """Iterate over slices of a string."""
-    pos = 0
-    if slice_length is None or slice_length <= 0:
-        slice_length = len(string)
-    while pos < len(string):
-        yield string[pos : pos + slice_length]
-        pos += slice_length
-
-
-def get_unicode_from_response(r):
-    """Returns the requested content back in unicode.
-
-    :param r: Response object to get unicode content from.
-
-    Tried:
-
-    1. charset from content-type
-    2. fall back and replace all unicode characters
-
-    :rtype: str
-    """
-    warnings.warn(
-        (
-            "In requests 3.0, get_unicode_from_response will be removed. For "
-            "more information, please see the discussion on issue #2266. (This"
-            " warning should only appear once.)"
-        ),
-        DeprecationWarning,
-    )
-
-    tried_encodings = []
-
-    # Try charset from content-type
-    encoding = get_encoding_from_headers(r.headers)
-
-    if encoding:
-        try:
-            return str(r.content, encoding)
-        except UnicodeError:
-            tried_encodings.append(encoding)
-
-    # Fall back:
-    try:
-        return str(r.content, encoding, errors="replace")
-    except TypeError:
-        return r.content
-
-
-# The unreserved URI characters (RFC 3986)
-UNRESERVED_SET = frozenset(
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789-._~"
-)
-
-
-def unquote_unreserved(uri):
-    """Un-escape any percent-escape sequences in a URI that are unreserved
-    characters. This leaves all reserved, illegal and non-ASCII bytes encoded.
-
-    :rtype: str
-    """
-    parts = uri.split("%")
-    for i in range(1, len(parts)):
-        h = parts[i][0:2]
-        if len(h) == 2 and h.isalnum():
-            try:
-                c = chr(int(h, 16))
-            except ValueError:
-                raise InvalidURL(f"Invalid percent-escape sequence: '{h}'")
-
-            if c in UNRESERVED_SET:
-                parts[i] = c + parts[i][2:]
-            else:
-                parts[i] = f"%{parts[i]}"
-        else:
-            parts[i] = f"%{parts[i]}"
-    return "".join(parts)
-
-
-def requote_uri(uri):
-    """Re-quote the given URI.
-
-    This function passes the given URI through an unquote/quote cycle to
-    ensure that it is fully and consistently quoted.
-
-    :rtype: str
-    """
-    safe_with_percent = "!#$%&'()*+,/:;=?@[]~"
-    safe_without_percent = "!#$&'()*+,/:;=?@[]~"
-    try:
-        # Unquote only the unreserved characters
-        # Then quote only illegal characters (do not quote reserved,
-        # unreserved, or '%')
-        return quote(unquote_unreserved(uri), safe=safe_with_percent)
-    except InvalidURL:
-        # We couldn't unquote the given URI, so let's try quoting it, but
-        # there may be unquoted '%'s in the URI. We need to make sure they're
-        # properly quoted so they do not cause issues elsewhere.
-        return quote(uri, safe=safe_without_percent)
-
-
-def address_in_network(ip, net):
-    """This function allows you to check if an IP belongs to a network subnet
-
-    Example: returns True if ip = 192.168.1.1 and net = 192.168.1.0/24
-             returns False if ip = 192.168.1.1 and net = 192.168.100.0/24
-
-    :rtype: bool
-    """
-    ipaddr = struct.unpack("=L", socket.inet_aton(ip))[0]
-    netaddr, bits = net.split("/")
-    netmask = struct.unpack("=L", socket.inet_aton(dotted_netmask(int(bits))))[0]
-    network = struct.unpack("=L", socket.inet_aton(netaddr))[0] & netmask
-    return (ipaddr & netmask) == (network & netmask)
-
-
-def dotted_netmask(mask):
-    """Converts mask from /xx format to xxx.xxx.xxx.xxx
-
-    Example: if mask is 24 function returns 255.255.255.0
-
-    :rtype: str
-    """
-    bits = 0xFFFFFFFF ^ (1 << 32 - mask) - 1
-    return socket.inet_ntoa(struct.pack(">I", bits))
-
-
-def is_ipv4_address(string_ip):
-    """
-    :rtype: bool
-    """
-    try:
-        socket.inet_aton(string_ip)
-    except OSError:
-        return False
-    return True
-
-
-def is_valid_cidr(string_network):
-    """
-    Very simple check of the cidr format in no_proxy variable.
-
-    :rtype: bool
-    """
-    if string_network.count("/") == 1:
-        try:
-            mask = int(string_network.split("/")[1])
-        except ValueError:
-            return False
-
-        if mask < 1 or mask > 32:
-            return False
-
-        try:
-            socket.inet_aton(string_network.split("/")[0])
-        except OSError:
-            return False
-    else:
-        return False
-    return True
-
-
-@contextlib.contextmanager
-def set_environ(env_name, value):
-    """Set the environment variable 'env_name' to 'value'
-
-    Save previous value, yield, and then restore the previous value stored in
-    the environment variable 'env_name'.
-
-    If 'value' is None, do nothing"""
-    value_changed = value is not None
-    if value_changed:
-        old_value = os.environ.get(env_name)
-        os.environ[env_name] = value
-    try:
-        yield
-    finally:
-        if value_changed:
-            if old_value is None:
-                del os.environ[env_name]
-            else:
-                os.environ[env_name] = old_value
-
-
-def should_bypass_proxies(url, no_proxy):
-    """
-    Returns whether we should bypass proxies or not.
-
-    :rtype: bool
-    """
-
-    # Prioritize lowercase environment variables over uppercase
-    # to keep a consistent behaviour with other http projects (curl, wget).
-    def get_proxy(key):
-        return os.environ.get(key) or os.environ.get(key.upper())
-
-    # First check whether no_proxy is defined. If it is, check that the URL
-    # we're getting isn't in the no_proxy list.
-    no_proxy_arg = no_proxy
-    if no_proxy is None:
-        no_proxy = get_proxy("no_proxy")
-    parsed = urlparse(url)
-
-    if parsed.hostname is None:
-        # URLs don't always have hostnames, e.g. file:/// urls.
-        return True
-
-    if no_proxy:
-        # We need to check whether we match here. We need to see if we match
-        # the end of the hostname, both with and without the port.
-        no_proxy = (host for host in no_proxy.replace(" ", "").split(",") if host)
-
-        if is_ipv4_address(parsed.hostname):
-            for proxy_ip in no_proxy:
-                if is_valid_cidr(proxy_ip):
-                    if address_in_network(parsed.hostname, proxy_ip):
-                        return True
-                elif parsed.hostname == proxy_ip:
-                    # If no_proxy ip was defined in plain IP notation instead of cidr notation &
-                    # matches the IP of the index
-                    return True
-        else:
-            host_with_port = parsed.hostname
-            if parsed.port:
-                host_with_port += f":{parsed.port}"
-
-            for host in no_proxy:
-                if parsed.hostname.endswith(host) or host_with_port.endswith(host):
-                    # The URL does match something in no_proxy, so we don't want
-                    # to apply the proxies on this URL.
-                    return True
-
-    with set_environ("no_proxy", no_proxy_arg):
-        # parsed.hostname can be `None` in cases such as a file URI.
-        try:
-            bypass = proxy_bypass(parsed.hostname)
-        except (TypeError, socket.gaierror):
-            bypass = False
-
-    if bypass:
-        return True
-
-    return False
-
-
-def get_environ_proxies(url, no_proxy=None):
-    """
-    Return a dict of environment proxies.
-
-    :rtype: dict
-    """
-    if should_bypass_proxies(url, no_proxy=no_proxy):
-        return {}
-    else:
-        return getproxies()
-
-
-def select_proxy(url, proxies):
-    """Select a proxy for the url, if applicable.
-
-    :param url: The url being for the request
-    :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs
-    """
-    proxies = proxies or {}
-    urlparts = urlparse(url)
-    if urlparts.hostname is None:
-        return proxies.get(urlparts.scheme, proxies.get("all"))
-
-    proxy_keys = [
-        urlparts.scheme + "://" + urlparts.hostname,
-        urlparts.scheme,
-        "all://" + urlparts.hostname,
-        "all",
-    ]
-    proxy = None
-    for proxy_key in proxy_keys:
-        if proxy_key in proxies:
-            proxy = proxies[proxy_key]
-            break
-
-    return proxy
-
-
-def resolve_proxies(request, proxies, trust_env=True):
-    """This method takes proxy information from a request and configuration
-    input to resolve a mapping of target proxies. This will consider settings
-    such as NO_PROXY to strip proxy configurations.
-
-    :param request: Request or PreparedRequest
-    :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs
-    :param trust_env: Boolean declaring whether to trust environment configs
-
-    :rtype: dict
-    """
-    proxies = proxies if proxies is not None else {}
-    url = request.url
-    scheme = urlparse(url).scheme
-    no_proxy = proxies.get("no_proxy")
-    new_proxies = proxies.copy()
-
-    if trust_env and not should_bypass_proxies(url, no_proxy=no_proxy):
-        environ_proxies = get_environ_proxies(url, no_proxy=no_proxy)
-
-        proxy = environ_proxies.get(scheme, environ_proxies.get("all"))
-
-        if proxy:
-            new_proxies.setdefault(scheme, proxy)
-    return new_proxies
-
-
-def default_user_agent(name="python-requests"):
-    """
-    Return a string representing the default user agent.
-
-    :rtype: str
-    """
-    return f"{name}/{__version__}"
-
-
-def default_headers():
-    """
-    :rtype: requests.structures.CaseInsensitiveDict
-    """
-    return CaseInsensitiveDict(
-        {
-            "User-Agent": default_user_agent(),
-            "Accept-Encoding": DEFAULT_ACCEPT_ENCODING,
-            "Accept": "*/*",
-            "Connection": "keep-alive",
-        }
-    )
-
-
-def parse_header_links(value):
-    """Return a list of parsed link headers proxies.
-
-    i.e. Link: ; rel=front; type="image/jpeg",; rel=back;type="image/jpeg"
-
-    :rtype: list
-    """
-
-    links = []
-
-    replace_chars = " '\""
-
-    value = value.strip(replace_chars)
-    if not value:
-        return links
-
-    for val in re.split(", *<", value):
-        try:
-            url, params = val.split(";", 1)
-        except ValueError:
-            url, params = val, ""
-
-        link = {"url": url.strip("<> '\"")}
-
-        for param in params.split(";"):
-            try:
-                key, value = param.split("=")
-            except ValueError:
-                break
-
-            link[key.strip(replace_chars)] = value.strip(replace_chars)
-
-        links.append(link)
-
-    return links
-
-
-# Null bytes; no need to recreate these on each call to guess_json_utf
-_null = "\x00".encode("ascii")  # encoding to ASCII for Python 3
-_null2 = _null * 2
-_null3 = _null * 3
-
-
-def guess_json_utf(data):
-    """
-    :rtype: str
-    """
-    # JSON always starts with two ASCII characters, so detection is as
-    # easy as counting the nulls and from their location and count
-    # determine the encoding. Also detect a BOM, if present.
-    sample = data[:4]
-    if sample in (codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE):
-        return "utf-32"  # BOM included
-    if sample[:3] == codecs.BOM_UTF8:
-        return "utf-8-sig"  # BOM included, MS style (discouraged)
-    if sample[:2] in (codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE):
-        return "utf-16"  # BOM included
-    nullcount = sample.count(_null)
-    if nullcount == 0:
-        return "utf-8"
-    if nullcount == 2:
-        if sample[::2] == _null2:  # 1st and 3rd are null
-            return "utf-16-be"
-        if sample[1::2] == _null2:  # 2nd and 4th are null
-            return "utf-16-le"
-        # Did not detect 2 valid UTF-16 ascii-range characters
-    if nullcount == 3:
-        if sample[:3] == _null3:
-            return "utf-32-be"
-        if sample[1:] == _null3:
-            return "utf-32-le"
-        # Did not detect a valid UTF-32 ascii-range character
-    return None
-
-
-def prepend_scheme_if_needed(url, new_scheme):
-    """Given a URL that may or may not have a scheme, prepend the given scheme.
-    Does not replace a present scheme with the one provided as an argument.
-
-    :rtype: str
-    """
-    parsed = parse_url(url)
-    scheme, auth, host, port, path, query, fragment = parsed
-
-    # A defect in urlparse determines that there isn't a netloc present in some
-    # urls. We previously assumed parsing was overly cautious, and swapped the
-    # netloc and path. Due to a lack of tests on the original defect, this is
-    # maintained with parse_url for backwards compatibility.
-    netloc = parsed.netloc
-    if not netloc:
-        netloc, path = path, netloc
-
-    if auth:
-        # parse_url doesn't provide the netloc with auth
-        # so we'll add it ourselves.
-        netloc = "@".join([auth, netloc])
-    if scheme is None:
-        scheme = new_scheme
-    if path is None:
-        path = ""
-
-    return urlunparse((scheme, netloc, path, "", query, fragment))
-
-
-def get_auth_from_url(url):
-    """Given a url with authentication components, extract them into a tuple of
-    username,password.
-
-    :rtype: (str,str)
-    """
-    parsed = urlparse(url)
-
-    try:
-        auth = (unquote(parsed.username), unquote(parsed.password))
-    except (AttributeError, TypeError):
-        auth = ("", "")
-
-    return auth
-
-
-def check_header_validity(header):
-    """Verifies that header parts don't contain leading whitespace
-    reserved characters, or return characters.
-
-    :param header: tuple, in the format (name, value).
-    """
-    name, value = header
-    _validate_header_part(header, name, 0)
-    _validate_header_part(header, value, 1)
-
-
-def _validate_header_part(header, header_part, header_validator_index):
-    if isinstance(header_part, str):
-        validator = _HEADER_VALIDATORS_STR[header_validator_index]
-    elif isinstance(header_part, bytes):
-        validator = _HEADER_VALIDATORS_BYTE[header_validator_index]
-    else:
-        raise InvalidHeader(
-            f"Header part ({header_part!r}) from {header} "
-            f"must be of type str or bytes, not {type(header_part)}"
-        )
-
-    if not validator.match(header_part):
-        header_kind = "name" if header_validator_index == 0 else "value"
-        raise InvalidHeader(
-            f"Invalid leading whitespace, reserved character(s), or return "
-            f"character(s) in header {header_kind}: {header_part!r}"
-        )
-
-
-def urldefragauth(url):
-    """
-    Given a url remove the fragment and the authentication part.
-
-    :rtype: str
-    """
-    scheme, netloc, path, params, query, fragment = urlparse(url)
-
-    # see func:`prepend_scheme_if_needed`
-    if not netloc:
-        netloc, path = path, netloc
-
-    netloc = netloc.rsplit("@", 1)[-1]
-
-    return urlunparse((scheme, netloc, path, params, query, ""))
-
-
-def rewind_body(prepared_request):
-    """Move file pointer back to its recorded starting position
-    so it can be read again on redirect.
-    """
-    body_seek = getattr(prepared_request.body, "seek", None)
-    if body_seek is not None and isinstance(
-        prepared_request._body_position, integer_types
-    ):
-        try:
-            body_seek(prepared_request._body_position)
-        except OSError:
-            raise UnrewindableBodyError(
-                "An error occurred when rewinding request body for redirect."
-            )
-    else:
-        raise UnrewindableBodyError("Unable to rewind request body for redirect.")
diff --git a/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/INSTALLER
deleted file mode 100755
index a1b589e3..00000000
--- a/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/INSTALLER
+++ /dev/null
@@ -1 +0,0 @@
-pip
diff --git a/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/LICENSE b/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/LICENSE
deleted file mode 100755
index 1cc22a5a..00000000
--- a/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/LICENSE
+++ /dev/null
@@ -1,18 +0,0 @@
-Copyright (c) 2010-2024 Benjamin Peterson
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/METADATA b/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/METADATA
deleted file mode 100755
index cfde03c2..00000000
--- a/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/METADATA
+++ /dev/null
@@ -1,43 +0,0 @@
-Metadata-Version: 2.1
-Name: six
-Version: 1.17.0
-Summary: Python 2 and 3 compatibility utilities
-Home-page: https://github.com/benjaminp/six
-Author: Benjamin Peterson
-Author-email: benjamin@python.org
-License: MIT
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 3
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Topic :: Software Development :: Libraries
-Classifier: Topic :: Utilities
-Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*
-License-File: LICENSE
-
-.. image:: https://img.shields.io/pypi/v/six.svg
-   :target: https://pypi.org/project/six/
-   :alt: six on PyPI
-
-.. image:: https://readthedocs.org/projects/six/badge/?version=latest
-   :target: https://six.readthedocs.io/
-   :alt: six's documentation on Read the Docs
-
-.. image:: https://img.shields.io/badge/license-MIT-green.svg
-   :target: https://github.com/benjaminp/six/blob/master/LICENSE
-   :alt: MIT License badge
-
-Six is a Python 2 and 3 compatibility library.  It provides utility functions
-for smoothing over the differences between the Python versions with the goal of
-writing Python code that is compatible on both Python versions.  See the
-documentation for more information on what is provided.
-
-Six supports Python 2.7 and 3.3+.  It is contained in only one Python
-file, so it can be easily copied into your project. (The copyright and license
-notice must be retained.)
-
-Online documentation is at https://six.readthedocs.io/.
-
-Bugs can be reported to https://github.com/benjaminp/six.  The code can also
-be found there.
diff --git a/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/RECORD b/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/RECORD
deleted file mode 100755
index 72d425d7..00000000
--- a/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/RECORD
+++ /dev/null
@@ -1,8 +0,0 @@
-six-1.17.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
-six-1.17.0.dist-info/LICENSE,sha256=Q3W6IOK5xsTnytKUCmKP2Q6VzD1Q7pKq51VxXYuh-9A,1066
-six-1.17.0.dist-info/METADATA,sha256=ViBCB4wnUlSfbYp8htvF3XCAiKe-bYBnLsewcQC3JGg,1658
-six-1.17.0.dist-info/RECORD,,
-six-1.17.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-six-1.17.0.dist-info/WHEEL,sha256=pxeNX5JdtCe58PUSYP9upmc7jdRPgvT0Gm9kb1SHlVw,109
-six-1.17.0.dist-info/top_level.txt,sha256=_iVH_iYEtEXnD8nYGQYpYFUvkUW9sEO1GYbkeKSAais,4
-six.py,sha256=xRyR9wPT1LNpbJI8tf7CE-BeddkhU5O--sfy-mo5BN8,34703
diff --git a/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/REQUESTED
deleted file mode 100755
index e69de29b..00000000
diff --git a/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/WHEEL
deleted file mode 100755
index 104f3874..00000000
--- a/apps/bitwarden_event_logs/lib/six-1.17.0.dist-info/WHEEL
+++ /dev/null
@@ -1,6 +0,0 @@
-Wheel-Version: 1.0
-Generator: setuptools (75.6.0)
-Root-Is-Purelib: true
-Tag: py2-none-any
-Tag: py3-none-any
-
diff --git a/apps/bitwarden_event_logs/lib/six.py b/apps/bitwarden_event_logs/lib/six.py
deleted file mode 100755
index 3de5969b..00000000
--- a/apps/bitwarden_event_logs/lib/six.py
+++ /dev/null
@@ -1,1003 +0,0 @@
-# Copyright (c) 2010-2024 Benjamin Peterson
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-"""Utilities for writing code that runs on Python 2 and 3"""
-
-from __future__ import absolute_import
-
-import functools
-import itertools
-import operator
-import sys
-import types
-
-__author__ = "Benjamin Peterson "
-__version__ = "1.17.0"
-
-
-# Useful for very coarse version differentiation.
-PY2 = sys.version_info[0] == 2
-PY3 = sys.version_info[0] == 3
-PY34 = sys.version_info[0:2] >= (3, 4)
-
-if PY3:
-    string_types = str,
-    integer_types = int,
-    class_types = type,
-    text_type = str
-    binary_type = bytes
-
-    MAXSIZE = sys.maxsize
-else:
-    string_types = basestring,
-    integer_types = (int, long)
-    class_types = (type, types.ClassType)
-    text_type = unicode
-    binary_type = str
-
-    if sys.platform.startswith("java"):
-        # Jython always uses 32 bits.
-        MAXSIZE = int((1 << 31) - 1)
-    else:
-        # It's possible to have sizeof(long) != sizeof(Py_ssize_t).
-        class X(object):
-
-            def __len__(self):
-                return 1 << 31
-        try:
-            len(X())
-        except OverflowError:
-            # 32-bit
-            MAXSIZE = int((1 << 31) - 1)
-        else:
-            # 64-bit
-            MAXSIZE = int((1 << 63) - 1)
-        del X
-
-if PY34:
-    from importlib.util import spec_from_loader
-else:
-    spec_from_loader = None
-
-
-def _add_doc(func, doc):
-    """Add documentation to a function."""
-    func.__doc__ = doc
-
-
-def _import_module(name):
-    """Import module, returning the module after the last dot."""
-    __import__(name)
-    return sys.modules[name]
-
-
-class _LazyDescr(object):
-
-    def __init__(self, name):
-        self.name = name
-
-    def __get__(self, obj, tp):
-        result = self._resolve()
-        setattr(obj, self.name, result)  # Invokes __set__.
-        try:
-            # This is a bit ugly, but it avoids running this again by
-            # removing this descriptor.
-            delattr(obj.__class__, self.name)
-        except AttributeError:
-            pass
-        return result
-
-
-class MovedModule(_LazyDescr):
-
-    def __init__(self, name, old, new=None):
-        super(MovedModule, self).__init__(name)
-        if PY3:
-            if new is None:
-                new = name
-            self.mod = new
-        else:
-            self.mod = old
-
-    def _resolve(self):
-        return _import_module(self.mod)
-
-    def __getattr__(self, attr):
-        _module = self._resolve()
-        value = getattr(_module, attr)
-        setattr(self, attr, value)
-        return value
-
-
-class _LazyModule(types.ModuleType):
-
-    def __init__(self, name):
-        super(_LazyModule, self).__init__(name)
-        self.__doc__ = self.__class__.__doc__
-
-    def __dir__(self):
-        attrs = ["__doc__", "__name__"]
-        attrs += [attr.name for attr in self._moved_attributes]
-        return attrs
-
-    # Subclasses should override this
-    _moved_attributes = []
-
-
-class MovedAttribute(_LazyDescr):
-
-    def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
-        super(MovedAttribute, self).__init__(name)
-        if PY3:
-            if new_mod is None:
-                new_mod = name
-            self.mod = new_mod
-            if new_attr is None:
-                if old_attr is None:
-                    new_attr = name
-                else:
-                    new_attr = old_attr
-            self.attr = new_attr
-        else:
-            self.mod = old_mod
-            if old_attr is None:
-                old_attr = name
-            self.attr = old_attr
-
-    def _resolve(self):
-        module = _import_module(self.mod)
-        return getattr(module, self.attr)
-
-
-class _SixMetaPathImporter(object):
-
-    """
-    A meta path importer to import six.moves and its submodules.
-
-    This class implements a PEP302 finder and loader. It should be compatible
-    with Python 2.5 and all existing versions of Python3
-    """
-
-    def __init__(self, six_module_name):
-        self.name = six_module_name
-        self.known_modules = {}
-
-    def _add_module(self, mod, *fullnames):
-        for fullname in fullnames:
-            self.known_modules[self.name + "." + fullname] = mod
-
-    def _get_module(self, fullname):
-        return self.known_modules[self.name + "." + fullname]
-
-    def find_module(self, fullname, path=None):
-        if fullname in self.known_modules:
-            return self
-        return None
-
-    def find_spec(self, fullname, path, target=None):
-        if fullname in self.known_modules:
-            return spec_from_loader(fullname, self)
-        return None
-
-    def __get_module(self, fullname):
-        try:
-            return self.known_modules[fullname]
-        except KeyError:
-            raise ImportError("This loader does not know module " + fullname)
-
-    def load_module(self, fullname):
-        try:
-            # in case of a reload
-            return sys.modules[fullname]
-        except KeyError:
-            pass
-        mod = self.__get_module(fullname)
-        if isinstance(mod, MovedModule):
-            mod = mod._resolve()
-        else:
-            mod.__loader__ = self
-        sys.modules[fullname] = mod
-        return mod
-
-    def is_package(self, fullname):
-        """
-        Return true, if the named module is a package.
-
-        We need this method to get correct spec objects with
-        Python 3.4 (see PEP451)
-        """
-        return hasattr(self.__get_module(fullname), "__path__")
-
-    def get_code(self, fullname):
-        """Return None
-
-        Required, if is_package is implemented"""
-        self.__get_module(fullname)  # eventually raises ImportError
-        return None
-    get_source = get_code  # same as get_code
-
-    def create_module(self, spec):
-        return self.load_module(spec.name)
-
-    def exec_module(self, module):
-        pass
-
-_importer = _SixMetaPathImporter(__name__)
-
-
-class _MovedItems(_LazyModule):
-
-    """Lazy loading of moved objects"""
-    __path__ = []  # mark as package
-
-
-_moved_attributes = [
-    MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
-    MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
-    MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
-    MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
-    MovedAttribute("intern", "__builtin__", "sys"),
-    MovedAttribute("map", "itertools", "builtins", "imap", "map"),
-    MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"),
-    MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"),
-    MovedAttribute("getoutput", "commands", "subprocess"),
-    MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
-    MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"),
-    MovedAttribute("reduce", "__builtin__", "functools"),
-    MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
-    MovedAttribute("StringIO", "StringIO", "io"),
-    MovedAttribute("UserDict", "UserDict", "collections", "IterableUserDict", "UserDict"),
-    MovedAttribute("UserList", "UserList", "collections"),
-    MovedAttribute("UserString", "UserString", "collections"),
-    MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
-    MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
-    MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
-    MovedModule("builtins", "__builtin__"),
-    MovedModule("configparser", "ConfigParser"),
-    MovedModule("collections_abc", "collections", "collections.abc" if sys.version_info >= (3, 3) else "collections"),
-    MovedModule("copyreg", "copy_reg"),
-    MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
-    MovedModule("dbm_ndbm", "dbm", "dbm.ndbm"),
-    MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread" if sys.version_info < (3, 9) else "_thread"),
-    MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
-    MovedModule("http_cookies", "Cookie", "http.cookies"),
-    MovedModule("html_entities", "htmlentitydefs", "html.entities"),
-    MovedModule("html_parser", "HTMLParser", "html.parser"),
-    MovedModule("http_client", "httplib", "http.client"),
-    MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
-    MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"),
-    MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
-    MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
-    MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
-    MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
-    MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
-    MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
-    MovedModule("cPickle", "cPickle", "pickle"),
-    MovedModule("queue", "Queue"),
-    MovedModule("reprlib", "repr"),
-    MovedModule("socketserver", "SocketServer"),
-    MovedModule("_thread", "thread", "_thread"),
-    MovedModule("tkinter", "Tkinter"),
-    MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
-    MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
-    MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
-    MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
-    MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
-    MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
-    MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
-    MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
-    MovedModule("tkinter_colorchooser", "tkColorChooser",
-                "tkinter.colorchooser"),
-    MovedModule("tkinter_commondialog", "tkCommonDialog",
-                "tkinter.commondialog"),
-    MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
-    MovedModule("tkinter_font", "tkFont", "tkinter.font"),
-    MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
-    MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
-                "tkinter.simpledialog"),
-    MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
-    MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
-    MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
-    MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
-    MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
-    MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
-]
-# Add windows specific modules.
-if sys.platform == "win32":
-    _moved_attributes += [
-        MovedModule("winreg", "_winreg"),
-    ]
-
-for attr in _moved_attributes:
-    setattr(_MovedItems, attr.name, attr)
-    if isinstance(attr, MovedModule):
-        _importer._add_module(attr, "moves." + attr.name)
-del attr
-
-_MovedItems._moved_attributes = _moved_attributes
-
-moves = _MovedItems(__name__ + ".moves")
-_importer._add_module(moves, "moves")
-
-
-class Module_six_moves_urllib_parse(_LazyModule):
-
-    """Lazy loading of moved objects in six.moves.urllib_parse"""
-
-
-_urllib_parse_moved_attributes = [
-    MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
-    MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
-    MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
-    MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
-    MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
-    MovedAttribute("urljoin", "urlparse", "urllib.parse"),
-    MovedAttribute("urlparse", "urlparse", "urllib.parse"),
-    MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
-    MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
-    MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
-    MovedAttribute("quote", "urllib", "urllib.parse"),
-    MovedAttribute("quote_plus", "urllib", "urllib.parse"),
-    MovedAttribute("unquote", "urllib", "urllib.parse"),
-    MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
-    MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"),
-    MovedAttribute("urlencode", "urllib", "urllib.parse"),
-    MovedAttribute("splitquery", "urllib", "urllib.parse"),
-    MovedAttribute("splittag", "urllib", "urllib.parse"),
-    MovedAttribute("splituser", "urllib", "urllib.parse"),
-    MovedAttribute("splitvalue", "urllib", "urllib.parse"),
-    MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
-    MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
-    MovedAttribute("uses_params", "urlparse", "urllib.parse"),
-    MovedAttribute("uses_query", "urlparse", "urllib.parse"),
-    MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
-]
-for attr in _urllib_parse_moved_attributes:
-    setattr(Module_six_moves_urllib_parse, attr.name, attr)
-del attr
-
-Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
-
-_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
-                      "moves.urllib_parse", "moves.urllib.parse")
-
-
-class Module_six_moves_urllib_error(_LazyModule):
-
-    """Lazy loading of moved objects in six.moves.urllib_error"""
-
-
-_urllib_error_moved_attributes = [
-    MovedAttribute("URLError", "urllib2", "urllib.error"),
-    MovedAttribute("HTTPError", "urllib2", "urllib.error"),
-    MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
-]
-for attr in _urllib_error_moved_attributes:
-    setattr(Module_six_moves_urllib_error, attr.name, attr)
-del attr
-
-Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
-
-_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
-                      "moves.urllib_error", "moves.urllib.error")
-
-
-class Module_six_moves_urllib_request(_LazyModule):
-
-    """Lazy loading of moved objects in six.moves.urllib_request"""
-
-
-_urllib_request_moved_attributes = [
-    MovedAttribute("urlopen", "urllib2", "urllib.request"),
-    MovedAttribute("install_opener", "urllib2", "urllib.request"),
-    MovedAttribute("build_opener", "urllib2", "urllib.request"),
-    MovedAttribute("pathname2url", "urllib", "urllib.request"),
-    MovedAttribute("url2pathname", "urllib", "urllib.request"),
-    MovedAttribute("getproxies", "urllib", "urllib.request"),
-    MovedAttribute("Request", "urllib2", "urllib.request"),
-    MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
-    MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
-    MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
-    MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
-    MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
-    MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
-    MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
-    MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
-    MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
-    MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
-    MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
-    MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
-    MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
-    MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
-    MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
-    MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
-    MovedAttribute("FileHandler", "urllib2", "urllib.request"),
-    MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
-    MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
-    MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
-    MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
-    MovedAttribute("urlretrieve", "urllib", "urllib.request"),
-    MovedAttribute("urlcleanup", "urllib", "urllib.request"),
-    MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
-    MovedAttribute("parse_http_list", "urllib2", "urllib.request"),
-    MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"),
-]
-if sys.version_info[:2] < (3, 14):
-    _urllib_request_moved_attributes.extend(
-        [
-            MovedAttribute("URLopener", "urllib", "urllib.request"),
-            MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
-        ]
-    )
-for attr in _urllib_request_moved_attributes:
-    setattr(Module_six_moves_urllib_request, attr.name, attr)
-del attr
-
-Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
-
-_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
-                      "moves.urllib_request", "moves.urllib.request")
-
-
-class Module_six_moves_urllib_response(_LazyModule):
-
-    """Lazy loading of moved objects in six.moves.urllib_response"""
-
-
-_urllib_response_moved_attributes = [
-    MovedAttribute("addbase", "urllib", "urllib.response"),
-    MovedAttribute("addclosehook", "urllib", "urllib.response"),
-    MovedAttribute("addinfo", "urllib", "urllib.response"),
-    MovedAttribute("addinfourl", "urllib", "urllib.response"),
-]
-for attr in _urllib_response_moved_attributes:
-    setattr(Module_six_moves_urllib_response, attr.name, attr)
-del attr
-
-Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
-
-_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
-                      "moves.urllib_response", "moves.urllib.response")
-
-
-class Module_six_moves_urllib_robotparser(_LazyModule):
-
-    """Lazy loading of moved objects in six.moves.urllib_robotparser"""
-
-
-_urllib_robotparser_moved_attributes = [
-    MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
-]
-for attr in _urllib_robotparser_moved_attributes:
-    setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
-del attr
-
-Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
-
-_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
-                      "moves.urllib_robotparser", "moves.urllib.robotparser")
-
-
-class Module_six_moves_urllib(types.ModuleType):
-
-    """Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
-    __path__ = []  # mark as package
-    parse = _importer._get_module("moves.urllib_parse")
-    error = _importer._get_module("moves.urllib_error")
-    request = _importer._get_module("moves.urllib_request")
-    response = _importer._get_module("moves.urllib_response")
-    robotparser = _importer._get_module("moves.urllib_robotparser")
-
-    def __dir__(self):
-        return ['parse', 'error', 'request', 'response', 'robotparser']
-
-_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
-                      "moves.urllib")
-
-
-def add_move(move):
-    """Add an item to six.moves."""
-    setattr(_MovedItems, move.name, move)
-
-
-def remove_move(name):
-    """Remove item from six.moves."""
-    try:
-        delattr(_MovedItems, name)
-    except AttributeError:
-        try:
-            del moves.__dict__[name]
-        except KeyError:
-            raise AttributeError("no such move, %r" % (name,))
-
-
-if PY3:
-    _meth_func = "__func__"
-    _meth_self = "__self__"
-
-    _func_closure = "__closure__"
-    _func_code = "__code__"
-    _func_defaults = "__defaults__"
-    _func_globals = "__globals__"
-else:
-    _meth_func = "im_func"
-    _meth_self = "im_self"
-
-    _func_closure = "func_closure"
-    _func_code = "func_code"
-    _func_defaults = "func_defaults"
-    _func_globals = "func_globals"
-
-
-try:
-    advance_iterator = next
-except NameError:
-    def advance_iterator(it):
-        return it.next()
-next = advance_iterator
-
-
-try:
-    callable = callable
-except NameError:
-    def callable(obj):
-        return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
-
-
-if PY3:
-    def get_unbound_function(unbound):
-        return unbound
-
-    create_bound_method = types.MethodType
-
-    def create_unbound_method(func, cls):
-        return func
-
-    Iterator = object
-else:
-    def get_unbound_function(unbound):
-        return unbound.im_func
-
-    def create_bound_method(func, obj):
-        return types.MethodType(func, obj, obj.__class__)
-
-    def create_unbound_method(func, cls):
-        return types.MethodType(func, None, cls)
-
-    class Iterator(object):
-
-        def next(self):
-            return type(self).__next__(self)
-
-    callable = callable
-_add_doc(get_unbound_function,
-         """Get the function out of a possibly unbound function""")
-
-
-get_method_function = operator.attrgetter(_meth_func)
-get_method_self = operator.attrgetter(_meth_self)
-get_function_closure = operator.attrgetter(_func_closure)
-get_function_code = operator.attrgetter(_func_code)
-get_function_defaults = operator.attrgetter(_func_defaults)
-get_function_globals = operator.attrgetter(_func_globals)
-
-
-if PY3:
-    def iterkeys(d, **kw):
-        return iter(d.keys(**kw))
-
-    def itervalues(d, **kw):
-        return iter(d.values(**kw))
-
-    def iteritems(d, **kw):
-        return iter(d.items(**kw))
-
-    def iterlists(d, **kw):
-        return iter(d.lists(**kw))
-
-    viewkeys = operator.methodcaller("keys")
-
-    viewvalues = operator.methodcaller("values")
-
-    viewitems = operator.methodcaller("items")
-else:
-    def iterkeys(d, **kw):
-        return d.iterkeys(**kw)
-
-    def itervalues(d, **kw):
-        return d.itervalues(**kw)
-
-    def iteritems(d, **kw):
-        return d.iteritems(**kw)
-
-    def iterlists(d, **kw):
-        return d.iterlists(**kw)
-
-    viewkeys = operator.methodcaller("viewkeys")
-
-    viewvalues = operator.methodcaller("viewvalues")
-
-    viewitems = operator.methodcaller("viewitems")
-
-_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
-_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
-_add_doc(iteritems,
-         "Return an iterator over the (key, value) pairs of a dictionary.")
-_add_doc(iterlists,
-         "Return an iterator over the (key, [values]) pairs of a dictionary.")
-
-
-if PY3:
-    def b(s):
-        return s.encode("latin-1")
-
-    def u(s):
-        return s
-    unichr = chr
-    import struct
-    int2byte = struct.Struct(">B").pack
-    del struct
-    byte2int = operator.itemgetter(0)
-    indexbytes = operator.getitem
-    iterbytes = iter
-    import io
-    StringIO = io.StringIO
-    BytesIO = io.BytesIO
-    del io
-    _assertCountEqual = "assertCountEqual"
-    if sys.version_info[1] <= 1:
-        _assertRaisesRegex = "assertRaisesRegexp"
-        _assertRegex = "assertRegexpMatches"
-        _assertNotRegex = "assertNotRegexpMatches"
-    else:
-        _assertRaisesRegex = "assertRaisesRegex"
-        _assertRegex = "assertRegex"
-        _assertNotRegex = "assertNotRegex"
-else:
-    def b(s):
-        return s
-    # Workaround for standalone backslash
-
-    def u(s):
-        return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
-    unichr = unichr
-    int2byte = chr
-
-    def byte2int(bs):
-        return ord(bs[0])
-
-    def indexbytes(buf, i):
-        return ord(buf[i])
-    iterbytes = functools.partial(itertools.imap, ord)
-    import StringIO
-    StringIO = BytesIO = StringIO.StringIO
-    _assertCountEqual = "assertItemsEqual"
-    _assertRaisesRegex = "assertRaisesRegexp"
-    _assertRegex = "assertRegexpMatches"
-    _assertNotRegex = "assertNotRegexpMatches"
-_add_doc(b, """Byte literal""")
-_add_doc(u, """Text literal""")
-
-
-def assertCountEqual(self, *args, **kwargs):
-    return getattr(self, _assertCountEqual)(*args, **kwargs)
-
-
-def assertRaisesRegex(self, *args, **kwargs):
-    return getattr(self, _assertRaisesRegex)(*args, **kwargs)
-
-
-def assertRegex(self, *args, **kwargs):
-    return getattr(self, _assertRegex)(*args, **kwargs)
-
-
-def assertNotRegex(self, *args, **kwargs):
-    return getattr(self, _assertNotRegex)(*args, **kwargs)
-
-
-if PY3:
-    exec_ = getattr(moves.builtins, "exec")
-
-    def reraise(tp, value, tb=None):
-        try:
-            if value is None:
-                value = tp()
-            if value.__traceback__ is not tb:
-                raise value.with_traceback(tb)
-            raise value
-        finally:
-            value = None
-            tb = None
-
-else:
-    def exec_(_code_, _globs_=None, _locs_=None):
-        """Execute code in a namespace."""
-        if _globs_ is None:
-            frame = sys._getframe(1)
-            _globs_ = frame.f_globals
-            if _locs_ is None:
-                _locs_ = frame.f_locals
-            del frame
-        elif _locs_ is None:
-            _locs_ = _globs_
-        exec("""exec _code_ in _globs_, _locs_""")
-
-    exec_("""def reraise(tp, value, tb=None):
-    try:
-        raise tp, value, tb
-    finally:
-        tb = None
-""")
-
-
-if sys.version_info[:2] > (3,):
-    exec_("""def raise_from(value, from_value):
-    try:
-        raise value from from_value
-    finally:
-        value = None
-""")
-else:
-    def raise_from(value, from_value):
-        raise value
-
-
-print_ = getattr(moves.builtins, "print", None)
-if print_ is None:
-    def print_(*args, **kwargs):
-        """The new-style print function for Python 2.4 and 2.5."""
-        fp = kwargs.pop("file", sys.stdout)
-        if fp is None:
-            return
-
-        def write(data):
-            if not isinstance(data, basestring):
-                data = str(data)
-            # If the file has an encoding, encode unicode with it.
-            if (isinstance(fp, file) and
-                    isinstance(data, unicode) and
-                    fp.encoding is not None):
-                errors = getattr(fp, "errors", None)
-                if errors is None:
-                    errors = "strict"
-                data = data.encode(fp.encoding, errors)
-            fp.write(data)
-        want_unicode = False
-        sep = kwargs.pop("sep", None)
-        if sep is not None:
-            if isinstance(sep, unicode):
-                want_unicode = True
-            elif not isinstance(sep, str):
-                raise TypeError("sep must be None or a string")
-        end = kwargs.pop("end", None)
-        if end is not None:
-            if isinstance(end, unicode):
-                want_unicode = True
-            elif not isinstance(end, str):
-                raise TypeError("end must be None or a string")
-        if kwargs:
-            raise TypeError("invalid keyword arguments to print()")
-        if not want_unicode:
-            for arg in args:
-                if isinstance(arg, unicode):
-                    want_unicode = True
-                    break
-        if want_unicode:
-            newline = unicode("\n")
-            space = unicode(" ")
-        else:
-            newline = "\n"
-            space = " "
-        if sep is None:
-            sep = space
-        if end is None:
-            end = newline
-        for i, arg in enumerate(args):
-            if i:
-                write(sep)
-            write(arg)
-        write(end)
-if sys.version_info[:2] < (3, 3):
-    _print = print_
-
-    def print_(*args, **kwargs):
-        fp = kwargs.get("file", sys.stdout)
-        flush = kwargs.pop("flush", False)
-        _print(*args, **kwargs)
-        if flush and fp is not None:
-            fp.flush()
-
-_add_doc(reraise, """Reraise an exception.""")
-
-if sys.version_info[0:2] < (3, 4):
-    # This does exactly the same what the :func:`py3:functools.update_wrapper`
-    # function does on Python versions after 3.2. It sets the ``__wrapped__``
-    # attribute on ``wrapper`` object and it doesn't raise an error if any of
-    # the attributes mentioned in ``assigned`` and ``updated`` are missing on
-    # ``wrapped`` object.
-    def _update_wrapper(wrapper, wrapped,
-                        assigned=functools.WRAPPER_ASSIGNMENTS,
-                        updated=functools.WRAPPER_UPDATES):
-        for attr in assigned:
-            try:
-                value = getattr(wrapped, attr)
-            except AttributeError:
-                continue
-            else:
-                setattr(wrapper, attr, value)
-        for attr in updated:
-            getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
-        wrapper.__wrapped__ = wrapped
-        return wrapper
-    _update_wrapper.__doc__ = functools.update_wrapper.__doc__
-
-    def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
-              updated=functools.WRAPPER_UPDATES):
-        return functools.partial(_update_wrapper, wrapped=wrapped,
-                                 assigned=assigned, updated=updated)
-    wraps.__doc__ = functools.wraps.__doc__
-
-else:
-    wraps = functools.wraps
-
-
-def with_metaclass(meta, *bases):
-    """Create a base class with a metaclass."""
-    # This requires a bit of explanation: the basic idea is to make a dummy
-    # metaclass for one level of class instantiation that replaces itself with
-    # the actual metaclass.
-    class metaclass(type):
-
-        def __new__(cls, name, this_bases, d):
-            if sys.version_info[:2] >= (3, 7):
-                # This version introduced PEP 560 that requires a bit
-                # of extra care (we mimic what is done by __build_class__).
-                resolved_bases = types.resolve_bases(bases)
-                if resolved_bases is not bases:
-                    d['__orig_bases__'] = bases
-            else:
-                resolved_bases = bases
-            return meta(name, resolved_bases, d)
-
-        @classmethod
-        def __prepare__(cls, name, this_bases):
-            return meta.__prepare__(name, bases)
-    return type.__new__(metaclass, 'temporary_class', (), {})
-
-
-def add_metaclass(metaclass):
-    """Class decorator for creating a class with a metaclass."""
-    def wrapper(cls):
-        orig_vars = cls.__dict__.copy()
-        slots = orig_vars.get('__slots__')
-        if slots is not None:
-            if isinstance(slots, str):
-                slots = [slots]
-            for slots_var in slots:
-                orig_vars.pop(slots_var)
-        orig_vars.pop('__dict__', None)
-        orig_vars.pop('__weakref__', None)
-        if hasattr(cls, '__qualname__'):
-            orig_vars['__qualname__'] = cls.__qualname__
-        return metaclass(cls.__name__, cls.__bases__, orig_vars)
-    return wrapper
-
-
-def ensure_binary(s, encoding='utf-8', errors='strict'):
-    """Coerce **s** to six.binary_type.
-
-    For Python 2:
-      - `unicode` -> encoded to `str`
-      - `str` -> `str`
-
-    For Python 3:
-      - `str` -> encoded to `bytes`
-      - `bytes` -> `bytes`
-    """
-    if isinstance(s, binary_type):
-        return s
-    if isinstance(s, text_type):
-        return s.encode(encoding, errors)
-    raise TypeError("not expecting type '%s'" % type(s))
-
-
-def ensure_str(s, encoding='utf-8', errors='strict'):
-    """Coerce *s* to `str`.
-
-    For Python 2:
-      - `unicode` -> encoded to `str`
-      - `str` -> `str`
-
-    For Python 3:
-      - `str` -> `str`
-      - `bytes` -> decoded to `str`
-    """
-    # Optimization: Fast return for the common case.
-    if type(s) is str:
-        return s
-    if PY2 and isinstance(s, text_type):
-        return s.encode(encoding, errors)
-    elif PY3 and isinstance(s, binary_type):
-        return s.decode(encoding, errors)
-    elif not isinstance(s, (text_type, binary_type)):
-        raise TypeError("not expecting type '%s'" % type(s))
-    return s
-
-
-def ensure_text(s, encoding='utf-8', errors='strict'):
-    """Coerce *s* to six.text_type.
-
-    For Python 2:
-      - `unicode` -> `unicode`
-      - `str` -> `unicode`
-
-    For Python 3:
-      - `str` -> `str`
-      - `bytes` -> decoded to `str`
-    """
-    if isinstance(s, binary_type):
-        return s.decode(encoding, errors)
-    elif isinstance(s, text_type):
-        return s
-    else:
-        raise TypeError("not expecting type '%s'" % type(s))
-
-
-def python_2_unicode_compatible(klass):
-    """
-    A class decorator that defines __unicode__ and __str__ methods under Python 2.
-    Under Python 3 it does nothing.
-
-    To support Python 2 and 3 with a single code base, define a __str__ method
-    returning text and apply this decorator to the class.
-    """
-    if PY2:
-        if '__str__' not in klass.__dict__:
-            raise ValueError("@python_2_unicode_compatible cannot be applied "
-                             "to %s because it doesn't define __str__()." %
-                             klass.__name__)
-        klass.__unicode__ = klass.__str__
-        klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
-    return klass
-
-
-# Complete the moves implementation.
-# This code is at the end of this module to speed up module loading.
-# Turn this module into a package.
-__path__ = []  # required for PEP 302 and PEP 451
-__package__ = __name__  # see PEP 366 @ReservedAssignment
-if globals().get("__spec__") is not None:
-    __spec__.submodule_search_locations = []  # PEP 451 @UndefinedVariable
-# Remove other six meta path importers, since they cause problems. This can
-# happen if six is removed from sys.modules and then reloaded. (Setuptools does
-# this for some reason.)
-if sys.meta_path:
-    for i, importer in enumerate(sys.meta_path):
-        # Here's some real nastiness: Another "instance" of the six module might
-        # be floating around. Therefore, we can't use isinstance() to check for
-        # the six meta path importer, since the other six instance will have
-        # inserted an importer with different class.
-        if (type(importer).__name__ == "_SixMetaPathImporter" and
-                importer.name == __name__):
-            del sys.meta_path[i]
-            break
-    del i, importer
-# Finally, add the importer to the meta path import hook.
-sys.meta_path.append(_importer)
diff --git a/apps/bitwarden_event_logs/lib/socks.py b/apps/bitwarden_event_logs/lib/socks.py
deleted file mode 100755
index 83b1435d..00000000
--- a/apps/bitwarden_event_logs/lib/socks.py
+++ /dev/null
@@ -1,847 +0,0 @@
-from base64 import b64encode
-try:
-    from collections.abc import Callable
-except ImportError:
-    from collections import Callable
-from errno import EOPNOTSUPP, EINVAL, EAGAIN
-import functools
-from io import BytesIO
-import logging
-import os
-from os import SEEK_CUR
-import socket
-import struct
-import sys
-
-__version__ = "1.7.1"
-
-
-if os.name == "nt" and sys.version_info < (3, 0):
-    try:
-        import win_inet_pton
-    except ImportError:
-        raise ImportError(
-            "To run PySocks on Windows you must install win_inet_pton")
-
-log = logging.getLogger(__name__)
-
-PROXY_TYPE_SOCKS4 = SOCKS4 = 1
-PROXY_TYPE_SOCKS5 = SOCKS5 = 2
-PROXY_TYPE_HTTP = HTTP = 3
-
-PROXY_TYPES = {"SOCKS4": SOCKS4, "SOCKS5": SOCKS5, "HTTP": HTTP}
-PRINTABLE_PROXY_TYPES = dict(zip(PROXY_TYPES.values(), PROXY_TYPES.keys()))
-
-_orgsocket = _orig_socket = socket.socket
-
-
-def set_self_blocking(function):
-
-    @functools.wraps(function)
-    def wrapper(*args, **kwargs):
-        self = args[0]
-        try:
-            _is_blocking = self.gettimeout()
-            if _is_blocking == 0:
-                self.setblocking(True)
-            return function(*args, **kwargs)
-        except Exception as e:
-            raise
-        finally:
-            # set orgin blocking
-            if _is_blocking == 0:
-                self.setblocking(False)
-    return wrapper
-
-
-class ProxyError(IOError):
-    """Socket_err contains original socket.error exception."""
-    def __init__(self, msg, socket_err=None):
-        self.msg = msg
-        self.socket_err = socket_err
-
-        if socket_err:
-            self.msg += ": {}".format(socket_err)
-
-    def __str__(self):
-        return self.msg
-
-
-class GeneralProxyError(ProxyError):
-    pass
-
-
-class ProxyConnectionError(ProxyError):
-    pass
-
-
-class SOCKS5AuthError(ProxyError):
-    pass
-
-
-class SOCKS5Error(ProxyError):
-    pass
-
-
-class SOCKS4Error(ProxyError):
-    pass
-
-
-class HTTPError(ProxyError):
-    pass
-
-SOCKS4_ERRORS = {
-    0x5B: "Request rejected or failed",
-    0x5C: ("Request rejected because SOCKS server cannot connect to identd on"
-           " the client"),
-    0x5D: ("Request rejected because the client program and identd report"
-           " different user-ids")
-}
-
-SOCKS5_ERRORS = {
-    0x01: "General SOCKS server failure",
-    0x02: "Connection not allowed by ruleset",
-    0x03: "Network unreachable",
-    0x04: "Host unreachable",
-    0x05: "Connection refused",
-    0x06: "TTL expired",
-    0x07: "Command not supported, or protocol error",
-    0x08: "Address type not supported"
-}
-
-DEFAULT_PORTS = {SOCKS4: 1080, SOCKS5: 1080, HTTP: 8080}
-
-
-def set_default_proxy(proxy_type=None, addr=None, port=None, rdns=True,
-                      username=None, password=None):
-    """Sets a default proxy.
-
-    All further socksocket objects will use the default unless explicitly
-    changed. All parameters are as for socket.set_proxy()."""
-    socksocket.default_proxy = (proxy_type, addr, port, rdns,
-                                username.encode() if username else None,
-                                password.encode() if password else None)
-
-
-def setdefaultproxy(*args, **kwargs):
-    if "proxytype" in kwargs:
-        kwargs["proxy_type"] = kwargs.pop("proxytype")
-    return set_default_proxy(*args, **kwargs)
-
-
-def get_default_proxy():
-    """Returns the default proxy, set by set_default_proxy."""
-    return socksocket.default_proxy
-
-getdefaultproxy = get_default_proxy
-
-
-def wrap_module(module):
-    """Attempts to replace a module's socket library with a SOCKS socket.
-
-    Must set a default proxy using set_default_proxy(...) first. This will
-    only work on modules that import socket directly into the namespace;
-    most of the Python Standard Library falls into this category."""
-    if socksocket.default_proxy:
-        module.socket.socket = socksocket
-    else:
-        raise GeneralProxyError("No default proxy specified")
-
-wrapmodule = wrap_module
-
-
-def create_connection(dest_pair,
-                      timeout=None, source_address=None,
-                      proxy_type=None, proxy_addr=None,
-                      proxy_port=None, proxy_rdns=True,
-                      proxy_username=None, proxy_password=None,
-                      socket_options=None):
-    """create_connection(dest_pair, *[, timeout], **proxy_args) -> socket object
-
-    Like socket.create_connection(), but connects to proxy
-    before returning the socket object.
-
-    dest_pair - 2-tuple of (IP/hostname, port).
-    **proxy_args - Same args passed to socksocket.set_proxy() if present.
-    timeout - Optional socket timeout value, in seconds.
-    source_address - tuple (host, port) for the socket to bind to as its source
-    address before connecting (only for compatibility)
-    """
-    # Remove IPv6 brackets on the remote address and proxy address.
-    remote_host, remote_port = dest_pair
-    if remote_host.startswith("["):
-        remote_host = remote_host.strip("[]")
-    if proxy_addr and proxy_addr.startswith("["):
-        proxy_addr = proxy_addr.strip("[]")
-
-    err = None
-
-    # Allow the SOCKS proxy to be on IPv4 or IPv6 addresses.
-    for r in socket.getaddrinfo(proxy_addr, proxy_port, 0, socket.SOCK_STREAM):
-        family, socket_type, proto, canonname, sa = r
-        sock = None
-        try:
-            sock = socksocket(family, socket_type, proto)
-
-            if socket_options:
-                for opt in socket_options:
-                    sock.setsockopt(*opt)
-
-            if isinstance(timeout, (int, float)):
-                sock.settimeout(timeout)
-
-            if proxy_type:
-                sock.set_proxy(proxy_type, proxy_addr, proxy_port, proxy_rdns,
-                               proxy_username, proxy_password)
-            if source_address:
-                sock.bind(source_address)
-
-            sock.connect((remote_host, remote_port))
-            return sock
-
-        except (socket.error, ProxyError) as e:
-            err = e
-            if sock:
-                sock.close()
-                sock = None
-
-    if err:
-        raise err
-
-    raise socket.error("gai returned empty list.")
-
-
-class _BaseSocket(socket.socket):
-    """Allows Python 2 delegated methods such as send() to be overridden."""
-    def __init__(self, *pos, **kw):
-        _orig_socket.__init__(self, *pos, **kw)
-
-        self._savedmethods = dict()
-        for name in self._savenames:
-            self._savedmethods[name] = getattr(self, name)
-            delattr(self, name)  # Allows normal overriding mechanism to work
-
-    _savenames = list()
-
-
-def _makemethod(name):
-    return lambda self, *pos, **kw: self._savedmethods[name](*pos, **kw)
-for name in ("sendto", "send", "recvfrom", "recv"):
-    method = getattr(_BaseSocket, name, None)
-
-    # Determine if the method is not defined the usual way
-    # as a function in the class.
-    # Python 2 uses __slots__, so there are descriptors for each method,
-    # but they are not functions.
-    if not isinstance(method, Callable):
-        _BaseSocket._savenames.append(name)
-        setattr(_BaseSocket, name, _makemethod(name))
-
-
-class socksocket(_BaseSocket):
-    """socksocket([family[, type[, proto]]]) -> socket object
-
-    Open a SOCKS enabled socket. The parameters are the same as
-    those of the standard socket init. In order for SOCKS to work,
-    you must specify family=AF_INET and proto=0.
-    The "type" argument must be either SOCK_STREAM or SOCK_DGRAM.
-    """
-
-    default_proxy = None
-
-    def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM,
-                 proto=0, *args, **kwargs):
-        if type not in (socket.SOCK_STREAM, socket.SOCK_DGRAM):
-            msg = "Socket type must be stream or datagram, not {!r}"
-            raise ValueError(msg.format(type))
-
-        super(socksocket, self).__init__(family, type, proto, *args, **kwargs)
-        self._proxyconn = None  # TCP connection to keep UDP relay alive
-
-        if self.default_proxy:
-            self.proxy = self.default_proxy
-        else:
-            self.proxy = (None, None, None, None, None, None)
-        self.proxy_sockname = None
-        self.proxy_peername = None
-
-        self._timeout = None
-
-    def _readall(self, file, count):
-        """Receive EXACTLY the number of bytes requested from the file object.
-
-        Blocks until the required number of bytes have been received."""
-        data = b""
-        while len(data) < count:
-            d = file.read(count - len(data))
-            if not d:
-                raise GeneralProxyError("Connection closed unexpectedly")
-            data += d
-        return data
-
-    def settimeout(self, timeout):
-        self._timeout = timeout
-        try:
-            # test if we're connected, if so apply timeout
-            peer = self.get_proxy_peername()
-            super(socksocket, self).settimeout(self._timeout)
-        except socket.error:
-            pass
-
-    def gettimeout(self):
-        return self._timeout
-
-    def setblocking(self, v):
-        if v:
-            self.settimeout(None)
-        else:
-            self.settimeout(0.0)
-
-    def set_proxy(self, proxy_type=None, addr=None, port=None, rdns=True,
-                  username=None, password=None):
-        """ Sets the proxy to be used.
-
-        proxy_type -  The type of the proxy to be used. Three types
-                        are supported: PROXY_TYPE_SOCKS4 (including socks4a),
-                        PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP
-        addr -        The address of the server (IP or DNS).
-        port -        The port of the server. Defaults to 1080 for SOCKS
-                        servers and 8080 for HTTP proxy servers.
-        rdns -        Should DNS queries be performed on the remote side
-                       (rather than the local side). The default is True.
-                       Note: This has no effect with SOCKS4 servers.
-        username -    Username to authenticate with to the server.
-                       The default is no authentication.
-        password -    Password to authenticate with to the server.
-                       Only relevant when username is also provided."""
-        self.proxy = (proxy_type, addr, port, rdns,
-                      username.encode() if username else None,
-                      password.encode() if password else None)
-
-    def setproxy(self, *args, **kwargs):
-        if "proxytype" in kwargs:
-            kwargs["proxy_type"] = kwargs.pop("proxytype")
-        return self.set_proxy(*args, **kwargs)
-
-    def bind(self, *pos, **kw):
-        """Implements proxy connection for UDP sockets.
-
-        Happens during the bind() phase."""
-        (proxy_type, proxy_addr, proxy_port, rdns, username,
-         password) = self.proxy
-        if not proxy_type or self.type != socket.SOCK_DGRAM:
-            return _orig_socket.bind(self, *pos, **kw)
-
-        if self._proxyconn:
-            raise socket.error(EINVAL, "Socket already bound to an address")
-        if proxy_type != SOCKS5:
-            msg = "UDP only supported by SOCKS5 proxy type"
-            raise socket.error(EOPNOTSUPP, msg)
-        super(socksocket, self).bind(*pos, **kw)
-
-        # Need to specify actual local port because
-        # some relays drop packets if a port of zero is specified.
-        # Avoid specifying host address in case of NAT though.
-        _, port = self.getsockname()
-        dst = ("0", port)
-
-        self._proxyconn = _orig_socket()
-        proxy = self._proxy_addr()
-        self._proxyconn.connect(proxy)
-
-        UDP_ASSOCIATE = b"\x03"
-        _, relay = self._SOCKS5_request(self._proxyconn, UDP_ASSOCIATE, dst)
-
-        # The relay is most likely on the same host as the SOCKS proxy,
-        # but some proxies return a private IP address (10.x.y.z)
-        host, _ = proxy
-        _, port = relay
-        super(socksocket, self).connect((host, port))
-        super(socksocket, self).settimeout(self._timeout)
-        self.proxy_sockname = ("0.0.0.0", 0)  # Unknown
-
-    def sendto(self, bytes, *args, **kwargs):
-        if self.type != socket.SOCK_DGRAM:
-            return super(socksocket, self).sendto(bytes, *args, **kwargs)
-        if not self._proxyconn:
-            self.bind(("", 0))
-
-        address = args[-1]
-        flags = args[:-1]
-
-        header = BytesIO()
-        RSV = b"\x00\x00"
-        header.write(RSV)
-        STANDALONE = b"\x00"
-        header.write(STANDALONE)
-        self._write_SOCKS5_address(address, header)
-
-        sent = super(socksocket, self).send(header.getvalue() + bytes, *flags,
-                                            **kwargs)
-        return sent - header.tell()
-
-    def send(self, bytes, flags=0, **kwargs):
-        if self.type == socket.SOCK_DGRAM:
-            return self.sendto(bytes, flags, self.proxy_peername, **kwargs)
-        else:
-            return super(socksocket, self).send(bytes, flags, **kwargs)
-
-    def recvfrom(self, bufsize, flags=0):
-        if self.type != socket.SOCK_DGRAM:
-            return super(socksocket, self).recvfrom(bufsize, flags)
-        if not self._proxyconn:
-            self.bind(("", 0))
-
-        buf = BytesIO(super(socksocket, self).recv(bufsize + 1024, flags))
-        buf.seek(2, SEEK_CUR)
-        frag = buf.read(1)
-        if ord(frag):
-            raise NotImplementedError("Received UDP packet fragment")
-        fromhost, fromport = self._read_SOCKS5_address(buf)
-
-        if self.proxy_peername:
-            peerhost, peerport = self.proxy_peername
-            if fromhost != peerhost or peerport not in (0, fromport):
-                raise socket.error(EAGAIN, "Packet filtered")
-
-        return (buf.read(bufsize), (fromhost, fromport))
-
-    def recv(self, *pos, **kw):
-        bytes, _ = self.recvfrom(*pos, **kw)
-        return bytes
-
-    def close(self):
-        if self._proxyconn:
-            self._proxyconn.close()
-        return super(socksocket, self).close()
-
-    def get_proxy_sockname(self):
-        """Returns the bound IP address and port number at the proxy."""
-        return self.proxy_sockname
-
-    getproxysockname = get_proxy_sockname
-
-    def get_proxy_peername(self):
-        """
-        Returns the IP and port number of the proxy.
-        """
-        return self.getpeername()
-
-    getproxypeername = get_proxy_peername
-
-    def get_peername(self):
-        """Returns the IP address and port number of the destination machine.
-
-        Note: get_proxy_peername returns the proxy."""
-        return self.proxy_peername
-
-    getpeername = get_peername
-
-    def _negotiate_SOCKS5(self, *dest_addr):
-        """Negotiates a stream connection through a SOCKS5 server."""
-        CONNECT = b"\x01"
-        self.proxy_peername, self.proxy_sockname = self._SOCKS5_request(
-            self, CONNECT, dest_addr)
-
-    def _SOCKS5_request(self, conn, cmd, dst):
-        """
-        Send SOCKS5 request with given command (CMD field) and
-        address (DST field). Returns resolved DST address that was used.
-        """
-        proxy_type, addr, port, rdns, username, password = self.proxy
-
-        writer = conn.makefile("wb")
-        reader = conn.makefile("rb", 0)  # buffering=0 renamed in Python 3
-        try:
-            # First we'll send the authentication packages we support.
-            if username and password:
-                # The username/password details were supplied to the
-                # set_proxy method so we support the USERNAME/PASSWORD
-                # authentication (in addition to the standard none).
-                writer.write(b"\x05\x02\x00\x02")
-            else:
-                # No username/password were entered, therefore we
-                # only support connections with no authentication.
-                writer.write(b"\x05\x01\x00")
-
-            # We'll receive the server's response to determine which
-            # method was selected
-            writer.flush()
-            chosen_auth = self._readall(reader, 2)
-
-            if chosen_auth[0:1] != b"\x05":
-                # Note: string[i:i+1] is used because indexing of a bytestring
-                # via bytestring[i] yields an integer in Python 3
-                raise GeneralProxyError(
-                    "SOCKS5 proxy server sent invalid data")
-
-            # Check the chosen authentication method
-
-            if chosen_auth[1:2] == b"\x02":
-                # Okay, we need to perform a basic username/password
-                # authentication.
-                if not (username and password):
-                    # Although we said we don't support authentication, the
-                    # server may still request basic username/password
-                    # authentication
-                    raise SOCKS5AuthError("No username/password supplied. "
-                                          "Server requested username/password"
-                                          " authentication")
-
-                writer.write(b"\x01" + chr(len(username)).encode()
-                             + username
-                             + chr(len(password)).encode()
-                             + password)
-                writer.flush()
-                auth_status = self._readall(reader, 2)
-                if auth_status[0:1] != b"\x01":
-                    # Bad response
-                    raise GeneralProxyError(
-                        "SOCKS5 proxy server sent invalid data")
-                if auth_status[1:2] != b"\x00":
-                    # Authentication failed
-                    raise SOCKS5AuthError("SOCKS5 authentication failed")
-
-                # Otherwise, authentication succeeded
-
-            # No authentication is required if 0x00
-            elif chosen_auth[1:2] != b"\x00":
-                # Reaching here is always bad
-                if chosen_auth[1:2] == b"\xFF":
-                    raise SOCKS5AuthError(
-                        "All offered SOCKS5 authentication methods were"
-                        " rejected")
-                else:
-                    raise GeneralProxyError(
-                        "SOCKS5 proxy server sent invalid data")
-
-            # Now we can request the actual connection
-            writer.write(b"\x05" + cmd + b"\x00")
-            resolved = self._write_SOCKS5_address(dst, writer)
-            writer.flush()
-
-            # Get the response
-            resp = self._readall(reader, 3)
-            if resp[0:1] != b"\x05":
-                raise GeneralProxyError(
-                    "SOCKS5 proxy server sent invalid data")
-
-            status = ord(resp[1:2])
-            if status != 0x00:
-                # Connection failed: server returned an error
-                error = SOCKS5_ERRORS.get(status, "Unknown error")
-                raise SOCKS5Error("{:#04x}: {}".format(status, error))
-
-            # Get the bound address/port
-            bnd = self._read_SOCKS5_address(reader)
-
-            super(socksocket, self).settimeout(self._timeout)
-            return (resolved, bnd)
-        finally:
-            reader.close()
-            writer.close()
-
-    def _write_SOCKS5_address(self, addr, file):
-        """
-        Return the host and port packed for the SOCKS5 protocol,
-        and the resolved address as a tuple object.
-        """
-        host, port = addr
-        proxy_type, _, _, rdns, username, password = self.proxy
-        family_to_byte = {socket.AF_INET: b"\x01", socket.AF_INET6: b"\x04"}
-
-        # If the given destination address is an IP address, we'll
-        # use the IP address request even if remote resolving was specified.
-        # Detect whether the address is IPv4/6 directly.
-        for family in (socket.AF_INET, socket.AF_INET6):
-            try:
-                addr_bytes = socket.inet_pton(family, host)
-                file.write(family_to_byte[family] + addr_bytes)
-                host = socket.inet_ntop(family, addr_bytes)
-                file.write(struct.pack(">H", port))
-                return host, port
-            except socket.error:
-                continue
-
-        # Well it's not an IP number, so it's probably a DNS name.
-        if rdns:
-            # Resolve remotely
-            host_bytes = host.encode("idna")
-            file.write(b"\x03" + chr(len(host_bytes)).encode() + host_bytes)
-        else:
-            # Resolve locally
-            addresses = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
-                                           socket.SOCK_STREAM,
-                                           socket.IPPROTO_TCP,
-                                           socket.AI_ADDRCONFIG)
-            # We can't really work out what IP is reachable, so just pick the
-            # first.
-            target_addr = addresses[0]
-            family = target_addr[0]
-            host = target_addr[4][0]
-
-            addr_bytes = socket.inet_pton(family, host)
-            file.write(family_to_byte[family] + addr_bytes)
-            host = socket.inet_ntop(family, addr_bytes)
-        file.write(struct.pack(">H", port))
-        return host, port
-
-    def _read_SOCKS5_address(self, file):
-        atyp = self._readall(file, 1)
-        if atyp == b"\x01":
-            addr = socket.inet_ntoa(self._readall(file, 4))
-        elif atyp == b"\x03":
-            length = self._readall(file, 1)
-            addr = self._readall(file, ord(length))
-        elif atyp == b"\x04":
-            addr = socket.inet_ntop(socket.AF_INET6, self._readall(file, 16))
-        else:
-            raise GeneralProxyError("SOCKS5 proxy server sent invalid data")
-
-        port = struct.unpack(">H", self._readall(file, 2))[0]
-        return addr, port
-
-    def _negotiate_SOCKS4(self, dest_addr, dest_port):
-        """Negotiates a connection through a SOCKS4 server."""
-        proxy_type, addr, port, rdns, username, password = self.proxy
-
-        writer = self.makefile("wb")
-        reader = self.makefile("rb", 0)  # buffering=0 renamed in Python 3
-        try:
-            # Check if the destination address provided is an IP address
-            remote_resolve = False
-            try:
-                addr_bytes = socket.inet_aton(dest_addr)
-            except socket.error:
-                # It's a DNS name. Check where it should be resolved.
-                if rdns:
-                    addr_bytes = b"\x00\x00\x00\x01"
-                    remote_resolve = True
-                else:
-                    addr_bytes = socket.inet_aton(
-                        socket.gethostbyname(dest_addr))
-
-            # Construct the request packet
-            writer.write(struct.pack(">BBH", 0x04, 0x01, dest_port))
-            writer.write(addr_bytes)
-
-            # The username parameter is considered userid for SOCKS4
-            if username:
-                writer.write(username)
-            writer.write(b"\x00")
-
-            # DNS name if remote resolving is required
-            # NOTE: This is actually an extension to the SOCKS4 protocol
-            # called SOCKS4A and may not be supported in all cases.
-            if remote_resolve:
-                writer.write(dest_addr.encode("idna") + b"\x00")
-            writer.flush()
-
-            # Get the response from the server
-            resp = self._readall(reader, 8)
-            if resp[0:1] != b"\x00":
-                # Bad data
-                raise GeneralProxyError(
-                    "SOCKS4 proxy server sent invalid data")
-
-            status = ord(resp[1:2])
-            if status != 0x5A:
-                # Connection failed: server returned an error
-                error = SOCKS4_ERRORS.get(status, "Unknown error")
-                raise SOCKS4Error("{:#04x}: {}".format(status, error))
-
-            # Get the bound address/port
-            self.proxy_sockname = (socket.inet_ntoa(resp[4:]),
-                                   struct.unpack(">H", resp[2:4])[0])
-            if remote_resolve:
-                self.proxy_peername = socket.inet_ntoa(addr_bytes), dest_port
-            else:
-                self.proxy_peername = dest_addr, dest_port
-        finally:
-            reader.close()
-            writer.close()
-
-    def _negotiate_HTTP(self, dest_addr, dest_port):
-        """Negotiates a connection through an HTTP server.
-
-        NOTE: This currently only supports HTTP CONNECT-style proxies."""
-        proxy_type, addr, port, rdns, username, password = self.proxy
-
-        # If we need to resolve locally, we do this now
-        addr = dest_addr if rdns else socket.gethostbyname(dest_addr)
-
-        http_headers = [
-            (b"CONNECT " + addr.encode("idna") + b":"
-             + str(dest_port).encode() + b" HTTP/1.1"),
-            b"Host: " + dest_addr.encode("idna")
-        ]
-
-        if username and password:
-            http_headers.append(b"Proxy-Authorization: basic "
-                                + b64encode(username + b":" + password))
-
-        http_headers.append(b"\r\n")
-
-        self.sendall(b"\r\n".join(http_headers))
-
-        # We just need the first line to check if the connection was successful
-        fobj = self.makefile()
-        status_line = fobj.readline()
-        fobj.close()
-
-        if not status_line:
-            raise GeneralProxyError("Connection closed unexpectedly")
-
-        try:
-            proto, status_code, status_msg = status_line.split(" ", 2)
-        except ValueError:
-            raise GeneralProxyError("HTTP proxy server sent invalid response")
-
-        if not proto.startswith("HTTP/"):
-            raise GeneralProxyError(
-                "Proxy server does not appear to be an HTTP proxy")
-
-        try:
-            status_code = int(status_code)
-        except ValueError:
-            raise HTTPError(
-                "HTTP proxy server did not return a valid HTTP status")
-
-        if status_code != 200:
-            error = "{}: {}".format(status_code, status_msg)
-            if status_code in (400, 403, 405):
-                # It's likely that the HTTP proxy server does not support the
-                # CONNECT tunneling method
-                error += ("\n[*] Note: The HTTP proxy server may not be"
-                          " supported by PySocks (must be a CONNECT tunnel"
-                          " proxy)")
-            raise HTTPError(error)
-
-        self.proxy_sockname = (b"0.0.0.0", 0)
-        self.proxy_peername = addr, dest_port
-
-    _proxy_negotiators = {
-                           SOCKS4: _negotiate_SOCKS4,
-                           SOCKS5: _negotiate_SOCKS5,
-                           HTTP: _negotiate_HTTP
-                         }
-
-    @set_self_blocking
-    def connect(self, dest_pair, catch_errors=None):
-        """
-        Connects to the specified destination through a proxy.
-        Uses the same API as socket's connect().
-        To select the proxy server, use set_proxy().
-
-        dest_pair - 2-tuple of (IP/hostname, port).
-        """
-        if len(dest_pair) != 2 or dest_pair[0].startswith("["):
-            # Probably IPv6, not supported -- raise an error, and hope
-            # Happy Eyeballs (RFC6555) makes sure at least the IPv4
-            # connection works...
-            raise socket.error("PySocks doesn't support IPv6: %s"
-                               % str(dest_pair))
-
-        dest_addr, dest_port = dest_pair
-
-        if self.type == socket.SOCK_DGRAM:
-            if not self._proxyconn:
-                self.bind(("", 0))
-            dest_addr = socket.gethostbyname(dest_addr)
-
-            # If the host address is INADDR_ANY or similar, reset the peer
-            # address so that packets are received from any peer
-            if dest_addr == "0.0.0.0" and not dest_port:
-                self.proxy_peername = None
-            else:
-                self.proxy_peername = (dest_addr, dest_port)
-            return
-
-        (proxy_type, proxy_addr, proxy_port, rdns, username,
-         password) = self.proxy
-
-        # Do a minimal input check first
-        if (not isinstance(dest_pair, (list, tuple))
-                or len(dest_pair) != 2
-                or not dest_addr
-                or not isinstance(dest_port, int)):
-            # Inputs failed, raise an error
-            raise GeneralProxyError(
-                "Invalid destination-connection (host, port) pair")
-
-        # We set the timeout here so that we don't hang in connection or during
-        # negotiation.
-        super(socksocket, self).settimeout(self._timeout)
-
-        if proxy_type is None:
-            # Treat like regular socket object
-            self.proxy_peername = dest_pair
-            super(socksocket, self).settimeout(self._timeout)
-            super(socksocket, self).connect((dest_addr, dest_port))
-            return
-
-        proxy_addr = self._proxy_addr()
-
-        try:
-            # Initial connection to proxy server.
-            super(socksocket, self).connect(proxy_addr)
-
-        except socket.error as error:
-            # Error while connecting to proxy
-            self.close()
-            if not catch_errors:
-                proxy_addr, proxy_port = proxy_addr
-                proxy_server = "{}:{}".format(proxy_addr, proxy_port)
-                printable_type = PRINTABLE_PROXY_TYPES[proxy_type]
-
-                msg = "Error connecting to {} proxy {}".format(printable_type,
-                                                                    proxy_server)
-                log.debug("%s due to: %s", msg, error)
-                raise ProxyConnectionError(msg, error)
-            else:
-                raise error
-
-        else:
-            # Connected to proxy server, now negotiate
-            try:
-                # Calls negotiate_{SOCKS4, SOCKS5, HTTP}
-                negotiate = self._proxy_negotiators[proxy_type]
-                negotiate(self, dest_addr, dest_port)
-            except socket.error as error:
-                if not catch_errors:
-                    # Wrap socket errors
-                    self.close()
-                    raise GeneralProxyError("Socket error", error)
-                else:
-                    raise error
-            except ProxyError:
-                # Protocol error while negotiating with proxy
-                self.close()
-                raise
-                
-    @set_self_blocking
-    def connect_ex(self, dest_pair):
-        """ https://docs.python.org/3/library/socket.html#socket.socket.connect_ex
-        Like connect(address), but return an error indicator instead of raising an exception for errors returned by the C-level connect() call (other problems, such as "host not found" can still raise exceptions).
-        """
-        try:
-            self.connect(dest_pair, catch_errors=True)
-            return 0
-        except OSError as e:
-            # If the error is numeric (socket errors are numeric), then return number as 
-            # connect_ex expects. Otherwise raise the error again (socket timeout for example)
-            if e.errno:
-                return e.errno
-            else:
-                raise
-
-    def _proxy_addr(self):
-        """
-        Return proxy address to connect to as tuple object
-        """
-        (proxy_type, proxy_addr, proxy_port, rdns, username,
-         password) = self.proxy
-        proxy_port = proxy_port or DEFAULT_PORTS.get(proxy_type)
-        if not proxy_port:
-            raise GeneralProxyError("Invalid proxy type")
-        return proxy_addr, proxy_port
diff --git a/apps/bitwarden_event_logs/lib/sockshandler.py b/apps/bitwarden_event_logs/lib/sockshandler.py
deleted file mode 100755
index 6a2ed81c..00000000
--- a/apps/bitwarden_event_logs/lib/sockshandler.py
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env python
-"""
-SocksiPy + urllib2 handler
-
-version: 0.3
-author: e
-
-This module provides a Handler which you can use with urllib2 to allow it to tunnel your connection through a socks.sockssocket socket, with out monkey patching the original socket...
-"""
-import socket
-import ssl
-
-try:
-    import urllib2
-    import httplib
-except ImportError: # Python 3
-    import urllib.request as urllib2
-    import http.client as httplib
-
-import socks # $ pip install PySocks
-
-def merge_dict(a, b):
-    d = a.copy()
-    d.update(b)
-    return d
-
-def is_ip(s):
-    try:
-        if ':' in s:
-            socket.inet_pton(socket.AF_INET6, s)
-        elif '.' in s:
-            socket.inet_aton(s)
-        else:
-            return False
-    except:
-        return False
-    else:
-        return True
-
-socks4_no_rdns = set()
-
-class SocksiPyConnection(httplib.HTTPConnection):
-    def __init__(self, proxytype, proxyaddr, proxyport=None, rdns=True, username=None, password=None, *args, **kwargs):
-        self.proxyargs = (proxytype, proxyaddr, proxyport, rdns, username, password)
-        httplib.HTTPConnection.__init__(self, *args, **kwargs)
-
-    def connect(self):
-        (proxytype, proxyaddr, proxyport, rdns, username, password) = self.proxyargs
-        rdns = rdns and proxyaddr not in socks4_no_rdns
-        while True:
-            try:
-                sock = socks.create_connection(
-                    (self.host, self.port), self.timeout, None,
-                    proxytype, proxyaddr, proxyport, rdns, username, password,
-                    ((socket.IPPROTO_TCP, socket.TCP_NODELAY, 1),))
-                break
-            except socks.SOCKS4Error as e:
-                if rdns and "0x5b" in str(e) and not is_ip(self.host):
-                    # Maybe a SOCKS4 server that doesn't support remote resolving
-                    # Let's try again
-                    rdns = False
-                    socks4_no_rdns.add(proxyaddr)
-                else:
-                    raise
-        self.sock = sock
-
-class SocksiPyConnectionS(httplib.HTTPSConnection):
-    def __init__(self, proxytype, proxyaddr, proxyport=None, rdns=True, username=None, password=None, *args, **kwargs):
-        self.proxyargs = (proxytype, proxyaddr, proxyport, rdns, username, password)
-        httplib.HTTPSConnection.__init__(self, *args, **kwargs)
-
-    def connect(self):
-        SocksiPyConnection.connect(self)
-        self.sock = self._context.wrap_socket(self.sock, server_hostname=self.host)
-        if not self._context.check_hostname and self._check_hostname:
-            try:
-                ssl.match_hostname(self.sock.getpeercert(), self.host)
-            except Exception:
-                self.sock.shutdown(socket.SHUT_RDWR)
-                self.sock.close()
-                raise
-
-class SocksiPyHandler(urllib2.HTTPHandler, urllib2.HTTPSHandler):
-    def __init__(self, *args, **kwargs):
-        self.args = args
-        self.kw = kwargs
-        urllib2.HTTPHandler.__init__(self)
-
-    def http_open(self, req):
-        def build(host, port=None, timeout=0, **kwargs):
-            kw = merge_dict(self.kw, kwargs)
-            conn = SocksiPyConnection(*self.args, host=host, port=port, timeout=timeout, **kw)
-            return conn
-        return self.do_open(build, req)
-
-    def https_open(self, req):
-        def build(host, port=None, timeout=0, **kwargs):
-            kw = merge_dict(self.kw, kwargs)
-            conn = SocksiPyConnectionS(*self.args, host=host, port=port, timeout=timeout, **kw)
-            return conn
-        return self.do_open(build, req)
-
-if __name__ == "__main__":
-    import sys
-    try:
-        port = int(sys.argv[1])
-    except (ValueError, IndexError):
-        port = 9050
-    opener = urllib2.build_opener(SocksiPyHandler(socks.PROXY_TYPE_SOCKS5, "localhost", port))
-    print("HTTP: " + opener.open("http://httpbin.org/ip").read().decode())
-    print("HTTPS: " + opener.open("https://httpbin.org/ip").read().decode())
diff --git a/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/INSTALLER
deleted file mode 100755
index a1b589e3..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/INSTALLER
+++ /dev/null
@@ -1 +0,0 @@
-pip
diff --git a/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/LICENSE b/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/LICENSE
deleted file mode 100755
index d13065d5..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "{}"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright 2021 Splunk Inc.
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/METADATA b/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/METADATA
deleted file mode 100755
index 542ab03f..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/METADATA
+++ /dev/null
@@ -1,28 +0,0 @@
-Metadata-Version: 2.1
-Name: solnlib
-Version: 7.0.0
-Summary: The Splunk Software Development Kit for Splunk Solutions
-Home-page: https://github.com/splunk/addonfactory-solutions-library-python
-License: Apache-2.0
-Keywords: splunk,ucc
-Author: Splunk
-Author-email: addonfactory@splunk.com
-Requires-Python: >=3.7,<3.14
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: Apache Software License
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: 3.8
-Classifier: Programming Language :: Python :: 3.9
-Classifier: Programming Language :: Python :: 3.10
-Classifier: Programming Language :: Python :: 3.11
-Classifier: Programming Language :: Python :: 3.12
-Classifier: Programming Language :: Python :: 3.13
-Classifier: Topic :: Software Development :: Code Generators
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Requires-Dist: defusedxml (>=0.7)
-Requires-Dist: sortedcontainers (>=2)
-Requires-Dist: splunk-sdk (>=2.0.2)
-Project-URL: Repository, https://github.com/splunk/addonfactory-solutions-library-python
diff --git a/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/RECORD b/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/RECORD
deleted file mode 100755
index 1cceb35c..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/RECORD
+++ /dev/null
@@ -1,40 +0,0 @@
-solnlib-7.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
-solnlib-7.0.0.dist-info/LICENSE,sha256=Xvvd894DEl8lUHPEeFU-Ya18RW7Hc2IlPTZS_bE3Hgs,11341
-solnlib-7.0.0.dist-info/METADATA,sha256=K6kaGCMmzvwPa45GhHTWfT5d-ckfTwYYqS3Kg2NxCkM,1254
-solnlib-7.0.0.dist-info/RECORD,,
-solnlib-7.0.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-solnlib-7.0.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
-solnlib/__init__.py,sha256=I4q1InhCUhAyPjqhRQCbgZ9Ya3CndtnjJyTkRtfep10,1302
-solnlib/_settings.py,sha256=GIIg9GB8AKSfIDq1J3Qszq_RzUCdPxNsGsMmSBFtd0A,678
-solnlib/_utils.py,sha256=3f4ggQuURl8VkCh517w_hnhtYDfNW-Fm5bPxMPyy2yA,2739
-solnlib/acl.py,sha256=RY99GZcF8VUAOc9p7oWpYssidttDuapXok5-ZG2jg3o,5905
-solnlib/alerts_rest_client.py,sha256=4jc9gF0tID3aeNxfaCSDMwOPo-VMz8zlxqoBjUhM9X4,8681
-solnlib/bulletin_rest_client.py,sha256=ZLMHnN2bIw0TB2FXyf-2Y-I6EQsK-V3vPCj5sNdG4uE,5942
-solnlib/concurrent/concurrent_executor.py,sha256=H1uYRz82WZ3Fpswq_1jmJ0UGPgNy4EbzfZlgoTU5jIY,3485
-solnlib/concurrent/process_pool.py,sha256=aci4XRKKuwvx5Xu4pa4cqqgRgMyKw6NqtzTzieAz9Cs,2192
-solnlib/concurrent/thread_pool.py,sha256=tFuNjndBihMApgZzDXePDzauptGT9B2Pm4ffE7Z3e68,10466
-solnlib/conf_manager.py,sha256=EtJcvTCtLxFj1uKeLryj76R5VnXTLsV_DCTMyhLevpU,19344
-solnlib/credentials.py,sha256=0Pbn-Cth6rTpHyBtL5uFL7gC2zz2A-525O1nGJ2XpoA,12098
-solnlib/file_monitor.py,sha256=QeMAm5anPy7jf7M22mOvsCnn1gD7-IHQ_R-036sIo9w,3978
-solnlib/hec_config.py,sha256=DeCkxqazb0G1fNhcjfEdc9cTZBHTN8pRMLUFkcjPs50,5054
-solnlib/log.py,sha256=w3AGpL8VjHW2FP3V-bOGym0zm2iAAiG2_ciD95WIqSc,11933
-solnlib/modular_input/__init__.py,sha256=2ZaLwmHL7DQSxdvlpr_DIBWRRPzmP1UaKdE8Ixrm-Rc,1190
-solnlib/modular_input/checkpointer.py,sha256=dpiueA_QsFj3lpKCKtNomGLqEkpVm-LD7R5UuOwt3Y4,8692
-solnlib/modular_input/event.py,sha256=YNbIVpHom8Ya6TmY_NsBjej5_tqChmGAM1WQqq-iKik,7873
-solnlib/modular_input/event_writer.py,sha256=nNLh48zyHQtDyK6VOBvx2SP97ctPjrhvp2RiobL6wes,17148
-solnlib/modular_input/modinput.py,sha256=C4ctMCqLylbv0IYC-dyFdowmAckJFtaQA4fnTa8cpVs,5150
-solnlib/modular_input/modular_input.py,sha256=QuFR0O5Fbf89re-FG4i67p2inxn9aZIDZ-hYIJDYR6c,18048
-solnlib/net_utils.py,sha256=LkWGYcRgj-B7wpP8WIAgGl6yFuDAwnNXVyTnG6D-rEE,4063
-solnlib/orphan_process_monitor.py,sha256=vK_Lz8VIj59EvHcr475m4ZI29jlLtkZaPVqtG3xSMoM,3218
-solnlib/pattern.py,sha256=lS_jzA3efz1XZlgCZ0kbPbOniPgC7hy-aVXQJnjIbOE,1162
-solnlib/rest.py,sha256=KISfYwRchp_LyM5Hq3LZP6PqR9SzUSiIpqwY4tAEphU,2945
-solnlib/schedule/job.py,sha256=gzGf-EVztTQtUqUvpKyZCo_UHWTYXudPSeG4l1U-jVk,3060
-solnlib/schedule/scheduler.py,sha256=LNcub_Hvm_E6X7phxlfitO2Lq0IrqDsHvNSqU0CHjOE,4719
-solnlib/server_info.py,sha256=wJFZuyDI-A9bR-qFA5BdKgIvlk2x5AepOMjEJ3-dCR8,9319
-solnlib/soln_exceptions.py,sha256=TXUAVom2F5xqU0fspKG-cq5vCxFnJila_xbXMlWkAAI,1019
-solnlib/splunk_rest_client.py,sha256=7yiCtyM6oOhPnu4gFR_lhaWV9hmZBtKCgijRL0hyEKY,7809
-solnlib/splunkenv.py,sha256=E8bfYOFVQOl5BRyE05wQbZNTimFrqlIbWFRJsknVYws,12475
-solnlib/time_parser.py,sha256=vQ90V20ZhpFTt52YfIeWiNLXvUIvyQgK3fL2gv67jE8,4668
-solnlib/timer_queue.py,sha256=ehmAH2zgTzpixiXcnC4Cn7X3B1vqBIu4u4pQ4NaA5rM,9972
-solnlib/user_access.py,sha256=paouy4pV4svGe4dS6XEXidPdvBg8llkwT_59hqOPsxM,29175
-solnlib/utils.py,sha256=oNxr6oU0mR1cIO6j7TyCjb4KkPE-6RuqfM62ABT6xn4,5887
diff --git a/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/REQUESTED
deleted file mode 100755
index e69de29b..00000000
diff --git a/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/WHEEL
deleted file mode 100755
index 258a6ff3..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib-7.0.0.dist-info/WHEEL
+++ /dev/null
@@ -1,4 +0,0 @@
-Wheel-Version: 1.0
-Generator: poetry-core 1.6.1
-Root-Is-Purelib: true
-Tag: py3-none-any
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__init__.py b/apps/bitwarden_event_logs/lib/solnlib/__init__.py
deleted file mode 100755
index 32596d9b..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/__init__.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""The Splunk Software Development Kit for Solutions."""
-
-from . import (
-    acl,
-    bulletin_rest_client,
-    conf_manager,
-    credentials,
-    file_monitor,
-    hec_config,
-    log,
-    net_utils,
-    orphan_process_monitor,
-    pattern,
-    server_info,
-    splunk_rest_client,
-    splunkenv,
-    time_parser,
-    timer_queue,
-    user_access,
-    utils,
-)
-
-__all__ = [
-    "acl",
-    "bulletin_rest_client",
-    "conf_manager",
-    "credentials",
-    "file_monitor",
-    "hec_config",
-    "log",
-    "net_utils",
-    "orphan_process_monitor",
-    "pattern",
-    "server_info",
-    "splunk_rest_client",
-    "splunkenv",
-    "time_parser",
-    "timer_queue",
-    "user_access",
-    "utils",
-]
-
-__version__ = "7.0.0"
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/__init__.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/__init__.cpython-39.pyc
deleted file mode 100755
index e87c91d8..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/__init__.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/_settings.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/_settings.cpython-39.pyc
deleted file mode 100755
index 60d13937..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/_settings.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/_utils.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/_utils.cpython-39.pyc
deleted file mode 100755
index ad522533..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/_utils.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/acl.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/acl.cpython-39.pyc
deleted file mode 100755
index c65174b8..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/acl.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/bulletin_rest_client.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/bulletin_rest_client.cpython-39.pyc
deleted file mode 100755
index 0ddaab61..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/bulletin_rest_client.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/conf_manager.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/conf_manager.cpython-39.pyc
deleted file mode 100755
index 9f34346c..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/conf_manager.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/credentials.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/credentials.cpython-39.pyc
deleted file mode 100755
index bfd72e8d..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/credentials.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/file_monitor.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/file_monitor.cpython-39.pyc
deleted file mode 100755
index 197e4008..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/file_monitor.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/hec_config.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/hec_config.cpython-39.pyc
deleted file mode 100755
index 327aac05..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/hec_config.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/log.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/log.cpython-39.pyc
deleted file mode 100755
index 0423eabb..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/log.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/net_utils.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/net_utils.cpython-39.pyc
deleted file mode 100755
index 429009e8..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/net_utils.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/orphan_process_monitor.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/orphan_process_monitor.cpython-39.pyc
deleted file mode 100755
index b183cfe3..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/orphan_process_monitor.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/pattern.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/pattern.cpython-39.pyc
deleted file mode 100755
index 539167b9..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/pattern.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/server_info.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/server_info.cpython-39.pyc
deleted file mode 100755
index 36da991c..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/server_info.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/soln_exceptions.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/soln_exceptions.cpython-39.pyc
deleted file mode 100755
index f8c36808..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/soln_exceptions.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/splunk_rest_client.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/splunk_rest_client.cpython-39.pyc
deleted file mode 100755
index 8c1fa9f2..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/splunk_rest_client.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/splunkenv.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/splunkenv.cpython-39.pyc
deleted file mode 100755
index ea5da717..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/splunkenv.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/time_parser.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/time_parser.cpython-39.pyc
deleted file mode 100755
index ff083650..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/time_parser.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/timer_queue.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/timer_queue.cpython-39.pyc
deleted file mode 100755
index 6cc60a7f..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/timer_queue.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/user_access.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/user_access.cpython-39.pyc
deleted file mode 100755
index 85e781d9..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/user_access.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/utils.cpython-39.pyc b/apps/bitwarden_event_logs/lib/solnlib/__pycache__/utils.cpython-39.pyc
deleted file mode 100755
index d8b7838e..00000000
Binary files a/apps/bitwarden_event_logs/lib/solnlib/__pycache__/utils.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/solnlib/_settings.py b/apps/bitwarden_event_logs/lib/solnlib/_settings.py
deleted file mode 100755
index 1f3501de..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/_settings.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-"""This module provide settings that can be used to disable/switch features."""
-
-use_btool = False
diff --git a/apps/bitwarden_event_logs/lib/solnlib/_utils.py b/apps/bitwarden_event_logs/lib/solnlib/_utils.py
deleted file mode 100755
index 3b98aac8..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/_utils.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-"""This module provide utils that are private to solnlib."""
-
-import re
-from typing import Any, Dict, Optional, Union
-
-from splunklib import binding, client
-
-from solnlib import splunk_rest_client
-from solnlib.utils import retry
-
-
-@retry(exceptions=[binding.HTTPError])
-def get_collection_data(
-    collection_name: str,
-    session_key: str,
-    app: str,
-    owner: Optional[str] = None,
-    scheme: Optional[str] = None,
-    host: Optional[str] = None,
-    port: Optional[Union[str, int]] = None,
-    fields: Optional[Dict] = None,
-    **context: Any,
-) -> client.KVStoreCollectionData:
-    """Get collection data, if there is no such collection - creates one.
-
-    Arguments:
-        collection_name: Collection name of KV Store checkpointer.
-        session_key: Splunk access token.
-        app: App name of namespace.
-        owner: Owner of namespace, default is `nobody`.
-        scheme: The access scheme, default is None.
-        host: The host name, default is None.
-        port: The port number, default is None.
-        fields: Fields used to initialize the collection if it's missing.
-        context: Other configurations for Splunk rest client.
-
-    Raises:
-        binding.HTTPError: HTTP error different from 404, for example 503 when
-            KV Store is initializing and not ready to serve requests.
-        KeyError: KV Store did not get collection_name.
-
-    Returns:
-        KV Store collections data instance.
-    """
-    kvstore = splunk_rest_client.SplunkRestClient(
-        session_key, app, owner=owner, scheme=scheme, host=host, port=port, **context
-    ).kvstore
-
-    collection_name = re.sub(r"[^\w]+", "_", collection_name)
-    try:
-        kvstore.get(name=collection_name)
-    except binding.HTTPError as e:
-        if e.status != 404:
-            raise
-
-        fields = fields if fields is not None else {}
-        kvstore.create(collection_name, fields=fields)
-
-    collections = kvstore.list(search=collection_name)
-    for collection in collections:
-        if collection.name == collection_name:
-            return collection.data
-    else:
-        raise KeyError(f"Get collection data: {collection_name} failed.")
diff --git a/apps/bitwarden_event_logs/lib/solnlib/acl.py b/apps/bitwarden_event_logs/lib/solnlib/acl.py
deleted file mode 100755
index ce6f6eaa..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/acl.py
+++ /dev/null
@@ -1,182 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module contains interfaces that support CRUD operations on ACL."""
-
-import json
-from typing import List
-
-from splunklib import binding
-
-from . import splunk_rest_client as rest_client
-from .utils import retry
-
-__all__ = ["ACLException", "ACLManager"]
-
-
-class ACLException(Exception):
-    """Exception raised by ACLManager."""
-
-    pass
-
-
-class ACLManager:
-    """ACL manager.
-
-    Examples:
-       >>> import solnlib.acl as sacl
-       >>> saclm = sacl.ACLManager(session_key, 'Splunk_TA_test')
-       >>> saclm.get('data/transforms/extractions')
-       >>> saclm.update('data/transforms/extractions/_acl',
-                        perms_read=['*'], perms_write=['*'])
-    """
-
-    def __init__(
-        self,
-        session_key: str,
-        app: str,
-        owner: str = "nobody",
-        scheme: str = None,
-        host: str = None,
-        port: int = None,
-        **context: dict
-    ):
-        """Initializes ACLManager.
-
-        Arguments:
-            session_key: Splunk access token.
-            app: App name of namespace.
-            owner: (optional) Owner of namespace, default is `nobody`.
-            scheme: (optional) The access scheme, default is None.
-            host: (optional) The host name, default is None.
-            port: (optional) The port number, default is None.
-            context: Other configurations for Splunk rest client.
-        """
-        self._rest_client = rest_client.SplunkRestClient(
-            session_key,
-            app,
-            owner=owner,
-            scheme=scheme,
-            host=host,
-            port=port,
-            **context
-        )
-
-    @retry(exceptions=[binding.HTTPError])
-    def get(self, path: str) -> dict:
-        """Get ACL of  /servicesNS/{`owner`}/{`app`}/{`path`}.
-
-        Arguments:
-            path: Path of ACL relative to /servicesNS/{`owner`}/{`app`}
-
-        Returns:
-            A dict contains ACL.
-
-        Raises:
-            ACLException: If `path` is invalid.
-
-        Examples:
-           >>> aclm = acl.ACLManager(session_key, 'Splunk_TA_test')
-           >>> perms = aclm.get('data/transforms/extractions/_acl')
-        """
-
-        try:
-            content = self._rest_client.get(path, output_mode="json").body.read()
-        except binding.HTTPError as e:
-            if e.status != 404:
-                raise
-
-            raise ACLException("Invalid endpoint: %s.", path)
-
-        return json.loads(content)["entry"][0]["acl"]
-
-    @retry(exceptions=[binding.HTTPError])
-    def update(
-        self,
-        path: str,
-        owner: str = None,
-        perms_read: List = None,
-        perms_write: List = None,
-    ) -> dict:
-        """Update ACL of /servicesNS/{`owner`}/{`app`}/{`path`}.
-
-        If the ACL is per-entity (ends in /acl), owner can be reassigned. If
-        the acl is endpoint-level (ends in _acl), owner will be ignored. The
-        'sharing' setting is always retrieved from the current.
-
-        Arguments:
-            path: Path of ACL relative to /servicesNS/{owner}/{app}. MUST
-                end with /acl or /_acl indicating whether the permission is applied
-                at the per-entity level or endpoint level respectively.
-            owner: (optional) New owner of ACL, default is `nobody`.
-            perms_read: (optional) List of roles (['*'] for all roles). If
-                unspecified we will POST with current (if available) perms.read,
-                default is None.
-            perms_write: (optional) List of roles (['*'] for all roles). If
-                unspecified we will POST with current (if available) perms.write,
-                default is None.
-
-        Returns:
-            A dict contains ACL after update.
-
-        Raises:
-            ACLException: If `path` is invalid.
-
-        Examples:
-           >>> aclm = acl.ACLManager(session_key, 'Splunk_TA_test')
-           >>> perms = aclm.update('data/transforms/extractions/_acl',
-                                   perms_read=['admin'], perms_write=['admin'])
-        """
-
-        if not path.endswith("/acl") and not path.endswith("/_acl"):
-            raise ACLException(
-                "Invalid endpoint: %s, must end with /acl or /_acl." % path
-            )
-
-        curr_acl = self.get(path)
-
-        postargs = {}
-        if perms_read:
-            postargs["perms.read"] = ",".join(perms_read)
-        else:
-            curr_read = curr_acl["perms"].get("read", [])
-            if curr_read:
-                postargs["perms.read"] = ",".join(curr_read)
-
-        if perms_write:
-            postargs["perms.write"] = ",".join(perms_write)
-        else:
-            curr_write = curr_acl["perms"].get("write", [])
-            if curr_write:
-                postargs["perms.write"] = ",".join(curr_write)
-
-        if path.endswith("/acl"):
-            # Allow ownership to be reset only at entity level.
-            postargs["owner"] = owner or curr_acl["owner"]
-
-        postargs["sharing"] = curr_acl["sharing"]
-
-        try:
-            content = self._rest_client.post(
-                path, body=binding._encode(**postargs), output_mode="json"
-            ).body.read()
-        except binding.HTTPError as e:
-            if e.status != 404:
-                raise
-
-            raise ACLException("Invalid endpoint: %s.", path)
-
-        return json.loads(content)["entry"][0]["acl"]
diff --git a/apps/bitwarden_event_logs/lib/solnlib/alerts_rest_client.py b/apps/bitwarden_event_logs/lib/solnlib/alerts_rest_client.py
deleted file mode 100755
index 430aacfe..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/alerts_rest_client.py
+++ /dev/null
@@ -1,258 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-import json
-from enum import Enum
-from typing import Tuple, Union, Optional
-
-from solnlib import splunk_rest_client as rest_client
-
-
-class AlertType(Enum):
-    CUSTOM = "custom"
-    NUMBER_OF_EVENTS = "number of events"
-    NUMBER_OF_HOSTS = "number of hosts"
-    NUMBER_OF_SOURCES = "number of sources"
-
-
-class AlertSeverity(Enum):
-    DEBUG = 1
-    INFO = 2
-    WARN = 3
-    ERROR = 4
-    SEVERE = 5
-    FATAL = 6
-
-
-class AlertComparator(Enum):
-    GREATER_THAN = "greater than"
-    LESS_THAN = "less than"
-    EQUAL_TO = "equal to"
-    RISES_BY = "rises by"
-    DROPS_BY = "drops by"
-    RISES_BY_PERC = "rises by perc"
-    DROPS_BY_PERC = "drops by perc"
-
-
-class AlertsRestClient:
-    """REST client for handling alerts."""
-
-    ENDPOINT = "/servicesNS/{owner}/{app}/saved/searches"
-    headers = [("Content-Type", "application/json")]
-
-    def __init__(
-        self,
-        session_key: str,
-        app: str,
-        owner: str = "nobody",
-        **context: dict,
-    ):
-        """Initializes AlertsRestClient.
-
-        Arguments:
-            session_key: Splunk access token.
-            app: App name of namespace.
-            context: Other configurations for Splunk rest client.
-        """
-        self.session_key = session_key
-        self.app = app
-
-        self._rest_client = rest_client.SplunkRestClient(
-            self.session_key,
-            app=self.app,
-            owner=owner,
-            **context,
-        )
-
-        self.endpoint = self.ENDPOINT.format(owner=owner, app=app)
-
-    def create_search_alert(
-        self,
-        name: str,
-        search: str,
-        *,
-        disabled: bool = True,
-        description: str = "",
-        alert_type: AlertType = AlertType.NUMBER_OF_EVENTS,
-        alert_condition: str = "",
-        alert_comparator: AlertComparator = AlertComparator.GREATER_THAN,
-        alert_threshold: Union[int, float, str] = 0,
-        time_window: Tuple[str, str] = ("-15m", "now"),
-        alert_severity: AlertSeverity = AlertSeverity.WARN,
-        cron_schedule: str = "* * * * *",
-        expires: Union[int, str] = "24h",
-        **kwargs,
-    ):
-        """Creates a search alert in Splunk.
-
-        Arguments:
-            name: Name of the alert.
-            search: Search query for the alert.
-            disabled: Whether the alert is disabled. Default is True.
-            description: Description of the alert.
-            alert_type: Type of the alert (see AlertType). If it equals to CUSTOM, Splunk executes a check in
-                alert_condition. Otherwise, alert_comparator and alert_threshold are used.
-            alert_condition: Condition for the alert.
-            alert_comparator: Comparator for the alert. Default is GREATER_THAN.
-            alert_threshold: Threshold for the alert. Default is 0.
-            time_window: Time window for the alert. Tuple of earliest and latest time. Default is ("-15m", "now").
-            alert_severity: Severity level of the alert. Default is WARN.
-            cron_schedule: Cron schedule for the alert. Default is "* * * * *".
-            expires: Expiration time for the alert (i.e. how long you can access the result of triggered alert).
-                Default is "24h".
-            kwargs: Additional parameters for the alert. See Splunk documentation for more details.
-        """
-        params = {
-            "output_mode": "json",
-            "name": name,
-            "search": search,
-            "description": description,
-            "alert_type": alert_type.value,
-            "alert_condition": alert_condition,
-            "alert_comparator": alert_comparator.value,
-            "alert_threshold": alert_threshold,
-            "alert.severity": str(alert_severity.value),
-            "is_scheduled": "1",
-            "cron_schedule": cron_schedule,
-            "dispatch.earliest_time": time_window[0],
-            "dispatch.latest_time": time_window[1],
-            "alert.digest_mode": "1",
-            "alert.expires": str(expires),
-            "disabled": "1" if disabled else "0",
-            "realtime_schedule": "1",
-        }
-
-        params.update(kwargs)
-
-        self._rest_client.post(self.endpoint, body=params, headers=self.headers)
-
-    def delete_search_alert(self, name: str):
-        """Deletes a search alert in Splunk.
-
-        Arguments:
-            name: Name of the alert to delete.
-        """
-        self._rest_client.delete(f"{self.endpoint}/{name}")
-
-    def get_search_alert(self, name: str):
-        """Retrieves a specific search alert from Splunk.
-
-        Arguments:
-            name: Name of the alert to retrieve.
-
-        Returns:
-            A dictionary containing the alert details.
-        """
-        response = (
-            self._rest_client.get(f"{self.endpoint}/{name}", output_mode="json")
-            .body.read()
-            .decode("utf-8")
-        )
-
-        return json.loads(response)
-
-    def get_all_search_alerts(self):
-        """Retrieves all search alerts from Splunk.
-
-        Returns:
-            A dictionary containing all search alerts.
-        """
-        response = (
-            self._rest_client.get(self.endpoint, output_mode="json")
-            .body.read()
-            .decode("utf-8")
-        )
-
-        return json.loads(response)
-
-    def update_search_alert(
-        self,
-        name: str,
-        *,
-        search: Optional[str] = None,
-        disabled: Optional[bool] = None,
-        description: Optional[str] = None,
-        alert_type: Optional[AlertType] = None,
-        alert_condition: Optional[str] = None,
-        alert_comparator: Optional[AlertComparator] = None,
-        alert_threshold: Optional[Union[int, float, str]] = None,
-        time_window: Optional[Tuple[str, str]] = None,
-        alert_severity: Optional[AlertSeverity] = None,
-        cron_schedule: Optional[str] = None,
-        expires: Optional[Union[int, str]] = None,
-        **kwargs,
-    ):
-        """Updates a search alert in Splunk.
-
-        Arguments:
-            name: Name of the alert to update.
-            search: Search query for the alert.
-            disabled: Whether the alert is disabled.
-            description: Description of the alert.
-            alert_type: Type of the alert (see AlertType). If it equals to CUSTOM, Splunk executes a check in
-                alert_condition. Otherwise, alert_comparator and alert_threshold are used.
-            alert_condition: Condition for the alert.
-            alert_comparator: Comparator for the alert.
-            alert_threshold: Threshold for the alert.
-            time_window: Time window for the alert. Tuple of earliest and latest time.
-            alert_severity: Severity level of the alert.
-            cron_schedule: Cron schedule for the alert.
-            expires: Expiration time for the alert.
-            kwargs: Additional parameters for the alert. See Splunk documentation for more details.
-        """
-        params = {
-            "output_mode": "json",
-        }
-
-        if search:
-            params["search"] = search
-
-        if disabled is not None:
-            params["disabled"] = "1" if disabled else "0"
-
-        if description:
-            params["description"] = description
-
-        if alert_type:
-            params["alert_type"] = alert_type.value
-
-        if alert_condition:
-            params["alert_condition"] = alert_condition
-
-        if alert_comparator:
-            params["alert_comparator"] = alert_comparator.value
-
-        if alert_threshold:
-            params["alert_threshold"] = str(alert_threshold)
-
-        if time_window:
-            params["dispatch.earliest_time"] = time_window[0]
-            params["dispatch.latest_time"] = time_window[1]
-
-        if alert_severity:
-            params["alert.severity"] = str(alert_severity.value)
-
-        if cron_schedule:
-            params["is_scheduled"] = "1"
-            params["cron_schedule"] = cron_schedule
-
-        if expires:
-            params["alert.expires"] = str(expires)
-
-        params.update(kwargs)
-
-        self._rest_client.post(
-            f"{self.endpoint}/{name}", body=params, headers=self.headers
-        )
diff --git a/apps/bitwarden_event_logs/lib/solnlib/bulletin_rest_client.py b/apps/bitwarden_event_logs/lib/solnlib/bulletin_rest_client.py
deleted file mode 100755
index 1fb786f7..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/bulletin_rest_client.py
+++ /dev/null
@@ -1,151 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-from solnlib import splunk_rest_client as rest_client
-from typing import Optional, List
-import json
-
-__all__ = ["BulletinRestClient"]
-
-
-class BulletinRestClient:
-    """REST client for handling Bulletin messages."""
-
-    MESSAGES_ENDPOINT = "/services/messages"
-
-    headers = [("Content-Type", "application/json")]
-
-    class Severity:
-        INFO = "info"
-        WARNING = "warn"
-        ERROR = "error"
-
-    def __init__(
-        self,
-        message_name: str,
-        session_key: str,
-        app: str,
-        **context: dict,
-    ):
-        """Initializes BulletinRestClient.
-            When creating a new bulletin message, you must provide a name, which is a kind of ID.
-            If you try to create another message with the same name (ID), the API will not add another message
-            to the bulletin, but it will overwrite the existing one. Similar behaviour applies to deletion.
-            To delete a message, you must indicate the name (ID) of the message.
-            To provide better and easier control over bulletin messages, this client works in such a way
-            that there is one instance responsible for handling one specific message.
-            If you need to add another message to bulletin create another instance
-            with a different 'message_name'
-            e.g.
-            msg_1 = BulletinRestClient("message_1", "")
-            msg_2 = BulletinRestClient("message_2", "")
-
-        Arguments:
-            message_name: Name of the message in the Splunk's bulletin.
-            session_key: Splunk access token.
-            app: App name of namespace.
-            context: Other configurations for Splunk rest client.
-        """
-
-        self.message_name = message_name
-        self.session_key = session_key
-        self.app = app
-
-        self._rest_client = rest_client.SplunkRestClient(
-            self.session_key, app=self.app, **context
-        )
-
-    def create_message(
-        self,
-        msg: str,
-        severity: Severity = Severity.WARNING,
-        capabilities: Optional[List[str]] = None,
-        roles: Optional[List] = None,
-    ):
-        """Creates a message in the Splunk's bulletin. Calling this method
-        multiple times for the same instance will overwrite existing message.
-
-        Arguments:
-            msg: The message which will be displayed in the Splunk's bulletin
-            severity: Severity level of the message. It has to be one of: 'info', 'warn', 'error'.
-                If wrong severity is given, ValueError will be raised.
-            capabilities: One or more capabilities that users must have to view the message.
-                Capability names are validated.
-                This argument should be provided as a list of string/s e.g. capabilities=['one', 'two'].
-                If a non-existent capability is used, HTTP 400 BAD REQUEST exception will be raised.
-                If argument is not a List[str] ValueError will be raised.
-            roles: One or more roles that users must have to view the message. Role names are validated.
-                This argument should be provided as a list of string/s e.g. roles=['user', 'admin'].
-                If a non-existent role is used, HTTP 400 BAD REQUEST exception will be raised.
-                If argument is not a List[str] ValueError will be raised.
-        """
-        body = {
-            "name": self.message_name,
-            "value": msg,
-            "severity": severity,
-            "capability": [],
-            "role": [],
-        }
-
-        if severity not in (
-            self.Severity.INFO,
-            self.Severity.WARNING,
-            self.Severity.ERROR,
-        ):
-            raise ValueError(
-                "Severity must be one of ("
-                "'BulletinRestClient.Severity.INFO', "
-                "'BulletinRestClient.Severity.WARNING', "
-                "'BulletinRestClient.Severity.ERROR'"
-                ")."
-            )
-
-        if capabilities:
-            body["capability"] = self._validate_and_get_body_value(
-                capabilities, "Capabilities must be a list of strings."
-            )
-
-        if roles:
-            body["role"] = self._validate_and_get_body_value(
-                roles, "Roles must be a list of strings."
-            )
-
-        self._rest_client.post(self.MESSAGES_ENDPOINT, body=body, headers=self.headers)
-
-    def get_message(self):
-        """Get specific message created by this instance."""
-        endpoint = f"{self.MESSAGES_ENDPOINT}/{self.message_name}"
-        response = self._rest_client.get(endpoint, output_mode="json").body.read()
-        return json.loads(response)
-
-    def get_all_messages(self):
-        """Get all messages in the bulletin."""
-        response = self._rest_client.get(
-            self.MESSAGES_ENDPOINT, output_mode="json"
-        ).body.read()
-        return json.loads(response)
-
-    def delete_message(self):
-        """Delete specific message created by this instance."""
-        endpoint = f"{self.MESSAGES_ENDPOINT}/{self.message_name}"
-        self._rest_client.delete(endpoint)
-
-    @staticmethod
-    def _validate_and_get_body_value(arg, error_msg) -> List:
-        if type(arg) is list and (all(isinstance(el, str) for el in arg)):
-            return [el for el in arg]
-        else:
-            raise ValueError(error_msg)
diff --git a/apps/bitwarden_event_logs/lib/solnlib/concurrent/concurrent_executor.py b/apps/bitwarden_event_logs/lib/solnlib/concurrent/concurrent_executor.py
deleted file mode 100755
index 98dafc2a..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/concurrent/concurrent_executor.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""Concurrent executor provides concurrent executing function either in a
-thread pool or a process pool."""
-
-import solnlib.concurrent.process_pool as pp
-import solnlib.concurrent.thread_pool as tp
-
-
-class ConcurrentExecutor:
-    def __init__(self, config):
-        """
-        :param config: dict like object, contains thread_min_size (int),
-                       thread_max_size (int), daemonize_thread (bool),
-                       process_size (int)
-        """
-
-        self._io_executor = tp.ThreadPool(
-            config.get("thread_min_size", 0),
-            config.get("thread_max_size", 0),
-            config.get("task_queue_size", 1024),
-            config.get("daemonize_thread", True),
-        )
-        self._compute_executor = None
-        if config.get("process_size", 0):
-            self._compute_executor = pp.ProcessPool(config.get("process_size", 0))
-
-    def start(self):
-        self._io_executor.start()
-
-    def tear_down(self):
-        self._io_executor.tear_down()
-        if self._compute_executor is not None:
-            self._compute_executor.tear_down()
-
-    def run_io_func_sync(self, func, args=(), kwargs=None):
-        """
-        :param func: callable
-        :param args: free params
-        :param kwargs: named params
-        :return whatever the func returns
-        """
-
-        return self._io_executor.apply(func, args, kwargs)
-
-    def run_io_func_async(self, func, args=(), kwargs=None, callback=None):
-        """
-        :param func: callable
-        :param args: free params
-        :param kwargs: named params
-        :calllback: when func is done and without exception, call the callback
-        :return whatever the func returns
-        """
-
-        return self._io_executor.apply_async(func, args, kwargs, callback)
-
-    def enqueue_io_funcs(self, funcs, block=True):
-        """run jobs in a fire and forget way, no result will be handled over to
-        clients.
-
-        :param funcs: tuple/list-like or generator like object, func shall be
-                      callable
-        """
-
-        return self._io_executor.enqueue_funcs(funcs, block)
-
-    def run_compute_func_sync(self, func, args=(), kwargs={}):
-        """
-        :param func: callable
-        :param args: free params
-        :param kwargs: named params
-        :return whatever the func returns
-        """
-
-        assert self._compute_executor is not None
-        return self._compute_executor.apply(func, args, kwargs)
-
-    def run_compute_func_async(self, func, args=(), kwargs={}, callback=None):
-        """
-        :param func: callable
-        :param args: free params
-        :param kwargs: named params
-        :calllback: when func is done and without exception, call the callback
-        :return whatever the func returns
-        """
-
-        assert self._compute_executor is not None
-        return self._compute_executor.apply_async(func, args, kwargs, callback)
diff --git a/apps/bitwarden_event_logs/lib/solnlib/concurrent/process_pool.py b/apps/bitwarden_event_logs/lib/solnlib/concurrent/process_pool.py
deleted file mode 100755
index e900bfe4..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/concurrent/process_pool.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""A wrapper of multiprocessing.pool."""
-
-import multiprocessing
-
-import logging
-
-
-class ProcessPool:
-    """A simple wrapper of multiprocessing.pool."""
-
-    def __init__(self, size=0, maxtasksperchild=10000):
-        if size <= 0:
-            size = multiprocessing.cpu_count()
-        self.size = size
-        self._pool = multiprocessing.Pool(
-            processes=size, maxtasksperchild=maxtasksperchild
-        )
-        self._stopped = False
-
-    def tear_down(self):
-        """Tear down the pool."""
-
-        if self._stopped:
-            logging.info("ProcessPool has already stopped.")
-            return
-        self._stopped = True
-
-        self._pool.close()
-        self._pool.join()
-        logging.info("ProcessPool stopped.")
-
-    def apply(self, func, args=(), kwargs={}):
-        """
-        :param func: callable
-        :param args: free params
-        :param kwargs: named params
-        :return whatever the func returns
-        """
-
-        if self._stopped:
-            logging.info("ProcessPool has already stopped.")
-            return None
-
-        return self._pool.apply(func, args, kwargs)
-
-    def apply_async(self, func, args=(), kwargs={}, callback=None):
-        """
-        :param func: callable
-        :param args: free params
-        :param kwargs: named params
-        :callback: when func is done without exception, call this callack
-        :return whatever the func returns
-        """
-
-        if self._stopped:
-            logging.info("ProcessPool has already stopped.")
-            return None
-
-        return self._pool.apply_async(func, args, kwargs, callback)
diff --git a/apps/bitwarden_event_logs/lib/solnlib/concurrent/thread_pool.py b/apps/bitwarden_event_logs/lib/solnlib/concurrent/thread_pool.py
deleted file mode 100755
index 212e5ad4..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/concurrent/thread_pool.py
+++ /dev/null
@@ -1,347 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""A simple thread pool implementation."""
-
-import multiprocessing
-import queue
-import threading
-import traceback
-from time import time
-import logging
-
-
-class ThreadPool:
-    """A simple thread pool implementation."""
-
-    _high_watermark = 0.2
-    _resize_window = 10
-
-    def __init__(self, min_size=1, max_size=128, task_queue_size=1024, daemon=True):
-        assert task_queue_size
-
-        if not min_size or min_size <= 0:
-            min_size = multiprocessing.cpu_count()
-
-        if not max_size or max_size <= 0:
-            max_size = multiprocessing.cpu_count() * 8
-
-        self._min_size = min_size
-        self._max_size = max_size
-        self._daemon = daemon
-
-        self._work_queue = queue.Queue(task_queue_size)
-        self._thrs = []
-        for _ in range(min_size):
-            thr = threading.Thread(target=self._run)
-            self._thrs.append(thr)
-        self._admin_queue = queue.Queue()
-        self._admin_thr = threading.Thread(target=self._do_admin)
-        self._last_resize_time = time()
-        self._last_size = min_size
-        self._lock = threading.Lock()
-        self._occupied_threads = 0
-        self._count_lock = threading.Lock()
-        self._started = False
-
-    def start(self):
-        """Start threads in the pool."""
-
-        with self._lock:
-            if self._started:
-                return
-            self._started = True
-
-            for thr in self._thrs:
-                thr.daemon = self._daemon
-                thr.start()
-
-            self._admin_thr.start()
-        logging.info("ThreadPool started.")
-
-    def tear_down(self):
-        """Tear down thread pool."""
-
-        with self._lock:
-            if not self._started:
-                return
-            self._started = False
-
-            for thr in self._thrs:
-                self._work_queue.put(None, block=True)
-
-            self._admin_queue.put(None)
-
-            if not self._daemon:
-                logging.info("Wait for threads to stop.")
-                for thr in self._thrs:
-                    thr.join()
-            self._admin_thr.join()
-
-        logging.info("ThreadPool stopped.")
-
-    def enqueue_funcs(self, funcs, block=True):
-        """run jobs in a fire and forget way, no result will be handled over to
-        clients.
-
-        :param funcs: tuple/list-like or generator like object, func shall be
-                      callable
-        """
-
-        if not self._started:
-            logging.info("ThreadPool has already stopped.")
-            return
-
-        for func in funcs:
-            self._work_queue.put(func, block)
-
-    def apply_async(self, func, args=(), kwargs=None, callback=None):
-        """
-        :param func: callable
-        :param args: free params
-        :param kwargs: named params
-        :callback: when func is done and without exception, call the callback
-        :return AsyncResult, clients can poll or wait the result through it
-        """
-
-        if not self._started:
-            logging.info("ThreadPool has already stopped.")
-            return None
-
-        res = AsyncResult(func, args, kwargs, callback)
-        self._work_queue.put(res)
-        return res
-
-    def apply(self, func, args=(), kwargs=None):
-        """
-        :param func: callable
-        :param args: free params
-        :param kwargs: named params
-        :return whatever the func returns
-        """
-
-        if not self._started:
-            logging.info("ThreadPool has already stopped.")
-            return None
-
-        res = self.apply_async(func, args, kwargs)
-        return res.get()
-
-    def size(self):
-        return self._last_size
-
-    def resize(self, new_size):
-        """Resize the pool size, spawn or destroy threads if necessary."""
-
-        if new_size <= 0:
-            return
-
-        if self._lock.locked() or not self._started:
-            logging.info(
-                "Try to resize thread pool during the tear " "down process, do nothing"
-            )
-            return
-
-        with self._lock:
-            self._remove_exited_threads_with_lock()
-            size = self._last_size
-            self._last_size = new_size
-            if new_size > size:
-                for _ in range(new_size - size):
-                    thr = threading.Thread(target=self._run)
-                    thr.daemon = self._daemon
-                    thr.start()
-                    self._thrs.append(thr)
-            elif new_size < size:
-                for _ in range(size - new_size):
-                    self._work_queue.put(None)
-        logging.info("Finished ThreadPool resizing. New size=%d", new_size)
-
-    def _remove_exited_threads_with_lock(self):
-        """Join the exited threads last time when resize was called."""
-
-        joined_thrs = set()
-        for thr in self._thrs:
-            if not thr.is_alive():
-                try:
-                    if not thr.daemon:
-                        thr.join(timeout=0.5)
-                    joined_thrs.add(thr.ident)
-                except RuntimeError:
-                    pass
-
-        if joined_thrs:
-            live_thrs = []
-            for thr in self._thrs:
-                if thr.ident not in joined_thrs:
-                    live_thrs.append(thr)
-            self._thrs = live_thrs
-
-    def _do_resize_according_to_loads(self):
-        if (
-            self._last_resize_time
-            and time() - self._last_resize_time < self._resize_window
-        ):
-            return
-
-        thr_size = self._last_size
-        free_thrs = thr_size - self._occupied_threads
-        work_size = self._work_queue.qsize()
-
-        logging.debug(
-            "current_thr_size=%s, free_thrs=%s, work_size=%s",
-            thr_size,
-            free_thrs,
-            work_size,
-        )
-        if work_size and work_size > free_thrs:
-            if thr_size < self._max_size:
-                thr_size = min(thr_size * 2, self._max_size)
-                self.resize(thr_size)
-        elif free_thrs > 0:
-            free = free_thrs * 1.0
-            if free / thr_size >= self._high_watermark and free_thrs >= 2:
-                # 20 % thrs are idle, tear down half of the idle ones
-                thr_size = thr_size - int(free_thrs // 2)
-                if thr_size > self._min_size:
-                    self.resize(thr_size)
-        self._last_resize_time = time()
-
-    def _do_admin(self):
-        admin_q = self._admin_queue
-        resize_win = self._resize_window
-        while 1:
-            try:
-                wakup = admin_q.get(timeout=resize_win + 1)
-            except queue.Empty:
-                self._do_resize_according_to_loads()
-                continue
-
-            if wakup is None:
-                break
-            else:
-                self._do_resize_according_to_loads()
-        logging.info(
-            "ThreadPool admin thread=%s stopped.", threading.current_thread().getName()
-        )
-
-    def _run(self):
-        """Threads callback func, run forever to handle jobs from the job
-        queue."""
-
-        work_queue = self._work_queue
-        count_lock = self._count_lock
-        while 1:
-            logging.debug("Going to get job")
-            func = work_queue.get()
-            if func is None:
-                break
-
-            if not self._started:
-                break
-
-            logging.debug("Going to exec job")
-            with count_lock:
-                self._occupied_threads += 1
-
-            try:
-                func()
-            except Exception:
-                logging.error(traceback.format_exc())
-
-            with count_lock:
-                self._occupied_threads -= 1
-
-            logging.debug("Done with exec job")
-            logging.info("Thread work_queue_size=%d", work_queue.qsize())
-
-        logging.debug("Worker thread %s stopped.", threading.current_thread().getName())
-
-
-class AsyncResult:
-    def __init__(self, func, args, kwargs, callback):
-        self._func = func
-        self._args = args
-        self._kwargs = kwargs
-        self._callback = callback
-        self._q = queue.Queue()
-
-    def __call__(self):
-        try:
-            if self._args and self._kwargs:
-                res = self._func(*self._args, **self._kwargs)
-            elif self._args:
-                res = self._func(*self._args)
-            elif self._kwargs:
-                res = self._func(**self._kwargs)
-            else:
-                res = self._func()
-        except Exception as e:
-            self._q.put(e)
-            return
-        else:
-            self._q.put(res)
-
-        if self._callback is not None:
-            self._callback()
-
-    def get(self, timeout=None):
-        """Return the result when it arrives.
-
-        If timeout is not None and the result does not arrive within
-        timeout seconds then multiprocessing.TimeoutError is raised. If
-        the remote call raised an exception then that exception will be
-        reraised by get().
-        """
-
-        try:
-            res = self._q.get(timeout=timeout)
-        except queue.Empty:
-            raise multiprocessing.TimeoutError("Timed out")
-
-        if isinstance(res, Exception):
-            raise res
-        return res
-
-    def wait(self, timeout=None):
-        """Wait until the result is available or until timeout seconds pass."""
-
-        try:
-            res = self._q.get(timeout=timeout)
-        except queue.Empty:
-            pass
-        else:
-            self._q.put(res)
-
-    def ready(self):
-        """Return whether the call has completed."""
-
-        return len(self._q)
-
-    def successful(self):
-        """Return whether the call completed without raising an exception.
-
-        Will raise AssertionError if the result is not ready.
-        """
-
-        if not self.ready():
-            raise AssertionError("Function is not ready")
-        res = self._q.get()
-        self._q.put(res)
-
-        if isinstance(res, Exception):
-            return False
-        return True
diff --git a/apps/bitwarden_event_logs/lib/solnlib/conf_manager.py b/apps/bitwarden_event_logs/lib/solnlib/conf_manager.py
deleted file mode 100755
index 203164b4..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/conf_manager.py
+++ /dev/null
@@ -1,617 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module contains simple interfaces for Splunk config file management,
-you can update/get/delete stanzas and encrypt/decrypt some fields of stanza
-automatically."""
-
-import json
-import logging
-import traceback
-from typing import List, Union, Dict, NoReturn
-
-from splunklib import binding, client
-
-from . import splunk_rest_client as rest_client
-from .credentials import CredentialManager, CredentialNotExistException
-from .utils import retry
-from .net_utils import is_valid_port, is_valid_hostname
-from .soln_exceptions import (
-    ConfManagerException,
-    ConfStanzaNotExistException,
-    InvalidPortError,
-    InvalidHostnameError,
-)
-
-__all__ = [
-    "ConfFile",
-    "ConfManager",
-]
-
-
-class ConfFile:
-    """Configuration file."""
-
-    ENCRYPTED_TOKEN = "******"
-
-    reserved_keys = ("userName", "appName")
-
-    def __init__(
-        self,
-        name: str,
-        conf: client.ConfigurationFile,
-        session_key: str,
-        app: str,
-        owner: str = "nobody",
-        scheme: str = None,
-        host: str = None,
-        port: int = None,
-        realm: str = None,
-        **context: dict,
-    ):
-        """Initializes ConfFile.
-
-        Arguments:
-            name: Configuration file name.
-            conf: Configuration file object.
-            session_key: Splunk access token.
-            app: App name of namespace.
-            owner: (optional) Owner of namespace, default is `nobody`.
-            scheme: (optional) The access scheme, default is None.
-            host: (optional) The host name, default is None.
-            port: (optional) The port number, default is None.
-            realm: (optional) Realm of credential, default is None.
-            context: Other configurations for Splunk rest client.
-        """
-        self._name = name
-        self._conf = conf
-        self._session_key = session_key
-        self._app = app
-        self._owner = owner
-        self._scheme = scheme
-        self._host = host
-        self._port = port
-        self._context = context
-        self._cred_manager = None
-        # 'realm' is set to provided 'realm' argument otherwise as default
-        # behaviour it is set to 'APP_NAME'.
-        if realm is None:
-            self._realm = self._app
-        else:
-            self._realm = realm
-
-    @property
-    @retry(exceptions=[binding.HTTPError])
-    def _cred_mgr(self):
-        if self._cred_manager is None:
-            self._cred_manager = CredentialManager(
-                self._session_key,
-                self._app,
-                owner=self._owner,
-                realm=self._realm,
-                scheme=self._scheme,
-                host=self._host,
-                port=self._port,
-                **self._context,
-            )
-
-        return self._cred_manager
-
-    def _filter_stanza(self, stanza):
-        for k in self.reserved_keys:
-            if k in stanza:
-                del stanza[k]
-
-        return stanza
-
-    def _encrypt_stanza(self, stanza_name, stanza, encrypt_keys):
-        if not encrypt_keys:
-            return stanza
-
-        encrypt_stanza_keys = [k for k in encrypt_keys if k in stanza]
-        encrypt_fields = {key: stanza[key] for key in encrypt_stanza_keys}
-        if not encrypt_fields:
-            return stanza
-        self._cred_mgr.set_password(stanza_name, json.dumps(encrypt_fields))
-
-        for key in encrypt_stanza_keys:
-            stanza[key] = self.ENCRYPTED_TOKEN
-
-        return stanza
-
-    def _decrypt_stanza(self, stanza_name, encrypted_stanza):
-        encrypted_keys = [
-            key
-            for key in encrypted_stanza
-            if encrypted_stanza[key] == self.ENCRYPTED_TOKEN
-        ]
-        if encrypted_keys:
-            encrypted_fields = json.loads(self._cred_mgr.get_password(stanza_name))
-            for key in encrypted_keys:
-                encrypted_stanza[key] = encrypted_fields[key]
-
-        return encrypted_stanza
-
-    def _delete_stanza_creds(self, stanza_name):
-        self._cred_mgr.delete_password(stanza_name)
-
-    @retry(exceptions=[binding.HTTPError])
-    def stanza_exist(self, stanza_name: str) -> bool:
-        """Check whether stanza exists.
-
-        Arguments:
-            stanza_name: Stanza name.
-
-        Returns:
-            True if stanza exists else False.
-
-        Examples:
-           >>> from solnlib import conf_manager
-           >>> cfm = conf_manager.ConfManager(session_key,
-                                              'Splunk_TA_test')
-           >>> conf = cfm.get_conf('test')
-           >>> conf.stanza_exist('test_stanza')
-        """
-
-        try:
-            self._conf.list(name=stanza_name)[0]
-        except binding.HTTPError as e:
-            if e.status != 404:
-                raise
-
-            return False
-
-        return True
-
-    @retry(exceptions=[binding.HTTPError])
-    def get(self, stanza_name: str, only_current_app: bool = False) -> dict:
-        """Get stanza from configuration file.
-
-        Result is like:
-
-            {
-                'disabled': '0',
-                'eai:appName': 'solnlib_demo',
-                'eai:userName': 'nobody',
-                'k1': '1',
-                'k2': '2'
-            }
-
-        Arguments:
-            stanza_name: Stanza name.
-            only_current_app: Only include current app.
-
-        Returns:
-            Stanza.
-
-        Raises:
-            ConfStanzaNotExistException: If stanza does not exist.
-
-        Examples:
-           >>> from solnlib import conf_manager
-           >>> cfm = conf_manager.ConfManager(session_key,
-                                              'Splunk_TA_test')
-           >>> conf = cfm.get_conf('test')
-           >>> conf.get('test_stanza')
-        """
-
-        try:
-            if only_current_app:
-                stanza_mgrs = self._conf.list(
-                    search="eai:acl.app={} name={}".format(
-                        self._app, stanza_name.replace("=", r"\=")
-                    )
-                )
-            else:
-                stanza_mgrs = self._conf.list(name=stanza_name)
-        except binding.HTTPError as e:
-            if e.status != 404:
-                raise
-
-            raise ConfStanzaNotExistException(
-                f"Stanza: {stanza_name} does not exist in {self._name}.conf"
-            )
-
-        if len(stanza_mgrs) == 0:
-            raise ConfStanzaNotExistException(
-                f"Stanza: {stanza_name} does not exist in {self._name}.conf"
-            )
-
-        stanza = self._decrypt_stanza(stanza_mgrs[0].name, stanza_mgrs[0].content)
-        stanza["eai:access"] = stanza_mgrs[0].access
-        stanza["eai:appName"] = stanza_mgrs[0].access.app
-        return stanza
-
-    @retry(exceptions=[binding.HTTPError])
-    def get_all(self, only_current_app: bool = False) -> dict:
-        """Get all stanzas from configuration file.
-
-        Result is like:
-
-            {
-                'test':
-                    {
-                        'disabled': '0',
-                        'eai:appName': 'solnlib_demo',
-                        'eai:userName': 'nobody',
-                        'k1': '1',
-                        'k2': '2'
-                    }
-            }
-
-        Arguments:
-            only_current_app: Only include current app.
-
-        Returns:
-            Dict of stanzas.
-
-        Examples:
-           >>> from solnlib import conf_manager
-           >>> cfm = conf_manager.ConfManager(session_key,
-                                              'Splunk_TA_test')
-           >>> conf = cfm.get_conf('test')
-           >>> conf.get_all()
-        """
-
-        if only_current_app:
-            stanza_mgrs = self._conf.list(search=f"eai:acl.app={self._app}")
-        else:
-            stanza_mgrs = self._conf.list()
-        res = {}
-        for stanza_mgr in stanza_mgrs:
-            name = stanza_mgr.name
-            key_values = self._decrypt_stanza(name, stanza_mgr.content)
-            key_values["eai:access"] = stanza_mgr.access
-            key_values["eai:appName"] = stanza_mgr.access.app
-            res[name] = key_values
-        return res
-
-    @retry(exceptions=[binding.HTTPError])
-    def update(self, stanza_name: str, stanza: dict, encrypt_keys: List[str] = None):
-        """Update stanza.
-
-        It will try to encrypt the credential automatically fist if
-        encrypt_keys are not None else keep stanza untouched.
-
-        Arguments:
-            stanza_name: Stanza name.
-            stanza: Stanza to update.
-            encrypt_keys: Field names to encrypt.
-
-        Examples:
-           >>> from solnlib import conf_manager
-           >>> cfm = conf_manager.ConfManager(session_key,
-                                              'Splunk_TA_test')
-           >>> conf = cfm.get_conf('test')
-           >>> conf.update('test_stanza', {'k1': 1, 'k2': 2}, ['k1'])
-        """
-
-        stanza = self._filter_stanza(stanza)
-        encrypted_stanza = self._encrypt_stanza(stanza_name, stanza, encrypt_keys)
-
-        try:
-            stanza_mgr = self._conf.list(name=stanza_name)[0]
-        except binding.HTTPError as e:
-            if e.status != 404:
-                raise
-
-            stanza_mgr = self._conf.create(stanza_name)
-
-        stanza_mgr.submit(encrypted_stanza)
-
-    @retry(exceptions=[binding.HTTPError])
-    def delete(self, stanza_name: str):
-        """Delete stanza.
-
-        Arguments:
-            stanza_name: Stanza name to delete.
-
-        Raises:
-            ConfStanzaNotExistException: If stanza does not exist.
-
-        Examples:
-           >>> from solnlib import conf_manager
-           >>> cfm = conf_manager.ConfManager(session_key,
-                                              'Splunk_TA_test')
-           >>> conf = cfm.get_conf('test')
-           >>> conf.delete('test_stanza')
-        """
-
-        try:
-            self._cred_mgr.delete_password(stanza_name)
-        except CredentialNotExistException:
-            pass
-
-        try:
-            self._conf.delete(stanza_name)
-        except KeyError:
-            logging.error(
-                "Delete stanza: %s error: %s.", stanza_name, traceback.format_exc()
-            )
-            raise ConfStanzaNotExistException(
-                f"Stanza: {stanza_name} does not exist in {self._name}.conf"
-            )
-
-    @retry(exceptions=[binding.HTTPError])
-    def reload(self):
-        """Reload configuration file.
-
-        Examples:
-           >>> from solnlib import conf_manager
-           >>> cfm = conf_manager.ConfManager(session_key,
-                                              'Splunk_TA_test')
-           >>> conf = cfm.get_conf('test')
-           >>> conf.reload()
-        """
-
-        self._conf.get("_reload")
-
-
-class ConfManager:
-    """Configuration file manager.
-
-    Examples:
-
-        >>> from solnlib import conf_manager
-        >>> cfm = conf_manager.ConfManager(session_key,
-                                          'Splunk_TA_test')
-
-    Examples:
-        If stanza in passwords.conf is formatted as below:
-
-        `credential:__REST_CREDENTIAL__#Splunk_TA_test#configs/conf-CONF_FILENAME:STANZA_NAME``splunk_cred_sep``1:`
-
-        >>> from solnlib import conf_manager
-        >>> cfm = conf_manager.ConfManager(
-                session_key,
-                'Splunk_TA_test',
-                realm='__REST_CREDENTIAL__#Splunk_TA_test#configs/conf-CONF_FILENAME'
-            )
-    """
-
-    def __init__(
-        self,
-        session_key: str,
-        app: str,
-        owner: str = "nobody",
-        scheme: str = None,
-        host: str = None,
-        port: int = None,
-        realm: str = None,
-        **context: dict,
-    ):
-        """Initializes ConfManager.
-
-        Arguments:
-            session_key: Splunk access token.
-            app: App name of namespace.
-            owner: (optional) Owner of namespace, default is `nobody`.
-            scheme: (optional) The access scheme, default is None.
-            host: (optional) The host name, default is None.
-            port: (optional) The port number, default is None.
-            realm: (optional) Realm of credential, default is None.
-            context: Other configurations for Splunk rest client.
-        """
-        self._session_key = session_key
-        self._app = app
-        self._owner = owner
-        self._scheme = scheme
-        self._host = host
-        self._port = port
-        self._context = context
-        self._rest_client = rest_client.SplunkRestClient(
-            self._session_key,
-            self._app,
-            owner=self._owner,
-            scheme=self._scheme,
-            host=self._host,
-            port=self._port,
-            **self._context,
-        )
-        self._confs = None
-        self._realm = realm
-
-    @retry(exceptions=[binding.HTTPError])
-    def get_conf(self, name: str, refresh: bool = False) -> ConfFile:
-        """Get conf file.
-
-        Arguments:
-            name: Conf file name.
-            refresh: (optional) Flag to refresh conf file list, default is False.
-
-        Returns:
-            Conf file object.
-
-        Raises:
-            ConfManagerException: If `conf_file` does not exist.
-        """
-
-        if self._confs is None or refresh:
-            # Fix bug that can't pass `-` as app name.
-            curr_app = self._rest_client.namespace.app
-            self._rest_client.namespace.app = "dummy"
-            self._confs = self._rest_client.confs
-            self._rest_client.namespace.app = curr_app
-
-        try:
-            conf = self._confs[name]
-        except KeyError:
-            raise ConfManagerException(f"Config file: {name} does not exist.")
-
-        return ConfFile(
-            name,
-            conf,
-            self._session_key,
-            self._app,
-            self._owner,
-            self._scheme,
-            self._host,
-            self._port,
-            self._realm,
-            **self._context,
-        )
-
-    @retry(exceptions=[binding.HTTPError])
-    def create_conf(self, name: str) -> ConfFile:
-        """Create conf file.
-
-        Arguments:
-            name: Conf file name.
-
-        Returns:
-            Conf file object.
-        """
-
-        if self._confs is None:
-            self._confs = self._rest_client.confs
-
-        conf = self._confs.create(name)
-        return ConfFile(
-            name,
-            conf,
-            self._session_key,
-            self._app,
-            self._owner,
-            self._scheme,
-            self._host,
-            self._port,
-            self._realm,
-            **self._context,
-        )
-
-
-def get_log_level(
-    *,
-    logger: logging.Logger,
-    session_key: str,
-    app_name: str,
-    conf_name: str,
-    log_stanza: str = "logging",
-    log_level_field: str = "loglevel",
-    default_log_level: str = "INFO",
-) -> str:
-    """This function returns the log level for the addon from configuration
-    file.
-
-    Arguments:
-        logger: Logger.
-        session_key: Splunk access token.
-        app_name: Add-on name.
-        conf_name: Configuration file name where logging stanza is.
-        log_stanza: Logging stanza to define `log_level_field` and its value.
-        log_level_field: Logging level field name under logging stanza.
-        default_log_level: Default log level to return in case of errors.
-
-    Returns:
-        Log level defined under `logging.log_level_field` field in `conf_name`
-        file. In case of any error, `default_log_level` will be returned.
-
-    Examples:
-        >>> from solnlib import conf_manager
-        >>> log_level = conf_manager.get_log_level(
-        >>>     logger,
-        >>>     "session_key",
-        >>>     "ADDON_NAME",
-        >>>     "splunk_ta_addon_settings",
-        >>> )
-    """
-    try:
-        cfm = ConfManager(
-            session_key,
-            app_name,
-            realm=f"__REST_CREDENTIAL__#{app_name}#configs/conf-{conf_name}",
-        )
-        conf = cfm.get_conf(conf_name)
-    except ConfManagerException:
-        logger.error(
-            f"Failed to fetch configuration file {conf_name}, "
-            f"taking {default_log_level} as log level."
-        )
-        return default_log_level
-    try:
-        logging_details = conf.get(log_stanza)
-        return logging_details.get(log_level_field, default_log_level)
-    except ConfStanzaNotExistException:
-        logger.error(
-            f'"logging" stanza does not exist under {conf_name}, '
-            f"taking {default_log_level} as log level."
-        )
-        return default_log_level
-
-
-def get_proxy_dict(
-    logger: logging.Logger,
-    session_key: str,
-    app_name: str,
-    conf_name: str,
-    proxy_stanza: str = "proxy",
-    **kwargs,
-) -> Union[Dict[str, str], NoReturn]:
-    """This function returns the proxy settings for the addon from
-    configuration file.
-
-    Arguments:
-        logger: Logger.
-        session_key: Splunk access token.
-        app_name: Add-on name.
-        conf_name: Configuration file name where logging stanza is.
-        proxy_stanza: Proxy stanza that would contain the Proxy details
-    Returns:
-        A dictionary is returned with stanza details present in the file.
-        The keys related to `eai` are removed before returning.
-
-    Examples:
-        >>> from solnlib import conf_manager
-        >>> proxy_details = conf_manager.get_proxy_dict(
-        >>>     logger,
-        >>>     "session_key",
-        >>>     "ADDON_NAME",
-        >>>     "splunk_ta_addon_settings",
-        >>> )
-    """
-    proxy_dict = {}
-    try:
-        cfm = ConfManager(
-            session_key,
-            app_name,
-            realm=f"__REST_CREDENTIAL__#{app_name}#configs/conf-{conf_name}",
-        )
-        conf = cfm.get_conf(conf_name)
-    except Exception:
-        raise ConfManagerException(f"Failed to fetch configuration file '{conf_name}'.")
-    else:
-        try:
-            proxy_dict = conf.get(proxy_stanza)
-        except Exception:
-            raise ConfStanzaNotExistException(
-                f"Failed to fetch '{proxy_stanza}' from the configuration file '{conf_name}'. "
-            )
-        else:
-            # remove the other fields that are added by ConfFile class
-            proxy_dict.pop("disabled", None)
-            proxy_dict.pop("eai:access", None)
-            proxy_dict.pop("eai:appName", None)
-            proxy_dict.pop("eai:userName", None)
-
-            if "proxy_port" in kwargs:
-                if not is_valid_port(proxy_dict.get(kwargs["proxy_port"])):
-                    logger.error("Invalid proxy port provided.")
-                    raise InvalidPortError("The provided port is not valid.")
-            if "proxy_host" in kwargs:
-                if not is_valid_hostname(proxy_dict.get(kwargs["proxy_host"])):
-                    logger.error("Invalid proxy host provided.")
-                    raise InvalidHostnameError("The provided hostname is not valid.")
-    return proxy_dict
diff --git a/apps/bitwarden_event_logs/lib/solnlib/credentials.py b/apps/bitwarden_event_logs/lib/solnlib/credentials.py
deleted file mode 100755
index 29ee1ff6..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/credentials.py
+++ /dev/null
@@ -1,337 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module contains Splunk credential related interfaces."""
-
-import re
-import warnings
-from typing import Dict, List
-
-from splunklib import binding, client
-
-from . import splunk_rest_client as rest_client
-from .utils import retry
-
-__all__ = [
-    "CredentialException",
-    "CredentialNotExistException",
-    "CredentialManager",
-]
-
-
-class CredentialException(Exception):
-    """General exception regarding credentials."""
-
-    pass
-
-
-class CredentialNotExistException(Exception):
-    """Exception is raised when credentials do not exist."""
-
-    pass
-
-
-class CredentialManager:
-    """Credential manager.
-
-    Examples:
-       >>> from solnlib import credentials
-       >>> cm = credentials.CredentialManager(session_key,
-                                              'Splunk_TA_test',
-                                              realm='realm_test')
-    """
-
-    # Splunk can only encrypt string with length <=255
-    SPLUNK_CRED_LEN_LIMIT = 255
-
-    # Splunk credential separator
-    SEP = "``splunk_cred_sep``"
-
-    # Splunk credential end mark
-    END_MARK = (
-        "``splunk_cred_sep``S``splunk_cred_sep``P``splunk_cred_sep``L``splunk_cred_sep``"
-        "U``splunk_cred_sep``N``splunk_cred_sep``K``splunk_cred_sep``"
-    )
-
-    def __init__(
-        self,
-        session_key: str,
-        app: str,
-        owner: str = "nobody",
-        realm: str = None,
-        scheme: str = None,
-        host: str = None,
-        port: int = None,
-        **context: dict,
-    ):
-        """Initializes CredentialManager.
-
-        Arguments:
-            session_key: Splunk access token.
-            app: App name of namespace.
-            owner: (optional) Owner of namespace, default is `nobody`.
-            realm: (optional) Realm of credential, default is None.
-            scheme: (optional) The access scheme, default is None.
-            host: (optional) The host name, default is None.
-            port: (optional) The port number, default is None.
-            context: Other configurations for Splunk rest client.
-        """
-        self._realm = realm
-        self.service = rest_client.SplunkRestClient(
-            session_key,
-            app,
-            owner=owner,
-            scheme=scheme,
-            host=host,
-            port=port,
-            **context,
-        )
-        self._storage_passwords = self.service.storage_passwords
-
-    @retry(exceptions=[binding.HTTPError])
-    def get_password(self, user: str) -> str:
-        """Get password.
-
-        Arguments:
-            user: User name.
-
-        Returns:
-            Clear user password.
-
-        Raises:
-            CredentialNotExistException: If password for 'realm:user' doesn't exist.
-
-        Examples:
-           >>> from solnlib import credentials
-           >>> cm = credentials.CredentialManager(session_key,
-                                                  'Splunk_TA_test',
-                                                  realm='realm_test')
-           >>> cm.get_password('testuser2')
-        """
-        if self._realm is not None:
-            passwords = self.get_clear_passwords_in_realm()
-        else:
-            passwords = self.get_clear_passwords()
-        for password in passwords:
-            if password["username"] == user and password["realm"] == self._realm:
-                return password["clear_password"]
-
-        raise CredentialNotExistException(
-            f"Failed to get password of realm={self._realm}, user={user}."
-        )
-
-    @retry(exceptions=[binding.HTTPError])
-    def set_password(self, user: str, password: str):
-        """Set password.
-
-        Arguments:
-            user: User name.
-            password: User password.
-
-        Examples:
-           >>> from solnlib import credentials
-           >>> cm = credentials.CredentialManager(session_key,
-                                                  'Splunk_TA_test',
-                                                  realm='realm_test')
-           >>> cm.set_password('testuser1', 'password1')
-        """
-        length = 0
-        index = 1
-        while length < len(password):
-            curr_str = password[
-                length : length + self.SPLUNK_CRED_LEN_LIMIT  # noqa: E203
-            ]
-            partial_user = self.SEP.join([user, str(index)])
-            self._update_password(partial_user, curr_str)
-            length += self.SPLUNK_CRED_LEN_LIMIT
-            index += 1
-
-        # Append another stanza to mark the end of the password
-        partial_user = self.SEP.join([user, str(index)])
-        self._update_password(partial_user, self.END_MARK)
-
-    @retry(exceptions=[binding.HTTPError])
-    def _update_password(self, user: str, password: str):
-        """Update password.
-
-        Arguments:
-            user: User name.
-            password: User password.
-
-        Examples:
-           >>> from solnlib import credentials
-           >>> cm = credentials.CredentialManager(session_key,
-                                                  'Splunk_TA_test',
-                                                  realm='realm_test')
-           >>> cm._update_password('testuser1', 'password1')
-        """
-        try:
-            self._storage_passwords.create(password, user, self._realm)
-        except binding.HTTPError as ex:
-            if ex.status == 409:
-                if self._realm is not None:
-                    passwords = self.get_raw_passwords_in_realm()
-                else:
-                    passwords = self.get_raw_passwords()
-                for pwd_stanza in passwords:
-                    if pwd_stanza.realm == self._realm and pwd_stanza.username == user:
-                        pwd_stanza.update(password=password)
-                        return
-                raise ValueError(
-                    f"Can not get the password object for realm: {self._realm} user: {user}"
-                )
-            else:
-                raise ex
-
-    @retry(exceptions=[binding.HTTPError])
-    def delete_password(self, user: str):
-        """Delete password.
-
-        Arguments:
-            user: User name.
-
-        Raises:
-             CredentialNotExistException: If password of realm:user doesn't exist.
-
-        Examples:
-           >>> from solnlib import credentials
-           >>> cm = credentials.CredentialManager(session_key,
-                                                  'Splunk_TA_test',
-                                                  realm='realm_test')
-           >>> cm.delete_password('testuser1')
-        """
-        if self._realm is not None:
-            passwords = self.get_raw_passwords_in_realm()
-        else:
-            passwords = self.get_raw_passwords()
-        deleted = False
-        ent_pattern = re.compile(
-            r"({}{}\d+)".format(user.replace("\\", "\\\\"), self.SEP)
-        )
-        for password in passwords:
-            match = (user == password.username) or ent_pattern.match(password.username)
-            if match and password.realm == self._realm:
-                password.delete()
-                deleted = True
-
-        if not deleted:
-            raise CredentialNotExistException(
-                f"Failed to delete password of realm={self._realm}, user={user}"
-            )
-
-    def get_raw_passwords(self) -> List[client.StoragePassword]:
-        """Returns all passwords in the "raw" format."""
-        warnings.warn(
-            "Please pass realm to the CredentialManager, "
-            "so it can utilize get_raw_passwords_in_realm method instead."
-        )
-        return self._storage_passwords.list(count=-1)
-
-    def get_raw_passwords_in_realm(self) -> List[client.StoragePassword]:
-        """Returns all passwords within the realm in the "raw" format."""
-        if self._realm is None:
-            raise ValueError("No realm was specified")
-        return self._storage_passwords.list(count=-1, search=f"realm={self._realm}")
-
-    def get_clear_passwords(self) -> List[Dict[str, str]]:
-        """Returns all passwords in the "clear" format."""
-        warnings.warn(
-            "Please pass realm to the CredentialManager, "
-            "so it can utilize get_clear_passwords_in_realm method instead."
-        )
-        raw_passwords = self.get_raw_passwords()
-        return self._get_clear_passwords(raw_passwords)
-
-    def get_clear_passwords_in_realm(self) -> List[Dict[str, str]]:
-        """Returns all passwords within the realm in the "clear" format."""
-        if self._realm is None:
-            raise ValueError("No realm was specified")
-        raw_passwords = self.get_raw_passwords_in_realm()
-        return self._get_clear_passwords(raw_passwords)
-
-    def _get_all_passwords_in_realm(self) -> List[client.StoragePassword]:
-        warnings.warn(
-            "_get_all_passwords_in_realm is deprecated, "
-            "please use get_raw_passwords_in_realm instead.",
-            stacklevel=2,
-        )
-        if self._realm:
-            all_passwords = self._storage_passwords.list(
-                count=-1, search=f"realm={self._realm}"
-            )
-        else:
-            all_passwords = self._storage_passwords.list(count=-1, search="")
-        return all_passwords
-
-    def _get_clear_passwords(
-        self, passwords: List[client.StoragePassword]
-    ) -> List[Dict[str, str]]:
-        results = {}
-        ptn = re.compile(rf"(.+){self.SEP}(\d+)")
-        for password in passwords:
-            match = ptn.match(password.name)
-            if match:
-                actual_name = match.group(1) + ":"
-                index = int(match.group(2))
-                if actual_name in results:
-                    exist_stanza = results[actual_name]
-                else:
-                    exist_stanza = {}
-                    exist_stanza["name"] = actual_name
-                    exist_stanza["realm"] = password.realm
-                    exist_stanza["username"] = password.username.split(self.SEP)[0]
-                    exist_stanza["clears"] = {}
-                    results[actual_name] = exist_stanza
-
-                exist_stanza["clears"][index] = password.clear_password
-
-        # Backward compatibility
-        # To deal with the password with only one stanza which is generated by the old version.
-        for password in passwords:
-            match = ptn.match(password.name)
-            if (not match) and (password.name not in results):
-                results[password.name] = {
-                    "name": password.name,
-                    "realm": password.realm,
-                    "username": password.username,
-                    "clear_password": password.clear_password,
-                }
-
-        # Merge password by index
-        for name, values in list(results.items()):
-            field_clear = values.get("clears")
-            if field_clear:
-                clear_password = ""
-                for index in sorted(field_clear.keys()):
-                    if field_clear[index] != self.END_MARK:
-                        clear_password += field_clear[index]
-                    else:
-                        break
-                values["clear_password"] = clear_password
-
-                del values["clears"]
-
-        return list(results.values())
-
-    @retry(exceptions=[binding.HTTPError])
-    def _get_all_passwords(self) -> List[Dict[str, str]]:
-        warnings.warn(
-            "_get_all_passwords is deprecated, "
-            "please use get_all_passwords_in_realm instead.",
-            stacklevel=2,
-        )
-        passwords = self._storage_passwords.list(count=-1)
-        return self._get_clear_passwords(passwords)
diff --git a/apps/bitwarden_event_logs/lib/solnlib/file_monitor.py b/apps/bitwarden_event_logs/lib/solnlib/file_monitor.py
deleted file mode 100755
index 971d1024..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/file_monitor.py
+++ /dev/null
@@ -1,133 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module contains file monitoring class that can be used to check files
-change periodically and call callback function to handle properly when
-detecting files change."""
-import logging
-import os.path as op
-import threading
-import time
-import traceback
-from typing import Any, Callable, List
-
-__all__ = ["FileChangesChecker", "FileMonitor"]
-
-
-class FileChangesChecker:
-    """Files change checker."""
-
-    def __init__(self, callback: Callable[[List[str]], Any], files: List):
-        """Initializes FileChangesChecker.
-
-        Arguments:
-            callback: Callback function for files change.
-            files: Files to be monitored with full path.
-        """
-        self._callback = callback
-        self._files = files
-
-        self.file_mtimes = {file_name: None for file_name in self._files}
-        for k in self.file_mtimes:
-            try:
-                self.file_mtimes[k] = op.getmtime(k)
-            except OSError:
-                logging.debug(f"Getmtime for {k}, failed: {traceback.format_exc()}")
-
-    def check_changes(self) -> bool:
-        """Check files change.
-
-        If some files are changed and callback function is not None, call
-        callback function to handle files change.
-
-        Returns:
-            True if files changed else False
-        """
-        logging.debug(f"Checking files={self._files}")
-        file_mtimes = self.file_mtimes
-        changed_files = []
-        for f, last_mtime in list(file_mtimes.items()):
-            try:
-                current_mtime = op.getmtime(f)
-                if current_mtime != last_mtime:
-                    file_mtimes[f] = current_mtime
-                    changed_files.append(f)
-                    logging.info(f"Detect {f} has changed", f)
-            except OSError:
-                pass
-        if changed_files:
-            if self._callback:
-                self._callback(changed_files)
-            return True
-        return False
-
-
-class FileMonitor:
-    """Files change monitor.
-
-    Monitor files change in a separated thread and call callback
-    when there is files change.
-
-    Examples:
-      >>> import solnlib.file_monitor as fm
-      >>> fm = fm.FileMonitor(fm_callback, files_list, 5)
-      >>> fm.start()
-    """
-
-    def __init__(
-        self, callback: Callable[[List[str]], Any], files: List, interval: int = 1
-    ):
-        """Initializes FileMonitor.
-
-        Arguments:
-            callback: Callback for handling files change.
-            files: Files to monitor.
-            interval: Interval to check files change.
-        """
-        self._checker = FileChangesChecker(callback, files)
-        self._thr = threading.Thread(target=self._do_monitor)
-        self._thr.daemon = True
-        self._interval = interval
-        self._started = False
-
-    def start(self):
-        """Start file monitor.
-
-        Start a background thread to monitor files change.
-        """
-
-        if self._started:
-            return
-        self._started = True
-
-        self._thr.start()
-
-    def stop(self):
-        """Stop file monitor.
-
-        Stop the background thread to monitor files change.
-        """
-
-        self._started = False
-
-    def _do_monitor(self):
-        while self._started:
-            self._checker.check_changes()
-
-            for _ in range(self._interval):
-                if not self._started:
-                    break
-                time.sleep(1)
diff --git a/apps/bitwarden_event_logs/lib/solnlib/hec_config.py b/apps/bitwarden_event_logs/lib/solnlib/hec_config.py
deleted file mode 100755
index d5c7cd24..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/hec_config.py
+++ /dev/null
@@ -1,182 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-from splunklib import binding
-
-from . import splunk_rest_client as rest_client
-from .utils import retry
-
-__all__ = ["HECConfig"]
-
-
-class HECConfig:
-    """HTTP Event Collector configuration."""
-
-    input_type = "http"
-
-    def __init__(
-        self,
-        session_key: str,
-        scheme: str = None,
-        host: str = None,
-        port: int = None,
-        **context: dict
-    ):
-        """Initializes HECConfig.
-
-        Arguments:
-            session_key: Splunk access token.
-            scheme: (optional) The access scheme, default is None.
-            host: (optional) The host name, default is None.
-            port: (optional) The port number, default is None.
-            context: Other configurations for Splunk rest client.
-        """
-        self._rest_client = rest_client.SplunkRestClient(
-            session_key,
-            "splunk_httpinput",
-            scheme=scheme,
-            host=host,
-            port=port,
-            **context
-        )
-
-    @retry(exceptions=[binding.HTTPError])
-    def get_settings(self) -> dict:
-        """Get http data input global settings.
-
-        Returns:
-            HTTP global settings, for example:
-
-                {
-                    'enableSSL': 1,
-                    'disabled': 0,
-                    'useDeploymentServer': 0,
-                    'port': 8088
-                }
-        """
-
-        return self._do_get_input(self.input_type).content
-
-    @retry(exceptions=[binding.HTTPError])
-    def update_settings(self, settings: dict):
-        """Update http data input global settings.
-
-        Arguments:
-            settings: HTTP global settings.
-        """
-
-        res = self._do_get_input(self.input_type)
-        res.update(**settings)
-
-    @retry(exceptions=[binding.HTTPError])
-    def create_input(self, name: str, stanza: dict) -> dict:
-        """Create http data input.
-
-        Arguments:
-            name: HTTP data input name.
-            stanza: Data input stanza content.
-
-        Returns:
-            Created input.
-
-        Examples:
-           >>> from solnlib.hec_config import HECConfig
-           >>> hec = HECConfig(session_key)
-           >>> hec.create_input('my_hec_data_input',
-                                {'index': 'main', 'sourcetype': 'hec'})
-        """
-
-        res = self._rest_client.inputs.create(name, self.input_type, **stanza)
-        return res.content
-
-    @retry(exceptions=[binding.HTTPError])
-    def update_input(self, name: str, stanza: dict):
-        """Update http data input.
-
-        It will create if the data input doesn't exist.
-
-        Arguments:
-            name: HTTP data input name.
-            stanza: Data input stanza.
-
-        Examples:
-           >>> from solnlib import HEConfig
-           >>> hec = HECConfig(session_key)
-           >>> hec.update_input('my_hec_data_input',
-                                {'index': 'main', 'sourcetype': 'hec2'})
-        """
-
-        res = self._do_get_input(name)
-        if res is None:
-            return self.create_input(name, stanza)
-        res.update(**stanza)
-
-    @retry(exceptions=[binding.HTTPError])
-    def delete_input(self, name: str):
-        """Delete http data input.
-
-        Arguments:
-            name: HTTP data input name.
-        """
-
-        try:
-            self._rest_client.inputs.delete(name, self.input_type)
-        except KeyError:
-            pass
-
-    @retry(exceptions=[binding.HTTPError])
-    def get_input(self, name: str) -> dict:
-        """Get http data input.
-
-        Arguments:
-            name: HTTP event collector data input name.
-
-        Returns:
-            HTTP event collector data input config dict.
-        """
-
-        res = self._do_get_input(name)
-        if res:
-            return res.content
-        else:
-            return None
-
-    def _do_get_input(self, name):
-        try:
-            return self._rest_client.inputs[(name, self.input_type)]
-        except KeyError:
-            return None
-
-    @retry(exceptions=[binding.HTTPError])
-    def get_limits(self) -> dict:
-        """Get HTTP input limits.
-
-        Returns:
-            HTTP input limits.
-        """
-
-        return self._rest_client.confs["limits"]["http_input"].content
-
-    @retry(exceptions=[binding.HTTPError])
-    def set_limits(self, limits: dict):
-        """Set HTTP input limits.
-
-        Arguments:
-            limits: HTTP input limits.
-        """
-
-        res = self._rest_client.confs["limits"]["http_input"]
-        res.submit(limits)
diff --git a/apps/bitwarden_event_logs/lib/solnlib/log.py b/apps/bitwarden_event_logs/lib/solnlib/log.py
deleted file mode 100755
index e1c0511c..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/log.py
+++ /dev/null
@@ -1,373 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module provides log functionalities."""
-
-import logging
-import logging.handlers
-import os.path as op
-import traceback
-from functools import partial
-from threading import Lock
-from typing import Dict, Any
-
-from .pattern import Singleton
-from .splunkenv import make_splunkhome_path
-
-__all__ = ["log_enter_exit", "LogException", "Logs"]
-
-
-def log_enter_exit(logger: logging.Logger):
-    """Decorator for logger to log function enter and exit.
-
-    This decorator will generate a lot of debug log, please add this
-    only when it is required.
-
-    Arguments:
-        logger: Logger to decorate.
-
-    Examples:
-        >>> @log_enter_exit
-        >>> def myfunc():
-        >>>     doSomething()
-    """
-
-    def log_decorator(func):
-        def wrapper(*args, **kwargs):
-            logger.debug("%s entered", func.__name__)
-            result = func(*args, **kwargs)
-            logger.debug("%s exited", func.__name__)
-            return result
-
-        return wrapper
-
-    return log_decorator
-
-
-class LogException(Exception):
-    """Exception raised by Logs class."""
-
-    pass
-
-
-class Logs(metaclass=Singleton):
-    """A singleton class that manage all kinds of logger.
-
-    Examples:
-      >>> from solnlib import log
-      >>> log.Logs.set_context(directory='/var/log/test',
-                               namespace='test')
-      >>> logger = log.Logs().get_logger('mymodule')
-      >>> logger.set_level(logging.DEBUG)
-      >>> logger.debug('a debug log')
-    """
-
-    # Normal logger settings
-    _default_directory = None
-    _default_namespace = None
-    _default_log_format = (
-        "%(asctime)s log_level=%(levelname)s pid=%(process)d tid=%(threadName)s "
-        "file=%(filename)s:%(funcName)s:%(lineno)d | %(message)s"
-    )
-    _default_log_level = logging.INFO
-    _default_max_bytes = 25000000
-    _default_backup_count = 5
-
-    # Default root logger settings
-    _default_root_logger_log_file = "solnlib"
-
-    @classmethod
-    def set_context(cls, **context: dict):
-        """Set log context.
-
-        List of keyword arguments:
-
-            directory: Log directory, default is splunk log root directory.
-            namespace: Logger namespace, default is None.
-            log_format: Log format, default is `_default_log_format`.
-            log_level: Log level, default is logging.INFO.
-            max_bytes: The maximum log file size before rollover, default is 25000000.
-            backup_count: The number of log files to retain,default is 5.
-            root_logger_log_file: Root logger log file name, default is 'solnlib'   .
-
-        Arguments:
-            context: Keyword arguments. See list of arguments above.
-        """
-        if "directory" in context:
-            cls._default_directory = context["directory"]
-        if "namespace" in context:
-            cls._default_namespace = context["namespace"]
-        if "log_format" in context:
-            cls._default_log_format = context["log_format"]
-        if "log_level" in context:
-            cls._default_log_level = context["log_level"]
-        if "max_bytes" in context:
-            cls._default_max_bytes = context["max_bytes"]
-        if "backup_count" in context:
-            cls._default_backup_count = context["backup_count"]
-        if "root_logger_log_file" in context:
-            cls._default_root_logger_log_file = context["root_logger_log_file"]
-            cls._reset_root_logger()
-
-    @classmethod
-    def _reset_root_logger(cls):
-        logger = logging.getLogger()
-        log_file = cls._get_log_file(cls._default_root_logger_log_file)
-        file_handler = logging.handlers.RotatingFileHandler(
-            log_file,
-            mode="a",
-            maxBytes=cls._default_max_bytes,
-            backupCount=cls._default_backup_count,
-        )
-        file_handler.setFormatter(logging.Formatter(cls._default_log_format))
-        logger.addHandler(file_handler)
-        logger.setLevel(cls._default_log_level)
-
-    @classmethod
-    def _get_log_file(cls, name):
-        if cls._default_namespace:
-            name = f"{cls._default_namespace}_{name}.log"
-        else:
-            name = f"{name}.log"
-
-        if cls._default_directory:
-            directory = cls._default_directory
-        else:
-            try:
-                directory = make_splunkhome_path(["var", "log", "splunk"])
-            except KeyError:
-                raise LogException(
-                    "Log directory is empty, please set log directory "
-                    'by calling Logs.set_context(directory="/var/log/...").'
-                )
-        log_file = op.sep.join([directory, name])
-
-        return log_file
-
-    def __init__(self):
-        self._lock = Lock()
-        self._loggers = {}
-
-    def get_logger(self, name: str) -> logging.Logger:
-        """Get logger with the name of `name`.
-
-        If logger with the name of `name` exists just return else create a new
-        logger with the name of `name`.
-
-        Arguments:
-            name: Logger name, it will be used as log file name too.
-
-        Returns:
-            A named logger.
-        """
-
-        with self._lock:
-            log_file = self._get_log_file(name)
-            if log_file in self._loggers:
-                return self._loggers[log_file]
-
-            logger = logging.getLogger(log_file)
-            handler_exists = any(
-                [True for h in logger.handlers if h.baseFilename == log_file]
-            )
-            if not handler_exists:
-                file_handler = logging.handlers.RotatingFileHandler(
-                    log_file,
-                    mode="a",
-                    maxBytes=self._default_max_bytes,
-                    backupCount=self._default_backup_count,
-                )
-                file_handler.setFormatter(logging.Formatter(self._default_log_format))
-                logger.addHandler(file_handler)
-                logger.setLevel(self._default_log_level)
-                logger.propagate = False
-
-            self._loggers[log_file] = logger
-            return logger
-
-    def set_level(self, level: int, name: str = None):
-        """Set log level of logger.
-
-        Set log level of all logger if `name` is None else of
-        logger with the name of `name`.
-
-        Arguments:
-            level: Log level to set.
-            name: The name of logger, default is None.
-        """
-
-        with self._lock:
-            if name:
-                log_file = self._get_log_file(name)
-                logger = self._loggers.get(log_file)
-                if logger:
-                    logger.setLevel(level)
-            else:
-                self._default_log_level = level
-                for logger in list(self._loggers.values()):
-                    logger.setLevel(level)
-                logging.getLogger().setLevel(level)
-
-
-def log_event(
-    logger: logging.Logger, key_values: Dict[str, Any], log_level: int = logging.INFO
-):
-    """General function to log any event in key-value format."""
-    message = " ".join([f"{k}={v}" for k, v in key_values.items()])
-    logger.log(log_level, message)
-
-
-def modular_input_start(logger: logging.Logger, modular_input_name: str):
-    """Specific function to log the start of the modular input."""
-    log_event(
-        logger,
-        {
-            "action": "started",
-            "modular_input_name": modular_input_name,
-        },
-    )
-
-
-def modular_input_end(logger: logging.Logger, modular_input_name: str):
-    """Specific function to log the end of the modular input."""
-    log_event(
-        logger,
-        {
-            "action": "ended",
-            "modular_input_name": modular_input_name,
-        },
-    )
-
-
-def _base_error_log(
-    logger,
-    exc: Exception,
-    exe_label,
-    full_msg: bool = True,
-    msg_before: str = None,
-    msg_after: str = None,
-):
-    log_exception(
-        logger,
-        exc,
-        exc_label=exe_label,
-        full_msg=full_msg,
-        msg_before=msg_before,
-        msg_after=msg_after,
-    )
-
-
-log_connection_error = partial(_base_error_log, exe_label="Connection Error")
-log_configuration_error = partial(_base_error_log, exe_label="Configuration Error")
-log_permission_error = partial(_base_error_log, exe_label="Permission Error")
-log_authentication_error = partial(_base_error_log, exe_label="Authentication Error")
-log_server_error = partial(_base_error_log, exe_label="Server Error")
-
-
-def events_ingested(
-    logger: logging.Logger,
-    modular_input_name: str,
-    sourcetype: str,
-    n_events: int,
-    index: str,
-    account: str = None,
-    host: str = None,
-    license_usage_source: str = None,
-):
-    """Specific function to log the basic information of events ingested for
-    the monitoring dashboard.
-
-    Arguments:
-        logger: Add-on logger.
-        modular_input_name: Full name of the modular input. It needs to be in a format `://`.
-            In case of invalid format ValueError is raised.
-        sourcetype: Source type used to write event.
-        n_events: Number of ingested events.
-        index: Index used to write event.
-        license_usage_source: source used to match data with license_usage.log.
-        account: Account used to write event. (optional)
-        host: Host used to write event. (optional)
-    """
-
-    if "://" in modular_input_name:
-        input_name = modular_input_name.split("/")[-1]
-    else:
-        raise ValueError(
-            f"Invalid modular input name: {modular_input_name}. "
-            f"It should be in format ://"
-        )
-
-    result = {
-        "action": "events_ingested",
-        "modular_input_name": license_usage_source
-        if license_usage_source
-        else modular_input_name,
-        "sourcetype_ingested": sourcetype,
-        "n_events": n_events,
-        "event_input": input_name,
-        "event_index": index,
-    }
-
-    if account:
-        result["event_account"] = account
-
-    if host:
-        result["event_host"] = host
-
-    log_event(logger, result)
-
-
-def log_exception(
-    logger: logging.Logger,
-    e: Exception,
-    exc_label: str,
-    full_msg: bool = True,
-    msg_before: str = None,
-    msg_after: str = None,
-    log_level: int = logging.ERROR,
-):
-    """General function to log exceptions.
-
-    Arguments:
-        logger: Add-on logger.
-        e: Exception to log.
-        exc_label: label for the error to categorize it.
-        full_msg: if set to True, full traceback will be logged. Default: True
-        msg_before: custom message before exception traceback. Default: None
-        msg_after: custom message after exception traceback. Default: None
-        log_level: Log level to log exception. Default: ERROR.
-    """
-
-    msg = _get_exception_message(e, full_msg, msg_before, msg_after)
-    logger.log(log_level, f'exc_l="{exc_label}" {msg}')
-
-
-def _get_exception_message(
-    e: Exception,
-    full_msg: bool = True,
-    msg_before: str = None,
-    msg_after: str = None,
-) -> str:
-    exc_type, exc_value, exc_traceback = type(e), e, e.__traceback__
-    if full_msg:
-        error = traceback.format_exception(exc_type, exc_value, exc_traceback)
-    else:
-        error = traceback.format_exception_only(exc_type, exc_value)
-
-    msg_start = msg_before if msg_before is not None else ""
-    msg_mid = "".join(error)
-    msg_end = msg_after if msg_after is not None else ""
-    return f"{msg_start}\n{msg_mid}\n{msg_end}"
diff --git a/apps/bitwarden_event_logs/lib/solnlib/modular_input/__init__.py b/apps/bitwarden_event_logs/lib/solnlib/modular_input/__init__.py
deleted file mode 100755
index 1b6d6eb3..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/modular_input/__init__.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""Splunk modular input."""
-
-from splunklib.modularinput.argument import Argument
-
-from .checkpointer import CheckpointerException, FileCheckpointer, KVStoreCheckpointer
-from .event import EventException, HECEvent, XMLEvent
-from .event_writer import ClassicEventWriter, HECEventWriter
-from .modular_input import ModularInput, ModularInputException
-
-__all__ = [
-    "EventException",
-    "XMLEvent",
-    "HECEvent",
-    "ClassicEventWriter",
-    "HECEventWriter",
-    "CheckpointerException",
-    "KVStoreCheckpointer",
-    "FileCheckpointer",
-    "Argument",
-    "ModularInputException",
-    "ModularInput",
-]
diff --git a/apps/bitwarden_event_logs/lib/solnlib/modular_input/checkpointer.py b/apps/bitwarden_event_logs/lib/solnlib/modular_input/checkpointer.py
deleted file mode 100755
index 378b2f33..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/modular_input/checkpointer.py
+++ /dev/null
@@ -1,263 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module provides two kinds of checkpointer: KVStoreCheckpointer,
-FileCheckpointer for modular input to save checkpoint."""
-
-import base64
-import json
-import logging
-import os
-import os.path as op
-import traceback
-import warnings
-from abc import ABCMeta, abstractmethod
-from typing import Any, Dict, Iterable, Optional
-
-from splunklib import binding
-
-from solnlib import _utils, utils
-
-__all__ = ["CheckpointerException", "KVStoreCheckpointer", "FileCheckpointer"]
-
-
-class CheckpointerException(Exception):
-    pass
-
-
-class Checkpointer(metaclass=ABCMeta):
-    """Base class of checkpointer."""
-
-    @abstractmethod
-    def update(self, key: str, state: Any):
-        """Updates document with an id that equals to `key` and `state` as
-        document data."""
-
-    @abstractmethod
-    def batch_update(self, states: Iterable[Dict[str, Any]]):
-        """Updates multiple documents."""
-
-    @abstractmethod
-    def get(self, key: str) -> dict:
-        """Gets document with an id that equals to `key`."""
-
-    @abstractmethod
-    def delete(self, key: str):
-        """Deletes document with an id that equals to `key`."""
-
-
-class KVStoreCheckpointer(Checkpointer):
-    """KVStore checkpointer.
-
-    Use KVStore to save modular input checkpoint.
-
-    More information about KV Store in Splunk is
-    [here](https://dev.splunk.com/enterprise/docs/developapps/manageknowledge/kvstore/aboutkvstorecollections).
-
-    Examples:
-        >>> from solnlib.modular_input import checkpointer
-        >>> checkpoint = checkpointer.KVStoreCheckpointer(
-                "unique_addon_checkpoints",
-                "session_key",
-                "unique_addon"
-            )
-        >>> checkpoint.update("input_1", {"timestamp": 1638043093})
-        >>> checkpoint.get("input_1")
-        >>> # returns {"timestamp": 1638043093}
-    """
-
-    def __init__(
-        self,
-        collection_name: str,
-        session_key: str,
-        app: str,
-        owner: Optional[str] = "nobody",
-        scheme: Optional[str] = None,
-        host: Optional[str] = None,
-        port: Optional[int] = None,
-        **context: Any,
-    ):
-        """Initializes KVStoreCheckpointer.
-
-        Arguments:
-            collection_name: Collection name of kvstore checkpointer.
-            session_key: Splunk access token.
-            app: App name of namespace.
-            owner: (optional) Owner of namespace, default is `nobody`.
-            scheme: (optional) The access scheme, default is None.
-            host: (optional) The host name, default is None.
-            port: (optional) The port number, default is None.
-            context: Other configurations for Splunk rest client.
-
-        Raises:
-            binding.HTTPError: HTTP error different from 404, for example 503
-                when KV Store is initializing and not ready to serve requests.
-            CheckpointerException: If init KV Store checkpointer failed.
-        """
-        try:
-            if not context.get("pool_connections"):
-                context["pool_connections"] = 5
-            if not context.get("pool_maxsize"):
-                context["pool_maxsize"] = 5
-            self._collection_data = _utils.get_collection_data(
-                collection_name,
-                session_key,
-                app,
-                owner,
-                scheme,
-                host,
-                port,
-                {"state": "string"},
-                **context,
-            )
-        except KeyError:
-            raise CheckpointerException("Get KV Store checkpointer failed.")
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def update(self, key: str, state: Any) -> None:
-        """Updates document with an id that equals to `key` and `state` as
-        document data.
-
-        Arguments:
-            key: `id` of the document to update.
-            state: Document data to update. It can be integer, string,
-                or a dict, or anything that can be an argument to `json.dumps`.
-
-        Raises:
-            binding.HTTPError: when an error occurred in Splunk, for example,
-                when Splunk is restarting and KV Store is not yet initialized.
-        """
-        record = {"_key": key, "state": json.dumps(state)}
-        self._collection_data.batch_save(record)
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def batch_update(self, states: Iterable[Dict[str, Any]]) -> None:
-        """Updates multiple documents.
-
-        Arguments:
-            states: Iterable that contains documents to update. Document should
-                be a dict with at least "state" key.
-
-        Raises:
-            binding.HTTPError: when an error occurred in Splunk, for example,
-                when Splunk is restarting and KV Store is not yet initialized.
-        """
-        for state in states:
-            state["state"] = json.dumps(state["state"])
-        self._collection_data.batch_save(*states)
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def get(self, key: str) -> Optional[Any]:
-        """Gets document with an id that equals to `key`.
-
-        Arguments:
-            key: `id` of the document to get.
-
-        Raises:
-            binding.HTTPError: When an error occurred in Splunk (not 404 code),
-                can be 503 code, when Splunk is restarting and KV Store is not
-                yet initialized.
-
-        Returns:
-            Document data under `key` or `None` in case of no data.
-        """
-        try:
-            record = self._collection_data.query_by_id(key)
-        except binding.HTTPError as e:
-            if e.status != 404:
-                logging.error(f"Get checkpoint failed: {traceback.format_exc()}.")
-                raise
-            return None
-        return json.loads(record["state"])
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def delete(self, key: str) -> None:
-        """Deletes document with an id that equals to `key`.
-
-        Arguments:
-            key: `id` of the document to delete.
-
-        Raises:
-            binding.HTTPError: When an error occurred in Splunk (not 404 code),
-                can be 503 code, when Splunk is restarting and KV Store is not
-                yet initialized.
-        """
-        try:
-            self._collection_data.delete_by_id(key)
-        except binding.HTTPError as e:
-            if e.status != 404:
-                logging.error(f"Delete checkpoint failed: {traceback.format_exc()}.")
-                raise
-
-
-class FileCheckpointer(Checkpointer):
-    """File checkpointer.
-
-    Use file to save modular input checkpoint.
-
-    Examples:
-        >>> from solnlib.modular_input import checkpointer
-        >>> ck = checkpointer.FileCheckpointer('/opt/splunk/var/...')
-        >>> ck.update(...)
-        >>> ck.get(...)
-    """
-
-    def __init__(self, checkpoint_dir: str):
-        """Initializes FileCheckpointer.
-
-        Arguments:
-            checkpoint_dir: Checkpoint directory.
-        """
-        warnings.warn(
-            "FileCheckpointer is deprecated, please use KVStoreCheckpointer",
-            stacklevel=2,
-        )
-        self._checkpoint_dir = checkpoint_dir
-
-    def encode_key(self, key):
-        return base64.b64encode(key.encode()).decode()
-
-    def update(self, key, state):
-        file_name = op.join(self._checkpoint_dir, self.encode_key(key))
-        with open(file_name + "_new", "w") as fp:
-            json.dump(state, fp)
-
-        if op.exists(file_name):
-            try:
-                os.remove(file_name)
-            except OSError:
-                pass
-
-        os.rename(file_name + "_new", file_name)
-
-    def batch_update(self, states):
-        for state in states:
-            self.update(state["_key"], state["state"])
-
-    def get(self, key):
-        file_name = op.join(self._checkpoint_dir, self.encode_key(key))
-        try:
-            with open(file_name) as fp:
-                return json.load(fp)
-        except (OSError, ValueError):
-            return None
-
-    def delete(self, key):
-        file_name = op.join(self._checkpoint_dir, self.encode_key(key))
-        try:
-            os.remove(file_name)
-        except OSError:
-            pass
diff --git a/apps/bitwarden_event_logs/lib/solnlib/modular_input/event.py b/apps/bitwarden_event_logs/lib/solnlib/modular_input/event.py
deleted file mode 100755
index 916ba660..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/modular_input/event.py
+++ /dev/null
@@ -1,255 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module provides Splunk modular input event encapsulation."""
-
-import json
-from typing import List
-from xml.etree import ElementTree as ET  # nosemgrep
-
-import defusedxml.ElementTree as defused_et
-
-__all__ = ["EventException", "XMLEvent", "HECEvent"]
-
-
-class EventException(Exception):
-    pass
-
-
-class Event:
-    """Base class of modular input event."""
-
-    def __init__(
-        self,
-        data: dict,
-        time: float = None,
-        index: str = None,
-        host: str = None,
-        source: str = None,
-        sourcetype: str = None,
-        fields: dict = None,
-        stanza: str = None,
-        unbroken: bool = False,
-        done: bool = False,
-    ):
-        """Modular input event.
-
-        Arguments:
-            data: Event data.
-            time: (optional) Event timestamp, default is None.
-            index: (optional) The index event will be written to, default is None.
-            host: (optional) Event host, default is None.
-            source: (optional) Event source, default is None.
-            sourcetype: (optional) Event sourcetype, default is None.
-            fields: (optional) Event fields, default is None.
-            stanza: (optional) Event stanza name, default is None.
-            unbroken: (optional) Event unbroken flag, default is False.
-            done: (optional) The last unbroken event, default is False.
-
-        Examples:
-           >>> event = Event(
-           >>>     data='This is a test data.',
-           >>>     time=1372274622.493,
-           >>>     index='main',
-           >>>     host='localhost',
-           >>>     source='Splunk',
-           >>>     sourcetype='misc',
-           >>>     fields= {'Cloud':'AWS','region': 'us-west-1'},
-           >>>     stanza='test_scheme://test',
-           >>>     unbroken=True,
-           >>>     done=True)
-        """
-
-        self._data = data
-        self._time = "%.3f" % time if time else None
-        self._index = index
-        self._host = host
-        self._source = source
-        self._sourcetype = sourcetype
-        if fields:
-            self._fields = fields
-        self._stanza = stanza
-        if not unbroken and done:
-            raise EventException('Invalid combination of "unbroken" and "done".')
-        self._unbroken = unbroken
-        self._done = done
-
-    def __str__(self):
-        event = {
-            "data": self._data,
-            "time": float(self._time) if self._time else self._time,
-            "index": self._index,
-            "host": self._host,
-            "source": self._source,
-            "sourcetype": self._sourcetype,
-            "stanza": self._stanza,
-            "unbroken": self._unbroken,
-            "done": self._done,
-        }
-
-        if hasattr(self, "_fields"):
-            event["fields"] = self._fields
-
-        return json.dumps(event)
-
-    @classmethod
-    def format_events(cls, events: List) -> List:
-        """Format events to list of string.
-
-        Arguments:
-            events: List of events to format.
-
-        Returns:
-            List of formatted events string.
-        """
-
-        raise EventException('Unimplemented "format_events".')
-
-
-class XMLEvent(Event):
-    """XML event."""
-
-    def _to_xml(self):
-        _event = ET.Element("event")
-        if self._stanza:
-            _event.set("stanza", self._stanza)
-        if self._unbroken:
-            _event.set("unbroken", str(int(self._unbroken)))
-
-        if self._time:
-            ET.SubElement(_event, "time").text = self._time
-
-        sub_elements = [
-            ("index", self._index),
-            ("host", self._host),
-            ("source", self._source),
-            ("sourcetype", self._sourcetype),
-        ]
-        for node, value in sub_elements:
-            if value:
-                ET.SubElement(_event, node).text = value
-
-        if isinstance(self._data, str):
-            ET.SubElement(_event, "data").text = self._data
-        else:
-            ET.SubElement(_event, "data").text = json.dumps(self._data)
-
-        if self._done:
-            ET.SubElement(_event, "done")
-
-        return _event
-
-    @classmethod
-    def format_events(cls, events: List) -> List:
-        """Format events to list of string.
-
-        Arguments:
-            events: List of events to format.
-
-        Returns:
-            List of formatted events string, example::
-
-                [
-                    '
-                    
-                    
-                    main
-                    localhost
-                    test
-                    test
-                    {"kk": [1, 2, 3]}
-                    
-                    
-                    
-                    
-                    main
-                    localhost
-                    test
-                    test
-                    {"kk": [3, 2, 3]}
-                    
-                    
-                    '
-                ]
-        """
-
-        stream = ET.Element("stream")
-        for event in events:
-            stream.append(event._to_xml())
-
-        return [
-            defused_et.tostring(stream, encoding="utf-8", method="xml").decode("utf-8")
-        ]
-
-
-class HECEvent(Event):
-    """HEC event."""
-
-    max_hec_event_length = 1000000
-
-    def _to_hec(self, event_field):
-        event = {}
-        event[event_field] = self._data
-        if self._time:
-            event["time"] = float(self._time)
-        if self._index:
-            event["index"] = self._index
-        if self._host:
-            event["host"] = self._host
-        if self._source:
-            event["source"] = self._source
-        if self._sourcetype:
-            event["sourcetype"] = self._sourcetype
-        if hasattr(self, "_fields"):
-            event["fields"] = self._fields
-
-        return json.dumps(event, ensure_ascii=False)
-
-    @classmethod
-    def format_events(cls, events: List, event_field: str = "event") -> List:
-        """Format events to list of string.
-
-        Arguments:
-            events: List of events to format.
-            event_field: Event field.
-
-        Returns:
-            List of formatted events string, example::
-
-                [
-                    '{"index": "main", ... "event": {"kk": [1, 2, 3]}}\\n
-                    {"index": "main", ... "event": {"kk": [3, 2, 3]}}',
-                '...'
-                ]
-        """
-
-        size = 0
-        new_events, batched_events = [], []
-        events = [event._to_hec(event_field) for event in events]
-        for event in events:
-            new_length = size + len(event) + len(batched_events) - 1
-            if new_length >= cls.max_hec_event_length:
-                if batched_events:
-                    new_events.append("\n".join(batched_events))
-                del batched_events[:]
-                size = 0
-
-            batched_events.append(event)
-            size = size + len(event)
-        if batched_events:
-            new_events.append("\n".join(batched_events))
-
-        return new_events
diff --git a/apps/bitwarden_event_logs/lib/solnlib/modular_input/event_writer.py b/apps/bitwarden_event_logs/lib/solnlib/modular_input/event_writer.py
deleted file mode 100755
index 06a14ae8..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/modular_input/event_writer.py
+++ /dev/null
@@ -1,510 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module provides two kinds of event writers (ClassicEventWriter,
-HECEventWriter) to write Splunk modular input events."""
-
-import logging
-import multiprocessing
-import sys
-import threading
-import time
-import traceback
-import warnings
-from abc import ABCMeta, abstractmethod
-from random import randint
-from typing import List, Union
-
-from splunklib import binding
-
-from .. import splunk_rest_client as rest_client
-from .. import utils
-from ..hec_config import HECConfig
-from ..splunkenv import get_splunkd_access_info, get_scheme_from_hec_settings
-from ..utils import retry
-from .event import HECEvent, XMLEvent
-
-__all__ = ["ClassicEventWriter", "HECEventWriter"]
-
-
-deprecation_msg = (
-    "Function 'create_from_token' is deprecated and incompatible with 'global_settings_schema=True'. "
-    "Use 'create_from_token_with_session_key' instead."
-)
-
-
-class FunctionDeprecated(Exception):
-    pass
-
-
-class EventWriter(metaclass=ABCMeta):
-    """Base class of event writer."""
-
-    description = "EventWriter"
-
-    @abstractmethod
-    def create_event(
-        self,
-        data: dict,
-        time: float = None,
-        index: str = None,
-        host: str = None,
-        source: str = None,
-        sourcetype: str = None,
-        fields: dict = None,
-        stanza: str = None,
-        unbroken: bool = False,
-        done: bool = False,
-    ) -> Union[XMLEvent, HECEvent]:
-        """Create a new event.
-
-        Arguments:
-            data: Event data.
-            time: (optional) Event timestamp, default is None.
-            index: (optional) The index event will be written to, default is None.
-            host: (optional) Event host, default is None.
-            source: (optional) Event source, default is None.
-            sourcetype: (optional) Event sourcetype, default is None.
-            fields: (optional) Event fields, default is None.
-            stanza: (optional) Event stanza name, default is None.
-            unbroken: (optional) Event unbroken flag, default is False.
-                It is only meaningful when for XMLEvent when using ClassicEventWriter.
-            done: (optional) The last unbroken event, default is False.
-                It is only meaningful when for XMLEvent when using ClassicEventWriter.
-
-        Examples:
-           >>> ew = event_writer.HECEventWriter(...)
-           >>> event = ew.create_event(
-           >>>     data='This is a test data.',
-           >>>     time='%.3f' % 1372274622.493,
-           >>>     index='main',
-           >>>     host='localhost',
-           >>>     source='Splunk',
-           >>>     sourcetype='misc',
-           >>>     fields={'accountid': '603514901691', 'Cloud': u'AWS'},
-           >>>     stanza='test_scheme://test',
-           >>>     unbroken=True,
-           >>>     done=True)
-        """
-
-        pass
-
-    @abstractmethod
-    def write_events(self, events: List):
-        """Write events.
-
-        Arguments:
-            events: List of events to write.
-
-        Examples:
-           >>> from solnlib.modular_input import event_writer
-           >>> ew = event_writer.EventWriter(...)
-           >>> ew.write_events([event1, event2])
-        """
-
-        pass
-
-
-class ClassicEventWriter(EventWriter):
-    """Classic event writer.
-
-    Use sys.stdout as the output.
-
-    Examples:
-        >>> from solnlib.modular_input import event_writer
-        >>> ew = event_writer.ClassicEventWriter()
-        >>> ew.write_events([event1, event2])
-    """
-
-    description = "ClassicEventWriter"
-
-    def __init__(self, lock: Union[threading.Lock, multiprocessing.Lock] = None):
-        """Initializes ClassicEventWriter.
-
-        Arguments:
-            lock: (optional) lock to exclusively access stdout.
-                by default, it is None and it will use threading safe lock.
-                if user would like to make the lock multiple-process safe, user should
-                pass in multiprocessing.Lock() instead
-        """
-        if lock is None:
-            self._lock = threading.Lock()
-        else:
-            self._lock = lock
-
-    def create_event(
-        self,
-        data: dict,
-        time: float = None,
-        index: str = None,
-        host: str = None,
-        source: str = None,
-        sourcetype: str = None,
-        fields: dict = None,
-        stanza: str = None,
-        unbroken: bool = False,
-        done: bool = False,
-    ):
-        """Create a new XMLEvent object."""
-
-        return XMLEvent(
-            data,
-            time=time,
-            index=index,
-            host=host,
-            source=source,
-            sourcetype=sourcetype,
-            stanza=stanza,
-            unbroken=unbroken,
-            done=done,
-        )
-
-    def write_events(self, events):
-        if not events:
-            return
-
-        stdout = sys.stdout
-
-        data = "".join([event for event in XMLEvent.format_events(events)])
-        with self._lock:
-            stdout.write(data)
-            stdout.flush()
-
-
-class HECEventWriter(EventWriter):
-    """HEC event writer.
-
-    Use Splunk HEC as the output.
-
-    Examples:
-        >>> from solnlib.modular_input import event_writer
-        >>> ew = event_writer.HECEventWriter(hec_input_name, session_key)
-        >>> ew.write_events([event1, event2])
-    """
-
-    WRITE_EVENT_RETRIES = 5
-    HTTP_INPUT_CONFIG_ENDPOINT = "/servicesNS/nobody/splunk_httpinput/data/inputs/http"
-    HTTP_EVENT_COLLECTOR_ENDPOINT = "/services/collector"
-    TOO_MANY_REQUESTS = 429  # we exceeded rate limit
-    SERVICE_UNAVAILABLE = 503  # remote service is temporary unavailable
-
-    description = "HECEventWriter"
-
-    headers = [("Content-Type", "application/json")]
-
-    def __init__(
-        self,
-        hec_input_name: str,
-        session_key: str,
-        scheme: str = None,
-        host: str = None,
-        port: int = None,
-        hec_uri: str = None,
-        hec_token: str = None,
-        global_settings_schema: bool = True,
-        logger: logging.Logger = None,
-        **context: dict
-    ):
-        """Initializes HECEventWriter.
-
-        Arguments:
-            hec_input_name: Splunk HEC input name.
-            session_key: Splunk access token.
-            scheme: (optional) The access scheme, default is None.
-            host: (optional) The host name, default is None.
-            port: (optional) The port number, default is None.
-            hec_uri: (optional) If hec_uri and hec_token are provided, they will
-                higher precedence than hec_input_name.
-            hec_token: (optional) HEC token.
-            global_settings_schema: (optional) if True, scheme will be set based on HEC global settings, default False.
-            logger: Logger object.
-            context: Other configurations for Splunk rest client.
-        """
-        super().__init__()
-        self._session_key = session_key
-        if logger:
-            self.logger = logger
-        else:
-            self.logger = logging
-
-        if hec_uri and hec_token:
-            scheme, host, hec_port = utils.extract_http_scheme_host_port(hec_uri)
-        else:
-            if not all([scheme, host, port]):
-                scheme, host, port = get_splunkd_access_info(self._session_key)
-            hec_port, hec_token = self._get_hec_config(
-                hec_input_name, session_key, scheme, host, port, **context
-            )
-
-        if global_settings_schema:
-            scheme = get_scheme_from_hec_settings(self._session_key)
-
-        if not context.get("pool_connections"):
-            context["pool_connections"] = 10
-
-        if not context.get("pool_maxsize"):
-            context["pool_maxsize"] = 10
-
-        self._rest_client = rest_client.SplunkRestClient(
-            hec_token, app="-", scheme=scheme, host=host, port=hec_port, **context
-        )
-
-    @staticmethod
-    def create_from_token(
-        hec_uri: str,
-        hec_token: str,
-        global_settings_schema: bool = False,
-        **context: dict
-    ) -> "HECEventWriter":
-        """Given HEC URI and HEC token, create HECEventWriter object. This
-        function simplifies the standalone mode HECEventWriter usage (not in a
-        modinput).
-
-        Arguments:
-            hec_uri: HTTP Event Collector URI, like https://localhost:8088.
-            hec_token: HTTP Event Collector token.
-            global_settings_schema: (optional) if True, scheme will be set based on HEC global settings, default False.
-            context: Other configurations.
-
-        Returns:
-            Created HECEventWriter.
-        """
-
-        warnings.warn(deprecation_msg, DeprecationWarning, stacklevel=2)
-
-        if global_settings_schema:
-            raise FunctionDeprecated(deprecation_msg)
-
-        return HECEventWriter(
-            None,
-            None,
-            None,
-            None,
-            None,
-            hec_uri=hec_uri,
-            hec_token=hec_token,
-            global_settings_schema=global_settings_schema,
-            **context
-        )
-
-    @staticmethod
-    def create_from_input(
-        hec_input_name: str,
-        splunkd_uri: str,
-        session_key: str,
-        global_settings_schema: bool = False,
-        **context: dict
-    ) -> "HECEventWriter":
-        """Given HEC input stanza name, splunkd URI and splunkd session key,
-        create HECEventWriter object. HEC URI and token etc will be discovered
-        from HEC input stanza. When hitting HEC event limit, the underlying
-        code will increase the HEC event limit automatically by calling
-        corresponding REST API against splunkd_uri by using session_key.
-
-        Arguments:
-            hec_input_name: Splunk HEC input name.
-            splunkd_uri: Splunkd URI, like https://localhost:8089
-            session_key: Splunkd access token.
-            global_settings_schema: (optional) if True, scheme will be set based on HEC global settings, default False.
-            context: Other configurations.
-
-        Returns:
-            Created HECEventWriter.
-        """
-
-        scheme, host, port = utils.extract_http_scheme_host_port(splunkd_uri)
-        return HECEventWriter(
-            hec_input_name,
-            session_key,
-            scheme,
-            host,
-            port,
-            global_settings_schema=global_settings_schema,
-            **context
-        )
-
-    @staticmethod
-    def create_from_token_with_session_key(
-        splunkd_uri: str,
-        session_key: str,
-        hec_uri: str,
-        hec_token: str,
-        global_settings_schema: bool = False,
-        **context: dict
-    ) -> "HECEventWriter":
-        """Given Splunkd URI, Splunkd session key, HEC URI and HEC token,
-        create HECEventWriter object. When hitting HEC event limit, the event
-        writer will increase the HEC event limit automatically by calling
-        corresponding REST API against splunkd_uri by using session_key.
-
-        Arguments:
-            splunkd_uri: Splunkd URI, like https://localhost:8089.
-            session_key: Splunkd access token.
-            hec_uri: Http Event Collector URI, like https://localhost:8088.
-            hec_token: Http Event Collector token.
-            global_settings_schema: (optional) if True, scheme will be set based on HEC global settings, default False.
-            context: Other configurations.
-
-        Returns:
-            Created HECEventWriter.
-        """
-
-        scheme, host, port = utils.extract_http_scheme_host_port(splunkd_uri)
-        return HECEventWriter(
-            None,
-            session_key,
-            scheme,
-            host,
-            port,
-            hec_uri=hec_uri,
-            hec_token=hec_token,
-            global_settings_schema=global_settings_schema,
-            **context
-        )
-
-    @retry(exceptions=[binding.HTTPError])
-    def _get_hec_config(
-        self, hec_input_name, session_key, scheme, host, port, **context
-    ):
-        hc = HECConfig(session_key, scheme=scheme, host=host, port=port, **context)
-        settings = hc.get_settings()
-        if utils.is_true(settings.get("disabled")):
-            # Enable HEC input
-            self.logger.info("Enabling HEC")
-            settings["disabled"] = "0"
-            settings["enableSSL"] = context.get("hec_enablessl", "1")
-            settings["port"] = context.get("hec_port", "8088")
-            hc.update_settings(settings)
-
-        hec_input = hc.get_input(hec_input_name)
-        if not hec_input:
-            # Create HEC input
-            self.logger.info("Create HEC datainput, name=%s", hec_input_name)
-            hinput = {
-                "index": context.get("index", "main"),
-            }
-
-            if context.get("sourcetype"):
-                hinput["sourcetype"] = context["sourcetype"]
-
-            if context.get("token"):
-                hinput["token"] = context["token"]
-
-            if context.get("source"):
-                hinput["source"] = context["source"]
-
-            if context.get("host"):
-                hinput["host"] = context["host"]
-
-            hec_input = hc.create_input(hec_input_name, hinput)
-
-        limits = hc.get_limits()
-        HECEvent.max_hec_event_length = int(limits.get("max_content_length", 1000000))
-
-        return settings["port"], hec_input["token"]
-
-    def create_event(
-        self,
-        data: dict,
-        time: float = None,
-        index: str = None,
-        host: str = None,
-        source: str = None,
-        sourcetype: str = None,
-        fields: dict = None,
-        stanza: str = None,
-        unbroken: bool = False,
-        done: bool = False,
-    ) -> HECEvent:
-        """Create a new HECEvent object.
-
-        Arguments:
-            data: Event data.
-            time: (optional) Event timestamp, default is None.
-            index: (optional) The index event will be written to, default is None.
-            host: (optional) Event host, default is None.
-            source: (optional) Event source, default is None.
-            sourcetype: (optional) Event sourcetype, default is None.
-            fields: (optional) Event fields, default is None.
-            stanza: (optional) Event stanza name, default is None.
-            unbroken: (optional) Event unbroken flag, default is False.
-                It is only meaningful when for XMLEvent when using ClassicEventWriter.
-            done: (optional) The last unbroken event, default is False.
-                It is only meaningful when for XMLEvent when using ClassicEventWriter.
-
-        Returns:
-            Created HECEvent.
-        """
-
-        return HECEvent(
-            data,
-            time=time,
-            index=index,
-            host=host,
-            source=source,
-            sourcetype=sourcetype,
-            fields=fields,
-        )
-
-    def write_events(
-        self,
-        events: List,
-        retries: int = WRITE_EVENT_RETRIES,
-        event_field: str = "event",
-    ):
-        """Write events to index in bulk.
-
-        Arguments:
-            events: List of events.
-            retries: Number of retries for writing events to index.
-            event_field: Event field.
-        """
-        if not events:
-            return
-
-        last_ex = None
-        for event in HECEvent.format_events(events, event_field):
-            for i in range(retries):
-                try:
-                    self._rest_client.post(
-                        self.HTTP_EVENT_COLLECTOR_ENDPOINT,
-                        body=event.encode("utf-8"),
-                        headers=self.headers,
-                    )
-                except binding.HTTPError as e:
-                    self.logger.warn(
-                        "Write events through HEC failed. Status=%s", e.status
-                    )
-                    last_ex = e
-                    if e.status in [self.TOO_MANY_REQUESTS, self.SERVICE_UNAVAILABLE]:
-                        # wait time for n retries: 10, 20, 40, 80, 80, 80, 80, ....
-                        sleep_time = min(((2 ** (i + 1)) * 5), 80)
-                        if i < retries - 1:
-                            random_millisecond = randint(0, 1000) / 1000.0
-                            time.sleep(sleep_time + random_millisecond)
-                    else:
-                        raise last_ex
-                else:
-                    break
-            else:
-                # When failed after retry, we reraise the exception
-                # to exit the function to let client handle this situation
-                self.logger.error(
-                    "Write events through HEC failed: %s. status=%s",
-                    traceback.format_exc(),
-                    last_ex.status,
-                )
-                raise last_ex
diff --git a/apps/bitwarden_event_logs/lib/solnlib/modular_input/modinput.py b/apps/bitwarden_event_logs/lib/solnlib/modular_input/modinput.py
deleted file mode 100755
index 0d591923..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/modular_input/modinput.py
+++ /dev/null
@@ -1,161 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import subprocess
-import sys
-import traceback
-
-import solnlib.splunkenv as sp
-import logging
-
-
-def _parse_modinput_configs(root, outer_block, inner_block):
-    """When user splunkd spawns modinput script to do config check or run.
-
-    
-    
-      localhost.localdomain
-      https://127.0.0.1:8089
-      xxxyyyzzz
-      ckpt_dir
-      
-        
-          60
-            localhost.localdomain
-            snow
-            10
-        
-        ...
-      
-    
-
-    When user create an stanza through data input on WebUI
-
-    
-    
-      localhost.localdomain
-      https://127.0.0.1:8089
-      xxxyyyzzz
-      ckpt_dir
-      
-        60
-        
-        localhost.localdomain
-        snow
-        10
-      
-    
-    """
-
-    confs = root.getElementsByTagName(outer_block)
-    if not confs:
-        logging.error("Invalid config, missing %s section", outer_block)
-        raise Exception(f"Invalid config, missing {outer_block} section")
-
-    configs = []
-    stanzas = confs[0].getElementsByTagName(inner_block)
-    for stanza in stanzas:
-        config = {}
-        stanza_name = stanza.getAttribute("name")
-        if not stanza_name:
-            logging.error("Invalid config, missing name")
-            raise Exception("Invalid config, missing name")
-
-        config["name"] = stanza_name
-        params = stanza.getElementsByTagName("param")
-        for param in params:
-            name = param.getAttribute("name")
-            if (
-                name
-                and param.firstChild
-                and param.firstChild.nodeType == param.firstChild.TEXT_NODE
-            ):
-                config[name] = param.firstChild.data
-        configs.append(config)
-    return configs
-
-
-def parse_modinput_configs(config_str):
-    """
-    @config_str: modinput XML configuration feed by splunkd
-    @return: meta_config and stanza_config
-    """
-
-    import defusedxml.minidom as xdm
-
-    meta_configs = {
-        "server_host": None,
-        "server_uri": None,
-        "session_key": None,
-        "checkpoint_dir": None,
-    }
-    root = xdm.parseString(config_str)
-    doc = root.documentElement
-    for tag in meta_configs.keys():
-        nodes = doc.getElementsByTagName(tag)
-        if not nodes:
-            logging.error("Invalid config, missing %s section", tag)
-            raise Exception("Invalid config, missing %s section", tag)
-
-        if nodes[0].firstChild and nodes[0].firstChild.nodeType == nodes[0].TEXT_NODE:
-            meta_configs[tag] = nodes[0].firstChild.data
-        else:
-            logging.error("Invalid config, expect text ndoe")
-            raise Exception("Invalid config, expect text ndoe")
-
-    if doc.nodeName == "input":
-        configs = _parse_modinput_configs(doc, "configuration", "stanza")
-    else:
-        configs = _parse_modinput_configs(root, "items", "item")
-    return meta_configs, configs
-
-
-def get_modinput_configs_from_cli(modinput, modinput_stanza=None):
-    """
-    @modinput: modinput name
-    @modinput_stanza: modinput stanza name, for multiple instance only
-    """
-
-    assert modinput
-
-    splunkbin = sp.get_splunk_bin()
-    cli = [splunkbin, "cmd", "splunkd", "print-modinput-config", modinput]
-    if modinput_stanza:
-        cli.append(modinput_stanza)
-
-    out, err = subprocess.Popen(
-        cli, stdout=subprocess.PIPE, stderr=subprocess.PIPE
-    ).communicate()
-    if err:
-        logging.error("Failed to get modinput configs with error: %s", err)
-        return None, None
-    else:
-        return parse_modinput_configs(out)
-
-
-def get_modinput_config_str_from_stdin():
-    """Get modinput from stdin which is feed by splunkd."""
-
-    try:
-        return sys.stdin.read(5000)
-    except Exception:
-        logging.error(traceback.format_exc())
-        raise
-
-
-def get_modinput_configs_from_stdin():
-    config_str = get_modinput_config_str_from_stdin()
-    return parse_modinput_configs(config_str)
diff --git a/apps/bitwarden_event_logs/lib/solnlib/modular_input/modular_input.py b/apps/bitwarden_event_logs/lib/solnlib/modular_input/modular_input.py
deleted file mode 100755
index 0889f7a9..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/modular_input/modular_input.py
+++ /dev/null
@@ -1,509 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module provides a base class of Splunk modular input."""
-
-import logging
-import sys
-import traceback
-from abc import ABCMeta, abstractmethod
-from typing import Callable, List
-from urllib import parse as urlparse
-from xml.etree import ElementTree as ET  # nosemgrep
-
-import defusedxml.ElementTree as defused_et
-from splunklib import binding
-from splunklib.modularinput.argument import Argument
-from splunklib.modularinput.input_definition import InputDefinition
-from splunklib.modularinput.scheme import Scheme
-from splunklib.modularinput.validation_definition import ValidationDefinition
-
-from .. import utils
-from ..orphan_process_monitor import OrphanProcessMonitor
-from . import checkpointer, event_writer
-
-__all__ = ["ModularInputException", "ModularInput"]
-
-
-class ModularInputException(Exception):
-    """Exception for ModularInput class."""
-
-    pass
-
-
-class ModularInput(metaclass=ABCMeta):
-    """Base class of Splunk modular input.
-
-    It's a base modular input, it should be inherited by sub modular input. For
-    sub modular input, properties: 'app', 'name', 'title' and 'description' must
-    be overriden, also there are some other optional properties can be overriden
-    like: 'use_external_validation', 'use_single_instance', 'use_kvstore_checkpointer'
-    and 'use_hec_event_writer'.
-
-    Notes: If you set 'KVStoreCheckpointer' or 'use_hec_event_writer' to True,
-    you must override the corresponding 'kvstore_checkpointer_collection_name'
-    and 'hec_input_name'.
-
-    Examples:
-
-       >>> class TestModularInput(ModularInput):
-       >>>     app = 'TestApp'
-       >>>     name = 'test_modular_input'
-       >>>     title = 'Test modular input'
-       >>>     description = 'This is a test modular input'
-       >>>     use_external_validation = True
-       >>>     use_single_instance = False
-       >>>     use_kvstore_checkpointer = True
-       >>>     kvstore_checkpointer_collection_name = 'TestCheckpoint'
-       >>>     use_hec_event_writer = True
-       >>>     hec_input_name = 'TestEventWriter'
-       >>>
-       >>>     def extra_arguments(self):
-       >>>         ... .. .
-       >>>
-       >>>     def do_validation(self, parameters):
-       >>>         ... .. .
-       >>>
-       >>>     def do_run(self, inputs):
-       >>>         ... .. .
-       >>>
-       >>> if __name__ == '__main__':
-       >>>     md = TestModularInput()
-       >>>     md.execute()
-    """
-
-    # App name, must be overridden
-    app = None
-    # Modular input name, must be overridden
-    name = None
-    # Modular input scheme title, must be overridden
-    title = None
-    # Modular input scheme description, must be overridden
-    description = None
-    # Modular input scheme use external validation, default is False
-    use_external_validation = False
-    # Modular input scheme use single instance mode, default is False
-    use_single_instance = False
-    # Use kvstore as checkpointer, default is True
-    use_kvstore_checkpointer = True
-    # Collection name of kvstore checkpointer, must be overridden if
-    # use_kvstore_checkpointer is True
-    kvstore_checkpointer_collection_name = None
-    # Use hec event writer
-    use_hec_event_writer = True
-    # Input name of Splunk HEC, must be overridden if use_hec_event_writer
-    # is True
-    hec_input_name = None
-    hec_global_settings_schema = False
-
-    def __init__(self):
-        # Validate properties
-        self._validate_properties()
-        # Modular input state
-        self.should_exit = False
-        # Metadata
-        self.server_host_name = None
-        self.server_uri = None
-        self.server_scheme = None
-        self.server_host = None
-        self.server_port = None
-        self.session_key = None
-        # Modular input config name
-        self.config_name = None
-        # Checkpoint dir
-        self._checkpoint_dir = None
-        # Checkpointer
-        self._checkpointer = None
-        # Orphan process monitor
-        self._orphan_monitor = None
-        # Event writer
-        self._event_writer = None
-
-    def _validate_properties(self):
-        if not all([self.app, self.name, self.title, self.description]):
-            raise ModularInputException(
-                'Attributes: "app", "name", "title", "description" must '
-                "be overriden."
-            )
-
-        if self.use_kvstore_checkpointer:
-            if self.kvstore_checkpointer_collection_name is None:
-                raise ModularInputException(
-                    'Attribute: "kvstore_checkpointer_collection_name" must'
-                    'be overriden if "use_kvstore_checkpointer" is True".'
-                )
-            elif self.kvstore_checkpointer_collection_name.strip() == "":
-                raise ModularInputException(
-                    'Attribute: "kvstore_checkpointer_collection_name" can'
-                    " not be empty."
-                )
-
-        if self.use_hec_event_writer:
-            if self.hec_input_name is None:
-                raise ModularInputException(
-                    'Attribute: "hec_input_name" must be overriden '
-                    'if "use_hec_event_writer" is True.'
-                )
-            elif self.hec_input_name.strip() == "":
-                raise ModularInputException(
-                    'Attribute: "hec_input_name" can not be empty.'
-                )
-
-    @property
-    def checkpointer(self) -> checkpointer.Checkpointer:
-        """Get checkpointer object.
-
-        The checkpointer returned depends on use_kvstore_checkpointer flag,
-        if use_kvstore_checkpointer is true will return an KVStoreCheckpointer
-        object else an FileCheckpointer object.
-
-        Returns:
-            A checkpointer object.
-        """
-
-        if self._checkpointer is not None:
-            return self._checkpointer
-
-        self._checkpointer = self._create_checkpointer()
-        return self._checkpointer
-
-    def _create_checkpointer(self):
-        if self.use_kvstore_checkpointer:
-            checkpointer_name = ":".join(
-                [self.app, self.config_name, self.kvstore_checkpointer_collection_name]
-            )
-            try:
-                return checkpointer.KVStoreCheckpointer(
-                    checkpointer_name,
-                    self.session_key,
-                    self.app,
-                    owner="nobody",
-                    scheme=self.server_scheme,
-                    host=self.server_host,
-                    port=self.server_port,
-                )
-            except binding.HTTPError:
-                logging.error(
-                    "Failed to init kvstore checkpointer: %s.", traceback.format_exc()
-                )
-                raise
-        else:
-            return checkpointer.FileCheckpointer(self._checkpoint_dir)
-
-    @property
-    def event_writer(self) -> event_writer.EventWriter:
-        """Get event writer object.
-
-        The event writer returned depends on use_hec_event_writer flag,
-        if use_hec_event_writer is true will return an HECEventWriter
-        object else an ClassicEventWriter object.
-
-        Returns:
-            Event writer object.
-        """
-
-        if self._event_writer is not None:
-            return self._event_writer
-
-        self._event_writer = self._create_event_writer()
-        return self._event_writer
-
-    def _create_event_writer(self):
-        if self.use_hec_event_writer:
-            hec_input_name = ":".join([self.app, self.hec_input_name])
-            try:
-                return event_writer.HECEventWriter(
-                    hec_input_name,
-                    self.session_key,
-                    scheme=self.server_scheme,
-                    host=self.server_host,
-                    port=self.server_port,
-                    global_settings_schema=self.hec_global_settings_schema,
-                )
-            except binding.HTTPError:
-                logging.error(
-                    "Failed to init HECEventWriter: %s.", traceback.format_exc()
-                )
-                raise
-        else:
-            return event_writer.ClassicEventWriter()
-
-    def _update_metadata(self, metadata):
-        self.server_host_name = metadata["server_host"]
-        splunkd = urlparse.urlsplit(metadata["server_uri"])
-        self.server_uri = splunkd.geturl()
-        self.server_scheme = splunkd.scheme
-        self.server_host = splunkd.hostname
-        self.server_port = splunkd.port
-        self.session_key = metadata["session_key"]
-        self._checkpoint_dir = metadata["checkpoint_dir"]
-
-    def _do_scheme(self):
-        scheme = Scheme(self.title)
-        scheme.description = self.description
-        scheme.use_external_validation = self.use_external_validation
-        scheme.streaming_mode = Scheme.streaming_mode_xml
-        scheme.use_single_instance = self.use_single_instance
-
-        for argument in self.extra_arguments():
-            name = argument["name"]
-            title = argument.get("title", None)
-            description = argument.get("description", None)
-            validation = argument.get("validation", None)
-            data_type = argument.get("data_type", Argument.data_type_string)
-            required_on_edit = argument.get("required_on_edit", False)
-            required_on_create = argument.get("required_on_create", False)
-
-            scheme.add_argument(
-                Argument(
-                    name,
-                    title=title,
-                    description=description,
-                    validation=validation,
-                    data_type=data_type,
-                    required_on_edit=required_on_edit,
-                    required_on_create=required_on_create,
-                )
-            )
-
-        return defused_et.tostring(scheme.to_xml(), encoding="unicode")
-
-    def extra_arguments(self) -> List:
-        """Extra arguments for modular input.
-
-        Default implementation is returning an empty list.
-
-        Returns:
-            List of arguments like::
-
-                [
-                    {
-                        'name': 'arg1',
-                        'title': 'arg1 title',
-                        'description': 'arg1 description',
-                        'validation': 'arg1 validation statement',
-                        'data_type': Argument.data_type_string,
-                        'required_on_edit': False,
-                        'required_on_create': False
-                    },
-                    {...},
-                    {...}
-                ]
-        """
-
-        return []
-
-    def do_validation(self, parameters):
-        """Handles external validation for modular input kinds.
-
-        When Splunk calls a modular input script in validation mode, it will
-        pass in an XML document giving information about the Splunk instance
-        (so you can call back into it if needed) and the name and parameters
-        of the proposed input. If this function does not throw an exception,
-        the validation is assumed to succeed. Otherwise any errors thrown will
-        be turned into a string and logged back to Splunk.
-
-        Arguments:
-            parameters: The parameters of input passed by splunkd.
-
-        Raises:
-            Exception: If validation is failed.
-        """
-
-        pass
-
-    @abstractmethod
-    def do_run(self, inputs: dict):
-        """Runs this modular input.
-
-        Arguments:
-            inputs: Command line arguments passed to this modular input.
-                For single instance mode, inputs like::
-
-                    {
-                    'stanza_name1': {'arg1': 'arg1_value', 'arg2': 'arg2_value', ...}
-                    'stanza_name2': {'arg1': 'arg1_value', 'arg2': 'arg2_value', ...}
-                    'stanza_name3': {'arg1': 'arg1_value', 'arg2': 'arg2_value', ...}
-                    }
-
-                For multiple instance mode, inputs like::
-
-                    {
-                    'stanza_name1': {'arg1': 'arg1_value', 'arg2': 'arg2_value', ...}
-                    }
-        """
-
-        pass
-
-    def register_teardown_handler(self, handler: Callable, *args):
-        """Register teardown signal handler.
-
-        Arguments:
-            handler: Teardown signal handler.
-            args: Arguments to the handler.
-
-        Examples:
-           >>> mi = ModularInput(...)
-           >>> def teardown_handler(arg1, arg2, ...):
-           >>>     ...
-           >>> mi.register_teardown_handler(teardown_handler, arg1, arg2, ...)
-        """
-
-        def _teardown_handler(signum, frame):
-            handler(*args)
-
-        utils.handle_teardown_signals(_teardown_handler)
-
-    def register_orphan_handler(self, handler: Callable, *args):
-        """Register orphan process handler.
-
-        Arguments:
-            handler: Teardown signal handler.
-            args: Arguments to the handler.
-
-        Examples:
-           >>> mi = ModularInput(...)
-           >>> def orphan_handler(arg1, arg2, ...):
-           >>>     ...
-           >>> mi.register_orphan_handler(orphan_handler, arg1, arg2, ...)
-        """
-
-        def _orphan_handler():
-            handler(*args)
-
-        if self._orphan_monitor is None:
-            self._orphan_monitor = OrphanProcessMonitor(_orphan_handler)
-            self._orphan_monitor.start()
-
-    def get_validation_definition(self) -> dict:
-        """Get validation definition.
-
-        This method can be overwritten to get validation definition from
-        other input instead `stdin`.
-
-        Returns:
-            A dict object must contains `metadata` and `parameters`::
-
-                example: {
-                    'metadata': {
-                    'session_key': 'iCKPS0cvmpyeJk...sdaf',
-                    'server_host': 'test-test.com',
-                    'server_uri': 'https://127.0.0.1:8089',
-                    'checkpoint_dir': '/tmp'
-                    },
-                    parameters: {'args1': value1, 'args2': value2}
-                }
-        """
-
-        validation_definition = ValidationDefinition.parse(sys.stdin)
-        return {
-            "metadata": validation_definition.metadata,
-            "parameters": validation_definition.parameters,
-        }
-
-    def get_input_definition(self) -> dict:
-        """Get input definition.
-
-        This method can be overwritten to get input definition from
-        other input instead `stdin`.
-
-        Returns:
-            A dict object must contain `metadata` and `inputs`::
-
-                example: {
-                    'metadata': {
-                    'session_key': 'iCKPS0cvmpyeJk...sdaf',
-                    'server_host': 'test-test.com',
-                    'server_uri': 'https://127.0.0.1:8089',
-                    'checkpoint_dir': '/tmp'
-                    },
-                    inputs: {
-                    'stanza1': {'arg1': value1, 'arg2': value2},
-                    'stanza2': {'arg1': value1, 'arg2': value2}
-                    }
-                }
-        """
-
-        input_definition = InputDefinition.parse(sys.stdin)
-        return {
-            "metadata": input_definition.metadata,
-            "inputs": input_definition.inputs,
-        }
-
-    def execute(self):
-        """Modular input entry.
-
-        Examples:
-           >>> class TestModularInput(ModularInput):
-           >>>         ... .. .
-           >>>
-           >>> if __name__ == '__main__':
-           >>>     md = TestModularInput()
-           >>>     md.execute()
-        """
-
-        if len(sys.argv) == 1:
-            try:
-                input_definition = self.get_input_definition()
-                self._update_metadata(input_definition["metadata"])
-                if self.use_single_instance:
-                    self.config_name = self.name
-                else:
-                    self.config_name = list(input_definition["inputs"].keys())[0]
-                self.do_run(input_definition["inputs"])
-                logging.info("Modular input: %s exit normally.", self.name)
-                return 0
-            except Exception:
-                logging.error(
-                    "Modular input: %s exit with exception: %s.",
-                    self.name,
-                    traceback.format_exc(),
-                )
-                return 1
-            finally:
-                # Stop orphan monitor if any
-                if self._orphan_monitor:
-                    self._orphan_monitor.stop()
-
-        elif str(sys.argv[1]).lower() == "--scheme":
-            sys.stdout.write(self._do_scheme())
-            sys.stdout.flush()
-            return 0
-
-        elif sys.argv[1].lower() == "--validate-arguments":
-            try:
-                validation_definition = self.get_validation_definition()
-                self._update_metadata(validation_definition["metadata"])
-                self.do_validation(validation_definition["parameters"])
-                return 0
-            except Exception as e:
-                logging.error(
-                    "Modular input: %s validate arguments with exception: %s.",
-                    self.name,
-                    traceback.format_exc(),
-                )
-                root = ET.Element("error")
-                ET.SubElement(root, "message").text = str(e)
-                sys.stderr.write(defused_et.tostring(root))
-                sys.stderr.flush()
-                return 1
-        else:
-            logging.error(
-                'Modular input: %s run with invalid arguments: "%s".',
-                self.name,
-                " ".join(sys.argv[1:]),
-            )
-            return 1
diff --git a/apps/bitwarden_event_logs/lib/solnlib/net_utils.py b/apps/bitwarden_event_logs/lib/solnlib/net_utils.py
deleted file mode 100755
index bdc76a4d..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/net_utils.py
+++ /dev/null
@@ -1,155 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""Net utilities."""
-import re
-import socket
-
-__all__ = ["resolve_hostname", "validate_scheme_host_port"]
-
-from typing import Optional, Union
-
-
-def resolve_hostname(addr: str) -> Optional[str]:
-    """Try to resolve an IP to a host name and returns None on common failures.
-
-    Arguments:
-        addr: IP address to resolve.
-
-    Returns:
-        Host name if success else None.
-
-    Raises:
-        ValueError: If `addr` is not a valid address.
-    """
-
-    if is_valid_ip(addr):
-        try:
-            name, _, _ = socket.gethostbyaddr(addr)
-            return name
-        except socket.gaierror:
-            # [Errno 8] nodename nor servname provided, or not known
-            pass
-        except socket.herror:
-            # [Errno 1] Unknown host
-            pass
-        except socket.timeout:
-            # Timeout.
-            pass
-
-        return None
-    else:
-        raise ValueError("Invalid ip address.")
-
-
-def is_valid_ip(addr: str) -> bool:
-    """Validate an IPV4 address.
-
-    Arguments:
-        addr: IP address to validate.
-
-    Returns:
-        True if is valid else False.
-    """
-
-    ip_rx = re.compile(
-        r"""
-        ^(((
-              [0-1]\d{2}                  # matches 000-199
-            | 2[0-4]\d                    # matches 200-249
-            | 25[0-5]                     # matches 250-255
-            | \d{1,2}                     # matches 0-9, 00-99
-        )\.){3})                          # 3 of the preceding stanzas
-        ([0-1]\d{2}|2[0-4]\d|25[0-5]|\d{1,2})$     # final octet
-    """,
-        re.VERBOSE,
-    )
-
-    try:
-        return ip_rx.match(addr.strip())
-    except AttributeError:
-        # Value was not a string
-        return False
-
-
-def is_valid_hostname(hostname: str) -> bool:
-    """Validate a host name.
-
-    Arguments:
-        hostname: host name to validate.
-
-    Returns:
-        True if is valid else False.
-    """
-    # Splunk IPv6 support.
-    # https://docs.splunk.com/Documentation/Splunk/9.0.0/Admin/ConfigureSplunkforIPv6#Change_the_prioritization_of_IPv4_and_IPv6_communications
-    if hostname == "[::1]":
-        return True
-
-    if len(hostname) > 255:
-        return False
-    if hostname[-1:] == ".":
-        hostname = hostname[:-1]
-    allowed = re.compile(r"(?!-)(::)?[A-Z\d-]{1,63}(? bool:
-    """Validate a port.
-
-    Arguments:
-        port: port to validate.
-
-    Returns:
-        True if is valid else False.
-    """
-
-    try:
-        return 0 < int(port) <= 65535
-    except ValueError:
-        return False
-
-
-def is_valid_scheme(scheme: str) -> bool:
-    """Validate a scheme.
-
-    Arguments:
-        scheme: scheme to validate.
-
-    Returns:
-        True if is valid else False.
-    """
-
-    return scheme.lower() in ("http", "https")
-
-
-def validate_scheme_host_port(scheme: str, host: str, port: Union[str, int]):
-    """Validates scheme, host and port.
-
-    Arguments:
-        scheme: scheme to validate.
-        host: hostname to validate.
-        port: port to validate.
-
-    Raises:
-        ValueError: if scheme, host or port are invalid.
-    """
-    if scheme is not None and not is_valid_scheme(scheme):
-        raise ValueError("Invalid scheme")
-    if host is not None and not is_valid_hostname(host):
-        raise ValueError("Invalid host")
-    if port is not None and not is_valid_port(port):
-        raise ValueError("Invalid port")
diff --git a/apps/bitwarden_event_logs/lib/solnlib/orphan_process_monitor.py b/apps/bitwarden_event_logs/lib/solnlib/orphan_process_monitor.py
deleted file mode 100755
index d71543ad..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/orphan_process_monitor.py
+++ /dev/null
@@ -1,120 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""Orphan process monitor."""
-
-import os
-import threading
-import time
-from typing import Callable
-
-__all__ = ["OrphanProcessChecker", "OrphanProcessMonitor"]
-
-
-class OrphanProcessChecker:
-    """Orphan process checker.
-
-    Only work for Linux platform. On Windows platform, is_orphan is
-    always False and there is no need to do this monitoring on Windows.
-    """
-
-    def __init__(self, callback: Callable = None):
-        """Initializes OrphanProcessChecker.
-
-        Arguments:
-            callback: (optional) Callback for orphan process.
-        """
-        if os.name == "nt":
-            self._ppid = 0
-        else:
-            self._ppid = os.getppid()
-        self._callback = callback
-
-    def is_orphan(self) -> bool:
-        """Check process is orphan.
-
-        For windows platform just return False.
-
-        Returns:
-            True for orphan process else False.
-        """
-
-        if os.name == "nt":
-            return False
-        return self._ppid != os.getppid()
-
-    def check_orphan(self) -> bool:
-        """Check if the process becomes orphan.
-
-        If the process becomes orphan then call callback function
-        to handle properly.
-
-        Returns:
-            True for orphan process else False.
-        """
-
-        res = self.is_orphan()
-        if res and self._callback:
-            self._callback()
-        return res
-
-
-class OrphanProcessMonitor:
-    """Orphan process monitor.
-
-    Check if process become orphan in background thread per interval and
-    call callback if process become orphan.
-    """
-
-    def __init__(self, callback: Callable, interval: int = 1):
-        """Initializes OrphanProcessMonitor.
-
-        Arguments:
-            callback: Callback for orphan process monitor.
-            interval: (optional) Interval to monitor.
-        """
-        self._checker = OrphanProcessChecker(callback)
-        self._thr = threading.Thread(target=self._do_monitor)
-        self._thr.daemon = True
-        self._started = False
-        self._interval = interval
-
-    def start(self):
-        """Start orphan process monitor."""
-
-        if self._started:
-            return
-        self._started = True
-
-        self._thr.start()
-
-    def stop(self):
-        """Stop orphan process monitor."""
-
-        joinable = self._started
-        self._started = False
-        if joinable:
-            self._thr.join(timeout=1)
-
-    def _do_monitor(self):
-        while self._started:
-            if self._checker.check_orphan():
-                break
-
-            for _ in range(self._interval):
-                if not self._started:
-                    break
-                time.sleep(1)
diff --git a/apps/bitwarden_event_logs/lib/solnlib/pattern.py b/apps/bitwarden_event_logs/lib/solnlib/pattern.py
deleted file mode 100755
index 8008d2c8..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/pattern.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module provides some common used patterns."""
-
-__all__ = ["Singleton"]
-
-
-class Singleton(type):
-    """Singleton meta class.
-
-    Examples:
-       >>> class Test(object):
-       >>>     __metaclass__ = Singleton
-       >>>
-       >>>     def __init__(self):
-       >>>         pass
-    """
-
-    def __init__(cls, name, bases, attrs):
-        super().__init__(name, bases, attrs)
-        cls._instance = None
-
-    def __call__(cls, *args, **kwargs):
-        if cls._instance is None:
-            cls._instance = super().__call__(*args, **kwargs)
-        return cls._instance
diff --git a/apps/bitwarden_event_logs/lib/solnlib/rest.py b/apps/bitwarden_event_logs/lib/solnlib/rest.py
deleted file mode 100755
index df13c303..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/rest.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import json
-import urllib.parse
-from traceback import format_exc
-from typing import Optional
-
-import requests
-
-import logging
-
-
-def splunkd_request(
-    splunkd_uri,
-    session_key,
-    method="GET",
-    headers=None,
-    data=None,
-    timeout=300,
-    retry=1,
-    verify=False,
-) -> Optional[requests.Response]:
-
-    headers = headers if headers is not None else {}
-    headers["Authorization"] = f"Splunk {session_key}"
-    content_type = headers.get("Content-Type")
-    if not content_type:
-        content_type = headers.get("content-type")
-
-    if not content_type:
-        content_type = "application/x-www-form-urlencoded"
-        headers["Content-Type"] = content_type
-
-    if data is not None:
-        if content_type == "application/json":
-            data = json.dumps(data)
-        else:
-            data = urllib.parse.urlencode(data)
-
-    msg_temp = "Failed to send rest request=%s, errcode=%s, reason=%s"
-    resp = None
-    for _ in range(retry):
-        try:
-            resp = requests.request(
-                method=method,
-                url=splunkd_uri,
-                data=data,
-                headers=headers,
-                timeout=timeout,
-                verify=verify,
-            )
-        except Exception:
-            logging.error(msg_temp, splunkd_uri, "unknown", format_exc())
-        else:
-            if resp.status_code not in (200, 201):
-                if not (method == "GET" and resp.status_code == 404):
-                    logging.debug(
-                        msg_temp, splunkd_uri, resp.status_code, code_to_msg(resp)
-                    )
-            else:
-                return resp
-    else:
-        return resp
-
-
-def code_to_msg(response: requests.Response):
-    code_msg_tbl = {
-        400: f"Request error. reason={response.text}",
-        401: "Authentication failure, invalid access credentials.",
-        402: "In-use license disables this feature.",
-        403: "Insufficient permission.",
-        404: "Requested endpoint does not exist.",
-        409: f"Invalid operation for this endpoint. reason={response.text}",
-        500: f"Unspecified internal server error. reason={response.text}",
-        503: (
-            "Feature is disabled in the configuration file. "
-            "reason={}".format(response.text)
-        ),
-    }
-
-    return code_msg_tbl.get(response.status_code, response.text)
diff --git a/apps/bitwarden_event_logs/lib/solnlib/schedule/job.py b/apps/bitwarden_event_logs/lib/solnlib/schedule/job.py
deleted file mode 100755
index bc1ff6de..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/schedule/job.py
+++ /dev/null
@@ -1,122 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import threading
-import time
-
-
-class Job:
-    """Timer wraps the callback and timestamp related stuff."""
-
-    _ident = 0
-    _lock = threading.Lock()
-
-    def __init__(self, func, job_props, interval, when=None, job_id=None):
-        """
-        @job_props: dict like object
-        @func: execution function
-        @interval: execution interval
-        @when: seconds from epoch
-        @job_id: a unique id for the job
-        """
-
-        self._props = job_props
-        self._func = func
-        if when is None:
-            self._when = time.time()
-        else:
-            self._when = when
-        self._interval = interval
-
-        if job_id is not None:
-            self._id = job_id
-        else:
-            with Job._lock:
-                self._id = Job._ident + 1
-                Job._ident = Job._ident + 1
-        self._stopped = False
-
-    def ident(self):
-        return self._id
-
-    def get_interval(self):
-        return self._interval
-
-    def set_interval(self, interval):
-        self._interval = interval
-
-    def get_expiration(self):
-        return self._when
-
-    def set_initial_due_time(self, when):
-        if self._when is None:
-            self._when = when
-
-    def update_expiration(self):
-        self._when += self._interval
-
-    def get(self, key, default):
-        return self._props.get(key, default)
-
-    def get_props(self):
-        return self._props
-
-    def set_props(self, props):
-        self._props = props
-
-    def __cmp__(self, other):
-        if other is None:
-            return 1
-
-        self_k = (self.get_expiration(), self.ident())
-        other_k = (other.get_expiration(), other.ident())
-
-        if self_k == other_k:
-            return 0
-        elif self_k < other_k:
-            return -1
-        else:
-            return 1
-
-    def __eq__(self, other):
-        return isinstance(other, Job) and (self.ident() == other.ident())
-
-    def __lt__(self, other):
-        return self.__cmp__(other) == -1
-
-    def __gt__(self, other):
-        return self.__cmp__(other) == 1
-
-    def __ne__(self, other):
-        return not self.__eq__(other)
-
-    def __le__(self, other):
-        return self.__lt__(other) or self.__eq__(other)
-
-    def __ge__(self, other):
-        return self.__gt__(other) or self.__eq__(other)
-
-    def __hash__(self):
-        return self.ident()
-
-    def __call__(self):
-        self._func(self)
-
-    def stop(self):
-        self._stopped = True
-
-    def stopped(self):
-        return self._stopped
diff --git a/apps/bitwarden_event_logs/lib/solnlib/schedule/scheduler.py b/apps/bitwarden_event_logs/lib/solnlib/schedule/scheduler.py
deleted file mode 100755
index 5d53b439..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/schedule/scheduler.py
+++ /dev/null
@@ -1,162 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import queue
-import random
-import threading
-from time import time
-
-import logging
-
-
-class Scheduler:
-    """A simple scheduler which schedules the periodic or once event."""
-
-    import sortedcontainers as sc
-
-    max_delay_time = 60
-
-    def __init__(self):
-        self._jobs = Scheduler.sc.SortedSet()
-        self._wakeup_q = queue.Queue()
-        self._lock = threading.Lock()
-        self._thr = threading.Thread(target=self._do_jobs)
-        # FIXME: the `daemon` property HAS to be passed in init() call ONLY,
-        # the below attribute setting is of incorrect spelling
-        self._thr.deamon = True
-        self._started = False
-
-    def start(self):
-        """Start the schduler which will start the internal thread for
-        scheduling jobs.
-
-        Please do tear_down when doing cleanup
-        """
-
-        if self._started:
-            logging.info("Scheduler already started.")
-            return
-        self._started = True
-
-        self._thr.start()
-
-    def tear_down(self):
-        """Stop the schduler which will stop the internal thread for scheduling
-        jobs."""
-
-        if not self._started:
-            logging.info("Scheduler already tear down.")
-            return
-
-        self._wakeup_q.put(True)
-
-    def _do_jobs(self):
-        while 1:
-            (sleep_time, jobs) = self.get_ready_jobs()
-            self._do_execution(jobs)
-            try:
-                done = self._wakeup_q.get(timeout=sleep_time)
-            except queue.Empty:
-                pass
-            else:
-                if done:
-                    break
-        self._started = False
-        logging.info("Scheduler exited.")
-
-    def get_ready_jobs(self):
-        """
-        @return: a 2 element tuple. The first element is the next ready
-                 duration. The second element is ready jobs list
-        """
-
-        now = time()
-        ready_jobs = []
-        sleep_time = 1
-
-        with self._lock:
-            job_set = self._jobs
-            total_jobs = len(job_set)
-            for job in job_set:
-                if job.get_expiration() <= now:
-                    ready_jobs.append(job)
-
-            if ready_jobs:
-                del job_set[: len(ready_jobs)]
-
-            for job in ready_jobs:
-                if job.get_interval() != 0 and not job.stopped():
-                    # repeated job, calculate next due time and enqueue
-                    job.update_expiration()
-                    job_set.add(job)
-
-            if job_set:
-                sleep_time = job_set[0].get_expiration() - now
-                if sleep_time < 0:
-                    logging.warn("Scheduler satuation, sleep_time=%s", sleep_time)
-                    sleep_time = 0.1
-
-        if ready_jobs:
-            logging.info(
-                "Get %d ready jobs, next duration is %f, "
-                "and there are %s jobs scheduling",
-                len(ready_jobs),
-                sleep_time,
-                total_jobs,
-            )
-
-        ready_jobs.sort(key=lambda job: job.get("priority", 0), reverse=True)
-        return (sleep_time, ready_jobs)
-
-    def add_jobs(self, jobs):
-        with self._lock:
-            now = time()
-            job_set = self._jobs
-            for job in jobs:
-                delay_time = random.randrange(0, self.max_delay_time)
-                job.set_initial_due_time(now + delay_time)
-                job_set.add(job)
-        self._wakeup()
-
-    def update_jobs(self, jobs):
-        with self._lock:
-            job_set = self._jobs
-            for njob in jobs:
-                job_set.discard(njob)
-                job_set.add(njob)
-        self._wakeup()
-
-    def remove_jobs(self, jobs):
-        with self._lock:
-            job_set = self._jobs
-            for njob in jobs:
-                njob.stop()
-                job_set.discard(njob)
-        self._wakeup()
-
-    def number_of_jobs(self):
-        with self._lock:
-            return len(self._jobs)
-
-    def disable_randomization(self):
-        self.max_delay_time = 1
-
-    def _wakeup(self):
-        self._wakeup_q.put(None)
-
-    def _do_execution(self, jobs):
-        for job in jobs:
-            job()
diff --git a/apps/bitwarden_event_logs/lib/solnlib/server_info.py b/apps/bitwarden_event_logs/lib/solnlib/server_info.py
deleted file mode 100755
index 56f2c006..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/server_info.py
+++ /dev/null
@@ -1,308 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module contains Splunk server info related functionalities."""
-
-import os
-import json
-from typing import Any, Dict, Optional
-
-try:
-    from splunk.rest import getWebCertFile, getWebKeyFile
-except (ModuleNotFoundError, ImportError):
-
-    def getWebCertFile():
-        return None
-
-    def getWebKeyFile():
-        return None
-
-
-try:
-    from splunk.rest import is_cert_or_key_encrypted
-except (ModuleNotFoundError, ImportError):
-
-    def is_cert_or_key_encrypted(cert_filename):
-        return False
-
-
-from splunklib import binding
-from solnlib import splunk_rest_client as rest_client
-from solnlib import utils
-from solnlib.splunkenv import get_splunkd_access_info
-
-__all__ = ["ServerInfo", "ServerInfoException"]
-
-
-class ServerInfoException(Exception):
-    """Exception raised by ServerInfo class."""
-
-    pass
-
-
-class ServerInfo:
-    """This class is a wrapper of Splunk server info."""
-
-    SHC_MEMBER_ENDPOINT = "/services/shcluster/member/members"
-    SHC_CAPTAIN_INFO_ENDPOINT = "/services/shcluster/captain/info"
-
-    def __init__(
-        self,
-        session_key: str,
-        scheme: Optional[str] = None,
-        host: Optional[str] = None,
-        port: Optional[int] = None,
-        **context: Any
-    ):
-        """Initializes ServerInfo.
-
-        Arguments:
-            session_key: Splunk access token.
-            scheme: The access scheme, default is None.
-            host: The host name, default is None.
-            port: The port number, default is None.
-            context: Other configurations for Splunk rest client.
-        """
-        is_localhost = False
-        if not all([scheme, host, port]) and os.environ.get("SPLUNK_HOME"):
-            scheme, host, port = get_splunkd_access_info(session_key)
-            is_localhost = (
-                host == "localhost" or host == "127.0.0.1" or host in ("::1", "[::1]")
-            )
-
-        web_key_file = getWebKeyFile()
-        web_cert_file = getWebCertFile()
-        if web_cert_file and (
-            web_key_file is None or not is_cert_or_key_encrypted(web_key_file)
-        ):
-            context["cert_file"] = web_cert_file
-
-            if web_key_file is not None:
-                context["key_file"] = web_key_file
-
-            if all([is_localhost, context.get("verify") is None]):
-                # NOTE: this is specifically for mTLS communication
-                # ONLY if scheme, host, port aren't provided AND user hasn't provided server certificate
-                # we set verify to off (similar to 'rest.simpleRequest' implementation)
-                context["verify"] = False
-
-        self._rest_client = rest_client.SplunkRestClient(
-            session_key, "-", scheme=scheme, host=host, port=port, **context
-        )
-
-    @classmethod
-    def from_server_uri(
-        cls, server_uri: str, session_key: str, **context: Any
-    ) -> "ServerInfo":
-        """Creates ServerInfo class using server_uri and session_key.
-
-        Note: splunktalib uses these parameters to create it's ServerInfo class,
-        so this method should ease the transition from splunktalib to solnlib.
-
-        Arguments:
-            server_uri: splunkd URI.
-            session_key: Splunk access token.
-            context: Other configurations for Splunk rest client.
-
-        Returns:
-            An instance of `ServerInfo`.
-
-        Raises:
-            ValueError: server_uri is in the wrong format.
-        """
-        scheme, host, port = utils.extract_http_scheme_host_port(server_uri)
-        return ServerInfo(
-            session_key,
-            scheme=scheme,
-            host=host,
-            port=port,
-            **context,
-        )
-
-    def to_dict(self) -> Dict:
-        """Returns server information in a form dictionary.
-
-        Note: This method is implemented here to have compatibility with splunktalib's
-        analogue.
-
-        Returns:
-            Server information in a dictionary format.
-        """
-        return self._server_info()
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def _server_info(self):
-        return self._rest_client.info
-
-    @property
-    def server_name(self) -> str:
-        """Get server name.
-
-        Returns:
-            Server name.
-        """
-        return self._server_info()["serverName"]
-
-    @property
-    def guid(self) -> str:
-        """Get guid for the server.
-
-        Returns:
-            Server GUID.
-        """
-        return self._server_info()["guid"]
-
-    @property
-    def version(self) -> str:
-        """Get Splunk server version.
-
-        Returns:
-            Splunk version.
-        """
-        return self._server_info()["version"]
-
-    def is_captain(self) -> bool:
-        """Check if this server is SHC captain.
-
-        Note during a rolling start of SH members, the captain may be changed
-        from machine to machine. To avoid the race condition, client may need
-        do necessary sleep and then poll `is_captain_ready() == True` and then
-        check `is_captain()`. See `is_captain_ready()` for more details.
-
-        Returns:
-            True if this server is SHC captain else False.
-        """
-
-        return "shc_captain" in self._server_info()["server_roles"]
-
-    def is_cloud_instance(self) -> bool:
-        """Check if this server is a cloud instance.
-
-        Returns:
-            True if this server is a cloud instance else False.
-        """
-
-        try:
-            return self._server_info()["instance_type"] == "cloud"
-        except KeyError:
-            return False
-
-    def is_search_head(self) -> bool:
-        """Check if this server is a search head.
-
-        Returns:
-            True if this server is a search head else False.
-        """
-
-        server_info = self._server_info()
-        for sh in ("search_head", "cluster_search_head"):
-            if sh in server_info["server_roles"]:
-                return True
-
-        return False
-
-    def is_shc_member(self) -> bool:
-        """Check if this server is a SHC member.
-
-        Returns:
-            True if this server is a SHC member else False.
-        """
-
-        server_info = self._server_info()
-        for sh in ("shc_member", "shc_captain"):
-            if sh in server_info["server_roles"]:
-                return True
-
-        return False
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def get_shc_members(self) -> list:
-        """Get SHC members.
-
-        Raises:
-            ServerInfoException: If this server has no SHC members.
-
-        Returns:
-            List of SHC members [(label, peer_scheme_host_port) ...].
-        """
-        try:
-            content = self._rest_client.get(
-                self.SHC_MEMBER_ENDPOINT, output_mode="json"
-            ).body.read()
-        except binding.HTTPError as e:
-            if e.status != 404 and e.status != 503:
-                raise
-
-            raise ServerInfoException(
-                "This server is not a SHC member and has no SHC members."
-            )
-
-        members = []
-        for member in json.loads(content)["entry"]:
-            content = member["content"]
-            members.append((content["label"], content["peer_scheme_host_port"]))
-
-        return members
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def is_captain_ready(self) -> bool:
-        """Check if captain is ready.
-
-        Client usually first polls this function until captain is ready
-        and then call is_captain to detect current captain machine
-
-        Returns:
-            True if captain is ready else False.
-
-        Examples:
-            >>> from solnlib import server_info
-            >>> serverinfo = server_info.ServerInfo(session_key)
-            >>> while 1:
-            >>>    if serverinfo.is_captain_ready():
-            >>>        break
-            >>>    time.sleep(2)
-            >>>
-            >>> # If do_stuff can only be executed in SH captain
-            >>> if serverinfo.is_captain():
-            >>>    do_stuff()
-        """
-
-        cap_info = self.captain_info()
-        return utils.is_true(cap_info["service_ready_flag"]) and utils.is_false(
-            cap_info["maintenance_mode"]
-        )
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def captain_info(self) -> dict:
-        """Get captain information.
-
-        Raises:
-            ServerInfoException: If there is SHC is not enabled.
-
-        Returns:
-            Captain information.
-        """
-
-        try:
-            content = self._rest_client.get(
-                self.SHC_CAPTAIN_INFO_ENDPOINT, output_mode="json"
-            ).body.read()
-        except binding.HTTPError as e:
-            if e.status == 503 and "not available" in str(e):
-                raise ServerInfoException(str(e))
-            raise
-
-        return json.loads(content)["entry"][0]["content"]
diff --git a/apps/bitwarden_event_logs/lib/solnlib/soln_exceptions.py b/apps/bitwarden_event_logs/lib/solnlib/soln_exceptions.py
deleted file mode 100755
index 65d74a64..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/soln_exceptions.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-class ConfManagerException(Exception):
-    """Exception raised by ConfManager class."""
-
-    pass
-
-
-class ConfStanzaNotExistException(Exception):
-    """Exception raised by ConfFile class."""
-
-    pass
-
-
-class InvalidPortError(ValueError):
-    """Exception raised when an invalid proxy port is provided."""
-
-    pass
-
-
-class InvalidHostnameError(ValueError):
-    """Exception raised when an invalid proxy hostname is provided."""
-
-    pass
diff --git a/apps/bitwarden_event_logs/lib/solnlib/splunk_rest_client.py b/apps/bitwarden_event_logs/lib/solnlib/splunk_rest_client.py
deleted file mode 100755
index d960a2e3..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/splunk_rest_client.py
+++ /dev/null
@@ -1,245 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module proxy all REST call to splunklib SDK, it handles proxy, certs
-etc in this centralized location.
-
-All clients should use SplunkRestProxy to do REST call instead of
-calling splunklib SDK directly in business logic code.
-"""
-
-import logging
-import os
-import sys
-import traceback
-import solnlib
-
-from io import BytesIO
-from urllib.parse import quote
-from urllib3.util.retry import Retry
-from splunklib import binding, client
-
-from .net_utils import validate_scheme_host_port
-from .splunkenv import get_splunkd_access_info
-
-__all__ = ["SplunkRestClient"]
-MAX_REQUEST_RETRIES = 5
-
-
-def _get_proxy_info(context):
-    if not context.get("proxy_hostname") or not context.get("proxy_port"):
-        return None
-
-    user_pass = ""
-    if context.get("proxy_username") and context.get("proxy_password"):
-        username = quote(context["proxy_username"], safe="")
-        password = quote(context["proxy_password"], safe="")
-        user_pass = f"{username}:{password}@"
-
-    proxy = "http://{user_pass}{host}:{port}".format(
-        user_pass=user_pass, host=context["proxy_hostname"], port=context["proxy_port"]
-    )
-    proxies = {
-        "http": proxy,
-        "https": proxy,
-    }
-    return proxies
-
-
-def _request_handler(context):
-    """
-    :param context: Http connection context can contain the following
-        key/values: {
-        'proxy_hostname': string,
-        'proxy_port': int,
-        'proxy_username': string,
-        'proxy_password': string,
-        'key_file': string,
-        'cert_file': string
-        'pool_connections', int,
-        'pool_maxsize', int,
-        }
-    :type content: dict
-    """
-
-    try:
-        import requests
-    except ImportError:
-        # FIXME proxy ?
-        return binding.handler(
-            key_file=context.get("key_file"), cert_file=context.get("cert_file")
-        )
-
-    try:
-        requests.urllib3.disable_warnings()
-    except AttributeError:
-        pass
-
-    proxies = _get_proxy_info(context)
-    verify = context.get("verify", False)
-
-    if context.get("key_file") and context.get("cert_file"):
-        # cert: if tuple, ('cert', 'key') pair as per requests library
-        cert = context["cert_file"], context["key_file"]
-    elif context.get("cert_file"):
-        cert = context["cert_file"]
-    elif context.get("cert"):
-        # as the solnlib uses requests, we need to have a check for 'cert' key as well
-        cert = context["cert"]
-    else:
-        cert = None
-
-    retries = Retry(
-        total=MAX_REQUEST_RETRIES,
-        backoff_factor=0.3,
-        status_forcelist=[500, 502, 503, 504],
-        allowed_methods=["GET", "POST", "PUT", "DELETE"],
-        raise_on_status=False,
-    )
-    if context.get("pool_connections", 0):
-        logging.info("Use HTTP connection pooling")
-        session = requests.Session()
-        adapter = requests.adapters.HTTPAdapter(
-            max_retries=retries,
-            pool_connections=context.get("pool_connections", 10),
-            pool_maxsize=context.get("pool_maxsize", 10),
-        )
-        session.mount("https://", adapter)
-        req_func = session.request
-    else:
-        req_func = requests.request
-
-    def request(url, message, **kwargs):
-        """
-        :param url: URL
-        :type url: string
-        :param message: Can contain following key/values: {
-            'method': 'GET' or 'DELETE', or 'PUT' or 'POST'
-            'headers': [[key, value], [key, value], ...],
-            'body': string
-            }
-        :type message: dict
-        """
-
-        body = message.get("body")
-        headers = {
-            "User-Agent": f"solnlib/{solnlib.__version__} rest-client {sys.platform}",
-            "Accept": "*/*",
-            "Connection": "Keep-Alive",
-        }
-
-        if body:
-            headers["Content-Length"] = str(len(body))
-
-        for key, value in message["headers"]:
-            headers[key] = value
-
-        method = message.get("method", "GET")
-
-        try:
-            resp = req_func(
-                method,
-                url,
-                data=body,
-                headers=headers,
-                stream=False,
-                verify=verify,
-                proxies=proxies,
-                cert=cert,
-                **kwargs,
-            )
-        except Exception:
-            logging.error(
-                "Failed to issue http request=%s to url=%s, error=%s",
-                method,
-                url,
-                traceback.format_exc(),
-            )
-            raise
-
-        return {
-            "status": resp.status_code,
-            "reason": resp.reason,
-            "headers": dict(resp.headers),
-            "body": BytesIO(resp.content),
-        }
-
-    return request
-
-
-class SplunkRestClient(client.Service):
-    """Splunk REST client."""
-
-    def __init__(
-        self,
-        session_key: str,
-        app: str,
-        owner: str = "nobody",
-        scheme: str = None,
-        host: str = None,
-        port: int = None,
-        **context: dict,
-    ):
-        """Initializes SplunkRestClient.
-
-        Arguments `scheme`, `host` and `port` are optional in the Splunk
-        environment (when environment variable SPLUNK_HOME is set). In this
-        situation `get_splunkd_access_info` will be used to set `scheme`,
-        `host` and `port`. In case of using `SplunkRestClient` outside of
-        Splunk environment - `scheme`, `host` and `port` should be provided.
-
-        Arguments:
-            session_key: Splunk access token.
-            app: App name of namespace.
-            owner: Owner of namespace, default is `nobody`.
-            scheme: The access scheme, default is None.
-            host: The host name, default is None.
-            port: The port number, default is None.
-            context: Other configurations, it can contain `proxy_hostname`,
-                `proxy_port`, `proxy_username`, `proxy_password`, then proxy will
-                be accounted and setup, all REST APIs to splunkd will be through
-                the proxy. If `context` contains `key_file`, `cert_file`, then
-                certification will be accounted and setup, all REST APIs to splunkd
-                will use certification. If `context` contains `pool_connections`,
-                `pool_maxsize`, then HTTP connection will be pooled.
-
-        Raises:
-            ValueError: if scheme, host or port are invalid.
-        """
-        # Only do splunkd URI discovery in SPLUNK env (SPLUNK_HOME is set).
-        if not all([scheme, host, port]) and os.environ.get("SPLUNK_HOME"):
-            scheme, host, port = get_splunkd_access_info(session_key)
-        if os.environ.get("SPLUNK_HOME") is None:
-            if not all([scheme, host, port]):
-                raise ValueError(
-                    "scheme, host, port should be provided outside of Splunk environment"
-                )
-
-        validate_scheme_host_port(scheme, host, port)
-        if host == "[::1]":
-            host = "::1"
-
-        handler = _request_handler(context)
-        super().__init__(
-            handler=handler,
-            scheme=scheme,
-            host=host,
-            port=port,
-            token=session_key,
-            app=app,
-            owner=owner,
-            autologin=True,
-        )
diff --git a/apps/bitwarden_event_logs/lib/solnlib/splunkenv.py b/apps/bitwarden_event_logs/lib/solnlib/splunkenv.py
deleted file mode 100755
index 09ce12de..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/splunkenv.py
+++ /dev/null
@@ -1,414 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""Splunk platform related utilities."""
-
-
-import os
-import os.path as op
-import socket
-import subprocess
-import json
-from configparser import ConfigParser
-from io import StringIO
-from typing import List, Optional, Tuple, Union
-import __main__
-from solnlib._settings import use_btool
-from .utils import is_true
-
-try:
-    from splunk.rest import simpleRequest
-except ImportError:
-
-    def simpleRequest(*args, **kwargs):
-        raise ImportError("This module requires Splunk to be installed.")
-
-
-try:
-    from splunk import getSessionKey
-except ImportError:
-
-    def getSessionKey(*args, **kwargs):
-        raise ImportError("This module requires Splunk to be installed.")
-
-
-try:
-    from splunk.clilib.bundle_paths import make_splunkhome_path as msp
-except ImportError:
-
-    def msp(*args, **kwargs):
-        raise ImportError("This module requires Splunk to be installed.")
-
-
-__all__ = [
-    "make_splunkhome_path",
-    "get_splunk_host_info",
-    "get_splunk_bin",
-    "get_splunkd_access_info",
-    "get_scheme_from_hec_settings",
-    "get_splunkd_uri",
-    "get_conf_key_value",
-    "get_conf_stanza",
-    "get_conf_stanzas",
-]
-
-ETC_LEAF = "etc"
-APP_SYSTEM = "system"
-APP_HEC = "splunk_httpinput"
-
-
-class SessionKeyNotFound(Exception):
-    pass
-
-
-def make_splunkhome_path(parts: Union[List, Tuple]) -> str:
-    """Construct absolute path by $SPLUNK_HOME and `parts`.
-
-    Concatenate $SPLUNK_HOME and `parts` to an absolute path.
-    For example, `parts` is ['etc', 'apps', 'Splunk_TA_test'],
-    the return path will be $SPLUNK_HOME/etc/apps/Splunk_TA_test.
-    Note: this function assumed SPLUNK_HOME is in environment varialbes.
-
-    Arguments:
-        parts: Path parts.
-
-    Returns:
-        Absolute path.
-
-    Raises:
-        ValueError: Escape from intended parent directories.
-    """
-    return msp(parts)
-
-
-def get_splunk_host_info(session_key: Optional[str] = None) -> Tuple:
-    """Get splunk host info.
-
-    Arguments:
-        session_key: Needed to make a call to config endpoint. If 'None', solnlib will try to get it from
-            splunk.getSessionKey() and/or __main__ module and if it won't get it, SessionKeyNotFound will be raised.
-    Returns:
-        Tuple of (server_name, host_name).
-    """
-
-    server_name = get_conf_key_value(
-        "server",
-        "general",
-        "serverName",
-        APP_SYSTEM,
-        session_key=session_key,
-    )
-    host_name = socket.gethostname()
-
-    return server_name, host_name
-
-
-def get_splunk_bin() -> str:
-    """Get absolute path of splunk CLI.
-
-    Returns:
-        Absolute path of splunk CLI.
-    """
-
-    if os.name == "nt":
-        splunk_bin = "splunk.exe"
-    else:
-        splunk_bin = "splunk"
-    return make_splunkhome_path(("bin", splunk_bin))
-
-
-def get_splunkd_access_info(session_key: Optional[str] = None) -> Tuple[str, str, int]:
-    """Get splunkd server access info.
-
-    Arguments:
-        session_key: Needed to make a call to config endpoint. If 'None', solnlib will try to get it from
-            splunk.getSessionKey() and/or __main__ module and if it won't get it, SessionKeyNotFound will be raised.
-    Returns:
-        Tuple of (scheme, host, port).
-    """
-    enable_splunkd_ssl = get_conf_key_value(
-        "server",
-        "sslConfig",
-        "enableSplunkdSSL",
-        APP_SYSTEM,
-        session_key=session_key,
-    )
-
-    if is_true(enable_splunkd_ssl):
-        scheme = "https"
-    else:
-        scheme = "http"
-
-    host_port = get_conf_key_value(
-        "web",
-        "settings",
-        "mgmtHostPort",
-        APP_SYSTEM,
-        session_key=session_key,
-    )
-    host_port = host_port.strip()
-    host_port_split_parts = host_port.split(":")
-    host = ":".join(host_port_split_parts[:-1])
-    port = int(host_port_split_parts[-1])
-
-    if "SPLUNK_BINDIP" in os.environ:
-        bindip = os.environ["SPLUNK_BINDIP"]
-        port_idx = bindip.rfind(":")
-        host = bindip[:port_idx] if port_idx > 0 else bindip
-
-    return scheme, host, port
-
-
-def get_scheme_from_hec_settings(session_key: Optional[str] = None) -> str:
-    """Get scheme from HEC global settings.
-
-    Arguments:
-        session_key: Needed to make a call to config endpoint. If 'None', solnlib will try to get it from
-            splunk.getSessionKey() and/or __main__ module and if it won't get it, SessionKeyNotFound will be raised.
-    Returns:
-        scheme (str)
-    """
-    try:
-        ssl_enabled = get_conf_key_value(
-            "inputs",
-            "http",
-            "enableSSL",
-            APP_HEC,
-            session_key=session_key,
-        )
-    except KeyError:
-        raise KeyError(
-            "Cannot get enableSSL setting form conf: 'inputs' and stanza: '[http]'. "
-            "Verify that your Splunk instance has the inputs.conf file with the correct [http] stanza. "
-            "For more information see: "
-            "https://docs.splunk.com/Documentation/Splunk/9.2.0/Data/UseHECusingconffiles"
-        )
-
-    if is_true(ssl_enabled):
-        scheme = "https"
-    else:
-        scheme = "http"
-
-    return scheme
-
-
-def get_splunkd_uri(session_key: Optional[str] = None) -> str:
-    """Get splunkd uri.
-
-    Arguments:
-        session_key: Needed to make a call to config endpoint. If 'None', solnlib will try to get it from
-            splunk.getSessionKey() and/or __main__ module and if it won't get it, SessionKeyNotFound will be raised.
-    Returns:
-        Splunkd uri.
-    """
-
-    if os.environ.get("SPLUNKD_URI"):
-        return os.environ["SPLUNKD_URI"]
-
-    scheme, host, port = get_splunkd_access_info(session_key)
-    return f"{scheme}://{host}:{port}"
-
-
-def get_conf_key_value(
-    conf_name: str,
-    stanza: str,
-    key: str,
-    app_name: str,
-    session_key: Optional[str] = None,
-    user: str = "nobody",
-    raw_output: Optional[bool] = False,
-) -> Union[str, List, dict]:
-    """Get value of `key` of `stanza` in `conf_name`.
-
-    Arguments:
-        conf_name: Config file.
-        stanza: Stanza name.
-        key: Key name in the stanza.
-        app_name: Application name. To make a call to global context use '-' as app_name and set raw_output=True.
-            In that case manual parsing is needed as response may be the list with multiple entries.
-        session_key: Needed to make a call to config endpoint. If 'None', solnlib will try to get it from
-            splunk.getSessionKey() and/or __main__ module and if it won't get it, SessionKeyNotFound will be raised.
-        user: used for set user context in API call. Optional.
-        raw_output: if 'true' full, decoded response in json format will be returned. It should be set to True when
-            app_name is a global context '/-/'. In that case splunk API may return multiple entries.
-
-    Returns:
-        Config value.
-
-    Raises:
-        KeyError: If `stanza` or `key` doesn't exist.
-    """
-
-    if use_btool:
-        app = None if app_name == "-" else app_name
-        stanzas = get_conf_stanzas(conf_name, app)
-        return stanzas[stanza][key]
-
-    stanzas = _get_conf_stanzas_from_splunk_api(
-        conf_name, app_name, session_key=session_key, user=user, stanza=stanza
-    )
-
-    if raw_output:
-        return stanzas
-
-    stanza = stanzas.get("entry")[0].get("content")
-    requested_key = stanza[key]
-    return requested_key
-
-
-def get_conf_stanza(
-    conf_name: str,
-    stanza: str,
-    app_name: str,
-    session_key: Optional[str] = None,
-    user: str = "nobody",
-    raw_output: Optional[bool] = False,
-) -> dict:
-    """Get `stanza` in `conf_name`.
-
-    Arguments:
-        conf_name: Config file.
-        stanza: Stanza name.
-        app_name: Application name. To make a call to global context use '-' as app_name and set raw_output=True.
-            In that case manual parsing is needed as response may be the list with multiple entries.
-        session_key: Needed to make a call to config endpoint. If 'None', solnlib will try to get it from
-            splunk.getSessionKey() and/or __main__ module and if it won't get it, SessionKeyNotFound will be raised.
-        user: used for set user context in API call. Optional.
-        raw_output: if 'true' full, decoded response in json format will be returned. It should be set to True when
-            app_name is a global context '/-/'. In that case splunk API may return multiple entries.
-
-    Returns:
-        Config stanza.
-
-    Raises:
-         KeyError: If stanza doesn't exist.
-    """
-
-    if use_btool:
-        app = None if app_name == "-" else app_name
-        stanzas = get_conf_stanzas(conf_name, app)
-        return stanzas[stanza]
-
-    stanzas = _get_conf_stanzas_from_splunk_api(
-        conf_name, app_name, session_key=session_key, user=user, stanza=stanza
-    )
-
-    if raw_output:
-        return stanzas
-
-    stanza = stanzas.get("entry")[0].get("content")
-    return stanza
-
-
-def get_conf_stanzas(conf_name: str, app_name: Optional[str] = None) -> dict:
-    """Get stanzas of `conf_name`
-
-    Arguments:
-        conf_name: Config file.
-        app_name: Application name. Optional.
-
-    Returns:
-        Config stanzas.
-
-    Examples:
-       >>> stanzas = get_conf_stanzas('server')
-       >>> return: {'serverName': 'testServer', 'sessionTimeout': '1h', ...}
-    """
-
-    if conf_name.endswith(".conf"):
-        conf_name = conf_name[:-5]
-
-    # TODO: dynamically calculate SPLUNK_HOME
-    btool_cli = [
-        op.join(os.environ["SPLUNK_HOME"], "bin", "splunk"),
-        "cmd",
-        "btool",
-        conf_name,
-        "list",
-    ]
-
-    if app_name:
-        btool_cli.append(f"--app={app_name}")
-
-    p = subprocess.Popen(  # nosemgrep: python.lang.security.audit.dangerous-subprocess-use.dangerous-subprocess-use
-        btool_cli, stdout=subprocess.PIPE, stderr=subprocess.PIPE
-    )
-    out, _ = p.communicate()
-
-    if isinstance(out, bytes):
-        out = out.decode()
-
-    parser = ConfigParser(**{"strict": False})
-    parser.optionxform = str
-    parser.read_file(StringIO(out))
-
-    out = {}
-    for section in parser.sections():
-        out[section] = {item[0]: item[1] for item in parser.items(section, raw=True)}
-    return out
-
-
-def _get_conf_stanzas_from_splunk_api(
-    conf_name: str,
-    app_name: str,
-    session_key: Optional[str] = None,
-    user: str = "nobody",
-    stanza: Optional[str] = None,
-) -> dict:
-    """Get stanzas of `conf_name` using splunk API:
-
-    /servicesNS/{user}/{app_name}/configs/conf-{conf_name}/{stanza}
-
-    Arguments:
-        conf_name: Config file.
-        app_name: Application name. To make a call to global context use '-' as app_name and set raw_output=True.
-            In that case manual parsing is needed as response may be the list with multiple entries.
-        session_key: Needed to make a call to config endpoint. If 'None', solnlib will try to get it from
-            splunk.getSessionKey() and/or __main__ module and if it won't get it, SessionKeyNotFound will be raised.
-        user: used for set user context in API call. Optional.
-        stanza: Stanza name. Optional.
-
-    Returns:
-        json response.
-    """
-
-    url = f"/servicesNS/{user}/{app_name}/configs/conf-{conf_name}"
-
-    if stanza:
-        url = url + "/" + stanza
-
-    if not session_key:
-        session_key = getSessionKey()
-
-    if not session_key and hasattr(__main__, "___sessionKey"):
-        session_key = getattr(__main__, "___sessionKey")
-
-    if not session_key:
-        raise SessionKeyNotFound(
-            "Session key is missing. If you are using 'splunkenv' module in your TA, please ensure you are "
-            "providing session_key to it's functions. For more information "
-            "please see: https://splunk.github.io/addonfactory-solutions-library-python/release_7_0_0/"
-        )
-
-    server_response, server_content = simpleRequest(
-        url,
-        sessionKey=session_key,
-        getargs={"output_mode": "json"},
-    )
-
-    result = json.loads(server_content.decode())
-
-    return result
diff --git a/apps/bitwarden_event_logs/lib/solnlib/time_parser.py b/apps/bitwarden_event_logs/lib/solnlib/time_parser.py
deleted file mode 100755
index 64b40ebf..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/time_parser.py
+++ /dev/null
@@ -1,151 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""This module provides interfaces to parse and convert timestamp."""
-
-import datetime
-import json
-from typing import Any
-
-from splunklib import binding
-
-from . import splunk_rest_client as rest_client
-from .utils import retry
-
-__all__ = ["TimeParser"]
-
-
-class InvalidTimeFormatException(Exception):
-    """Exception for invalid time format."""
-
-    pass
-
-
-class TimeParser:
-    """Datetime parser.
-
-    Use splunkd rest to parse datetime.
-
-    Examples:
-       >>> from solnlib import time_parser
-       >>> tp = time_parser.TimeParser(session_key)
-       >>> tp.to_seconds('2011-07-06T21:54:23.000-07:00')
-       >>> tp.to_utc('2011-07-06T21:54:23.000-07:00')
-       >>> tp.to_local('2011-07-06T21:54:23.000-07:00')
-    """
-
-    URL = "/services/search/timeparser"
-
-    def __init__(
-        self,
-        session_key: str,
-        scheme: str = None,
-        host: str = None,
-        port: int = None,
-        **context: Any,
-    ):
-        """Initializes TimeParser.
-
-        Arguments:
-            session_key: Splunk access token.
-            scheme: (optional) The access scheme, default is None.
-            host: (optional) The host name, default is None.
-            port: (optional) The port number, default is None.
-            context: Other configurations for Splunk rest client.
-
-        Raises:
-            ValueError: if scheme, host or port are invalid.
-        """
-        self._rest_client = rest_client.SplunkRestClient(
-            session_key, "-", scheme=scheme, host=host, port=port, **context
-        )
-
-    @retry(exceptions=[binding.HTTPError])
-    def to_seconds(self, time_str: str) -> float:
-        """Parse `time_str` and convert to seconds since epoch.
-
-        Arguments:
-            time_str: ISO8601 format timestamp, example: 2011-07-06T21:54:23.000-07:00.
-
-        Raises:
-            binding.HTTPError: rest client returns an exception (everything
-                else than 400 code).
-            InvalidTimeFormatException: when time format is invalid (rest
-                client returns 400 code).
-
-        Returns:
-            Seconds since epoch.
-        """
-
-        try:
-            response = self._rest_client.get(
-                self.URL, output_mode="json", time=time_str, output_time_format="%s"
-            ).body.read()
-        except binding.HTTPError as e:
-            if e.status != 400:
-                raise
-
-            raise InvalidTimeFormatException(f"Invalid time format: {time_str}.")
-
-        seconds = json.loads(response)[time_str]
-        return float(seconds)
-
-    def to_utc(self, time_str: str) -> datetime.datetime:
-        """Parse `time_str` and convert to UTC timestamp.
-
-        Arguments:
-            time_str: ISO8601 format timestamp, example: 2011-07-06T21:54:23.000-07:00.
-
-        Raises:
-            binding.HTTPError: rest client returns an exception (everything
-                else than 400 code).
-            InvalidTimeFormatException: when time format is invalid (rest
-                client returns 400 code).
-
-        Returns:
-            UTC timestamp.
-        """
-
-        return datetime.datetime.utcfromtimestamp(self.to_seconds(time_str))
-
-    @retry(exceptions=[binding.HTTPError])
-    def to_local(self, time_str: str) -> str:
-        """Parse `time_str` and convert to local timestamp.
-
-        Arguments:
-            time_str: ISO8601 format timestamp, example: 2011-07-06T21:54:23.000-07:00.
-
-        Raises:
-            binding.HTTPError: rest client returns an exception (everything
-                else than 400 code).
-            InvalidTimeFormatException: when time format is invalid (rest
-                client returns 400 code).
-
-        Returns:
-            Local timestamp in ISO8601 format.
-        """
-
-        try:
-            response = self._rest_client.get(
-                self.URL, output_mode="json", time=time_str
-            ).body.read()
-        except binding.HTTPError as e:
-            if e.status != 400:
-                raise
-
-            raise InvalidTimeFormatException(f"Invalid time format: {time_str}.")
-
-        return json.loads(response)[time_str]
diff --git a/apps/bitwarden_event_logs/lib/solnlib/timer_queue.py b/apps/bitwarden_event_logs/lib/solnlib/timer_queue.py
deleted file mode 100755
index 53d7d439..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/timer_queue.py
+++ /dev/null
@@ -1,324 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""A simple thread safe timer queue implementation which has O(logn) time
-complexity."""
-import logging
-import queue as Queue
-import threading
-import traceback
-from time import time
-from typing import Callable, List, Tuple
-
-import sortedcontainers as sc
-
-__all__ = ["Timer", "TimerQueueStruct", "TimerQueue"]
-
-
-class Timer:
-    """Timer wraps the callback and timestamp related attributes."""
-
-    _ident = 0
-    _lock = threading.Lock()
-
-    def __init__(self, callback: Callable, when: int, interval: int, ident: int = None):
-        """Initializes Timer.
-
-        Arguments:
-            callback: Arbitrary callable object.
-            when: The first expiration time, seconds since epoch.
-            interval: Timer interval, if equals 0, one time timer, otherwise
-                the timer will be periodically executed.
-            ident: (optional) Timer identity.
-        """
-        self._callback = callback
-        self.when = when
-        self.interval = interval
-
-        if ident is not None:
-            self.ident = ident
-        else:
-            with Timer._lock:
-                self.ident = Timer._ident + 1
-                Timer._ident = Timer._ident + 1
-
-    def update_expiration(self):
-        self.when += self.interval
-
-    def __hash__(self):
-        return hash(self.ident)
-
-    def __eq__(self, other):
-        return isinstance(other, Timer) and (self.ident == other.ident)
-
-    def __lt__(self, other):
-        return (self.when, self.ident) < (other.when, other.ident)
-
-    def __le__(self, other):
-        return (self.when, self.ident) <= (other.when, other.ident)
-
-    def __gt__(self, other):
-        return (self.when, self.ident) > (other.when, other.ident)
-
-    def __ge__(self, other):
-        return (self.when, self.ident) >= (other.when, other.ident)
-
-    def __call__(self):
-        self._callback()
-
-
-TEARDOWN_SENTINEL = None
-
-
-class TimerQueueStruct:
-    """The underlying data structure for TimerQueue."""
-
-    def __init__(self):
-        self._timers = sc.SortedSet()
-        self._cancelling_timers = {}
-
-    def add_timer(
-        self, callback: Callable, when: int, interval: int, ident: int
-    ) -> Timer:
-        """Add timer to the data structure.
-
-        Arguments:
-            callback: Arbitrary callable object.
-            when: The first expiration time, seconds since epoch.
-            interval: Timer interval, if equals 0, one time timer, otherwise
-                the timer will be periodically executed
-            ident: (optional) Timer identity.
-
-        Returns:
-            A timer object which should not be manipulated directly by
-                clients. Used to delete/update the timer.
-        """
-
-        timer = Timer(callback, when, interval, ident)
-        self._timers.add(timer)
-        return timer
-
-    def remove_timer(self, timer: Timer):
-        """Remove timer from data structure.
-
-        Arguments:
-            timer: Timer object which is returned by ``TimerQueueStruct.add_timer``.
-        """
-
-        try:
-            self._timers.remove(timer)
-        except ValueError:
-            logging.info(
-                "Timer=%s is not in queue, move it to cancelling " "list", timer.ident
-            )
-        else:
-            self._cancelling_timers[timer.ident] = timer
-
-    def get_expired_timers(self) -> Tuple:
-        """Get a list of expired timers.
-
-        Returns:
-            A tuple of ``Timer``, empty list if there is no expired timers.
-        """
-
-        next_expired_time = 0
-        now = time()
-        expired_timers = []
-        for timer in self._timers:
-            if timer.when <= now:
-                expired_timers.append(timer)
-
-        if expired_timers:
-            del self._timers[: len(expired_timers)]
-
-        if self._timers:
-            next_expired_time = self._timers[0].when
-        return next_expired_time, expired_timers
-
-    def reset_timers(self, expired_timers: List[Timer]) -> bool:
-        """Re-add the expired periodical timers to data structure for next
-        round scheduling.
-
-        Arguments:
-            expired_timers: List of expired timers.
-
-        Returns:
-            True if there are timers added, False otherwise.
-        """
-
-        has_new_timer = False
-        cancelling_timers = self._cancelling_timers
-        for timer in expired_timers:
-            if timer.ident in cancelling_timers:
-                continue
-            elif timer.interval:
-                # Repeated timer
-                timer.update_expiration()
-                self._timers.add(timer)
-                has_new_timer = True
-        cancelling_timers.clear()
-        return has_new_timer
-
-    def check_and_execute(self) -> float:
-        """Get expired timers and execute callbacks for the timers.
-
-        Returns:
-            Duration of next expired timer.
-        """
-
-        (next_expired_time, expired_timers) = self.get_expired_timers()
-        for timer in expired_timers:
-            try:
-                timer()
-            except Exception:
-                logging.error(traceback.format_exc())
-
-        self.reset_timers(expired_timers)
-        return _calc_sleep_time(next_expired_time)
-
-
-class TimerQueue:
-    r"""A simple timer queue implementation.
-
-    It runs a separate thread to handle timers Note: to effectively use this
-    timer queue, the timer callback should be short, otherwise it will cause
-    other timers's delay execution. A typical use scenario in production is
-    that the timers are just a simple functions which inject themselvies to
-    a task queue and then they are picked up by a threading/process pool to
-    execute, as shows below:
-
-        Timers --enqueue---> TimerQueue --------expiration-----------
-                                                                    |
-                                                                    |
-                                                                   \|/
-        Threading/Process Pool <---- TaskQueue <--enqueue-- Timers' callback (nonblocking)
-
-    Examples:
-           >>> from solnlib import timer_queue
-           >>> tq = timer_queue.TimerQueue()
-           >>> tq.start()
-           >>> t = tq.add_timer(my_func, time.time(), 10)
-           >>> # do other stuff
-           >>> tq.stop()
-    """
-
-    def __init__(self):
-        self._timers = TimerQueueStruct()
-        self._lock = threading.Lock()
-        self._wakeup_queue = Queue.Queue()
-        self._thr = threading.Thread(target=self._check_and_execute)
-        self._thr.daemon = True
-        self._started = False
-
-    def start(self):
-        """Start the timer queue."""
-
-        if self._started:
-            return
-        self._started = True
-
-        self._thr.start()
-        logging.info("TimerQueue started.")
-
-    def stop(self):
-        """Stop the timer queue."""
-
-        if not self._started:
-            return
-        self._started = True
-
-        self._wakeup(TEARDOWN_SENTINEL)
-        self._thr.join()
-
-    def add_timer(
-        self, callback: Callable, when: int, interval: int, ident: int = None
-    ) -> Timer:
-        """Add timer to the queue.
-
-        Arguments:
-            callback: Arbitrary callable object.
-            when: The first expiration time, seconds since epoch.
-            interval: Timer interval, if equals 0, one time timer, otherwise
-                the timer will be periodically executed
-            ident: (optional) Timer identity.
-
-        Returns:
-            A timer object which should not be manipulated directly by
-                clients. Used to delete/update the timer.
-        """
-
-        with self._lock:
-            timer = self._timers.add_timer(callback, when, interval, ident)
-        self._wakeup()
-        return timer
-
-    def remove_timer(self, timer: Timer):
-        """Remove timer from the queue.
-
-        Arguments:
-            timer: Timer object to remove.
-        """
-
-        with self._lock:
-            self._timers.remove_timer(timer)
-
-    def _check_and_execute(self):
-        wakeup_queue = self._wakeup_queue
-        while 1:
-            (next_expired_time, expired_timers) = self._get_expired_timers()
-            for timer in expired_timers:
-                try:
-                    # Note, please make timer callback effective/short
-                    timer()
-                except Exception:
-                    logging.error(traceback.format_exc())
-
-            self._reset_timers(expired_timers)
-
-            sleep_time = _calc_sleep_time(next_expired_time)
-            try:
-                wakeup = wakeup_queue.get(timeout=sleep_time)
-                if wakeup is TEARDOWN_SENTINEL:
-                    break
-            except Queue.Empty:
-                pass
-        logging.info("TimerQueue stopped.")
-
-    def _get_expired_timers(self):
-        with self._lock:
-            return self._timers.get_expired_timers()
-
-    def _reset_timers(self, expired_timers):
-        with self._lock:
-            has_new_timer = self._timers.reset_timers(expired_timers)
-
-        if has_new_timer:
-            self._wakeup()
-
-    def _wakeup(self, something="not_None"):
-        self._wakeup_queue.put(something)
-
-
-def _calc_sleep_time(next_expired_time):
-    if next_expired_time:
-        now = time()
-        if now < next_expired_time:
-            sleep_time = next_expired_time - now
-        else:
-            sleep_time = 0.1
-    else:
-        sleep_time = 1
-    return sleep_time
diff --git a/apps/bitwarden_event_logs/lib/solnlib/user_access.py b/apps/bitwarden_event_logs/lib/solnlib/user_access.py
deleted file mode 100755
index 29b3d493..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/user_access.py
+++ /dev/null
@@ -1,949 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""Splunk user access control related utilities."""
-
-import json
-from typing import List, Optional
-
-from splunklib import binding
-
-from solnlib import _utils
-from solnlib import splunk_rest_client as rest_client
-from solnlib import utils
-
-__all__ = [
-    "ObjectACLException",
-    "ObjectACL",
-    "ObjectACLManagerException",
-    "ObjectACLManager",
-    "AppCapabilityManagerException",
-    "AppCapabilityManager",
-    "UserAccessException",
-    "check_user_access",
-    "InvalidSessionKeyException",
-    "get_current_username",
-    "UserNotExistException",
-    "get_user_capabilities",
-    "user_is_capable",
-    "get_user_roles",
-]
-
-
-class ObjectACLException(Exception):
-    pass
-
-
-class ObjectACL:
-    """Object ACL record.
-
-    Examples:
-       >>> from solnlib import user_access
-       >>> obj_acl = user_access.ObjectACL(
-       >>>    'test_collection',
-       >>>    '9defa6f510d711e6be16a45e60e34295',
-       >>>    'test_object',
-       >>>    'Splunk_TA_test',
-       >>>    'admin',
-       >>>    {'read': ['*'], 'write': ['admin'], 'delete': ['admin']},
-       >>>    False)
-    """
-
-    OBJ_COLLECTION_KEY = "obj_collection"
-    OBJ_ID_KEY = "obj_id"
-    OBJ_TYPE_KEY = "obj_type"
-    OBJ_APP_KEY = "obj_app"
-    OBJ_OWNER_KEY = "obj_owner"
-    OBJ_PERMS_KEY = "obj_perms"
-    OBJ_PERMS_READ_KEY = "read"
-    OBJ_PERMS_WRITE_KEY = "write"
-    OBJ_PERMS_DELETE_KEY = "delete"
-    OBJ_PERMS_ALLOW_ALL = "*"
-    OBJ_SHARED_BY_INCLUSION_KEY = "obj_shared_by_inclusion"
-
-    def __init__(
-        self,
-        obj_collection: str,
-        obj_id: str,
-        obj_type: str,
-        obj_app: str,
-        obj_owner: str,
-        obj_perms: dict,
-        obj_shared_by_inclusion: bool,
-    ):
-        """Initializes ObjectACL.
-
-        Arguments:
-            obj_collection: Collection where object currently stored.
-            obj_id: ID of this object.
-            obj_type: Type of this object.
-            obj_app: App of this object.
-            obj_owner: Owner of this object.
-            obj_perms: Object perms, like: {'read': ['*'], 'write': ['admin'], 'delete': ['admin']}.
-            obj_shared_by_inclusion: Flag of object is shared by inclusion.
-        """
-        self.obj_collection = obj_collection
-        self.obj_id = obj_id
-        self.obj_type = obj_type
-        self.obj_app = obj_app
-        self.obj_owner = obj_owner
-        self._check_perms(obj_perms)
-        self._obj_perms = obj_perms
-        self.obj_shared_by_inclusion = obj_shared_by_inclusion
-
-    @classmethod
-    def _check_perms(cls, obj_perms):
-        if not isinstance(obj_perms, dict):
-            raise ObjectACLException(
-                "Invalid object acl perms type: %s, should be a dict." % type(obj_perms)
-            )
-
-        if not (
-            cls.OBJ_PERMS_READ_KEY in obj_perms
-            and cls.OBJ_PERMS_WRITE_KEY in obj_perms
-            and cls.OBJ_PERMS_DELETE_KEY in obj_perms
-        ):
-            raise ObjectACLException(
-                "Invalid object acl perms: %s, "
-                "should include read, write and delete perms." % obj_perms
-            )
-
-    @property
-    def obj_perms(self):
-        return self._obj_perms
-
-    @obj_perms.setter
-    def obj_perms(self, obj_perms):
-        self._check_perms(obj_perms)
-        self._obj_perms = obj_perms
-
-    @property
-    def record(self) -> dict:
-        """Get object acl record.
-
-        Returns: Object acl record, like:
-
-            {
-                '_key': 'test_collection-1234',
-                'obj_collection': 'test_collection',
-                'obj_id': '1234',
-                'obj_type': 'test_object',
-                'obj_app': 'Splunk_TA_test',
-                'obj_owner': 'admin',
-                'obj_perms': {'read': ['*'], 'write': ['admin'], 'delete': ['admin']},
-                'obj_shared_by_inclusion': True
-            }
-        """
-
-        return {
-            "_key": self.generate_key(self.obj_collection, self.obj_id),
-            self.OBJ_COLLECTION_KEY: self.obj_collection,
-            self.OBJ_ID_KEY: self.obj_id,
-            self.OBJ_TYPE_KEY: self.obj_type,
-            self.OBJ_APP_KEY: self.obj_app,
-            self.OBJ_OWNER_KEY: self.obj_owner,
-            self.OBJ_PERMS_KEY: self._obj_perms,
-            self.OBJ_SHARED_BY_INCLUSION_KEY: self.obj_shared_by_inclusion,
-        }
-
-    @staticmethod
-    def generate_key(obj_collection: str, obj_id: str) -> str:
-        """Generate object acl record key.
-
-        Arguments:
-            obj_collection: Collection where object currently stored.
-            obj_id: ID of this object.
-
-        Returns:
-            Object acl record key.
-        """
-
-        return "{obj_collection}_{obj_id}".format(
-            obj_collection=obj_collection, obj_id=obj_id
-        )
-
-    @staticmethod
-    def parse(obj_acl_record: dict) -> "ObjectACL":
-        """Parse object acl record and construct a new `ObjectACL` object from
-        it.
-
-        Arguments:
-            obj_acl_record: Object acl record.
-
-        Returns:
-            New `ObjectACL` object.
-        """
-
-        return ObjectACL(
-            obj_acl_record[ObjectACL.OBJ_COLLECTION_KEY],
-            obj_acl_record[ObjectACL.OBJ_ID_KEY],
-            obj_acl_record[ObjectACL.OBJ_TYPE_KEY],
-            obj_acl_record[ObjectACL.OBJ_APP_KEY],
-            obj_acl_record[ObjectACL.OBJ_OWNER_KEY],
-            obj_acl_record[ObjectACL.OBJ_PERMS_KEY],
-            obj_acl_record[ObjectACL.OBJ_SHARED_BY_INCLUSION_KEY],
-        )
-
-    def merge(self, obj_acl: "ObjectACL"):
-        """Merge current object perms with perms of `obj_acl`.
-
-        Arguments:
-            obj_acl: Object acl to merge.
-        """
-
-        for perm_key in self._obj_perms:
-            self._obj_perms[perm_key] = list(
-                set.union(
-                    set(self._obj_perms[perm_key]), set(obj_acl._obj_perms[perm_key])
-                )
-            )
-            if self.OBJ_PERMS_ALLOW_ALL in self._obj_perms[perm_key]:
-                self._obj_perms[perm_key] = [self.OBJ_PERMS_ALLOW_ALL]
-
-    def __str__(self):
-        return json.dumps(self.record)
-
-
-class ObjectACLManagerException(Exception):
-    """Exception for ObjectACLManager."""
-
-    pass
-
-
-class ObjectACLNotExistException(Exception):
-    """Exception for the situation when ACL does not exist."""
-
-    pass
-
-
-class ObjectACLManager:
-    """Object ACL manager.
-
-    Examples:
-       >>> from solnlib import user_access
-       >>> oaclm = user_access.ObjectACLManager(session_key,
-                                                'Splunk_TA_test')
-    """
-
-    def __init__(
-        self,
-        collection_name: str,
-        session_key: str,
-        app: str,
-        owner: Optional[str] = "nobody",
-        scheme: Optional[str] = None,
-        host: Optional[str] = None,
-        port: Optional[int] = None,
-        **context: dict,
-    ):
-        """Initializes ObjectACLManager.
-
-        Arguments:
-            collection_name: Collection name to store object ACL info.
-            session_key: Splunk access token.
-            app: App name of namespace.
-            owner: (optional) Owner of namespace, default is `nobody`.
-            scheme: (optional) The access scheme, default is None.
-            host: (optional) The host name, default is None.
-            port: (optional) The port number, default is None.
-            context: Other configurations for Splunk rest client.
-
-        Raises:
-            ObjectACLManagerException: If init ObjectACLManager failed.
-        """
-        collection_name = "{app}_{collection_name}".format(
-            app=app, collection_name=collection_name
-        )
-        try:
-            self._collection_data = _utils.get_collection_data(
-                collection_name,
-                session_key,
-                app,
-                owner,
-                scheme,
-                host,
-                port,
-                None,
-                **context,
-            )
-        except KeyError:
-            raise ObjectACLManagerException(
-                f"Get object acl collection: {collection_name} fail."
-            )
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def update_acl(
-        self,
-        obj_collection: str,
-        obj_id: str,
-        obj_type: str,
-        obj_app: str,
-        obj_owner: str,
-        obj_perms: dict,
-        obj_shared_by_inclusion: bool = True,
-        replace_existing: bool = True,
-    ):
-        """Update acl info of object.
-
-        Construct a new object acl info first, if `replace_existing` is True
-        then replace existing acl info else merge new object acl info with the
-        old one and replace the old acl info with merged acl info.
-
-        Arguments:
-            obj_collection: Collection where object currently stored.
-            obj_id: ID of this object.
-            obj_type: Type of this object.
-            obj_app: App of this object.
-            obj_owner: Owner of this object.
-            obj_perms: Object perms, like:
-
-                {
-                    'read': ['*'],
-                    'write': ['admin'],
-                    'delete': ['admin']
-                }.
-            obj_shared_by_inclusion: (optional) Flag of object is shared by
-                inclusion, default is True.
-            replace_existing: (optional) Replace existing acl info flag, True
-                indicates replace old acl info with new one else merge with old
-                acl info, default is True.
-        """
-
-        obj_acl = ObjectACL(
-            obj_collection,
-            obj_id,
-            obj_type,
-            obj_app,
-            obj_owner,
-            obj_perms,
-            obj_shared_by_inclusion,
-        )
-
-        if not replace_existing:
-            try:
-                old_obj_acl = self.get_acl(obj_collection, obj_id)
-            except ObjectACLNotExistException:
-                old_obj_acl = None
-
-            if old_obj_acl:
-                obj_acl.merge(old_obj_acl)
-
-        self._collection_data.batch_save(obj_acl.record)
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def update_acls(
-        self,
-        obj_collection: str,
-        obj_ids: List[str],
-        obj_type: str,
-        obj_app: str,
-        obj_owner: str,
-        obj_perms: dict,
-        obj_shared_by_inclusion: bool = True,
-        replace_existing: bool = True,
-    ):
-        """Batch update object acl info to all provided `obj_ids`.
-
-        Arguments:
-            obj_collection: Collection where objects currently stored.
-            obj_ids: IDs list of objects.
-            obj_type: Type of this object.
-            obj_app: App of this object.
-            obj_owner: Owner of this object.
-            obj_perms: Object perms, like:
-
-                {
-                    'read': ['*'],
-                    'write': ['admin'],
-                    'delete': ['admin']
-                }.
-            obj_shared_by_inclusion: (optional) Flag of object is shared by
-                inclusion, default is True.
-            replace_existing: (optional) Replace existing acl info flag, True
-                indicates replace old acl info with new one else merge with old acl
-                info, default is True.
-        """
-
-        obj_acl_records = []
-        for obj_id in obj_ids:
-            obj_acl = ObjectACL(
-                obj_collection,
-                obj_id,
-                obj_type,
-                obj_app,
-                obj_owner,
-                obj_perms,
-                obj_shared_by_inclusion,
-            )
-
-            if not replace_existing:
-                try:
-                    old_obj_acl = self.get_acl(obj_collection, obj_id)
-                except ObjectACLNotExistException:
-                    old_obj_acl = None
-
-                if old_obj_acl:
-                    obj_acl.merge(old_obj_acl)
-
-            obj_acl_records.append(obj_acl.record)
-
-        self._collection_data.batch_save(*obj_acl_records)
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def get_acl(self, obj_collection: str, obj_id: str) -> "ObjectACL":
-        """Get acl info.
-
-        Query object acl info with parameter of the combination of
-        `obj_collection` and `obj_id` from `self.collection_name` and
-        return it.
-
-        Arguments:
-            obj_collection: Collection where object currently stored.
-            obj_id: ID of this object.
-
-        Returns:
-            Object acl info if success else None.
-
-        Raises:
-            ObjectACLNotExistException: If object ACL info does not exist.
-        """
-
-        key = ObjectACL.generate_key(obj_collection, obj_id)
-        try:
-            obj_acl = self._collection_data.query_by_id(key)
-        except binding.HTTPError as e:
-            if e.status != 404:
-                raise
-
-            raise ObjectACLNotExistException(
-                "Object ACL info of {}_{} does not exist.".format(
-                    obj_collection, obj_id
-                )
-            )
-
-        return ObjectACL.parse(obj_acl)
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def get_acls(self, obj_collection: str, obj_ids: List[str]) -> List[ObjectACL]:
-        """Batch get acl info.
-
-        Query objects acl info with parameter of the combination of
-        `obj_collection` and `obj_ids` from KVStore and return them.
-
-        Arguments:
-            obj_collection: Collection where object currently stored.
-            obj_ids: IDs of objects.
-
-        Returns:
-            List of `ObjectACL` instances.
-        """
-
-        query = json.dumps(
-            {
-                "$or": [
-                    {"_key": ObjectACL.generate_key(obj_collection, obj_id)}
-                    for obj_id in obj_ids
-                ]
-            }
-        )
-        obj_acls = self._collection_data.query(query=query)
-
-        return [ObjectACL.parse(obj_acl) for obj_acl in obj_acls]
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def delete_acl(self, obj_collection: str, obj_id: str):
-        """Delete acl info.
-
-        Query object acl info with parameter of the combination of
-        `obj_collection` and `obj_ids` from KVStore and delete it.
-
-        Arguments:
-            obj_collection: Collection where object currently stored.
-            obj_id: ID of this object.
-
-        Raises:
-            ObjectACLNotExistException: If object ACL info does not exist.
-        """
-
-        key = ObjectACL.generate_key(obj_collection, obj_id)
-        try:
-            self._collection_data.delete_by_id(key)
-        except binding.HTTPError as e:
-            if e.status != 404:
-                raise
-
-            raise ObjectACLNotExistException(
-                "Object ACL info of {}_{} does not exist.".format(
-                    obj_collection, obj_id
-                )
-            )
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def delete_acls(self, obj_collection: str, obj_ids: List[str]):
-        """Batch delete acl info.
-
-        Query objects acl info with parameter of the combination of
-        `obj_collection` and `obj_ids` from KVStore and delete them.
-
-        Arguments:
-            obj_collection: Collection where object currently stored.
-            obj_ids: IDs of objects.
-        """
-
-        query = json.dumps(
-            {
-                "$or": [
-                    {"_key": ObjectACL.generate_key(obj_collection, obj_id)}
-                    for obj_id in obj_ids
-                ]
-            }
-        )
-        self._collection_data.delete(query=query)
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def get_accessible_object_ids(
-        self, user: str, operation: str, obj_collection: str, obj_ids: List[str]
-    ) -> List[str]:
-        """Get accessible IDs of objects from `obj_acls`.
-
-        Arguments:
-            user: User name of current `operation`.
-            operation: User operation, possible option: (read/write/delete).
-            obj_collection: Collection where object currently stored.
-            obj_ids: IDs of objects.
-
-        Returns:
-            List of IDs of accessible objects.
-        """
-
-        obj_acls = self.get_acls(obj_collection, obj_ids)
-        accessible_obj_ids = []
-        for obj_acl in obj_acls:
-            perms = obj_acl.obj_perms[operation]
-            if ObjectACL.OBJ_PERMS_ALLOW_ALL in perms or user in perms:
-                accessible_obj_ids.append(obj_acl.obj_id)
-
-        return accessible_obj_ids
-
-
-class AppCapabilityManagerException(Exception):
-    """Exception for AppCapabilityManager."""
-
-    pass
-
-
-class AppCapabilityNotExistException(Exception):
-    """Exception for the situation when AppCapability does not exist for a
-    specific app."""
-
-    pass
-
-
-class AppCapabilityManager:
-    """App capability manager.
-
-    Examples:
-       >>> from solnlib import user_access
-       >>> acm = user_access.AppCapabilityManager('test_collection',
-                                                  session_key,
-                                                  'Splunk_TA_test')
-       >>> acm.register_capabilities(...)
-       >>> acm.unregister_capabilities(...)
-    """
-
-    def __init__(
-        self,
-        collection_name: str,
-        session_key: str,
-        app: str,
-        owner: str = "nobody",
-        scheme: str = None,
-        host: str = None,
-        port: int = None,
-        **context: dict,
-    ):
-        """Initializes AppCapabilityManager.
-
-        Arguments:
-            collection_name: Collection name to store capabilities.
-            session_key: Splunk access token.
-            app: App name of namespace.
-            owner: (optional) Owner of namespace, default is `nobody`.
-            scheme: (optional) The access scheme, default is None.
-            host: (optional) The host name, default is None.
-            port: (optional) The port number, default is None.
-            context: Other configurations for Splunk rest client.
-
-        Raises:
-            AppCapabilityManagerException: If init AppCapabilityManager failed.
-        """
-        self._app = app
-
-        collection_name = f"{app}_{collection_name}"
-        try:
-            self._collection_data = _utils.get_collection_data(
-                collection_name,
-                session_key,
-                app,
-                owner,
-                scheme,
-                host,
-                port,
-                None,
-                **context,
-            )
-        except KeyError:
-            raise AppCapabilityManagerException(
-                f"Get app capabilities collection: {collection_name} failed."
-            )
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def register_capabilities(self, capabilities: dict):
-        """Register app capabilities.
-
-        Arguments:
-            capabilities: App capabilities, example:
-
-                {
-                    'object_type1': {
-                        'read': 'read_app_object_type1',
-                        'write': 'write_app_object_type1',
-                        'delete': 'delete_app_object_type1'},
-                        'object_type2': {
-                        'read': 'read_app_object_type2',
-                        'write': 'write_app_object_type2',
-                        'delete': 'delete_app_object_type2'
-                    },
-                    ...
-                }
-        """
-
-        record = {"_key": self._app, "capabilities": capabilities}
-        self._collection_data.batch_save(record)
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def unregister_capabilities(self):
-        """Unregister app capabilities.
-
-        Raises:
-            AppCapabilityNotExistException: If app capabilities are not registered.
-        """
-
-        try:
-            self._collection_data.delete_by_id(self._app)
-        except binding.HTTPError as e:
-            if e.status != 404:
-                raise
-
-            raise AppCapabilityNotExistException(
-                "App capabilities for %s have not been registered." % self._app
-            )
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def capabilities_are_registered(self) -> bool:
-        """Check if app capabilities are registered.
-
-        Returns:
-            True if app capabilities are registered else False.
-        """
-
-        try:
-            self._collection_data.query_by_id(self._app)
-        except binding.HTTPError as e:
-            if e.status != 404:
-                raise
-
-            return False
-
-        return True
-
-    @utils.retry(exceptions=[binding.HTTPError])
-    def get_capabilities(self) -> dict:
-        """Get app capabilities.
-
-        Returns:
-            App capabilities.
-
-        Raises:
-             AppCapabilityNotExistException: If app capabilities are not registered.
-        """
-
-        try:
-            record = self._collection_data.query_by_id(self._app)
-        except binding.HTTPError as e:
-            if e.status != 404:
-                raise
-
-            raise AppCapabilityNotExistException(
-                "App capabilities for %s have not been registered." % self._app
-            )
-
-        return record["capabilities"]
-
-
-class UserAccessException(Exception):
-    """Exception for the situation when there is user access exception."""
-
-    pass
-
-
-def check_user_access(
-    session_key: str,
-    capabilities: dict,
-    obj_type: str,
-    operation: str,
-    scheme: str = None,
-    host: str = None,
-    port: int = None,
-    **context: dict,
-):
-    """User access checker.
-
-    It will fetch user capabilities from given `session_key` and check if
-    the capability extracted from `capabilities`, `obj_type` and `operation`
-    is contained, if user capabilities include the extracted capability user
-    access is ok else fail.
-
-    Arguments:
-        session_key: Splunk access token.
-        capabilities: App capabilities, example:
-
-            {
-                'object_type1': {
-                    'read': 'read_app_object_type1',
-                    'write': 'write_app_object_type1',
-                    'delete': 'delete_app_object_type1'},
-                    'object_type2': {
-                    'read': 'read_app_object_type2',
-                    'write': 'write_app_object_type2',
-                    'delete': 'delete_app_object_type2'
-                },
-                ...
-            }
-        obj_type: Object type.
-        operation: User operation, possible option: (read/write/delete).
-        scheme: (optional) The access scheme, default is None.
-        host: (optional) The host name, default is None.
-        port: (optional) The port number, default is None.
-        context: Other configurations for Splunk rest client.
-
-    Raises:
-        UserAccessException: If user access permission is denied.
-
-    Examples:
-       >>> from solnlib.user_access import check_user_access
-       >>> def fun():
-       >>>     check_user_access(
-       >>>         session_key, capabilities, 'test_object', 'read')
-       >>>     ...
-    """
-
-    username = get_current_username(
-        session_key, scheme=scheme, host=host, port=port, **context
-    )
-    capability = capabilities[obj_type][operation]
-    if not user_is_capable(
-        session_key,
-        username,
-        capability,
-        scheme=scheme,
-        host=host,
-        port=port,
-        **context,
-    ):
-        raise UserAccessException(
-            "Permission denied, %s does not have the capability: %s."
-            % (username, capability)
-        )
-
-
-class InvalidSessionKeyException(Exception):
-    """Exception when Splunk session key is invalid."""
-
-    pass
-
-
-@utils.retry(exceptions=[binding.HTTPError])
-def get_current_username(
-    session_key: str,
-    scheme: str = None,
-    host: str = None,
-    port: int = None,
-    **context: dict,
-) -> str:
-    """Get current user name from `session_key`.
-
-    Arguments:
-        session_key: Splunk access token.
-        scheme: (optional) The access scheme, default is None.
-        host: (optional) The host name, default is None.
-        port: (optional) The port number, default is None.
-        context: Other configurations for Splunk rest client.
-
-    Returns:
-        Current user name.
-
-    Raises:
-        InvalidSessionKeyException: If `session_key` is invalid.
-
-    Examples:
-       >>> from solnlib import user_access
-       >>> user_name = user_access.get_current_username(session_key)
-    """
-
-    _rest_client = rest_client.SplunkRestClient(
-        session_key, "-", scheme=scheme, host=host, port=port, **context
-    )
-    try:
-        response = _rest_client.get(
-            "/services/authentication/current-context", output_mode="json"
-        ).body.read()
-    except binding.HTTPError as e:
-        if e.status != 401:
-            raise
-
-        raise InvalidSessionKeyException("Invalid session key.")
-
-    return json.loads(response)["entry"][0]["content"]["username"]
-
-
-class UserNotExistException(Exception):
-    """Exception when user does not exist."""
-
-    pass
-
-
-@utils.retry(exceptions=[binding.HTTPError])
-def get_user_capabilities(
-    session_key: str,
-    username: str,
-    scheme: str = None,
-    host: str = None,
-    port: int = None,
-    **context: dict,
-) -> List[dict]:
-    """Get user capabilities.
-
-    Arguments:
-        session_key: Splunk access token.
-        scheme: (optional) The access scheme, default is None.
-        host: (optional) The host name, default is None.
-        port: (optional) The port number, default is None.
-        context: Other configurations for Splunk rest client.
-
-    Returns:
-        User capabilities.
-
-    Raises:
-        UserNotExistException: If `username` does not exist.
-
-    Examples:
-       >>> from solnlib import user_access
-       >>> user_capabilities = user_access.get_user_capabilities(
-       >>>     session_key, 'test_user')
-    """
-
-    _rest_client = rest_client.SplunkRestClient(
-        session_key, "-", scheme=scheme, host=host, port=port, **context
-    )
-    url = f"/services/authentication/users/{username}"
-    try:
-        response = _rest_client.get(url, output_mode="json").body.read()
-    except binding.HTTPError as e:
-        if e.status != 404:
-            raise
-
-        raise UserNotExistException("User: %s does not exist." % username)
-
-    return json.loads(response)["entry"][0]["content"]["capabilities"]
-
-
-def user_is_capable(
-    session_key: str,
-    username: str,
-    capability: str,
-    scheme: str = None,
-    host: str = None,
-    port: int = None,
-    **context: dict,
-) -> bool:
-    """Check if user is capable for given `capability`.
-
-    Arguments:
-        session_key: Splunk access token.
-        username: (optional) User name of roles to get.
-        capability: The capability we wish to check for.
-        scheme: (optional) The access scheme, default is None.
-        host: (optional) The host name, default is None.
-        port: (optional) The port number, default is None.
-        context: Other configurations for Splunk rest client.
-
-    Returns:
-        True if user is capable else False.
-
-    Raises:
-        UserNotExistException: If `username` does not exist.
-
-    Examples:
-       >>> from solnlib import user_access
-       >>> is_capable = user_access.user_is_capable(
-       >>>     session_key, 'test_user', 'object_read_capability')
-    """
-
-    capabilities = get_user_capabilities(
-        session_key, username, scheme=scheme, host=host, port=port, **context
-    )
-    return capability in capabilities
-
-
-@utils.retry(exceptions=[binding.HTTPError])
-def get_user_roles(
-    session_key: str, username: str, scheme=None, host=None, port=None, **context
-) -> List:
-    """Get user roles.
-
-    Arguments:
-        session_key: Splunk access token.
-        username: (optional) User name of roles to get.
-        scheme: (optional) The access scheme, default is None.
-        host: (optional) The host name, default is None.
-        port: (optional) The port number, default is None.
-        context: Other configurations for Splunk rest client.
-
-    Returns:
-        User roles.
-
-    Raises:
-        UserNotExistException: If `username` does not exist.
-
-    Examples:
-       >>> from solnlib import user_access
-       >>> user_roles = user_access.get_user_roles(session_key, 'test_user')
-    """
-
-    _rest_client = rest_client.SplunkRestClient(
-        session_key, "-", scheme=scheme, host=host, port=port, **context
-    )
-    url = f"/services/authentication/users/{username}"
-    try:
-        response = _rest_client.get(url, output_mode="json").body.read()
-    except binding.HTTPError as e:
-        if e.status != 404:
-            raise
-
-        raise UserNotExistException("User: %s does not exist." % username)
-
-    return json.loads(response)["entry"][0]["content"]["roles"]
diff --git a/apps/bitwarden_event_logs/lib/solnlib/utils.py b/apps/bitwarden_event_logs/lib/solnlib/utils.py
deleted file mode 100755
index b7954208..00000000
--- a/apps/bitwarden_event_logs/lib/solnlib/utils.py
+++ /dev/null
@@ -1,221 +0,0 @@
-#
-# Copyright 2025 Splunk Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""Common utilities."""
-
-import datetime
-import logging
-import os
-import signal
-import time
-import traceback
-from functools import wraps
-from typing import Any, Callable, List, Tuple, Union
-from urllib import parse as urlparse
-
-__all__ = [
-    "handle_teardown_signals",
-    "datetime_to_seconds",
-    "is_true",
-    "is_false",
-    "retry",
-    "extract_http_scheme_host_port",
-    "remove_http_proxy_env_vars",
-]
-
-
-def remove_http_proxy_env_vars() -> None:
-    """Removes HTTP(s) proxies from environment variables.
-
-    Removes the following environment variables:
-        * http_proxy
-        * https_proxy
-        * HTTP_PROXY
-        * HTTPS_PROXY
-
-    This function can be used in Splunk modular inputs code before starting the
-    ingestion to ensure that no proxy is going to be used when doing requests.
-    In case of proxy is needed, it can be defined in the modular inputs code.
-    """
-    env_vars_to_remove = (
-        "http_proxy",
-        "https_proxy",
-        "HTTP_PROXY",
-        "HTTPS_PROXY",
-    )
-    for env_var in env_vars_to_remove:
-        if env_var in os.environ:
-            del os.environ[env_var]
-
-
-def handle_teardown_signals(callback: Callable):
-    """Register handler for SIGTERM/SIGINT/SIGBREAK signal.
-
-    Catch SIGTERM/SIGINT/SIGBREAK signals, and invoke callback
-    Note: this should be called in main thread since Python only catches
-    signals in main thread.
-
-    Arguments:
-        callback: Callback for tear down signals.
-    """
-
-    signal.signal(signal.SIGTERM, callback)
-    signal.signal(signal.SIGINT, callback)
-
-    if os.name == "nt":
-        signal.signal(signal.SIGBREAK, callback)
-
-
-def datetime_to_seconds(dt: datetime.datetime) -> float:
-    """Convert UTC datetime to seconds since epoch.
-
-    Arguments:
-        dt: Date time.
-
-    Returns:
-        Seconds since epoch.
-    """
-
-    epoch_time = datetime.datetime.utcfromtimestamp(0)
-    return (dt - epoch_time).total_seconds()
-
-
-def is_true(val: Union[str, int]) -> bool:
-    """Decide if `val` is true.
-
-    Arguments:
-        val: Value to check.
-
-    Returns:
-        True or False.
-    """
-
-    value = str(val).strip().upper()
-    if value in ("1", "TRUE", "T", "Y", "YES"):
-        return True
-    return False
-
-
-def is_false(val: Union[str, int]) -> bool:
-    """Decide if `val` is false.
-
-    Arguments:
-        val: Value to check.
-
-    Returns:
-        True or False.
-    """
-
-    value = str(val).strip().upper()
-    if value in ("0", "FALSE", "F", "N", "NO", "NONE", ""):
-        return True
-    return False
-
-
-def retry(
-    retries: int = 3,
-    reraise: bool = True,
-    default_return: Any = None,
-    exceptions: List = None,
-):
-    """A decorator to run function with max `retries` times if there is
-    exception.
-
-    Arguments:
-        retries: (optional) Max retries times, default is 3.
-        reraise: Whether exception should be reraised, default is True.
-        default_return: (optional) Default return value for function
-            run after max retries and reraise is False.
-        exceptions: (optional) List of exceptions that should retry.
-    """
-
-    max_tries = max(retries, 0) + 1
-
-    def do_retry(func):
-        @wraps(func)
-        def wrapper(*args, **kwargs):
-            last_ex = None
-            for i in range(max_tries):
-                try:
-                    return func(*args, **kwargs)
-                except Exception as e:
-                    logging.warning(
-                        "Run function: %s failed: %s.",
-                        func.__name__,
-                        traceback.format_exc(),
-                    )
-                    if not exceptions or any(
-                        isinstance(e, exception) for exception in exceptions
-                    ):
-                        last_ex = e
-                        if i < max_tries - 1:
-                            time.sleep(2**i)
-                    else:
-                        raise
-
-            if reraise:
-                raise last_ex
-            else:
-                return default_return
-
-        return wrapper
-
-    return do_retry
-
-
-def extract_http_scheme_host_port(http_url: str) -> Tuple:
-    """Extract scheme, host and port from a HTTP URL.
-
-    Arguments:
-        http_url: HTTP URL to extract.
-
-    Returns:
-        A tuple of scheme, host and port
-
-    Raises:
-        ValueError: If `http_url` is not in http(s)://hostname:port format.
-    """
-
-    http_info = urlparse.urlparse(http_url)
-    if not http_info.scheme or not http_info.hostname or not http_info.port:
-        raise ValueError(http_url + " is not in http(s)://hostname:port format")
-    return http_info.scheme, http_info.hostname, http_info.port
-
-
-def get_appname_from_path(absolute_path):
-    """Gets name of the app from its path.
-
-    Arguments:
-        absolute_path: path of app
-
-    Returns:
-    """
-    absolute_path = os.path.normpath(absolute_path)
-    parts = absolute_path.split(os.path.sep)
-    parts.reverse()
-    for key in ("apps", "peer-apps", "manager-apps"):
-        try:
-            idx = parts.index(key)
-        except ValueError:
-            continue
-        else:
-            try:
-                if parts[idx + 1] == "etc":
-                    return parts[idx - 1]
-            except IndexError:
-                pass
-            continue
-    return "-"
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/INSTALLER
deleted file mode 100755
index a1b589e3..00000000
--- a/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/INSTALLER
+++ /dev/null
@@ -1 +0,0 @@
-pip
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/LICENSE b/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/LICENSE
deleted file mode 100755
index 668d8ecd..00000000
--- a/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/LICENSE
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright 2014-2019 Grant Jenks
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/METADATA b/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/METADATA
deleted file mode 100755
index dd28af42..00000000
--- a/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/METADATA
+++ /dev/null
@@ -1,264 +0,0 @@
-Metadata-Version: 2.1
-Name: sortedcontainers
-Version: 2.4.0
-Summary: Sorted Containers -- Sorted List, Sorted Dict, Sorted Set
-Home-page: http://www.grantjenks.com/docs/sortedcontainers/
-Author: Grant Jenks
-Author-email: contact@grantjenks.com
-License: Apache 2.0
-Platform: UNKNOWN
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: Apache Software License
-Classifier: Natural Language :: English
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.2
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: Implementation :: CPython
-Classifier: Programming Language :: Python :: Implementation :: PyPy
-
-Python Sorted Containers
-========================
-
-`Sorted Containers`_ is an Apache2 licensed `sorted collections library`_,
-written in pure-Python, and fast as C-extensions.
-
-Python's standard library is great until you need a sorted collections
-type. Many will attest that you can get really far without one, but the moment
-you **really need** a sorted list, sorted dict, or sorted set, you're faced
-with a dozen different implementations, most using C-extensions without great
-documentation and benchmarking.
-
-In Python, we can do better. And we can do it in pure-Python!
-
-.. code-block:: python
-
-    >>> from sortedcontainers import SortedList
-    >>> sl = SortedList(['e', 'a', 'c', 'd', 'b'])
-    >>> sl
-    SortedList(['a', 'b', 'c', 'd', 'e'])
-    >>> sl *= 10_000_000
-    >>> sl.count('c')
-    10000000
-    >>> sl[-3:]
-    ['e', 'e', 'e']
-    >>> from sortedcontainers import SortedDict
-    >>> sd = SortedDict({'c': 3, 'a': 1, 'b': 2})
-    >>> sd
-    SortedDict({'a': 1, 'b': 2, 'c': 3})
-    >>> sd.popitem(index=-1)
-    ('c', 3)
-    >>> from sortedcontainers import SortedSet
-    >>> ss = SortedSet('abracadabra')
-    >>> ss
-    SortedSet(['a', 'b', 'c', 'd', 'r'])
-    >>> ss.bisect_left('c')
-    2
-
-All of the operations shown above run in faster than linear time. The above
-demo also takes nearly a gigabyte of memory to run. When the sorted list is
-multiplied by ten million, it stores ten million references to each of "a"
-through "e". Each reference requires eight bytes in the sorted
-container. That's pretty hard to beat as it's the cost of a pointer to each
-object. It's also 66% less overhead than a typical binary tree implementation
-(e.g. Red-Black Tree, AVL-Tree, AA-Tree, Splay-Tree, Treap, etc.) for which
-every node must also store two pointers to children nodes.
-
-`Sorted Containers`_ takes all of the work out of Python sorted collections -
-making your deployment and use of Python easy. There's no need to install a C
-compiler or pre-build and distribute custom extensions. Performance is a
-feature and testing has 100% coverage with unit tests and hours of stress.
-
-.. _`Sorted Containers`: http://www.grantjenks.com/docs/sortedcontainers/
-.. _`sorted collections library`: http://www.grantjenks.com/docs/sortedcontainers/
-
-Testimonials
-------------
-
-**Alex Martelli**, `Fellow of the Python Software Foundation`_
-
-"Good stuff! ... I like the `simple, effective implementation`_ idea of
-splitting the sorted containers into smaller "fragments" to avoid the O(N)
-insertion costs."
-
-**Jeff Knupp**, `author of Writing Idiomatic Python and Python Trainer`_
-
-"That last part, "fast as C-extensions," was difficult to believe. I would need
-some sort of `Performance Comparison`_ to be convinced this is true. The author
-includes this in the docs. It is."
-
-**Kevin Samuel**, `Python and Django Trainer`_
-
-I'm quite amazed, not just by the code quality (it's incredibly readable and
-has more comment than code, wow), but the actual amount of work you put at
-stuff that is *not* code: documentation, benchmarking, implementation
-explanations. Even the git log is clean and the unit tests run out of the box
-on Python 2 and 3.
-
-**Mark Summerfield**, a short plea for `Python Sorted Collections`_
-
-Python's "batteries included" standard library seems to have a battery
-missing. And the argument that "we never had it before" has worn thin. It is
-time that Python offered a full range of collection classes out of the box,
-including sorted ones.
-
-`Sorted Containers`_ is used in popular open source projects such as:
-`Zipline`_, an algorithmic trading library from Quantopian; `Angr`_, a binary
-analysis platform from UC Santa Barbara; `Trio`_, an async I/O library; and
-`Dask Distributed`_, a distributed computation library supported by Continuum
-Analytics.
-
-.. _`Fellow of the Python Software Foundation`: https://en.wikipedia.org/wiki/Alex_Martelli
-.. _`simple, effective implementation`: http://www.grantjenks.com/docs/sortedcontainers/implementation.html
-.. _`author of Writing Idiomatic Python and Python Trainer`: https://jeffknupp.com/
-.. _`Python and Django Trainer`: https://www.elephorm.com/formateur/kevin-samuel
-.. _`Python Sorted Collections`: http://www.qtrac.eu/pysorted.html
-.. _`Zipline`: https://github.com/quantopian/zipline
-.. _`Angr`: https://github.com/angr/angr
-.. _`Trio`: https://github.com/python-trio/trio
-.. _`Dask Distributed`: https://github.com/dask/distributed
-
-Features
---------
-
-- Pure-Python
-- Fully documented
-- Benchmark comparison (alternatives, runtimes, load-factors)
-- 100% test coverage
-- Hours of stress testing
-- Performance matters (often faster than C implementations)
-- Compatible API (nearly identical to older blist and bintrees modules)
-- Feature-rich (e.g. get the five largest keys in a sorted dict: d.keys()[-5:])
-- Pragmatic design (e.g. SortedSet is a Python set with a SortedList index)
-- Developed on Python 3.7
-- Tested on CPython 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7 and PyPy, PyPy3
-
-.. image:: https://api.travis-ci.org/grantjenks/python-sortedcontainers.svg?branch=master
-   :target: http://www.grantjenks.com/docs/sortedcontainers/
-
-.. image:: https://ci.appveyor.com/api/projects/status/github/grantjenks/python-sortedcontainers?branch=master&svg=true
-   :target: http://www.grantjenks.com/docs/sortedcontainers/
-
-Quickstart
-----------
-
-Installing `Sorted Containers`_ is simple with `pip
-`_::
-
-    $ pip install sortedcontainers
-
-You can access documentation in the interpreter with Python's built-in `help`
-function. The `help` works on modules, classes and methods in `Sorted
-Containers`_.
-
-.. code-block:: python
-
-    >>> import sortedcontainers
-    >>> help(sortedcontainers)
-    >>> from sortedcontainers import SortedDict
-    >>> help(SortedDict)
-    >>> help(SortedDict.popitem)
-
-Documentation
--------------
-
-Complete documentation for `Sorted Containers`_ is available at
-http://www.grantjenks.com/docs/sortedcontainers/
-
-User Guide
-..........
-
-The user guide provides an introduction to `Sorted Containers`_ and extensive
-performance comparisons and analysis.
-
-- `Introduction`_
-- `Performance Comparison`_
-- `Load Factor Performance Comparison`_
-- `Runtime Performance Comparison`_
-- `Simulated Workload Performance Comparison`_
-- `Performance at Scale`_
-
-.. _`Introduction`: http://www.grantjenks.com/docs/sortedcontainers/introduction.html
-.. _`Performance Comparison`: http://www.grantjenks.com/docs/sortedcontainers/performance.html
-.. _`Load Factor Performance Comparison`: http://www.grantjenks.com/docs/sortedcontainers/performance-load.html
-.. _`Runtime Performance Comparison`: http://www.grantjenks.com/docs/sortedcontainers/performance-runtime.html
-.. _`Simulated Workload Performance Comparison`: http://www.grantjenks.com/docs/sortedcontainers/performance-workload.html
-.. _`Performance at Scale`: http://www.grantjenks.com/docs/sortedcontainers/performance-scale.html
-
-Community Guide
-...............
-
-The community guide provides information on the development of `Sorted
-Containers`_ along with support, implementation, and history details.
-
-- `Development and Support`_
-- `Implementation Details`_
-- `Release History`_
-
-.. _`Development and Support`: http://www.grantjenks.com/docs/sortedcontainers/development.html
-.. _`Implementation Details`: http://www.grantjenks.com/docs/sortedcontainers/implementation.html
-.. _`Release History`: http://www.grantjenks.com/docs/sortedcontainers/history.html
-
-API Documentation
-.................
-
-The API documentation provides information on specific functions, classes, and
-modules in the `Sorted Containers`_ package.
-
-- `Sorted List`_
-- `Sorted Dict`_
-- `Sorted Set`_
-
-.. _`Sorted List`: http://www.grantjenks.com/docs/sortedcontainers/sortedlist.html
-.. _`Sorted Dict`: http://www.grantjenks.com/docs/sortedcontainers/sorteddict.html
-.. _`Sorted Set`: http://www.grantjenks.com/docs/sortedcontainers/sortedset.html
-
-Talks
------
-
-- `Python Sorted Collections | PyCon 2016 Talk`_
-- `SF Python Holiday Party 2015 Lightning Talk`_
-- `DjangoCon 2015 Lightning Talk`_
-
-.. _`Python Sorted Collections | PyCon 2016 Talk`: http://www.grantjenks.com/docs/sortedcontainers/pycon-2016-talk.html
-.. _`SF Python Holiday Party 2015 Lightning Talk`: http://www.grantjenks.com/docs/sortedcontainers/sf-python-2015-lightning-talk.html
-.. _`DjangoCon 2015 Lightning Talk`: http://www.grantjenks.com/docs/sortedcontainers/djangocon-2015-lightning-talk.html
-
-Resources
----------
-
-- `Sorted Containers Documentation`_
-- `Sorted Containers at PyPI`_
-- `Sorted Containers at Github`_
-- `Sorted Containers Issue Tracker`_
-
-.. _`Sorted Containers Documentation`: http://www.grantjenks.com/docs/sortedcontainers/
-.. _`Sorted Containers at PyPI`: https://pypi.org/project/sortedcontainers/
-.. _`Sorted Containers at Github`: https://github.com/grantjenks/python-sortedcontainers
-.. _`Sorted Containers Issue Tracker`: https://github.com/grantjenks/python-sortedcontainers/issues
-
-Sorted Containers License
--------------------------
-
-Copyright 2014-2019 Grant Jenks
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/RECORD b/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/RECORD
deleted file mode 100755
index 6e7b29d3..00000000
--- a/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/RECORD
+++ /dev/null
@@ -1,11 +0,0 @@
-sortedcontainers-2.4.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
-sortedcontainers-2.4.0.dist-info/LICENSE,sha256=HbfK5_zmRS4uYI5AGg-VPgEz5MLXXbafuK6FHSCG9bY,557
-sortedcontainers-2.4.0.dist-info/METADATA,sha256=7t8RUQniFQAekE2giChRvq5QsDwLAWGouedLfP1nlHM,10666
-sortedcontainers-2.4.0.dist-info/RECORD,,
-sortedcontainers-2.4.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-sortedcontainers-2.4.0.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110
-sortedcontainers-2.4.0.dist-info/top_level.txt,sha256=AVs0q-qf-10gs1tkVhfALdebJo4uPuVVBX7YT91riQU,17
-sortedcontainers/__init__.py,sha256=X_X5LuRjve77KwuJQrDUSu0T8559YcoowQbAnjuM7TE,2131
-sortedcontainers/sorteddict.py,sha256=za5LnENZMGPIn_JZEr0S0tDXfEsxJsfEnanh6lLlTZM,22712
-sortedcontainers/sortedlist.py,sha256=rwA1dM8ce09eb2DMjLOfHoikhCx_Rfk5nuE_NSsfr3I,76331
-sortedcontainers/sortedset.py,sha256=5RI2CUJGMm1ig3-dhbOrzDl8aPqDePkoJPQoq0ROS7M,19825
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/REQUESTED
deleted file mode 100755
index e69de29b..00000000
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/WHEEL
deleted file mode 100755
index ef99c6cf..00000000
--- a/apps/bitwarden_event_logs/lib/sortedcontainers-2.4.0.dist-info/WHEEL
+++ /dev/null
@@ -1,6 +0,0 @@
-Wheel-Version: 1.0
-Generator: bdist_wheel (0.34.2)
-Root-Is-Purelib: true
-Tag: py2-none-any
-Tag: py3-none-any
-
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers/__init__.py b/apps/bitwarden_event_logs/lib/sortedcontainers/__init__.py
deleted file mode 100755
index a141dd1d..00000000
--- a/apps/bitwarden_event_logs/lib/sortedcontainers/__init__.py
+++ /dev/null
@@ -1,74 +0,0 @@
-"""Sorted Containers -- Sorted List, Sorted Dict, Sorted Set
-
-Sorted Containers is an Apache2 licensed containers library, written in
-pure-Python, and fast as C-extensions.
-
-Python's standard library is great until you need a sorted collections
-type. Many will attest that you can get really far without one, but the moment
-you **really need** a sorted list, dict, or set, you're faced with a dozen
-different implementations, most using C-extensions without great documentation
-and benchmarking.
-
-In Python, we can do better. And we can do it in pure-Python!
-
-::
-
-    >>> from sortedcontainers import SortedList
-    >>> sl = SortedList(['e', 'a', 'c', 'd', 'b'])
-    >>> sl
-    SortedList(['a', 'b', 'c', 'd', 'e'])
-    >>> sl *= 1000000
-    >>> sl.count('c')
-    1000000
-    >>> sl[-3:]
-    ['e', 'e', 'e']
-    >>> from sortedcontainers import SortedDict
-    >>> sd = SortedDict({'c': 3, 'a': 1, 'b': 2})
-    >>> sd
-    SortedDict({'a': 1, 'b': 2, 'c': 3})
-    >>> sd.popitem(index=-1)
-    ('c', 3)
-    >>> from sortedcontainers import SortedSet
-    >>> ss = SortedSet('abracadabra')
-    >>> ss
-    SortedSet(['a', 'b', 'c', 'd', 'r'])
-    >>> ss.bisect_left('c')
-    2
-
-Sorted Containers takes all of the work out of Python sorted types - making
-your deployment and use of Python easy. There's no need to install a C compiler
-or pre-build and distribute custom extensions. Performance is a feature and
-testing has 100% coverage with unit tests and hours of stress.
-
-:copyright: (c) 2014-2019 by Grant Jenks.
-:license: Apache 2.0, see LICENSE for more details.
-
-"""
-
-
-from .sortedlist import SortedList, SortedKeyList, SortedListWithKey
-from .sortedset import SortedSet
-from .sorteddict import (
-    SortedDict,
-    SortedKeysView,
-    SortedItemsView,
-    SortedValuesView,
-)
-
-__all__ = [
-    'SortedList',
-    'SortedKeyList',
-    'SortedListWithKey',
-    'SortedDict',
-    'SortedKeysView',
-    'SortedItemsView',
-    'SortedValuesView',
-    'SortedSet',
-]
-
-__title__ = 'sortedcontainers'
-__version__ = '2.4.0'
-__build__ = 0x020400
-__author__ = 'Grant Jenks'
-__license__ = 'Apache 2.0'
-__copyright__ = '2014-2019, Grant Jenks'
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers/__pycache__/__init__.cpython-39.pyc b/apps/bitwarden_event_logs/lib/sortedcontainers/__pycache__/__init__.cpython-39.pyc
deleted file mode 100755
index 4bdaa9a5..00000000
Binary files a/apps/bitwarden_event_logs/lib/sortedcontainers/__pycache__/__init__.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers/__pycache__/sorteddict.cpython-39.pyc b/apps/bitwarden_event_logs/lib/sortedcontainers/__pycache__/sorteddict.cpython-39.pyc
deleted file mode 100755
index cdc34559..00000000
Binary files a/apps/bitwarden_event_logs/lib/sortedcontainers/__pycache__/sorteddict.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers/__pycache__/sortedlist.cpython-39.pyc b/apps/bitwarden_event_logs/lib/sortedcontainers/__pycache__/sortedlist.cpython-39.pyc
deleted file mode 100755
index 5dbe1a35..00000000
Binary files a/apps/bitwarden_event_logs/lib/sortedcontainers/__pycache__/sortedlist.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers/__pycache__/sortedset.cpython-39.pyc b/apps/bitwarden_event_logs/lib/sortedcontainers/__pycache__/sortedset.cpython-39.pyc
deleted file mode 100755
index 4453e85e..00000000
Binary files a/apps/bitwarden_event_logs/lib/sortedcontainers/__pycache__/sortedset.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers/sorteddict.py b/apps/bitwarden_event_logs/lib/sortedcontainers/sorteddict.py
deleted file mode 100755
index 910f2608..00000000
--- a/apps/bitwarden_event_logs/lib/sortedcontainers/sorteddict.py
+++ /dev/null
@@ -1,812 +0,0 @@
-"""Sorted Dict
-==============
-
-:doc:`Sorted Containers` is an Apache2 licensed Python sorted
-collections library, written in pure-Python, and fast as C-extensions. The
-:doc:`introduction` is the best way to get started.
-
-Sorted dict implementations:
-
-.. currentmodule:: sortedcontainers
-
-* :class:`SortedDict`
-* :class:`SortedKeysView`
-* :class:`SortedItemsView`
-* :class:`SortedValuesView`
-
-"""
-
-import sys
-import warnings
-
-from itertools import chain
-
-from .sortedlist import SortedList, recursive_repr
-from .sortedset import SortedSet
-
-###############################################################################
-# BEGIN Python 2/3 Shims
-###############################################################################
-
-try:
-    from collections.abc import (
-        ItemsView, KeysView, Mapping, ValuesView, Sequence
-    )
-except ImportError:
-    from collections import ItemsView, KeysView, Mapping, ValuesView, Sequence
-
-###############################################################################
-# END Python 2/3 Shims
-###############################################################################
-
-
-class SortedDict(dict):
-    """Sorted dict is a sorted mutable mapping.
-
-    Sorted dict keys are maintained in sorted order. The design of sorted dict
-    is simple: sorted dict inherits from dict to store items and maintains a
-    sorted list of keys.
-
-    Sorted dict keys must be hashable and comparable. The hash and total
-    ordering of keys must not change while they are stored in the sorted dict.
-
-    Mutable mapping methods:
-
-    * :func:`SortedDict.__getitem__` (inherited from dict)
-    * :func:`SortedDict.__setitem__`
-    * :func:`SortedDict.__delitem__`
-    * :func:`SortedDict.__iter__`
-    * :func:`SortedDict.__len__` (inherited from dict)
-
-    Methods for adding items:
-
-    * :func:`SortedDict.setdefault`
-    * :func:`SortedDict.update`
-
-    Methods for removing items:
-
-    * :func:`SortedDict.clear`
-    * :func:`SortedDict.pop`
-    * :func:`SortedDict.popitem`
-
-    Methods for looking up items:
-
-    * :func:`SortedDict.__contains__` (inherited from dict)
-    * :func:`SortedDict.get` (inherited from dict)
-    * :func:`SortedDict.peekitem`
-
-    Methods for views:
-
-    * :func:`SortedDict.keys`
-    * :func:`SortedDict.items`
-    * :func:`SortedDict.values`
-
-    Methods for miscellany:
-
-    * :func:`SortedDict.copy`
-    * :func:`SortedDict.fromkeys`
-    * :func:`SortedDict.__reversed__`
-    * :func:`SortedDict.__eq__` (inherited from dict)
-    * :func:`SortedDict.__ne__` (inherited from dict)
-    * :func:`SortedDict.__repr__`
-    * :func:`SortedDict._check`
-
-    Sorted list methods available (applies to keys):
-
-    * :func:`SortedList.bisect_left`
-    * :func:`SortedList.bisect_right`
-    * :func:`SortedList.count`
-    * :func:`SortedList.index`
-    * :func:`SortedList.irange`
-    * :func:`SortedList.islice`
-    * :func:`SortedList._reset`
-
-    Additional sorted list methods available, if key-function used:
-
-    * :func:`SortedKeyList.bisect_key_left`
-    * :func:`SortedKeyList.bisect_key_right`
-    * :func:`SortedKeyList.irange_key`
-
-    Sorted dicts may only be compared for equality and inequality.
-
-    """
-    def __init__(self, *args, **kwargs):
-        """Initialize sorted dict instance.
-
-        Optional key-function argument defines a callable that, like the `key`
-        argument to the built-in `sorted` function, extracts a comparison key
-        from each dictionary key. If no function is specified, the default
-        compares the dictionary keys directly. The key-function argument must
-        be provided as a positional argument and must come before all other
-        arguments.
-
-        Optional iterable argument provides an initial sequence of pairs to
-        initialize the sorted dict. Each pair in the sequence defines the key
-        and corresponding value. If a key is seen more than once, the last
-        value associated with it is stored in the new sorted dict.
-
-        Optional mapping argument provides an initial mapping of items to
-        initialize the sorted dict.
-
-        If keyword arguments are given, the keywords themselves, with their
-        associated values, are added as items to the dictionary. If a key is
-        specified both in the positional argument and as a keyword argument,
-        the value associated with the keyword is stored in the
-        sorted dict.
-
-        Sorted dict keys must be hashable, per the requirement for Python's
-        dictionaries. Keys (or the result of the key-function) must also be
-        comparable, per the requirement for sorted lists.
-
-        >>> d = {'alpha': 1, 'beta': 2}
-        >>> SortedDict([('alpha', 1), ('beta', 2)]) == d
-        True
-        >>> SortedDict({'alpha': 1, 'beta': 2}) == d
-        True
-        >>> SortedDict(alpha=1, beta=2) == d
-        True
-
-        """
-        if args and (args[0] is None or callable(args[0])):
-            _key = self._key = args[0]
-            args = args[1:]
-        else:
-            _key = self._key = None
-
-        self._list = SortedList(key=_key)
-
-        # Reaching through ``self._list`` repeatedly adds unnecessary overhead
-        # so cache references to sorted list methods.
-
-        _list = self._list
-        self._list_add = _list.add
-        self._list_clear = _list.clear
-        self._list_iter = _list.__iter__
-        self._list_reversed = _list.__reversed__
-        self._list_pop = _list.pop
-        self._list_remove = _list.remove
-        self._list_update = _list.update
-
-        # Expose some sorted list methods publicly.
-
-        self.bisect_left = _list.bisect_left
-        self.bisect = _list.bisect_right
-        self.bisect_right = _list.bisect_right
-        self.index = _list.index
-        self.irange = _list.irange
-        self.islice = _list.islice
-        self._reset = _list._reset
-
-        if _key is not None:
-            self.bisect_key_left = _list.bisect_key_left
-            self.bisect_key_right = _list.bisect_key_right
-            self.bisect_key = _list.bisect_key
-            self.irange_key = _list.irange_key
-
-        self._update(*args, **kwargs)
-
-
-    @property
-    def key(self):
-        """Function used to extract comparison key from keys.
-
-        Sorted dict compares keys directly when the key function is none.
-
-        """
-        return self._key
-
-
-    @property
-    def iloc(self):
-        """Cached reference of sorted keys view.
-
-        Deprecated in version 2 of Sorted Containers. Use
-        :func:`SortedDict.keys` instead.
-
-        """
-        # pylint: disable=attribute-defined-outside-init
-        try:
-            return self._iloc
-        except AttributeError:
-            warnings.warn(
-                'sorted_dict.iloc is deprecated.'
-                ' Use SortedDict.keys() instead.',
-                DeprecationWarning,
-                stacklevel=2,
-            )
-            _iloc = self._iloc = SortedKeysView(self)
-            return _iloc
-
-
-    def clear(self):
-
-        """Remove all items from sorted dict.
-
-        Runtime complexity: `O(n)`
-
-        """
-        dict.clear(self)
-        self._list_clear()
-
-
-    def __delitem__(self, key):
-        """Remove item from sorted dict identified by `key`.
-
-        ``sd.__delitem__(key)`` <==> ``del sd[key]``
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
-        >>> del sd['b']
-        >>> sd
-        SortedDict({'a': 1, 'c': 3})
-        >>> del sd['z']
-        Traceback (most recent call last):
-          ...
-        KeyError: 'z'
-
-        :param key: `key` for item lookup
-        :raises KeyError: if key not found
-
-        """
-        dict.__delitem__(self, key)
-        self._list_remove(key)
-
-
-    def __iter__(self):
-        """Return an iterator over the keys of the sorted dict.
-
-        ``sd.__iter__()`` <==> ``iter(sd)``
-
-        Iterating the sorted dict while adding or deleting items may raise a
-        :exc:`RuntimeError` or fail to iterate over all keys.
-
-        """
-        return self._list_iter()
-
-
-    def __reversed__(self):
-        """Return a reverse iterator over the keys of the sorted dict.
-
-        ``sd.__reversed__()`` <==> ``reversed(sd)``
-
-        Iterating the sorted dict while adding or deleting items may raise a
-        :exc:`RuntimeError` or fail to iterate over all keys.
-
-        """
-        return self._list_reversed()
-
-
-    def __setitem__(self, key, value):
-        """Store item in sorted dict with `key` and corresponding `value`.
-
-        ``sd.__setitem__(key, value)`` <==> ``sd[key] = value``
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sd = SortedDict()
-        >>> sd['c'] = 3
-        >>> sd['a'] = 1
-        >>> sd['b'] = 2
-        >>> sd
-        SortedDict({'a': 1, 'b': 2, 'c': 3})
-
-        :param key: key for item
-        :param value: value for item
-
-        """
-        if key not in self:
-            self._list_add(key)
-        dict.__setitem__(self, key, value)
-
-    _setitem = __setitem__
-
-
-    def __or__(self, other):
-        if not isinstance(other, Mapping):
-            return NotImplemented
-        items = chain(self.items(), other.items())
-        return self.__class__(self._key, items)
-
-
-    def __ror__(self, other):
-        if not isinstance(other, Mapping):
-            return NotImplemented
-        items = chain(other.items(), self.items())
-        return self.__class__(self._key, items)
-
-
-    def __ior__(self, other):
-        self._update(other)
-        return self
-
-
-    def copy(self):
-        """Return a shallow copy of the sorted dict.
-
-        Runtime complexity: `O(n)`
-
-        :return: new sorted dict
-
-        """
-        return self.__class__(self._key, self.items())
-
-    __copy__ = copy
-
-
-    @classmethod
-    def fromkeys(cls, iterable, value=None):
-        """Return a new sorted dict initailized from `iterable` and `value`.
-
-        Items in the sorted dict have keys from `iterable` and values equal to
-        `value`.
-
-        Runtime complexity: `O(n*log(n))`
-
-        :return: new sorted dict
-
-        """
-        return cls((key, value) for key in iterable)
-
-
-    def keys(self):
-        """Return new sorted keys view of the sorted dict's keys.
-
-        See :class:`SortedKeysView` for details.
-
-        :return: new sorted keys view
-
-        """
-        return SortedKeysView(self)
-
-
-    def items(self):
-        """Return new sorted items view of the sorted dict's items.
-
-        See :class:`SortedItemsView` for details.
-
-        :return: new sorted items view
-
-        """
-        return SortedItemsView(self)
-
-
-    def values(self):
-        """Return new sorted values view of the sorted dict's values.
-
-        See :class:`SortedValuesView` for details.
-
-        :return: new sorted values view
-
-        """
-        return SortedValuesView(self)
-
-
-    if sys.hexversion < 0x03000000:
-        def __make_raise_attributeerror(original, alternate):
-            # pylint: disable=no-self-argument
-            message = (
-                'SortedDict.{original}() is not implemented.'
-                ' Use SortedDict.{alternate}() instead.'
-            ).format(original=original, alternate=alternate)
-            def method(self):
-                # pylint: disable=missing-docstring,unused-argument
-                raise AttributeError(message)
-            method.__name__ = original  # pylint: disable=non-str-assignment-to-dunder-name
-            method.__doc__ = message
-            return property(method)
-
-        iteritems = __make_raise_attributeerror('iteritems', 'items')
-        iterkeys = __make_raise_attributeerror('iterkeys', 'keys')
-        itervalues = __make_raise_attributeerror('itervalues', 'values')
-        viewitems = __make_raise_attributeerror('viewitems', 'items')
-        viewkeys = __make_raise_attributeerror('viewkeys', 'keys')
-        viewvalues = __make_raise_attributeerror('viewvalues', 'values')
-
-
-    class _NotGiven(object):
-        # pylint: disable=too-few-public-methods
-        def __repr__(self):
-            return ''
-
-    __not_given = _NotGiven()
-
-    def pop(self, key, default=__not_given):
-        """Remove and return value for item identified by `key`.
-
-        If the `key` is not found then return `default` if given. If `default`
-        is not given then raise :exc:`KeyError`.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
-        >>> sd.pop('c')
-        3
-        >>> sd.pop('z', 26)
-        26
-        >>> sd.pop('y')
-        Traceback (most recent call last):
-          ...
-        KeyError: 'y'
-
-        :param key: `key` for item
-        :param default: `default` value if key not found (optional)
-        :return: value for item
-        :raises KeyError: if `key` not found and `default` not given
-
-        """
-        if key in self:
-            self._list_remove(key)
-            return dict.pop(self, key)
-        else:
-            if default is self.__not_given:
-                raise KeyError(key)
-            return default
-
-
-    def popitem(self, index=-1):
-        """Remove and return ``(key, value)`` pair at `index` from sorted dict.
-
-        Optional argument `index` defaults to -1, the last item in the sorted
-        dict. Specify ``index=0`` for the first item in the sorted dict.
-
-        If the sorted dict is empty, raises :exc:`KeyError`.
-
-        If the `index` is out of range, raises :exc:`IndexError`.
-
-        Runtime complexity: `O(log(n))`
-
-        >>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
-        >>> sd.popitem()
-        ('c', 3)
-        >>> sd.popitem(0)
-        ('a', 1)
-        >>> sd.popitem(100)
-        Traceback (most recent call last):
-          ...
-        IndexError: list index out of range
-
-        :param int index: `index` of item (default -1)
-        :return: key and value pair
-        :raises KeyError: if sorted dict is empty
-        :raises IndexError: if `index` out of range
-
-        """
-        if not self:
-            raise KeyError('popitem(): dictionary is empty')
-
-        key = self._list_pop(index)
-        value = dict.pop(self, key)
-        return (key, value)
-
-
-    def peekitem(self, index=-1):
-        """Return ``(key, value)`` pair at `index` in sorted dict.
-
-        Optional argument `index` defaults to -1, the last item in the sorted
-        dict. Specify ``index=0`` for the first item in the sorted dict.
-
-        Unlike :func:`SortedDict.popitem`, the sorted dict is not modified.
-
-        If the `index` is out of range, raises :exc:`IndexError`.
-
-        Runtime complexity: `O(log(n))`
-
-        >>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
-        >>> sd.peekitem()
-        ('c', 3)
-        >>> sd.peekitem(0)
-        ('a', 1)
-        >>> sd.peekitem(100)
-        Traceback (most recent call last):
-          ...
-        IndexError: list index out of range
-
-        :param int index: index of item (default -1)
-        :return: key and value pair
-        :raises IndexError: if `index` out of range
-
-        """
-        key = self._list[index]
-        return key, self[key]
-
-
-    def setdefault(self, key, default=None):
-        """Return value for item identified by `key` in sorted dict.
-
-        If `key` is in the sorted dict then return its value. If `key` is not
-        in the sorted dict then insert `key` with value `default` and return
-        `default`.
-
-        Optional argument `default` defaults to none.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sd = SortedDict()
-        >>> sd.setdefault('a', 1)
-        1
-        >>> sd.setdefault('a', 10)
-        1
-        >>> sd
-        SortedDict({'a': 1})
-
-        :param key: key for item
-        :param default: value for item (default None)
-        :return: value for item identified by `key`
-
-        """
-        if key in self:
-            return self[key]
-        dict.__setitem__(self, key, default)
-        self._list_add(key)
-        return default
-
-
-    def update(self, *args, **kwargs):
-        """Update sorted dict with items from `args` and `kwargs`.
-
-        Overwrites existing items.
-
-        Optional arguments `args` and `kwargs` may be a mapping, an iterable of
-        pairs or keyword arguments. See :func:`SortedDict.__init__` for
-        details.
-
-        :param args: mapping or iterable of pairs
-        :param kwargs: keyword arguments mapping
-
-        """
-        if not self:
-            dict.update(self, *args, **kwargs)
-            self._list_update(dict.__iter__(self))
-            return
-
-        if not kwargs and len(args) == 1 and isinstance(args[0], dict):
-            pairs = args[0]
-        else:
-            pairs = dict(*args, **kwargs)
-
-        if (10 * len(pairs)) > len(self):
-            dict.update(self, pairs)
-            self._list_clear()
-            self._list_update(dict.__iter__(self))
-        else:
-            for key in pairs:
-                self._setitem(key, pairs[key])
-
-    _update = update
-
-
-    def __reduce__(self):
-        """Support for pickle.
-
-        The tricks played with caching references in
-        :func:`SortedDict.__init__` confuse pickle so customize the reducer.
-
-        """
-        items = dict.copy(self)
-        return (type(self), (self._key, items))
-
-
-    @recursive_repr()
-    def __repr__(self):
-        """Return string representation of sorted dict.
-
-        ``sd.__repr__()`` <==> ``repr(sd)``
-
-        :return: string representation
-
-        """
-        _key = self._key
-        type_name = type(self).__name__
-        key_arg = '' if _key is None else '{0!r}, '.format(_key)
-        item_format = '{0!r}: {1!r}'.format
-        items = ', '.join(item_format(key, self[key]) for key in self._list)
-        return '{0}({1}{{{2}}})'.format(type_name, key_arg, items)
-
-
-    def _check(self):
-        """Check invariants of sorted dict.
-
-        Runtime complexity: `O(n)`
-
-        """
-        _list = self._list
-        _list._check()
-        assert len(self) == len(_list)
-        assert all(key in self for key in _list)
-
-
-def _view_delitem(self, index):
-    """Remove item at `index` from sorted dict.
-
-    ``view.__delitem__(index)`` <==> ``del view[index]``
-
-    Supports slicing.
-
-    Runtime complexity: `O(log(n))` -- approximate.
-
-    >>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
-    >>> view = sd.keys()
-    >>> del view[0]
-    >>> sd
-    SortedDict({'b': 2, 'c': 3})
-    >>> del view[-1]
-    >>> sd
-    SortedDict({'b': 2})
-    >>> del view[:]
-    >>> sd
-    SortedDict({})
-
-    :param index: integer or slice for indexing
-    :raises IndexError: if index out of range
-
-    """
-    _mapping = self._mapping
-    _list = _mapping._list
-    dict_delitem = dict.__delitem__
-    if isinstance(index, slice):
-        keys = _list[index]
-        del _list[index]
-        for key in keys:
-            dict_delitem(_mapping, key)
-    else:
-        key = _list.pop(index)
-        dict_delitem(_mapping, key)
-
-
-class SortedKeysView(KeysView, Sequence):
-    """Sorted keys view is a dynamic view of the sorted dict's keys.
-
-    When the sorted dict's keys change, the view reflects those changes.
-
-    The keys view implements the set and sequence abstract base classes.
-
-    """
-    __slots__ = ()
-
-
-    @classmethod
-    def _from_iterable(cls, it):
-        return SortedSet(it)
-
-
-    def __getitem__(self, index):
-        """Lookup key at `index` in sorted keys views.
-
-        ``skv.__getitem__(index)`` <==> ``skv[index]``
-
-        Supports slicing.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
-        >>> skv = sd.keys()
-        >>> skv[0]
-        'a'
-        >>> skv[-1]
-        'c'
-        >>> skv[:]
-        ['a', 'b', 'c']
-        >>> skv[100]
-        Traceback (most recent call last):
-          ...
-        IndexError: list index out of range
-
-        :param index: integer or slice for indexing
-        :return: key or list of keys
-        :raises IndexError: if index out of range
-
-        """
-        return self._mapping._list[index]
-
-
-    __delitem__ = _view_delitem
-
-
-class SortedItemsView(ItemsView, Sequence):
-    """Sorted items view is a dynamic view of the sorted dict's items.
-
-    When the sorted dict's items change, the view reflects those changes.
-
-    The items view implements the set and sequence abstract base classes.
-
-    """
-    __slots__ = ()
-
-
-    @classmethod
-    def _from_iterable(cls, it):
-        return SortedSet(it)
-
-
-    def __getitem__(self, index):
-        """Lookup item at `index` in sorted items view.
-
-        ``siv.__getitem__(index)`` <==> ``siv[index]``
-
-        Supports slicing.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
-        >>> siv = sd.items()
-        >>> siv[0]
-        ('a', 1)
-        >>> siv[-1]
-        ('c', 3)
-        >>> siv[:]
-        [('a', 1), ('b', 2), ('c', 3)]
-        >>> siv[100]
-        Traceback (most recent call last):
-          ...
-        IndexError: list index out of range
-
-        :param index: integer or slice for indexing
-        :return: item or list of items
-        :raises IndexError: if index out of range
-
-        """
-        _mapping = self._mapping
-        _mapping_list = _mapping._list
-
-        if isinstance(index, slice):
-            keys = _mapping_list[index]
-            return [(key, _mapping[key]) for key in keys]
-
-        key = _mapping_list[index]
-        return key, _mapping[key]
-
-
-    __delitem__ = _view_delitem
-
-
-class SortedValuesView(ValuesView, Sequence):
-    """Sorted values view is a dynamic view of the sorted dict's values.
-
-    When the sorted dict's values change, the view reflects those changes.
-
-    The values view implements the sequence abstract base class.
-
-    """
-    __slots__ = ()
-
-
-    def __getitem__(self, index):
-        """Lookup value at `index` in sorted values view.
-
-        ``siv.__getitem__(index)`` <==> ``siv[index]``
-
-        Supports slicing.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
-        >>> svv = sd.values()
-        >>> svv[0]
-        1
-        >>> svv[-1]
-        3
-        >>> svv[:]
-        [1, 2, 3]
-        >>> svv[100]
-        Traceback (most recent call last):
-          ...
-        IndexError: list index out of range
-
-        :param index: integer or slice for indexing
-        :return: value or list of values
-        :raises IndexError: if index out of range
-
-        """
-        _mapping = self._mapping
-        _mapping_list = _mapping._list
-
-        if isinstance(index, slice):
-            keys = _mapping_list[index]
-            return [_mapping[key] for key in keys]
-
-        key = _mapping_list[index]
-        return _mapping[key]
-
-
-    __delitem__ = _view_delitem
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers/sortedlist.py b/apps/bitwarden_event_logs/lib/sortedcontainers/sortedlist.py
deleted file mode 100755
index e3b58eb9..00000000
--- a/apps/bitwarden_event_logs/lib/sortedcontainers/sortedlist.py
+++ /dev/null
@@ -1,2646 +0,0 @@
-"""Sorted List
-==============
-
-:doc:`Sorted Containers` is an Apache2 licensed Python sorted
-collections library, written in pure-Python, and fast as C-extensions. The
-:doc:`introduction` is the best way to get started.
-
-Sorted list implementations:
-
-.. currentmodule:: sortedcontainers
-
-* :class:`SortedList`
-* :class:`SortedKeyList`
-
-"""
-# pylint: disable=too-many-lines
-from __future__ import print_function
-
-import sys
-import traceback
-
-from bisect import bisect_left, bisect_right, insort
-from itertools import chain, repeat, starmap
-from math import log
-from operator import add, eq, ne, gt, ge, lt, le, iadd
-from textwrap import dedent
-
-###############################################################################
-# BEGIN Python 2/3 Shims
-###############################################################################
-
-try:
-    from collections.abc import Sequence, MutableSequence
-except ImportError:
-    from collections import Sequence, MutableSequence
-
-from functools import wraps
-from sys import hexversion
-
-if hexversion < 0x03000000:
-    from itertools import imap as map  # pylint: disable=redefined-builtin
-    from itertools import izip as zip  # pylint: disable=redefined-builtin
-    try:
-        from thread import get_ident
-    except ImportError:
-        from dummy_thread import get_ident
-else:
-    from functools import reduce
-    try:
-        from _thread import get_ident
-    except ImportError:
-        from _dummy_thread import get_ident
-
-
-def recursive_repr(fillvalue='...'):
-    "Decorator to make a repr function return fillvalue for a recursive call."
-    # pylint: disable=missing-docstring
-    # Copied from reprlib in Python 3
-    # https://hg.python.org/cpython/file/3.6/Lib/reprlib.py
-
-    def decorating_function(user_function):
-        repr_running = set()
-
-        @wraps(user_function)
-        def wrapper(self):
-            key = id(self), get_ident()
-            if key in repr_running:
-                return fillvalue
-            repr_running.add(key)
-            try:
-                result = user_function(self)
-            finally:
-                repr_running.discard(key)
-            return result
-
-        return wrapper
-
-    return decorating_function
-
-###############################################################################
-# END Python 2/3 Shims
-###############################################################################
-
-
-class SortedList(MutableSequence):
-    """Sorted list is a sorted mutable sequence.
-
-    Sorted list values are maintained in sorted order.
-
-    Sorted list values must be comparable. The total ordering of values must
-    not change while they are stored in the sorted list.
-
-    Methods for adding values:
-
-    * :func:`SortedList.add`
-    * :func:`SortedList.update`
-    * :func:`SortedList.__add__`
-    * :func:`SortedList.__iadd__`
-    * :func:`SortedList.__mul__`
-    * :func:`SortedList.__imul__`
-
-    Methods for removing values:
-
-    * :func:`SortedList.clear`
-    * :func:`SortedList.discard`
-    * :func:`SortedList.remove`
-    * :func:`SortedList.pop`
-    * :func:`SortedList.__delitem__`
-
-    Methods for looking up values:
-
-    * :func:`SortedList.bisect_left`
-    * :func:`SortedList.bisect_right`
-    * :func:`SortedList.count`
-    * :func:`SortedList.index`
-    * :func:`SortedList.__contains__`
-    * :func:`SortedList.__getitem__`
-
-    Methods for iterating values:
-
-    * :func:`SortedList.irange`
-    * :func:`SortedList.islice`
-    * :func:`SortedList.__iter__`
-    * :func:`SortedList.__reversed__`
-
-    Methods for miscellany:
-
-    * :func:`SortedList.copy`
-    * :func:`SortedList.__len__`
-    * :func:`SortedList.__repr__`
-    * :func:`SortedList._check`
-    * :func:`SortedList._reset`
-
-    Sorted lists use lexicographical ordering semantics when compared to other
-    sequences.
-
-    Some methods of mutable sequences are not supported and will raise
-    not-implemented error.
-
-    """
-    DEFAULT_LOAD_FACTOR = 1000
-
-
-    def __init__(self, iterable=None, key=None):
-        """Initialize sorted list instance.
-
-        Optional `iterable` argument provides an initial iterable of values to
-        initialize the sorted list.
-
-        Runtime complexity: `O(n*log(n))`
-
-        >>> sl = SortedList()
-        >>> sl
-        SortedList([])
-        >>> sl = SortedList([3, 1, 2, 5, 4])
-        >>> sl
-        SortedList([1, 2, 3, 4, 5])
-
-        :param iterable: initial values (optional)
-
-        """
-        assert key is None
-        self._len = 0
-        self._load = self.DEFAULT_LOAD_FACTOR
-        self._lists = []
-        self._maxes = []
-        self._index = []
-        self._offset = 0
-
-        if iterable is not None:
-            self._update(iterable)
-
-
-    def __new__(cls, iterable=None, key=None):
-        """Create new sorted list or sorted-key list instance.
-
-        Optional `key`-function argument will return an instance of subtype
-        :class:`SortedKeyList`.
-
-        >>> sl = SortedList()
-        >>> isinstance(sl, SortedList)
-        True
-        >>> sl = SortedList(key=lambda x: -x)
-        >>> isinstance(sl, SortedList)
-        True
-        >>> isinstance(sl, SortedKeyList)
-        True
-
-        :param iterable: initial values (optional)
-        :param key: function used to extract comparison key (optional)
-        :return: sorted list or sorted-key list instance
-
-        """
-        # pylint: disable=unused-argument
-        if key is None:
-            return object.__new__(cls)
-        else:
-            if cls is SortedList:
-                return object.__new__(SortedKeyList)
-            else:
-                raise TypeError('inherit SortedKeyList for key argument')
-
-
-    @property
-    def key(self):  # pylint: disable=useless-return
-        """Function used to extract comparison key from values.
-
-        Sorted list compares values directly so the key function is none.
-
-        """
-        return None
-
-
-    def _reset(self, load):
-        """Reset sorted list load factor.
-
-        The `load` specifies the load-factor of the list. The default load
-        factor of 1000 works well for lists from tens to tens-of-millions of
-        values. Good practice is to use a value that is the cube root of the
-        list size. With billions of elements, the best load factor depends on
-        your usage. It's best to leave the load factor at the default until you
-        start benchmarking.
-
-        See :doc:`implementation` and :doc:`performance-scale` for more
-        information.
-
-        Runtime complexity: `O(n)`
-
-        :param int load: load-factor for sorted list sublists
-
-        """
-        values = reduce(iadd, self._lists, [])
-        self._clear()
-        self._load = load
-        self._update(values)
-
-
-    def clear(self):
-        """Remove all values from sorted list.
-
-        Runtime complexity: `O(n)`
-
-        """
-        self._len = 0
-        del self._lists[:]
-        del self._maxes[:]
-        del self._index[:]
-        self._offset = 0
-
-    _clear = clear
-
-
-    def add(self, value):
-        """Add `value` to sorted list.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sl = SortedList()
-        >>> sl.add(3)
-        >>> sl.add(1)
-        >>> sl.add(2)
-        >>> sl
-        SortedList([1, 2, 3])
-
-        :param value: value to add to sorted list
-
-        """
-        _lists = self._lists
-        _maxes = self._maxes
-
-        if _maxes:
-            pos = bisect_right(_maxes, value)
-
-            if pos == len(_maxes):
-                pos -= 1
-                _lists[pos].append(value)
-                _maxes[pos] = value
-            else:
-                insort(_lists[pos], value)
-
-            self._expand(pos)
-        else:
-            _lists.append([value])
-            _maxes.append(value)
-
-        self._len += 1
-
-
-    def _expand(self, pos):
-        """Split sublists with length greater than double the load-factor.
-
-        Updates the index when the sublist length is less than double the load
-        level. This requires incrementing the nodes in a traversal from the
-        leaf node to the root. For an example traversal see
-        ``SortedList._loc``.
-
-        """
-        _load = self._load
-        _lists = self._lists
-        _index = self._index
-
-        if len(_lists[pos]) > (_load << 1):
-            _maxes = self._maxes
-
-            _lists_pos = _lists[pos]
-            half = _lists_pos[_load:]
-            del _lists_pos[_load:]
-            _maxes[pos] = _lists_pos[-1]
-
-            _lists.insert(pos + 1, half)
-            _maxes.insert(pos + 1, half[-1])
-
-            del _index[:]
-        else:
-            if _index:
-                child = self._offset + pos
-                while child:
-                    _index[child] += 1
-                    child = (child - 1) >> 1
-                _index[0] += 1
-
-
-    def update(self, iterable):
-        """Update sorted list by adding all values from `iterable`.
-
-        Runtime complexity: `O(k*log(n))` -- approximate.
-
-        >>> sl = SortedList()
-        >>> sl.update([3, 1, 2])
-        >>> sl
-        SortedList([1, 2, 3])
-
-        :param iterable: iterable of values to add
-
-        """
-        _lists = self._lists
-        _maxes = self._maxes
-        values = sorted(iterable)
-
-        if _maxes:
-            if len(values) * 4 >= self._len:
-                _lists.append(values)
-                values = reduce(iadd, _lists, [])
-                values.sort()
-                self._clear()
-            else:
-                _add = self.add
-                for val in values:
-                    _add(val)
-                return
-
-        _load = self._load
-        _lists.extend(values[pos:(pos + _load)]
-                      for pos in range(0, len(values), _load))
-        _maxes.extend(sublist[-1] for sublist in _lists)
-        self._len = len(values)
-        del self._index[:]
-
-    _update = update
-
-
-    def __contains__(self, value):
-        """Return true if `value` is an element of the sorted list.
-
-        ``sl.__contains__(value)`` <==> ``value in sl``
-
-        Runtime complexity: `O(log(n))`
-
-        >>> sl = SortedList([1, 2, 3, 4, 5])
-        >>> 3 in sl
-        True
-
-        :param value: search for value in sorted list
-        :return: true if `value` in sorted list
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            return False
-
-        pos = bisect_left(_maxes, value)
-
-        if pos == len(_maxes):
-            return False
-
-        _lists = self._lists
-        idx = bisect_left(_lists[pos], value)
-
-        return _lists[pos][idx] == value
-
-
-    def discard(self, value):
-        """Remove `value` from sorted list if it is a member.
-
-        If `value` is not a member, do nothing.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sl = SortedList([1, 2, 3, 4, 5])
-        >>> sl.discard(5)
-        >>> sl.discard(0)
-        >>> sl == [1, 2, 3, 4]
-        True
-
-        :param value: `value` to discard from sorted list
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            return
-
-        pos = bisect_left(_maxes, value)
-
-        if pos == len(_maxes):
-            return
-
-        _lists = self._lists
-        idx = bisect_left(_lists[pos], value)
-
-        if _lists[pos][idx] == value:
-            self._delete(pos, idx)
-
-
-    def remove(self, value):
-        """Remove `value` from sorted list; `value` must be a member.
-
-        If `value` is not a member, raise ValueError.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sl = SortedList([1, 2, 3, 4, 5])
-        >>> sl.remove(5)
-        >>> sl == [1, 2, 3, 4]
-        True
-        >>> sl.remove(0)
-        Traceback (most recent call last):
-          ...
-        ValueError: 0 not in list
-
-        :param value: `value` to remove from sorted list
-        :raises ValueError: if `value` is not in sorted list
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            raise ValueError('{0!r} not in list'.format(value))
-
-        pos = bisect_left(_maxes, value)
-
-        if pos == len(_maxes):
-            raise ValueError('{0!r} not in list'.format(value))
-
-        _lists = self._lists
-        idx = bisect_left(_lists[pos], value)
-
-        if _lists[pos][idx] == value:
-            self._delete(pos, idx)
-        else:
-            raise ValueError('{0!r} not in list'.format(value))
-
-
-    def _delete(self, pos, idx):
-        """Delete value at the given `(pos, idx)`.
-
-        Combines lists that are less than half the load level.
-
-        Updates the index when the sublist length is more than half the load
-        level. This requires decrementing the nodes in a traversal from the
-        leaf node to the root. For an example traversal see
-        ``SortedList._loc``.
-
-        :param int pos: lists index
-        :param int idx: sublist index
-
-        """
-        _lists = self._lists
-        _maxes = self._maxes
-        _index = self._index
-
-        _lists_pos = _lists[pos]
-
-        del _lists_pos[idx]
-        self._len -= 1
-
-        len_lists_pos = len(_lists_pos)
-
-        if len_lists_pos > (self._load >> 1):
-            _maxes[pos] = _lists_pos[-1]
-
-            if _index:
-                child = self._offset + pos
-                while child > 0:
-                    _index[child] -= 1
-                    child = (child - 1) >> 1
-                _index[0] -= 1
-        elif len(_lists) > 1:
-            if not pos:
-                pos += 1
-
-            prev = pos - 1
-            _lists[prev].extend(_lists[pos])
-            _maxes[prev] = _lists[prev][-1]
-
-            del _lists[pos]
-            del _maxes[pos]
-            del _index[:]
-
-            self._expand(prev)
-        elif len_lists_pos:
-            _maxes[pos] = _lists_pos[-1]
-        else:
-            del _lists[pos]
-            del _maxes[pos]
-            del _index[:]
-
-
-    def _loc(self, pos, idx):
-        """Convert an index pair (lists index, sublist index) into a single
-        index number that corresponds to the position of the value in the
-        sorted list.
-
-        Many queries require the index be built. Details of the index are
-        described in ``SortedList._build_index``.
-
-        Indexing requires traversing the tree from a leaf node to the root. The
-        parent of each node is easily computable at ``(pos - 1) // 2``.
-
-        Left-child nodes are always at odd indices and right-child nodes are
-        always at even indices.
-
-        When traversing up from a right-child node, increment the total by the
-        left-child node.
-
-        The final index is the sum from traversal and the index in the sublist.
-
-        For example, using the index from ``SortedList._build_index``::
-
-            _index = 14 5 9 3 2 4 5
-            _offset = 3
-
-        Tree::
-
-                 14
-              5      9
-            3   2  4   5
-
-        Converting an index pair (2, 3) into a single index involves iterating
-        like so:
-
-        1. Starting at the leaf node: offset + alpha = 3 + 2 = 5. We identify
-           the node as a left-child node. At such nodes, we simply traverse to
-           the parent.
-
-        2. At node 9, position 2, we recognize the node as a right-child node
-           and accumulate the left-child in our total. Total is now 5 and we
-           traverse to the parent at position 0.
-
-        3. Iteration ends at the root.
-
-        The index is then the sum of the total and sublist index: 5 + 3 = 8.
-
-        :param int pos: lists index
-        :param int idx: sublist index
-        :return: index in sorted list
-
-        """
-        if not pos:
-            return idx
-
-        _index = self._index
-
-        if not _index:
-            self._build_index()
-
-        total = 0
-
-        # Increment pos to point in the index to len(self._lists[pos]).
-
-        pos += self._offset
-
-        # Iterate until reaching the root of the index tree at pos = 0.
-
-        while pos:
-
-            # Right-child nodes are at odd indices. At such indices
-            # account the total below the left child node.
-
-            if not pos & 1:
-                total += _index[pos - 1]
-
-            # Advance pos to the parent node.
-
-            pos = (pos - 1) >> 1
-
-        return total + idx
-
-
-    def _pos(self, idx):
-        """Convert an index into an index pair (lists index, sublist index)
-        that can be used to access the corresponding lists position.
-
-        Many queries require the index be built. Details of the index are
-        described in ``SortedList._build_index``.
-
-        Indexing requires traversing the tree to a leaf node. Each node has two
-        children which are easily computable. Given an index, pos, the
-        left-child is at ``pos * 2 + 1`` and the right-child is at ``pos * 2 +
-        2``.
-
-        When the index is less than the left-child, traversal moves to the
-        left sub-tree. Otherwise, the index is decremented by the left-child
-        and traversal moves to the right sub-tree.
-
-        At a child node, the indexing pair is computed from the relative
-        position of the child node as compared with the offset and the remaining
-        index.
-
-        For example, using the index from ``SortedList._build_index``::
-
-            _index = 14 5 9 3 2 4 5
-            _offset = 3
-
-        Tree::
-
-                 14
-              5      9
-            3   2  4   5
-
-        Indexing position 8 involves iterating like so:
-
-        1. Starting at the root, position 0, 8 is compared with the left-child
-           node (5) which it is greater than. When greater the index is
-           decremented and the position is updated to the right child node.
-
-        2. At node 9 with index 3, we again compare the index to the left-child
-           node with value 4. Because the index is the less than the left-child
-           node, we simply traverse to the left.
-
-        3. At node 4 with index 3, we recognize that we are at a leaf node and
-           stop iterating.
-
-        4. To compute the sublist index, we subtract the offset from the index
-           of the leaf node: 5 - 3 = 2. To compute the index in the sublist, we
-           simply use the index remaining from iteration. In this case, 3.
-
-        The final index pair from our example is (2, 3) which corresponds to
-        index 8 in the sorted list.
-
-        :param int idx: index in sorted list
-        :return: (lists index, sublist index) pair
-
-        """
-        if idx < 0:
-            last_len = len(self._lists[-1])
-
-            if (-idx) <= last_len:
-                return len(self._lists) - 1, last_len + idx
-
-            idx += self._len
-
-            if idx < 0:
-                raise IndexError('list index out of range')
-        elif idx >= self._len:
-            raise IndexError('list index out of range')
-
-        if idx < len(self._lists[0]):
-            return 0, idx
-
-        _index = self._index
-
-        if not _index:
-            self._build_index()
-
-        pos = 0
-        child = 1
-        len_index = len(_index)
-
-        while child < len_index:
-            index_child = _index[child]
-
-            if idx < index_child:
-                pos = child
-            else:
-                idx -= index_child
-                pos = child + 1
-
-            child = (pos << 1) + 1
-
-        return (pos - self._offset, idx)
-
-
-    def _build_index(self):
-        """Build a positional index for indexing the sorted list.
-
-        Indexes are represented as binary trees in a dense array notation
-        similar to a binary heap.
-
-        For example, given a lists representation storing integers::
-
-            0: [1, 2, 3]
-            1: [4, 5]
-            2: [6, 7, 8, 9]
-            3: [10, 11, 12, 13, 14]
-
-        The first transformation maps the sub-lists by their length. The
-        first row of the index is the length of the sub-lists::
-
-            0: [3, 2, 4, 5]
-
-        Each row after that is the sum of consecutive pairs of the previous
-        row::
-
-            1: [5, 9]
-            2: [14]
-
-        Finally, the index is built by concatenating these lists together::
-
-            _index = [14, 5, 9, 3, 2, 4, 5]
-
-        An offset storing the start of the first row is also stored::
-
-            _offset = 3
-
-        When built, the index can be used for efficient indexing into the list.
-        See the comment and notes on ``SortedList._pos`` for details.
-
-        """
-        row0 = list(map(len, self._lists))
-
-        if len(row0) == 1:
-            self._index[:] = row0
-            self._offset = 0
-            return
-
-        head = iter(row0)
-        tail = iter(head)
-        row1 = list(starmap(add, zip(head, tail)))
-
-        if len(row0) & 1:
-            row1.append(row0[-1])
-
-        if len(row1) == 1:
-            self._index[:] = row1 + row0
-            self._offset = 1
-            return
-
-        size = 2 ** (int(log(len(row1) - 1, 2)) + 1)
-        row1.extend(repeat(0, size - len(row1)))
-        tree = [row0, row1]
-
-        while len(tree[-1]) > 1:
-            head = iter(tree[-1])
-            tail = iter(head)
-            row = list(starmap(add, zip(head, tail)))
-            tree.append(row)
-
-        reduce(iadd, reversed(tree), self._index)
-        self._offset = size * 2 - 1
-
-
-    def __delitem__(self, index):
-        """Remove value at `index` from sorted list.
-
-        ``sl.__delitem__(index)`` <==> ``del sl[index]``
-
-        Supports slicing.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sl = SortedList('abcde')
-        >>> del sl[2]
-        >>> sl
-        SortedList(['a', 'b', 'd', 'e'])
-        >>> del sl[:2]
-        >>> sl
-        SortedList(['d', 'e'])
-
-        :param index: integer or slice for indexing
-        :raises IndexError: if index out of range
-
-        """
-        if isinstance(index, slice):
-            start, stop, step = index.indices(self._len)
-
-            if step == 1 and start < stop:
-                if start == 0 and stop == self._len:
-                    return self._clear()
-                elif self._len <= 8 * (stop - start):
-                    values = self._getitem(slice(None, start))
-                    if stop < self._len:
-                        values += self._getitem(slice(stop, None))
-                    self._clear()
-                    return self._update(values)
-
-            indices = range(start, stop, step)
-
-            # Delete items from greatest index to least so
-            # that the indices remain valid throughout iteration.
-
-            if step > 0:
-                indices = reversed(indices)
-
-            _pos, _delete = self._pos, self._delete
-
-            for index in indices:
-                pos, idx = _pos(index)
-                _delete(pos, idx)
-        else:
-            pos, idx = self._pos(index)
-            self._delete(pos, idx)
-
-
-    def __getitem__(self, index):
-        """Lookup value at `index` in sorted list.
-
-        ``sl.__getitem__(index)`` <==> ``sl[index]``
-
-        Supports slicing.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sl = SortedList('abcde')
-        >>> sl[1]
-        'b'
-        >>> sl[-1]
-        'e'
-        >>> sl[2:5]
-        ['c', 'd', 'e']
-
-        :param index: integer or slice for indexing
-        :return: value or list of values
-        :raises IndexError: if index out of range
-
-        """
-        _lists = self._lists
-
-        if isinstance(index, slice):
-            start, stop, step = index.indices(self._len)
-
-            if step == 1 and start < stop:
-                # Whole slice optimization: start to stop slices the whole
-                # sorted list.
-
-                if start == 0 and stop == self._len:
-                    return reduce(iadd, self._lists, [])
-
-                start_pos, start_idx = self._pos(start)
-                start_list = _lists[start_pos]
-                stop_idx = start_idx + stop - start
-
-                # Small slice optimization: start index and stop index are
-                # within the start list.
-
-                if len(start_list) >= stop_idx:
-                    return start_list[start_idx:stop_idx]
-
-                if stop == self._len:
-                    stop_pos = len(_lists) - 1
-                    stop_idx = len(_lists[stop_pos])
-                else:
-                    stop_pos, stop_idx = self._pos(stop)
-
-                prefix = _lists[start_pos][start_idx:]
-                middle = _lists[(start_pos + 1):stop_pos]
-                result = reduce(iadd, middle, prefix)
-                result += _lists[stop_pos][:stop_idx]
-
-                return result
-
-            if step == -1 and start > stop:
-                result = self._getitem(slice(stop + 1, start + 1))
-                result.reverse()
-                return result
-
-            # Return a list because a negative step could
-            # reverse the order of the items and this could
-            # be the desired behavior.
-
-            indices = range(start, stop, step)
-            return list(self._getitem(index) for index in indices)
-        else:
-            if self._len:
-                if index == 0:
-                    return _lists[0][0]
-                elif index == -1:
-                    return _lists[-1][-1]
-            else:
-                raise IndexError('list index out of range')
-
-            if 0 <= index < len(_lists[0]):
-                return _lists[0][index]
-
-            len_last = len(_lists[-1])
-
-            if -len_last < index < 0:
-                return _lists[-1][len_last + index]
-
-            pos, idx = self._pos(index)
-            return _lists[pos][idx]
-
-    _getitem = __getitem__
-
-
-    def __setitem__(self, index, value):
-        """Raise not-implemented error.
-
-        ``sl.__setitem__(index, value)`` <==> ``sl[index] = value``
-
-        :raises NotImplementedError: use ``del sl[index]`` and
-            ``sl.add(value)`` instead
-
-        """
-        message = 'use ``del sl[index]`` and ``sl.add(value)`` instead'
-        raise NotImplementedError(message)
-
-
-    def __iter__(self):
-        """Return an iterator over the sorted list.
-
-        ``sl.__iter__()`` <==> ``iter(sl)``
-
-        Iterating the sorted list while adding or deleting values may raise a
-        :exc:`RuntimeError` or fail to iterate over all values.
-
-        """
-        return chain.from_iterable(self._lists)
-
-
-    def __reversed__(self):
-        """Return a reverse iterator over the sorted list.
-
-        ``sl.__reversed__()`` <==> ``reversed(sl)``
-
-        Iterating the sorted list while adding or deleting values may raise a
-        :exc:`RuntimeError` or fail to iterate over all values.
-
-        """
-        return chain.from_iterable(map(reversed, reversed(self._lists)))
-
-
-    def reverse(self):
-        """Raise not-implemented error.
-
-        Sorted list maintains values in ascending sort order. Values may not be
-        reversed in-place.
-
-        Use ``reversed(sl)`` for an iterator over values in descending sort
-        order.
-
-        Implemented to override `MutableSequence.reverse` which provides an
-        erroneous default implementation.
-
-        :raises NotImplementedError: use ``reversed(sl)`` instead
-
-        """
-        raise NotImplementedError('use ``reversed(sl)`` instead')
-
-
-    def islice(self, start=None, stop=None, reverse=False):
-        """Return an iterator that slices sorted list from `start` to `stop`.
-
-        The `start` and `stop` index are treated inclusive and exclusive,
-        respectively.
-
-        Both `start` and `stop` default to `None` which is automatically
-        inclusive of the beginning and end of the sorted list.
-
-        When `reverse` is `True` the values are yielded from the iterator in
-        reverse order; `reverse` defaults to `False`.
-
-        >>> sl = SortedList('abcdefghij')
-        >>> it = sl.islice(2, 6)
-        >>> list(it)
-        ['c', 'd', 'e', 'f']
-
-        :param int start: start index (inclusive)
-        :param int stop: stop index (exclusive)
-        :param bool reverse: yield values in reverse order
-        :return: iterator
-
-        """
-        _len = self._len
-
-        if not _len:
-            return iter(())
-
-        start, stop, _ = slice(start, stop).indices(self._len)
-
-        if start >= stop:
-            return iter(())
-
-        _pos = self._pos
-
-        min_pos, min_idx = _pos(start)
-
-        if stop == _len:
-            max_pos = len(self._lists) - 1
-            max_idx = len(self._lists[-1])
-        else:
-            max_pos, max_idx = _pos(stop)
-
-        return self._islice(min_pos, min_idx, max_pos, max_idx, reverse)
-
-
-    def _islice(self, min_pos, min_idx, max_pos, max_idx, reverse):
-        """Return an iterator that slices sorted list using two index pairs.
-
-        The index pairs are (min_pos, min_idx) and (max_pos, max_idx), the
-        first inclusive and the latter exclusive. See `_pos` for details on how
-        an index is converted to an index pair.
-
-        When `reverse` is `True`, values are yielded from the iterator in
-        reverse order.
-
-        """
-        _lists = self._lists
-
-        if min_pos > max_pos:
-            return iter(())
-
-        if min_pos == max_pos:
-            if reverse:
-                indices = reversed(range(min_idx, max_idx))
-                return map(_lists[min_pos].__getitem__, indices)
-
-            indices = range(min_idx, max_idx)
-            return map(_lists[min_pos].__getitem__, indices)
-
-        next_pos = min_pos + 1
-
-        if next_pos == max_pos:
-            if reverse:
-                min_indices = range(min_idx, len(_lists[min_pos]))
-                max_indices = range(max_idx)
-                return chain(
-                    map(_lists[max_pos].__getitem__, reversed(max_indices)),
-                    map(_lists[min_pos].__getitem__, reversed(min_indices)),
-                )
-
-            min_indices = range(min_idx, len(_lists[min_pos]))
-            max_indices = range(max_idx)
-            return chain(
-                map(_lists[min_pos].__getitem__, min_indices),
-                map(_lists[max_pos].__getitem__, max_indices),
-            )
-
-        if reverse:
-            min_indices = range(min_idx, len(_lists[min_pos]))
-            sublist_indices = range(next_pos, max_pos)
-            sublists = map(_lists.__getitem__, reversed(sublist_indices))
-            max_indices = range(max_idx)
-            return chain(
-                map(_lists[max_pos].__getitem__, reversed(max_indices)),
-                chain.from_iterable(map(reversed, sublists)),
-                map(_lists[min_pos].__getitem__, reversed(min_indices)),
-            )
-
-        min_indices = range(min_idx, len(_lists[min_pos]))
-        sublist_indices = range(next_pos, max_pos)
-        sublists = map(_lists.__getitem__, sublist_indices)
-        max_indices = range(max_idx)
-        return chain(
-            map(_lists[min_pos].__getitem__, min_indices),
-            chain.from_iterable(sublists),
-            map(_lists[max_pos].__getitem__, max_indices),
-        )
-
-
-    def irange(self, minimum=None, maximum=None, inclusive=(True, True),
-               reverse=False):
-        """Create an iterator of values between `minimum` and `maximum`.
-
-        Both `minimum` and `maximum` default to `None` which is automatically
-        inclusive of the beginning and end of the sorted list.
-
-        The argument `inclusive` is a pair of booleans that indicates whether
-        the minimum and maximum ought to be included in the range,
-        respectively. The default is ``(True, True)`` such that the range is
-        inclusive of both minimum and maximum.
-
-        When `reverse` is `True` the values are yielded from the iterator in
-        reverse order; `reverse` defaults to `False`.
-
-        >>> sl = SortedList('abcdefghij')
-        >>> it = sl.irange('c', 'f')
-        >>> list(it)
-        ['c', 'd', 'e', 'f']
-
-        :param minimum: minimum value to start iterating
-        :param maximum: maximum value to stop iterating
-        :param inclusive: pair of booleans
-        :param bool reverse: yield values in reverse order
-        :return: iterator
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            return iter(())
-
-        _lists = self._lists
-
-        # Calculate the minimum (pos, idx) pair. By default this location
-        # will be inclusive in our calculation.
-
-        if minimum is None:
-            min_pos = 0
-            min_idx = 0
-        else:
-            if inclusive[0]:
-                min_pos = bisect_left(_maxes, minimum)
-
-                if min_pos == len(_maxes):
-                    return iter(())
-
-                min_idx = bisect_left(_lists[min_pos], minimum)
-            else:
-                min_pos = bisect_right(_maxes, minimum)
-
-                if min_pos == len(_maxes):
-                    return iter(())
-
-                min_idx = bisect_right(_lists[min_pos], minimum)
-
-        # Calculate the maximum (pos, idx) pair. By default this location
-        # will be exclusive in our calculation.
-
-        if maximum is None:
-            max_pos = len(_maxes) - 1
-            max_idx = len(_lists[max_pos])
-        else:
-            if inclusive[1]:
-                max_pos = bisect_right(_maxes, maximum)
-
-                if max_pos == len(_maxes):
-                    max_pos -= 1
-                    max_idx = len(_lists[max_pos])
-                else:
-                    max_idx = bisect_right(_lists[max_pos], maximum)
-            else:
-                max_pos = bisect_left(_maxes, maximum)
-
-                if max_pos == len(_maxes):
-                    max_pos -= 1
-                    max_idx = len(_lists[max_pos])
-                else:
-                    max_idx = bisect_left(_lists[max_pos], maximum)
-
-        return self._islice(min_pos, min_idx, max_pos, max_idx, reverse)
-
-
-    def __len__(self):
-        """Return the size of the sorted list.
-
-        ``sl.__len__()`` <==> ``len(sl)``
-
-        :return: size of sorted list
-
-        """
-        return self._len
-
-
-    def bisect_left(self, value):
-        """Return an index to insert `value` in the sorted list.
-
-        If the `value` is already present, the insertion point will be before
-        (to the left of) any existing values.
-
-        Similar to the `bisect` module in the standard library.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sl = SortedList([10, 11, 12, 13, 14])
-        >>> sl.bisect_left(12)
-        2
-
-        :param value: insertion index of value in sorted list
-        :return: index
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            return 0
-
-        pos = bisect_left(_maxes, value)
-
-        if pos == len(_maxes):
-            return self._len
-
-        idx = bisect_left(self._lists[pos], value)
-        return self._loc(pos, idx)
-
-
-    def bisect_right(self, value):
-        """Return an index to insert `value` in the sorted list.
-
-        Similar to `bisect_left`, but if `value` is already present, the
-        insertion point will be after (to the right of) any existing values.
-
-        Similar to the `bisect` module in the standard library.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sl = SortedList([10, 11, 12, 13, 14])
-        >>> sl.bisect_right(12)
-        3
-
-        :param value: insertion index of value in sorted list
-        :return: index
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            return 0
-
-        pos = bisect_right(_maxes, value)
-
-        if pos == len(_maxes):
-            return self._len
-
-        idx = bisect_right(self._lists[pos], value)
-        return self._loc(pos, idx)
-
-    bisect = bisect_right
-    _bisect_right = bisect_right
-
-
-    def count(self, value):
-        """Return number of occurrences of `value` in the sorted list.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sl = SortedList([1, 2, 2, 3, 3, 3, 4, 4, 4, 4])
-        >>> sl.count(3)
-        3
-
-        :param value: value to count in sorted list
-        :return: count
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            return 0
-
-        pos_left = bisect_left(_maxes, value)
-
-        if pos_left == len(_maxes):
-            return 0
-
-        _lists = self._lists
-        idx_left = bisect_left(_lists[pos_left], value)
-        pos_right = bisect_right(_maxes, value)
-
-        if pos_right == len(_maxes):
-            return self._len - self._loc(pos_left, idx_left)
-
-        idx_right = bisect_right(_lists[pos_right], value)
-
-        if pos_left == pos_right:
-            return idx_right - idx_left
-
-        right = self._loc(pos_right, idx_right)
-        left = self._loc(pos_left, idx_left)
-        return right - left
-
-
-    def copy(self):
-        """Return a shallow copy of the sorted list.
-
-        Runtime complexity: `O(n)`
-
-        :return: new sorted list
-
-        """
-        return self.__class__(self)
-
-    __copy__ = copy
-
-
-    def append(self, value):
-        """Raise not-implemented error.
-
-        Implemented to override `MutableSequence.append` which provides an
-        erroneous default implementation.
-
-        :raises NotImplementedError: use ``sl.add(value)`` instead
-
-        """
-        raise NotImplementedError('use ``sl.add(value)`` instead')
-
-
-    def extend(self, values):
-        """Raise not-implemented error.
-
-        Implemented to override `MutableSequence.extend` which provides an
-        erroneous default implementation.
-
-        :raises NotImplementedError: use ``sl.update(values)`` instead
-
-        """
-        raise NotImplementedError('use ``sl.update(values)`` instead')
-
-
-    def insert(self, index, value):
-        """Raise not-implemented error.
-
-        :raises NotImplementedError: use ``sl.add(value)`` instead
-
-        """
-        raise NotImplementedError('use ``sl.add(value)`` instead')
-
-
-    def pop(self, index=-1):
-        """Remove and return value at `index` in sorted list.
-
-        Raise :exc:`IndexError` if the sorted list is empty or index is out of
-        range.
-
-        Negative indices are supported.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sl = SortedList('abcde')
-        >>> sl.pop()
-        'e'
-        >>> sl.pop(2)
-        'c'
-        >>> sl
-        SortedList(['a', 'b', 'd'])
-
-        :param int index: index of value (default -1)
-        :return: value
-        :raises IndexError: if index is out of range
-
-        """
-        if not self._len:
-            raise IndexError('pop index out of range')
-
-        _lists = self._lists
-
-        if index == 0:
-            val = _lists[0][0]
-            self._delete(0, 0)
-            return val
-
-        if index == -1:
-            pos = len(_lists) - 1
-            loc = len(_lists[pos]) - 1
-            val = _lists[pos][loc]
-            self._delete(pos, loc)
-            return val
-
-        if 0 <= index < len(_lists[0]):
-            val = _lists[0][index]
-            self._delete(0, index)
-            return val
-
-        len_last = len(_lists[-1])
-
-        if -len_last < index < 0:
-            pos = len(_lists) - 1
-            loc = len_last + index
-            val = _lists[pos][loc]
-            self._delete(pos, loc)
-            return val
-
-        pos, idx = self._pos(index)
-        val = _lists[pos][idx]
-        self._delete(pos, idx)
-        return val
-
-
-    def index(self, value, start=None, stop=None):
-        """Return first index of value in sorted list.
-
-        Raise ValueError if `value` is not present.
-
-        Index must be between `start` and `stop` for the `value` to be
-        considered present. The default value, None, for `start` and `stop`
-        indicate the beginning and end of the sorted list.
-
-        Negative indices are supported.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> sl = SortedList('abcde')
-        >>> sl.index('d')
-        3
-        >>> sl.index('z')
-        Traceback (most recent call last):
-          ...
-        ValueError: 'z' is not in list
-
-        :param value: value in sorted list
-        :param int start: start index (default None, start of sorted list)
-        :param int stop: stop index (default None, end of sorted list)
-        :return: index of value
-        :raises ValueError: if value is not present
-
-        """
-        _len = self._len
-
-        if not _len:
-            raise ValueError('{0!r} is not in list'.format(value))
-
-        if start is None:
-            start = 0
-        if start < 0:
-            start += _len
-        if start < 0:
-            start = 0
-
-        if stop is None:
-            stop = _len
-        if stop < 0:
-            stop += _len
-        if stop > _len:
-            stop = _len
-
-        if stop <= start:
-            raise ValueError('{0!r} is not in list'.format(value))
-
-        _maxes = self._maxes
-        pos_left = bisect_left(_maxes, value)
-
-        if pos_left == len(_maxes):
-            raise ValueError('{0!r} is not in list'.format(value))
-
-        _lists = self._lists
-        idx_left = bisect_left(_lists[pos_left], value)
-
-        if _lists[pos_left][idx_left] != value:
-            raise ValueError('{0!r} is not in list'.format(value))
-
-        stop -= 1
-        left = self._loc(pos_left, idx_left)
-
-        if start <= left:
-            if left <= stop:
-                return left
-        else:
-            right = self._bisect_right(value) - 1
-
-            if start <= right:
-                return start
-
-        raise ValueError('{0!r} is not in list'.format(value))
-
-
-    def __add__(self, other):
-        """Return new sorted list containing all values in both sequences.
-
-        ``sl.__add__(other)`` <==> ``sl + other``
-
-        Values in `other` do not need to be in sorted order.
-
-        Runtime complexity: `O(n*log(n))`
-
-        >>> sl1 = SortedList('bat')
-        >>> sl2 = SortedList('cat')
-        >>> sl1 + sl2
-        SortedList(['a', 'a', 'b', 'c', 't', 't'])
-
-        :param other: other iterable
-        :return: new sorted list
-
-        """
-        values = reduce(iadd, self._lists, [])
-        values.extend(other)
-        return self.__class__(values)
-
-    __radd__ = __add__
-
-
-    def __iadd__(self, other):
-        """Update sorted list with values from `other`.
-
-        ``sl.__iadd__(other)`` <==> ``sl += other``
-
-        Values in `other` do not need to be in sorted order.
-
-        Runtime complexity: `O(k*log(n))` -- approximate.
-
-        >>> sl = SortedList('bat')
-        >>> sl += 'cat'
-        >>> sl
-        SortedList(['a', 'a', 'b', 'c', 't', 't'])
-
-        :param other: other iterable
-        :return: existing sorted list
-
-        """
-        self._update(other)
-        return self
-
-
-    def __mul__(self, num):
-        """Return new sorted list with `num` shallow copies of values.
-
-        ``sl.__mul__(num)`` <==> ``sl * num``
-
-        Runtime complexity: `O(n*log(n))`
-
-        >>> sl = SortedList('abc')
-        >>> sl * 3
-        SortedList(['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c'])
-
-        :param int num: count of shallow copies
-        :return: new sorted list
-
-        """
-        values = reduce(iadd, self._lists, []) * num
-        return self.__class__(values)
-
-    __rmul__ = __mul__
-
-
-    def __imul__(self, num):
-        """Update the sorted list with `num` shallow copies of values.
-
-        ``sl.__imul__(num)`` <==> ``sl *= num``
-
-        Runtime complexity: `O(n*log(n))`
-
-        >>> sl = SortedList('abc')
-        >>> sl *= 3
-        >>> sl
-        SortedList(['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c'])
-
-        :param int num: count of shallow copies
-        :return: existing sorted list
-
-        """
-        values = reduce(iadd, self._lists, []) * num
-        self._clear()
-        self._update(values)
-        return self
-
-
-    def __make_cmp(seq_op, symbol, doc):
-        "Make comparator method."
-        def comparer(self, other):
-            "Compare method for sorted list and sequence."
-            if not isinstance(other, Sequence):
-                return NotImplemented
-
-            self_len = self._len
-            len_other = len(other)
-
-            if self_len != len_other:
-                if seq_op is eq:
-                    return False
-                if seq_op is ne:
-                    return True
-
-            for alpha, beta in zip(self, other):
-                if alpha != beta:
-                    return seq_op(alpha, beta)
-
-            return seq_op(self_len, len_other)
-
-        seq_op_name = seq_op.__name__
-        comparer.__name__ = '__{0}__'.format(seq_op_name)
-        doc_str = """Return true if and only if sorted list is {0} `other`.
-
-        ``sl.__{1}__(other)`` <==> ``sl {2} other``
-
-        Comparisons use lexicographical order as with sequences.
-
-        Runtime complexity: `O(n)`
-
-        :param other: `other` sequence
-        :return: true if sorted list is {0} `other`
-
-        """
-        comparer.__doc__ = dedent(doc_str.format(doc, seq_op_name, symbol))
-        return comparer
-
-
-    __eq__ = __make_cmp(eq, '==', 'equal to')
-    __ne__ = __make_cmp(ne, '!=', 'not equal to')
-    __lt__ = __make_cmp(lt, '<', 'less than')
-    __gt__ = __make_cmp(gt, '>', 'greater than')
-    __le__ = __make_cmp(le, '<=', 'less than or equal to')
-    __ge__ = __make_cmp(ge, '>=', 'greater than or equal to')
-    __make_cmp = staticmethod(__make_cmp)
-
-
-    def __reduce__(self):
-        values = reduce(iadd, self._lists, [])
-        return (type(self), (values,))
-
-
-    @recursive_repr()
-    def __repr__(self):
-        """Return string representation of sorted list.
-
-        ``sl.__repr__()`` <==> ``repr(sl)``
-
-        :return: string representation
-
-        """
-        return '{0}({1!r})'.format(type(self).__name__, list(self))
-
-
-    def _check(self):
-        """Check invariants of sorted list.
-
-        Runtime complexity: `O(n)`
-
-        """
-        try:
-            assert self._load >= 4
-            assert len(self._maxes) == len(self._lists)
-            assert self._len == sum(len(sublist) for sublist in self._lists)
-
-            # Check all sublists are sorted.
-
-            for sublist in self._lists:
-                for pos in range(1, len(sublist)):
-                    assert sublist[pos - 1] <= sublist[pos]
-
-            # Check beginning/end of sublists are sorted.
-
-            for pos in range(1, len(self._lists)):
-                assert self._lists[pos - 1][-1] <= self._lists[pos][0]
-
-            # Check _maxes index is the last value of each sublist.
-
-            for pos in range(len(self._maxes)):
-                assert self._maxes[pos] == self._lists[pos][-1]
-
-            # Check sublist lengths are less than double load-factor.
-
-            double = self._load << 1
-            assert all(len(sublist) <= double for sublist in self._lists)
-
-            # Check sublist lengths are greater than half load-factor for all
-            # but the last sublist.
-
-            half = self._load >> 1
-            for pos in range(0, len(self._lists) - 1):
-                assert len(self._lists[pos]) >= half
-
-            if self._index:
-                assert self._len == self._index[0]
-                assert len(self._index) == self._offset + len(self._lists)
-
-                # Check index leaf nodes equal length of sublists.
-
-                for pos in range(len(self._lists)):
-                    leaf = self._index[self._offset + pos]
-                    assert leaf == len(self._lists[pos])
-
-                # Check index branch nodes are the sum of their children.
-
-                for pos in range(self._offset):
-                    child = (pos << 1) + 1
-                    if child >= len(self._index):
-                        assert self._index[pos] == 0
-                    elif child + 1 == len(self._index):
-                        assert self._index[pos] == self._index[child]
-                    else:
-                        child_sum = self._index[child] + self._index[child + 1]
-                        assert child_sum == self._index[pos]
-        except:
-            traceback.print_exc(file=sys.stdout)
-            print('len', self._len)
-            print('load', self._load)
-            print('offset', self._offset)
-            print('len_index', len(self._index))
-            print('index', self._index)
-            print('len_maxes', len(self._maxes))
-            print('maxes', self._maxes)
-            print('len_lists', len(self._lists))
-            print('lists', self._lists)
-            raise
-
-
-def identity(value):
-    "Identity function."
-    return value
-
-
-class SortedKeyList(SortedList):
-    """Sorted-key list is a subtype of sorted list.
-
-    The sorted-key list maintains values in comparison order based on the
-    result of a key function applied to every value.
-
-    All the same methods that are available in :class:`SortedList` are also
-    available in :class:`SortedKeyList`.
-
-    Additional methods provided:
-
-    * :attr:`SortedKeyList.key`
-    * :func:`SortedKeyList.bisect_key_left`
-    * :func:`SortedKeyList.bisect_key_right`
-    * :func:`SortedKeyList.irange_key`
-
-    Some examples below use:
-
-    >>> from operator import neg
-    >>> neg
-    
-    >>> neg(1)
-    -1
-
-    """
-    def __init__(self, iterable=None, key=identity):
-        """Initialize sorted-key list instance.
-
-        Optional `iterable` argument provides an initial iterable of values to
-        initialize the sorted-key list.
-
-        Optional `key` argument defines a callable that, like the `key`
-        argument to Python's `sorted` function, extracts a comparison key from
-        each value. The default is the identity function.
-
-        Runtime complexity: `O(n*log(n))`
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList(key=neg)
-        >>> skl
-        SortedKeyList([], key=)
-        >>> skl = SortedKeyList([3, 1, 2], key=neg)
-        >>> skl
-        SortedKeyList([3, 2, 1], key=)
-
-        :param iterable: initial values (optional)
-        :param key: function used to extract comparison key (optional)
-
-        """
-        self._key = key
-        self._len = 0
-        self._load = self.DEFAULT_LOAD_FACTOR
-        self._lists = []
-        self._keys = []
-        self._maxes = []
-        self._index = []
-        self._offset = 0
-
-        if iterable is not None:
-            self._update(iterable)
-
-
-    def __new__(cls, iterable=None, key=identity):
-        return object.__new__(cls)
-
-
-    @property
-    def key(self):
-        "Function used to extract comparison key from values."
-        return self._key
-
-
-    def clear(self):
-        """Remove all values from sorted-key list.
-
-        Runtime complexity: `O(n)`
-
-        """
-        self._len = 0
-        del self._lists[:]
-        del self._keys[:]
-        del self._maxes[:]
-        del self._index[:]
-
-    _clear = clear
-
-
-    def add(self, value):
-        """Add `value` to sorted-key list.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList(key=neg)
-        >>> skl.add(3)
-        >>> skl.add(1)
-        >>> skl.add(2)
-        >>> skl
-        SortedKeyList([3, 2, 1], key=)
-
-        :param value: value to add to sorted-key list
-
-        """
-        _lists = self._lists
-        _keys = self._keys
-        _maxes = self._maxes
-
-        key = self._key(value)
-
-        if _maxes:
-            pos = bisect_right(_maxes, key)
-
-            if pos == len(_maxes):
-                pos -= 1
-                _lists[pos].append(value)
-                _keys[pos].append(key)
-                _maxes[pos] = key
-            else:
-                idx = bisect_right(_keys[pos], key)
-                _lists[pos].insert(idx, value)
-                _keys[pos].insert(idx, key)
-
-            self._expand(pos)
-        else:
-            _lists.append([value])
-            _keys.append([key])
-            _maxes.append(key)
-
-        self._len += 1
-
-
-    def _expand(self, pos):
-        """Split sublists with length greater than double the load-factor.
-
-        Updates the index when the sublist length is less than double the load
-        level. This requires incrementing the nodes in a traversal from the
-        leaf node to the root. For an example traversal see
-        ``SortedList._loc``.
-
-        """
-        _lists = self._lists
-        _keys = self._keys
-        _index = self._index
-
-        if len(_keys[pos]) > (self._load << 1):
-            _maxes = self._maxes
-            _load = self._load
-
-            _lists_pos = _lists[pos]
-            _keys_pos = _keys[pos]
-            half = _lists_pos[_load:]
-            half_keys = _keys_pos[_load:]
-            del _lists_pos[_load:]
-            del _keys_pos[_load:]
-            _maxes[pos] = _keys_pos[-1]
-
-            _lists.insert(pos + 1, half)
-            _keys.insert(pos + 1, half_keys)
-            _maxes.insert(pos + 1, half_keys[-1])
-
-            del _index[:]
-        else:
-            if _index:
-                child = self._offset + pos
-                while child:
-                    _index[child] += 1
-                    child = (child - 1) >> 1
-                _index[0] += 1
-
-
-    def update(self, iterable):
-        """Update sorted-key list by adding all values from `iterable`.
-
-        Runtime complexity: `O(k*log(n))` -- approximate.
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList(key=neg)
-        >>> skl.update([3, 1, 2])
-        >>> skl
-        SortedKeyList([3, 2, 1], key=)
-
-        :param iterable: iterable of values to add
-
-        """
-        _lists = self._lists
-        _keys = self._keys
-        _maxes = self._maxes
-        values = sorted(iterable, key=self._key)
-
-        if _maxes:
-            if len(values) * 4 >= self._len:
-                _lists.append(values)
-                values = reduce(iadd, _lists, [])
-                values.sort(key=self._key)
-                self._clear()
-            else:
-                _add = self.add
-                for val in values:
-                    _add(val)
-                return
-
-        _load = self._load
-        _lists.extend(values[pos:(pos + _load)]
-                      for pos in range(0, len(values), _load))
-        _keys.extend(list(map(self._key, _list)) for _list in _lists)
-        _maxes.extend(sublist[-1] for sublist in _keys)
-        self._len = len(values)
-        del self._index[:]
-
-    _update = update
-
-
-    def __contains__(self, value):
-        """Return true if `value` is an element of the sorted-key list.
-
-        ``skl.__contains__(value)`` <==> ``value in skl``
-
-        Runtime complexity: `O(log(n))`
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList([1, 2, 3, 4, 5], key=neg)
-        >>> 3 in skl
-        True
-
-        :param value: search for value in sorted-key list
-        :return: true if `value` in sorted-key list
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            return False
-
-        key = self._key(value)
-        pos = bisect_left(_maxes, key)
-
-        if pos == len(_maxes):
-            return False
-
-        _lists = self._lists
-        _keys = self._keys
-
-        idx = bisect_left(_keys[pos], key)
-
-        len_keys = len(_keys)
-        len_sublist = len(_keys[pos])
-
-        while True:
-            if _keys[pos][idx] != key:
-                return False
-            if _lists[pos][idx] == value:
-                return True
-            idx += 1
-            if idx == len_sublist:
-                pos += 1
-                if pos == len_keys:
-                    return False
-                len_sublist = len(_keys[pos])
-                idx = 0
-
-
-    def discard(self, value):
-        """Remove `value` from sorted-key list if it is a member.
-
-        If `value` is not a member, do nothing.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList([5, 4, 3, 2, 1], key=neg)
-        >>> skl.discard(1)
-        >>> skl.discard(0)
-        >>> skl == [5, 4, 3, 2]
-        True
-
-        :param value: `value` to discard from sorted-key list
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            return
-
-        key = self._key(value)
-        pos = bisect_left(_maxes, key)
-
-        if pos == len(_maxes):
-            return
-
-        _lists = self._lists
-        _keys = self._keys
-        idx = bisect_left(_keys[pos], key)
-        len_keys = len(_keys)
-        len_sublist = len(_keys[pos])
-
-        while True:
-            if _keys[pos][idx] != key:
-                return
-            if _lists[pos][idx] == value:
-                self._delete(pos, idx)
-                return
-            idx += 1
-            if idx == len_sublist:
-                pos += 1
-                if pos == len_keys:
-                    return
-                len_sublist = len(_keys[pos])
-                idx = 0
-
-
-    def remove(self, value):
-        """Remove `value` from sorted-key list; `value` must be a member.
-
-        If `value` is not a member, raise ValueError.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList([1, 2, 3, 4, 5], key=neg)
-        >>> skl.remove(5)
-        >>> skl == [4, 3, 2, 1]
-        True
-        >>> skl.remove(0)
-        Traceback (most recent call last):
-          ...
-        ValueError: 0 not in list
-
-        :param value: `value` to remove from sorted-key list
-        :raises ValueError: if `value` is not in sorted-key list
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            raise ValueError('{0!r} not in list'.format(value))
-
-        key = self._key(value)
-        pos = bisect_left(_maxes, key)
-
-        if pos == len(_maxes):
-            raise ValueError('{0!r} not in list'.format(value))
-
-        _lists = self._lists
-        _keys = self._keys
-        idx = bisect_left(_keys[pos], key)
-        len_keys = len(_keys)
-        len_sublist = len(_keys[pos])
-
-        while True:
-            if _keys[pos][idx] != key:
-                raise ValueError('{0!r} not in list'.format(value))
-            if _lists[pos][idx] == value:
-                self._delete(pos, idx)
-                return
-            idx += 1
-            if idx == len_sublist:
-                pos += 1
-                if pos == len_keys:
-                    raise ValueError('{0!r} not in list'.format(value))
-                len_sublist = len(_keys[pos])
-                idx = 0
-
-
-    def _delete(self, pos, idx):
-        """Delete value at the given `(pos, idx)`.
-
-        Combines lists that are less than half the load level.
-
-        Updates the index when the sublist length is more than half the load
-        level. This requires decrementing the nodes in a traversal from the
-        leaf node to the root. For an example traversal see
-        ``SortedList._loc``.
-
-        :param int pos: lists index
-        :param int idx: sublist index
-
-        """
-        _lists = self._lists
-        _keys = self._keys
-        _maxes = self._maxes
-        _index = self._index
-        keys_pos = _keys[pos]
-        lists_pos = _lists[pos]
-
-        del keys_pos[idx]
-        del lists_pos[idx]
-        self._len -= 1
-
-        len_keys_pos = len(keys_pos)
-
-        if len_keys_pos > (self._load >> 1):
-            _maxes[pos] = keys_pos[-1]
-
-            if _index:
-                child = self._offset + pos
-                while child > 0:
-                    _index[child] -= 1
-                    child = (child - 1) >> 1
-                _index[0] -= 1
-        elif len(_keys) > 1:
-            if not pos:
-                pos += 1
-
-            prev = pos - 1
-            _keys[prev].extend(_keys[pos])
-            _lists[prev].extend(_lists[pos])
-            _maxes[prev] = _keys[prev][-1]
-
-            del _lists[pos]
-            del _keys[pos]
-            del _maxes[pos]
-            del _index[:]
-
-            self._expand(prev)
-        elif len_keys_pos:
-            _maxes[pos] = keys_pos[-1]
-        else:
-            del _lists[pos]
-            del _keys[pos]
-            del _maxes[pos]
-            del _index[:]
-
-
-    def irange(self, minimum=None, maximum=None, inclusive=(True, True),
-               reverse=False):
-        """Create an iterator of values between `minimum` and `maximum`.
-
-        Both `minimum` and `maximum` default to `None` which is automatically
-        inclusive of the beginning and end of the sorted-key list.
-
-        The argument `inclusive` is a pair of booleans that indicates whether
-        the minimum and maximum ought to be included in the range,
-        respectively. The default is ``(True, True)`` such that the range is
-        inclusive of both minimum and maximum.
-
-        When `reverse` is `True` the values are yielded from the iterator in
-        reverse order; `reverse` defaults to `False`.
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList([11, 12, 13, 14, 15], key=neg)
-        >>> it = skl.irange(14.5, 11.5)
-        >>> list(it)
-        [14, 13, 12]
-
-        :param minimum: minimum value to start iterating
-        :param maximum: maximum value to stop iterating
-        :param inclusive: pair of booleans
-        :param bool reverse: yield values in reverse order
-        :return: iterator
-
-        """
-        min_key = self._key(minimum) if minimum is not None else None
-        max_key = self._key(maximum) if maximum is not None else None
-        return self._irange_key(
-            min_key=min_key, max_key=max_key,
-            inclusive=inclusive, reverse=reverse,
-        )
-
-
-    def irange_key(self, min_key=None, max_key=None, inclusive=(True, True),
-                   reverse=False):
-        """Create an iterator of values between `min_key` and `max_key`.
-
-        Both `min_key` and `max_key` default to `None` which is automatically
-        inclusive of the beginning and end of the sorted-key list.
-
-        The argument `inclusive` is a pair of booleans that indicates whether
-        the minimum and maximum ought to be included in the range,
-        respectively. The default is ``(True, True)`` such that the range is
-        inclusive of both minimum and maximum.
-
-        When `reverse` is `True` the values are yielded from the iterator in
-        reverse order; `reverse` defaults to `False`.
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList([11, 12, 13, 14, 15], key=neg)
-        >>> it = skl.irange_key(-14, -12)
-        >>> list(it)
-        [14, 13, 12]
-
-        :param min_key: minimum key to start iterating
-        :param max_key: maximum key to stop iterating
-        :param inclusive: pair of booleans
-        :param bool reverse: yield values in reverse order
-        :return: iterator
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            return iter(())
-
-        _keys = self._keys
-
-        # Calculate the minimum (pos, idx) pair. By default this location
-        # will be inclusive in our calculation.
-
-        if min_key is None:
-            min_pos = 0
-            min_idx = 0
-        else:
-            if inclusive[0]:
-                min_pos = bisect_left(_maxes, min_key)
-
-                if min_pos == len(_maxes):
-                    return iter(())
-
-                min_idx = bisect_left(_keys[min_pos], min_key)
-            else:
-                min_pos = bisect_right(_maxes, min_key)
-
-                if min_pos == len(_maxes):
-                    return iter(())
-
-                min_idx = bisect_right(_keys[min_pos], min_key)
-
-        # Calculate the maximum (pos, idx) pair. By default this location
-        # will be exclusive in our calculation.
-
-        if max_key is None:
-            max_pos = len(_maxes) - 1
-            max_idx = len(_keys[max_pos])
-        else:
-            if inclusive[1]:
-                max_pos = bisect_right(_maxes, max_key)
-
-                if max_pos == len(_maxes):
-                    max_pos -= 1
-                    max_idx = len(_keys[max_pos])
-                else:
-                    max_idx = bisect_right(_keys[max_pos], max_key)
-            else:
-                max_pos = bisect_left(_maxes, max_key)
-
-                if max_pos == len(_maxes):
-                    max_pos -= 1
-                    max_idx = len(_keys[max_pos])
-                else:
-                    max_idx = bisect_left(_keys[max_pos], max_key)
-
-        return self._islice(min_pos, min_idx, max_pos, max_idx, reverse)
-
-    _irange_key = irange_key
-
-
-    def bisect_left(self, value):
-        """Return an index to insert `value` in the sorted-key list.
-
-        If the `value` is already present, the insertion point will be before
-        (to the left of) any existing values.
-
-        Similar to the `bisect` module in the standard library.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList([5, 4, 3, 2, 1], key=neg)
-        >>> skl.bisect_left(1)
-        4
-
-        :param value: insertion index of value in sorted-key list
-        :return: index
-
-        """
-        return self._bisect_key_left(self._key(value))
-
-
-    def bisect_right(self, value):
-        """Return an index to insert `value` in the sorted-key list.
-
-        Similar to `bisect_left`, but if `value` is already present, the
-        insertion point will be after (to the right of) any existing values.
-
-        Similar to the `bisect` module in the standard library.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> from operator import neg
-        >>> skl = SortedList([5, 4, 3, 2, 1], key=neg)
-        >>> skl.bisect_right(1)
-        5
-
-        :param value: insertion index of value in sorted-key list
-        :return: index
-
-        """
-        return self._bisect_key_right(self._key(value))
-
-    bisect = bisect_right
-
-
-    def bisect_key_left(self, key):
-        """Return an index to insert `key` in the sorted-key list.
-
-        If the `key` is already present, the insertion point will be before (to
-        the left of) any existing keys.
-
-        Similar to the `bisect` module in the standard library.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList([5, 4, 3, 2, 1], key=neg)
-        >>> skl.bisect_key_left(-1)
-        4
-
-        :param key: insertion index of key in sorted-key list
-        :return: index
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            return 0
-
-        pos = bisect_left(_maxes, key)
-
-        if pos == len(_maxes):
-            return self._len
-
-        idx = bisect_left(self._keys[pos], key)
-
-        return self._loc(pos, idx)
-
-    _bisect_key_left = bisect_key_left
-
-
-    def bisect_key_right(self, key):
-        """Return an index to insert `key` in the sorted-key list.
-
-        Similar to `bisect_key_left`, but if `key` is already present, the
-        insertion point will be after (to the right of) any existing keys.
-
-        Similar to the `bisect` module in the standard library.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> from operator import neg
-        >>> skl = SortedList([5, 4, 3, 2, 1], key=neg)
-        >>> skl.bisect_key_right(-1)
-        5
-
-        :param key: insertion index of key in sorted-key list
-        :return: index
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            return 0
-
-        pos = bisect_right(_maxes, key)
-
-        if pos == len(_maxes):
-            return self._len
-
-        idx = bisect_right(self._keys[pos], key)
-
-        return self._loc(pos, idx)
-
-    bisect_key = bisect_key_right
-    _bisect_key_right = bisect_key_right
-
-
-    def count(self, value):
-        """Return number of occurrences of `value` in the sorted-key list.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList([4, 4, 4, 4, 3, 3, 3, 2, 2, 1], key=neg)
-        >>> skl.count(2)
-        2
-
-        :param value: value to count in sorted-key list
-        :return: count
-
-        """
-        _maxes = self._maxes
-
-        if not _maxes:
-            return 0
-
-        key = self._key(value)
-        pos = bisect_left(_maxes, key)
-
-        if pos == len(_maxes):
-            return 0
-
-        _lists = self._lists
-        _keys = self._keys
-        idx = bisect_left(_keys[pos], key)
-        total = 0
-        len_keys = len(_keys)
-        len_sublist = len(_keys[pos])
-
-        while True:
-            if _keys[pos][idx] != key:
-                return total
-            if _lists[pos][idx] == value:
-                total += 1
-            idx += 1
-            if idx == len_sublist:
-                pos += 1
-                if pos == len_keys:
-                    return total
-                len_sublist = len(_keys[pos])
-                idx = 0
-
-
-    def copy(self):
-        """Return a shallow copy of the sorted-key list.
-
-        Runtime complexity: `O(n)`
-
-        :return: new sorted-key list
-
-        """
-        return self.__class__(self, key=self._key)
-
-    __copy__ = copy
-
-
-    def index(self, value, start=None, stop=None):
-        """Return first index of value in sorted-key list.
-
-        Raise ValueError if `value` is not present.
-
-        Index must be between `start` and `stop` for the `value` to be
-        considered present. The default value, None, for `start` and `stop`
-        indicate the beginning and end of the sorted-key list.
-
-        Negative indices are supported.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList([5, 4, 3, 2, 1], key=neg)
-        >>> skl.index(2)
-        3
-        >>> skl.index(0)
-        Traceback (most recent call last):
-          ...
-        ValueError: 0 is not in list
-
-        :param value: value in sorted-key list
-        :param int start: start index (default None, start of sorted-key list)
-        :param int stop: stop index (default None, end of sorted-key list)
-        :return: index of value
-        :raises ValueError: if value is not present
-
-        """
-        _len = self._len
-
-        if not _len:
-            raise ValueError('{0!r} is not in list'.format(value))
-
-        if start is None:
-            start = 0
-        if start < 0:
-            start += _len
-        if start < 0:
-            start = 0
-
-        if stop is None:
-            stop = _len
-        if stop < 0:
-            stop += _len
-        if stop > _len:
-            stop = _len
-
-        if stop <= start:
-            raise ValueError('{0!r} is not in list'.format(value))
-
-        _maxes = self._maxes
-        key = self._key(value)
-        pos = bisect_left(_maxes, key)
-
-        if pos == len(_maxes):
-            raise ValueError('{0!r} is not in list'.format(value))
-
-        stop -= 1
-        _lists = self._lists
-        _keys = self._keys
-        idx = bisect_left(_keys[pos], key)
-        len_keys = len(_keys)
-        len_sublist = len(_keys[pos])
-
-        while True:
-            if _keys[pos][idx] != key:
-                raise ValueError('{0!r} is not in list'.format(value))
-            if _lists[pos][idx] == value:
-                loc = self._loc(pos, idx)
-                if start <= loc <= stop:
-                    return loc
-                elif loc > stop:
-                    break
-            idx += 1
-            if idx == len_sublist:
-                pos += 1
-                if pos == len_keys:
-                    raise ValueError('{0!r} is not in list'.format(value))
-                len_sublist = len(_keys[pos])
-                idx = 0
-
-        raise ValueError('{0!r} is not in list'.format(value))
-
-
-    def __add__(self, other):
-        """Return new sorted-key list containing all values in both sequences.
-
-        ``skl.__add__(other)`` <==> ``skl + other``
-
-        Values in `other` do not need to be in sorted-key order.
-
-        Runtime complexity: `O(n*log(n))`
-
-        >>> from operator import neg
-        >>> skl1 = SortedKeyList([5, 4, 3], key=neg)
-        >>> skl2 = SortedKeyList([2, 1, 0], key=neg)
-        >>> skl1 + skl2
-        SortedKeyList([5, 4, 3, 2, 1, 0], key=)
-
-        :param other: other iterable
-        :return: new sorted-key list
-
-        """
-        values = reduce(iadd, self._lists, [])
-        values.extend(other)
-        return self.__class__(values, key=self._key)
-
-    __radd__ = __add__
-
-
-    def __mul__(self, num):
-        """Return new sorted-key list with `num` shallow copies of values.
-
-        ``skl.__mul__(num)`` <==> ``skl * num``
-
-        Runtime complexity: `O(n*log(n))`
-
-        >>> from operator import neg
-        >>> skl = SortedKeyList([3, 2, 1], key=neg)
-        >>> skl * 2
-        SortedKeyList([3, 3, 2, 2, 1, 1], key=)
-
-        :param int num: count of shallow copies
-        :return: new sorted-key list
-
-        """
-        values = reduce(iadd, self._lists, []) * num
-        return self.__class__(values, key=self._key)
-
-
-    def __reduce__(self):
-        values = reduce(iadd, self._lists, [])
-        return (type(self), (values, self.key))
-
-
-    @recursive_repr()
-    def __repr__(self):
-        """Return string representation of sorted-key list.
-
-        ``skl.__repr__()`` <==> ``repr(skl)``
-
-        :return: string representation
-
-        """
-        type_name = type(self).__name__
-        return '{0}({1!r}, key={2!r})'.format(type_name, list(self), self._key)
-
-
-    def _check(self):
-        """Check invariants of sorted-key list.
-
-        Runtime complexity: `O(n)`
-
-        """
-        try:
-            assert self._load >= 4
-            assert len(self._maxes) == len(self._lists) == len(self._keys)
-            assert self._len == sum(len(sublist) for sublist in self._lists)
-
-            # Check all sublists are sorted.
-
-            for sublist in self._keys:
-                for pos in range(1, len(sublist)):
-                    assert sublist[pos - 1] <= sublist[pos]
-
-            # Check beginning/end of sublists are sorted.
-
-            for pos in range(1, len(self._keys)):
-                assert self._keys[pos - 1][-1] <= self._keys[pos][0]
-
-            # Check _keys matches _key mapped to _lists.
-
-            for val_sublist, key_sublist in zip(self._lists, self._keys):
-                assert len(val_sublist) == len(key_sublist)
-                for val, key in zip(val_sublist, key_sublist):
-                    assert self._key(val) == key
-
-            # Check _maxes index is the last value of each sublist.
-
-            for pos in range(len(self._maxes)):
-                assert self._maxes[pos] == self._keys[pos][-1]
-
-            # Check sublist lengths are less than double load-factor.
-
-            double = self._load << 1
-            assert all(len(sublist) <= double for sublist in self._lists)
-
-            # Check sublist lengths are greater than half load-factor for all
-            # but the last sublist.
-
-            half = self._load >> 1
-            for pos in range(0, len(self._lists) - 1):
-                assert len(self._lists[pos]) >= half
-
-            if self._index:
-                assert self._len == self._index[0]
-                assert len(self._index) == self._offset + len(self._lists)
-
-                # Check index leaf nodes equal length of sublists.
-
-                for pos in range(len(self._lists)):
-                    leaf = self._index[self._offset + pos]
-                    assert leaf == len(self._lists[pos])
-
-                # Check index branch nodes are the sum of their children.
-
-                for pos in range(self._offset):
-                    child = (pos << 1) + 1
-                    if child >= len(self._index):
-                        assert self._index[pos] == 0
-                    elif child + 1 == len(self._index):
-                        assert self._index[pos] == self._index[child]
-                    else:
-                        child_sum = self._index[child] + self._index[child + 1]
-                        assert child_sum == self._index[pos]
-        except:
-            traceback.print_exc(file=sys.stdout)
-            print('len', self._len)
-            print('load', self._load)
-            print('offset', self._offset)
-            print('len_index', len(self._index))
-            print('index', self._index)
-            print('len_maxes', len(self._maxes))
-            print('maxes', self._maxes)
-            print('len_keys', len(self._keys))
-            print('keys', self._keys)
-            print('len_lists', len(self._lists))
-            print('lists', self._lists)
-            raise
-
-
-SortedListWithKey = SortedKeyList
diff --git a/apps/bitwarden_event_logs/lib/sortedcontainers/sortedset.py b/apps/bitwarden_event_logs/lib/sortedcontainers/sortedset.py
deleted file mode 100755
index be2b8999..00000000
--- a/apps/bitwarden_event_logs/lib/sortedcontainers/sortedset.py
+++ /dev/null
@@ -1,733 +0,0 @@
-"""Sorted Set
-=============
-
-:doc:`Sorted Containers` is an Apache2 licensed Python sorted
-collections library, written in pure-Python, and fast as C-extensions. The
-:doc:`introduction` is the best way to get started.
-
-Sorted set implementations:
-
-.. currentmodule:: sortedcontainers
-
-* :class:`SortedSet`
-
-"""
-
-from itertools import chain
-from operator import eq, ne, gt, ge, lt, le
-from textwrap import dedent
-
-from .sortedlist import SortedList, recursive_repr
-
-###############################################################################
-# BEGIN Python 2/3 Shims
-###############################################################################
-
-try:
-    from collections.abc import MutableSet, Sequence, Set
-except ImportError:
-    from collections import MutableSet, Sequence, Set
-
-###############################################################################
-# END Python 2/3 Shims
-###############################################################################
-
-
-class SortedSet(MutableSet, Sequence):
-    """Sorted set is a sorted mutable set.
-
-    Sorted set values are maintained in sorted order. The design of sorted set
-    is simple: sorted set uses a set for set-operations and maintains a sorted
-    list of values.
-
-    Sorted set values must be hashable and comparable. The hash and total
-    ordering of values must not change while they are stored in the sorted set.
-
-    Mutable set methods:
-
-    * :func:`SortedSet.__contains__`
-    * :func:`SortedSet.__iter__`
-    * :func:`SortedSet.__len__`
-    * :func:`SortedSet.add`
-    * :func:`SortedSet.discard`
-
-    Sequence methods:
-
-    * :func:`SortedSet.__getitem__`
-    * :func:`SortedSet.__delitem__`
-    * :func:`SortedSet.__reversed__`
-
-    Methods for removing values:
-
-    * :func:`SortedSet.clear`
-    * :func:`SortedSet.pop`
-    * :func:`SortedSet.remove`
-
-    Set-operation methods:
-
-    * :func:`SortedSet.difference`
-    * :func:`SortedSet.difference_update`
-    * :func:`SortedSet.intersection`
-    * :func:`SortedSet.intersection_update`
-    * :func:`SortedSet.symmetric_difference`
-    * :func:`SortedSet.symmetric_difference_update`
-    * :func:`SortedSet.union`
-    * :func:`SortedSet.update`
-
-    Methods for miscellany:
-
-    * :func:`SortedSet.copy`
-    * :func:`SortedSet.count`
-    * :func:`SortedSet.__repr__`
-    * :func:`SortedSet._check`
-
-    Sorted list methods available:
-
-    * :func:`SortedList.bisect_left`
-    * :func:`SortedList.bisect_right`
-    * :func:`SortedList.index`
-    * :func:`SortedList.irange`
-    * :func:`SortedList.islice`
-    * :func:`SortedList._reset`
-
-    Additional sorted list methods available, if key-function used:
-
-    * :func:`SortedKeyList.bisect_key_left`
-    * :func:`SortedKeyList.bisect_key_right`
-    * :func:`SortedKeyList.irange_key`
-
-    Sorted set comparisons use subset and superset relations. Two sorted sets
-    are equal if and only if every element of each sorted set is contained in
-    the other (each is a subset of the other). A sorted set is less than
-    another sorted set if and only if the first sorted set is a proper subset
-    of the second sorted set (is a subset, but is not equal). A sorted set is
-    greater than another sorted set if and only if the first sorted set is a
-    proper superset of the second sorted set (is a superset, but is not equal).
-
-    """
-    def __init__(self, iterable=None, key=None):
-        """Initialize sorted set instance.
-
-        Optional `iterable` argument provides an initial iterable of values to
-        initialize the sorted set.
-
-        Optional `key` argument defines a callable that, like the `key`
-        argument to Python's `sorted` function, extracts a comparison key from
-        each value. The default, none, compares values directly.
-
-        Runtime complexity: `O(n*log(n))`
-
-        >>> ss = SortedSet([3, 1, 2, 5, 4])
-        >>> ss
-        SortedSet([1, 2, 3, 4, 5])
-        >>> from operator import neg
-        >>> ss = SortedSet([3, 1, 2, 5, 4], neg)
-        >>> ss
-        SortedSet([5, 4, 3, 2, 1], key=)
-
-        :param iterable: initial values (optional)
-        :param key: function used to extract comparison key (optional)
-
-        """
-        self._key = key
-
-        # SortedSet._fromset calls SortedSet.__init__ after initializing the
-        # _set attribute. So only create a new set if the _set attribute is not
-        # already present.
-
-        if not hasattr(self, '_set'):
-            self._set = set()
-
-        self._list = SortedList(self._set, key=key)
-
-        # Expose some set methods publicly.
-
-        _set = self._set
-        self.isdisjoint = _set.isdisjoint
-        self.issubset = _set.issubset
-        self.issuperset = _set.issuperset
-
-        # Expose some sorted list methods publicly.
-
-        _list = self._list
-        self.bisect_left = _list.bisect_left
-        self.bisect = _list.bisect
-        self.bisect_right = _list.bisect_right
-        self.index = _list.index
-        self.irange = _list.irange
-        self.islice = _list.islice
-        self._reset = _list._reset
-
-        if key is not None:
-            self.bisect_key_left = _list.bisect_key_left
-            self.bisect_key_right = _list.bisect_key_right
-            self.bisect_key = _list.bisect_key
-            self.irange_key = _list.irange_key
-
-        if iterable is not None:
-            self._update(iterable)
-
-
-    @classmethod
-    def _fromset(cls, values, key=None):
-        """Initialize sorted set from existing set.
-
-        Used internally by set operations that return a new set.
-
-        """
-        sorted_set = object.__new__(cls)
-        sorted_set._set = values
-        sorted_set.__init__(key=key)
-        return sorted_set
-
-
-    @property
-    def key(self):
-        """Function used to extract comparison key from values.
-
-        Sorted set compares values directly when the key function is none.
-
-        """
-        return self._key
-
-
-    def __contains__(self, value):
-        """Return true if `value` is an element of the sorted set.
-
-        ``ss.__contains__(value)`` <==> ``value in ss``
-
-        Runtime complexity: `O(1)`
-
-        >>> ss = SortedSet([1, 2, 3, 4, 5])
-        >>> 3 in ss
-        True
-
-        :param value: search for value in sorted set
-        :return: true if `value` in sorted set
-
-        """
-        return value in self._set
-
-
-    def __getitem__(self, index):
-        """Lookup value at `index` in sorted set.
-
-        ``ss.__getitem__(index)`` <==> ``ss[index]``
-
-        Supports slicing.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> ss = SortedSet('abcde')
-        >>> ss[2]
-        'c'
-        >>> ss[-1]
-        'e'
-        >>> ss[2:5]
-        ['c', 'd', 'e']
-
-        :param index: integer or slice for indexing
-        :return: value or list of values
-        :raises IndexError: if index out of range
-
-        """
-        return self._list[index]
-
-
-    def __delitem__(self, index):
-        """Remove value at `index` from sorted set.
-
-        ``ss.__delitem__(index)`` <==> ``del ss[index]``
-
-        Supports slicing.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> ss = SortedSet('abcde')
-        >>> del ss[2]
-        >>> ss
-        SortedSet(['a', 'b', 'd', 'e'])
-        >>> del ss[:2]
-        >>> ss
-        SortedSet(['d', 'e'])
-
-        :param index: integer or slice for indexing
-        :raises IndexError: if index out of range
-
-        """
-        _set = self._set
-        _list = self._list
-        if isinstance(index, slice):
-            values = _list[index]
-            _set.difference_update(values)
-        else:
-            value = _list[index]
-            _set.remove(value)
-        del _list[index]
-
-
-    def __make_cmp(set_op, symbol, doc):
-        "Make comparator method."
-        def comparer(self, other):
-            "Compare method for sorted set and set."
-            if isinstance(other, SortedSet):
-                return set_op(self._set, other._set)
-            elif isinstance(other, Set):
-                return set_op(self._set, other)
-            return NotImplemented
-
-        set_op_name = set_op.__name__
-        comparer.__name__ = '__{0}__'.format(set_op_name)
-        doc_str = """Return true if and only if sorted set is {0} `other`.
-
-        ``ss.__{1}__(other)`` <==> ``ss {2} other``
-
-        Comparisons use subset and superset semantics as with sets.
-
-        Runtime complexity: `O(n)`
-
-        :param other: `other` set
-        :return: true if sorted set is {0} `other`
-
-        """
-        comparer.__doc__ = dedent(doc_str.format(doc, set_op_name, symbol))
-        return comparer
-
-
-    __eq__ = __make_cmp(eq, '==', 'equal to')
-    __ne__ = __make_cmp(ne, '!=', 'not equal to')
-    __lt__ = __make_cmp(lt, '<', 'a proper subset of')
-    __gt__ = __make_cmp(gt, '>', 'a proper superset of')
-    __le__ = __make_cmp(le, '<=', 'a subset of')
-    __ge__ = __make_cmp(ge, '>=', 'a superset of')
-    __make_cmp = staticmethod(__make_cmp)
-
-
-    def __len__(self):
-        """Return the size of the sorted set.
-
-        ``ss.__len__()`` <==> ``len(ss)``
-
-        :return: size of sorted set
-
-        """
-        return len(self._set)
-
-
-    def __iter__(self):
-        """Return an iterator over the sorted set.
-
-        ``ss.__iter__()`` <==> ``iter(ss)``
-
-        Iterating the sorted set while adding or deleting values may raise a
-        :exc:`RuntimeError` or fail to iterate over all values.
-
-        """
-        return iter(self._list)
-
-
-    def __reversed__(self):
-        """Return a reverse iterator over the sorted set.
-
-        ``ss.__reversed__()`` <==> ``reversed(ss)``
-
-        Iterating the sorted set while adding or deleting values may raise a
-        :exc:`RuntimeError` or fail to iterate over all values.
-
-        """
-        return reversed(self._list)
-
-
-    def add(self, value):
-        """Add `value` to sorted set.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> ss = SortedSet()
-        >>> ss.add(3)
-        >>> ss.add(1)
-        >>> ss.add(2)
-        >>> ss
-        SortedSet([1, 2, 3])
-
-        :param value: value to add to sorted set
-
-        """
-        _set = self._set
-        if value not in _set:
-            _set.add(value)
-            self._list.add(value)
-
-    _add = add
-
-
-    def clear(self):
-        """Remove all values from sorted set.
-
-        Runtime complexity: `O(n)`
-
-        """
-        self._set.clear()
-        self._list.clear()
-
-
-    def copy(self):
-        """Return a shallow copy of the sorted set.
-
-        Runtime complexity: `O(n)`
-
-        :return: new sorted set
-
-        """
-        return self._fromset(set(self._set), key=self._key)
-
-    __copy__ = copy
-
-
-    def count(self, value):
-        """Return number of occurrences of `value` in the sorted set.
-
-        Runtime complexity: `O(1)`
-
-        >>> ss = SortedSet([1, 2, 3, 4, 5])
-        >>> ss.count(3)
-        1
-
-        :param value: value to count in sorted set
-        :return: count
-
-        """
-        return 1 if value in self._set else 0
-
-
-    def discard(self, value):
-        """Remove `value` from sorted set if it is a member.
-
-        If `value` is not a member, do nothing.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> ss = SortedSet([1, 2, 3, 4, 5])
-        >>> ss.discard(5)
-        >>> ss.discard(0)
-        >>> ss == set([1, 2, 3, 4])
-        True
-
-        :param value: `value` to discard from sorted set
-
-        """
-        _set = self._set
-        if value in _set:
-            _set.remove(value)
-            self._list.remove(value)
-
-    _discard = discard
-
-
-    def pop(self, index=-1):
-        """Remove and return value at `index` in sorted set.
-
-        Raise :exc:`IndexError` if the sorted set is empty or index is out of
-        range.
-
-        Negative indices are supported.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> ss = SortedSet('abcde')
-        >>> ss.pop()
-        'e'
-        >>> ss.pop(2)
-        'c'
-        >>> ss
-        SortedSet(['a', 'b', 'd'])
-
-        :param int index: index of value (default -1)
-        :return: value
-        :raises IndexError: if index is out of range
-
-        """
-        # pylint: disable=arguments-differ
-        value = self._list.pop(index)
-        self._set.remove(value)
-        return value
-
-
-    def remove(self, value):
-        """Remove `value` from sorted set; `value` must be a member.
-
-        If `value` is not a member, raise :exc:`KeyError`.
-
-        Runtime complexity: `O(log(n))` -- approximate.
-
-        >>> ss = SortedSet([1, 2, 3, 4, 5])
-        >>> ss.remove(5)
-        >>> ss == set([1, 2, 3, 4])
-        True
-        >>> ss.remove(0)
-        Traceback (most recent call last):
-          ...
-        KeyError: 0
-
-        :param value: `value` to remove from sorted set
-        :raises KeyError: if `value` is not in sorted set
-
-        """
-        self._set.remove(value)
-        self._list.remove(value)
-
-
-    def difference(self, *iterables):
-        """Return the difference of two or more sets as a new sorted set.
-
-        The `difference` method also corresponds to operator ``-``.
-
-        ``ss.__sub__(iterable)`` <==> ``ss - iterable``
-
-        The difference is all values that are in this sorted set but not the
-        other `iterables`.
-
-        >>> ss = SortedSet([1, 2, 3, 4, 5])
-        >>> ss.difference([4, 5, 6, 7])
-        SortedSet([1, 2, 3])
-
-        :param iterables: iterable arguments
-        :return: new sorted set
-
-        """
-        diff = self._set.difference(*iterables)
-        return self._fromset(diff, key=self._key)
-
-    __sub__ = difference
-
-
-    def difference_update(self, *iterables):
-        """Remove all values of `iterables` from this sorted set.
-
-        The `difference_update` method also corresponds to operator ``-=``.
-
-        ``ss.__isub__(iterable)`` <==> ``ss -= iterable``
-
-        >>> ss = SortedSet([1, 2, 3, 4, 5])
-        >>> _ = ss.difference_update([4, 5, 6, 7])
-        >>> ss
-        SortedSet([1, 2, 3])
-
-        :param iterables: iterable arguments
-        :return: itself
-
-        """
-        _set = self._set
-        _list = self._list
-        values = set(chain(*iterables))
-        if (4 * len(values)) > len(_set):
-            _set.difference_update(values)
-            _list.clear()
-            _list.update(_set)
-        else:
-            _discard = self._discard
-            for value in values:
-                _discard(value)
-        return self
-
-    __isub__ = difference_update
-
-
-    def intersection(self, *iterables):
-        """Return the intersection of two or more sets as a new sorted set.
-
-        The `intersection` method also corresponds to operator ``&``.
-
-        ``ss.__and__(iterable)`` <==> ``ss & iterable``
-
-        The intersection is all values that are in this sorted set and each of
-        the other `iterables`.
-
-        >>> ss = SortedSet([1, 2, 3, 4, 5])
-        >>> ss.intersection([4, 5, 6, 7])
-        SortedSet([4, 5])
-
-        :param iterables: iterable arguments
-        :return: new sorted set
-
-        """
-        intersect = self._set.intersection(*iterables)
-        return self._fromset(intersect, key=self._key)
-
-    __and__ = intersection
-    __rand__ = __and__
-
-
-    def intersection_update(self, *iterables):
-        """Update the sorted set with the intersection of `iterables`.
-
-        The `intersection_update` method also corresponds to operator ``&=``.
-
-        ``ss.__iand__(iterable)`` <==> ``ss &= iterable``
-
-        Keep only values found in itself and all `iterables`.
-
-        >>> ss = SortedSet([1, 2, 3, 4, 5])
-        >>> _ = ss.intersection_update([4, 5, 6, 7])
-        >>> ss
-        SortedSet([4, 5])
-
-        :param iterables: iterable arguments
-        :return: itself
-
-        """
-        _set = self._set
-        _list = self._list
-        _set.intersection_update(*iterables)
-        _list.clear()
-        _list.update(_set)
-        return self
-
-    __iand__ = intersection_update
-
-
-    def symmetric_difference(self, other):
-        """Return the symmetric difference with `other` as a new sorted set.
-
-        The `symmetric_difference` method also corresponds to operator ``^``.
-
-        ``ss.__xor__(other)`` <==> ``ss ^ other``
-
-        The symmetric difference is all values tha are in exactly one of the
-        sets.
-
-        >>> ss = SortedSet([1, 2, 3, 4, 5])
-        >>> ss.symmetric_difference([4, 5, 6, 7])
-        SortedSet([1, 2, 3, 6, 7])
-
-        :param other: `other` iterable
-        :return: new sorted set
-
-        """
-        diff = self._set.symmetric_difference(other)
-        return self._fromset(diff, key=self._key)
-
-    __xor__ = symmetric_difference
-    __rxor__ = __xor__
-
-
-    def symmetric_difference_update(self, other):
-        """Update the sorted set with the symmetric difference with `other`.
-
-        The `symmetric_difference_update` method also corresponds to operator
-        ``^=``.
-
-        ``ss.__ixor__(other)`` <==> ``ss ^= other``
-
-        Keep only values found in exactly one of itself and `other`.
-
-        >>> ss = SortedSet([1, 2, 3, 4, 5])
-        >>> _ = ss.symmetric_difference_update([4, 5, 6, 7])
-        >>> ss
-        SortedSet([1, 2, 3, 6, 7])
-
-        :param other: `other` iterable
-        :return: itself
-
-        """
-        _set = self._set
-        _list = self._list
-        _set.symmetric_difference_update(other)
-        _list.clear()
-        _list.update(_set)
-        return self
-
-    __ixor__ = symmetric_difference_update
-
-
-    def union(self, *iterables):
-        """Return new sorted set with values from itself and all `iterables`.
-
-        The `union` method also corresponds to operator ``|``.
-
-        ``ss.__or__(iterable)`` <==> ``ss | iterable``
-
-        >>> ss = SortedSet([1, 2, 3, 4, 5])
-        >>> ss.union([4, 5, 6, 7])
-        SortedSet([1, 2, 3, 4, 5, 6, 7])
-
-        :param iterables: iterable arguments
-        :return: new sorted set
-
-        """
-        return self.__class__(chain(iter(self), *iterables), key=self._key)
-
-    __or__ = union
-    __ror__ = __or__
-
-
-    def update(self, *iterables):
-        """Update the sorted set adding values from all `iterables`.
-
-        The `update` method also corresponds to operator ``|=``.
-
-        ``ss.__ior__(iterable)`` <==> ``ss |= iterable``
-
-        >>> ss = SortedSet([1, 2, 3, 4, 5])
-        >>> _ = ss.update([4, 5, 6, 7])
-        >>> ss
-        SortedSet([1, 2, 3, 4, 5, 6, 7])
-
-        :param iterables: iterable arguments
-        :return: itself
-
-        """
-        _set = self._set
-        _list = self._list
-        values = set(chain(*iterables))
-        if (4 * len(values)) > len(_set):
-            _list = self._list
-            _set.update(values)
-            _list.clear()
-            _list.update(_set)
-        else:
-            _add = self._add
-            for value in values:
-                _add(value)
-        return self
-
-    __ior__ = update
-    _update = update
-
-
-    def __reduce__(self):
-        """Support for pickle.
-
-        The tricks played with exposing methods in :func:`SortedSet.__init__`
-        confuse pickle so customize the reducer.
-
-        """
-        return (type(self), (self._set, self._key))
-
-
-    @recursive_repr()
-    def __repr__(self):
-        """Return string representation of sorted set.
-
-        ``ss.__repr__()`` <==> ``repr(ss)``
-
-        :return: string representation
-
-        """
-        _key = self._key
-        key = '' if _key is None else ', key={0!r}'.format(_key)
-        type_name = type(self).__name__
-        return '{0}({1!r}{2})'.format(type_name, list(self), key)
-
-
-    def _check(self):
-        """Check invariants of sorted set.
-
-        Runtime complexity: `O(n)`
-
-        """
-        _set = self._set
-        _list = self._list
-        _list._check()
-        assert len(_set) == len(_list)
-        assert all(value in _set for value in _list)
diff --git a/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/INSTALLER b/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/INSTALLER
deleted file mode 100755
index a1b589e3..00000000
--- a/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/INSTALLER
+++ /dev/null
@@ -1 +0,0 @@
-pip
diff --git a/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/METADATA b/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/METADATA
deleted file mode 100755
index 61191462..00000000
--- a/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/METADATA
+++ /dev/null
@@ -1,24 +0,0 @@
-Metadata-Version: 2.4
-Name: splunk-sdk
-Version: 2.1.1
-Summary: The Splunk Software Development Kit for Python.
-Home-page: http://github.com/splunk/splunk-sdk-python
-Author: Splunk, Inc.
-Author-email: devinfo@splunk.com
-License: http://www.apache.org/licenses/LICENSE-2.0
-Classifier: Programming Language :: Python
-Classifier: Development Status :: 6 - Mature
-Classifier: Environment :: Other Environment
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: Apache Software License
-Classifier: Operating System :: OS Independent
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
-Requires-Dist: deprecation
-Dynamic: author
-Dynamic: author-email
-Dynamic: classifier
-Dynamic: home-page
-Dynamic: license
-Dynamic: requires-dist
-Dynamic: summary
diff --git a/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/RECORD b/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/RECORD
deleted file mode 100755
index 6502ca44..00000000
--- a/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/RECORD
+++ /dev/null
@@ -1,33 +0,0 @@
-splunk_sdk-2.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
-splunk_sdk-2.1.1.dist-info/METADATA,sha256=MyXVkpgJEVd0UJRmktSvYwREeQovd-CMLD3WbOWzHzs,873
-splunk_sdk-2.1.1.dist-info/RECORD,,
-splunk_sdk-2.1.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-splunk_sdk-2.1.1.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
-splunk_sdk-2.1.1.dist-info/top_level.txt,sha256=taq2YYfOB31tNefwW73s54xytiB_sy8bpbyBAfn0kr8,10
-splunklib/__init__.py,sha256=pjiK7OL2TI19BVzBWu2hM651G3JW1JDUNYE0w_wu7Cw,1251
-splunklib/binding.py,sha256=KyxwcRdMh3RbFwf0qz5QqxUa62LACe-z7bvsTckz7kU,61494
-splunklib/client.py,sha256=F1-vwAGC8hlPGU1TysXECwki3bPfqFok02CPUcJscPA,154488
-splunklib/data.py,sha256=OlS_e7wxBt0k5EaP1kLSybfyrNTCBm3Y0rY8SrTlWbY,8252
-splunklib/modularinput/__init__.py,sha256=wa_qct5JdNcG8VAOnVFPDIjvfSukhMn9c0ApkwT6n8c,401
-splunklib/modularinput/argument.py,sha256=KEAweyWOfteXLcxPZmesoNDfEeT5fW4SBEIWNp-cF8U,4162
-splunklib/modularinput/event.py,sha256=XJ_P6wD2oP00a6uyvGE2QktIcLvKMgFGN4SQ070_YwQ,4433
-splunklib/modularinput/event_writer.py,sha256=A2t-EwevRk54r2HWKh2Cg3hGg-zKXe8ErDYSudm43XE,3664
-splunklib/modularinput/input_definition.py,sha256=8iJ6N7BbO93kHuOC5wVGJIZT_OBuJAt9G_GoUiqDb9I,1778
-splunklib/modularinput/scheme.py,sha256=xZv7a-VJ7NrcLcQT7Yh8LD4MmUWfcLVer52UIna_4aQ,2963
-splunklib/modularinput/script.py,sha256=Rxw7ILvAqoQxfGWD9MKyzm6IHOVxStRVqoIcQfAk9xA,6358
-splunklib/modularinput/utils.py,sha256=RU6yXLcICI6O9jRCGKtBwtBJREdjIUATyPkn-Ttf_zc,2610
-splunklib/modularinput/validation_definition.py,sha256=xtc-rykogtF6pyRRwaI-Ppaq1OTkyJI3JMe8bGHi8SY,2658
-splunklib/results.py,sha256=cI3cq5Pqdz_vdiGM4Bpl92reqJmav7w0qFOy_lgYMzs,12808
-splunklib/searchcommands/__init__.py,sha256=sgIL7b84ywgDuyO_xYoDY2HsSFniUxsR7LWTTs9lpXQ,6244
-splunklib/searchcommands/decorators.py,sha256=aKG0oIoNnKw0HIrhmenqWww-DYp6N1NtzP2s23pnW_E,15913
-splunklib/searchcommands/environment.py,sha256=Sk0Bq-09lqWqGc87BYhcYBE3F-kmpr7zyYPM1PKKhDE,4665
-splunklib/searchcommands/eventing_command.py,sha256=hTfWMdOtr0VEzqKJFdJ7_eF0__rAxfJKLjaNJdP_ad8,5428
-splunklib/searchcommands/external_search_command.py,sha256=OwpO7k8OlrHHHidwwisnEfKpFJpTaLoi4y8PUCHMiq4,8154
-splunklib/searchcommands/generating_command.py,sha256=WxFfgr4flJl2IwVL9j2_8DVIAkSDP2n6j_Q9ICRPYT8,19100
-splunklib/searchcommands/internals.py,sha256=o49_MI14KEgtwx7OJ-KfPc09iPglbRmpr-SS-sjFyfs,27782
-splunklib/searchcommands/reporting_command.py,sha256=aPCABSz0NvRxIX2UdGAZvEGGRV1mitLQf2xlejnveAk,10261
-splunklib/searchcommands/search_command.py,sha256=B4JtDF35WlZLWkEuFPQWTMXaEcPCH72vdAOu5zJAkxY,42090
-splunklib/searchcommands/streaming_command.py,sha256=RJJloaZGd8rQYUUWBLfV156787EzrbrqgPsALjq_KjA,7044
-splunklib/searchcommands/validators.py,sha256=r1jMANPh1IDNax3ClSaVa0SHrGnGHrfKkho1GaM0Mjk,12989
-splunklib/six.py,sha256=AR8CmBFvf0uhnNve3ZW5AHVnL2op8MrCFDb-INKOBxM,34649
-splunklib/utils.py,sha256=PLtvYMmEkap5hir35T9g0NXprvStctO9MmPUntIdUNo,1347
diff --git a/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/REQUESTED b/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/REQUESTED
deleted file mode 100755
index e69de29b..00000000
diff --git a/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/WHEEL b/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/WHEEL
deleted file mode 100755
index 1ef55833..00000000
--- a/apps/bitwarden_event_logs/lib/splunk_sdk-2.1.1.dist-info/WHEEL
+++ /dev/null
@@ -1,5 +0,0 @@
-Wheel-Version: 1.0
-Generator: setuptools (82.0.0)
-Root-Is-Purelib: true
-Tag: py3-none-any
-
diff --git a/apps/bitwarden_event_logs/lib/splunklib/__init__.py b/apps/bitwarden_event_logs/lib/splunklib/__init__.py
deleted file mode 100755
index 3dca1c4c..00000000
--- a/apps/bitwarden_event_logs/lib/splunklib/__init__.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright © 2011-2024 Splunk, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"): you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""Python library for Splunk."""
-
-import logging
-
-DEFAULT_LOG_FORMAT = (
-    "%(asctime)s, Level=%(levelname)s, Pid=%(process)s, Logger=%(name)s, File=%(filename)s, "
-    "Line=%(lineno)s, %(message)s"
-)
-DEFAULT_DATE_FORMAT = "%Y-%m-%d %H:%M:%S %Z"
-
-
-# To set the logging level of splunklib
-# ex. To enable debug logs, call this method with parameter 'logging.DEBUG'
-# default logging level is set to 'WARNING'
-def setup_logging(
-    level, log_format=DEFAULT_LOG_FORMAT, date_format=DEFAULT_DATE_FORMAT
-):
-    logging.basicConfig(level=level, format=log_format, datefmt=date_format)
-
-
-__version_info__ = (2, 1, 1)
-__version__ = ".".join(map(str, __version_info__))
diff --git a/apps/bitwarden_event_logs/lib/splunklib/__pycache__/__init__.cpython-39.pyc b/apps/bitwarden_event_logs/lib/splunklib/__pycache__/__init__.cpython-39.pyc
deleted file mode 100755
index 380acd51..00000000
Binary files a/apps/bitwarden_event_logs/lib/splunklib/__pycache__/__init__.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/splunklib/__pycache__/binding.cpython-39.pyc b/apps/bitwarden_event_logs/lib/splunklib/__pycache__/binding.cpython-39.pyc
deleted file mode 100755
index 4b02f154..00000000
Binary files a/apps/bitwarden_event_logs/lib/splunklib/__pycache__/binding.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/splunklib/__pycache__/client.cpython-39.pyc b/apps/bitwarden_event_logs/lib/splunklib/__pycache__/client.cpython-39.pyc
deleted file mode 100755
index 2e10c53a..00000000
Binary files a/apps/bitwarden_event_logs/lib/splunklib/__pycache__/client.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/splunklib/__pycache__/data.cpython-39.pyc b/apps/bitwarden_event_logs/lib/splunklib/__pycache__/data.cpython-39.pyc
deleted file mode 100755
index bba1dc72..00000000
Binary files a/apps/bitwarden_event_logs/lib/splunklib/__pycache__/data.cpython-39.pyc and /dev/null differ
diff --git a/apps/bitwarden_event_logs/lib/splunklib/binding.py b/apps/bitwarden_event_logs/lib/splunklib/binding.py
deleted file mode 100755
index d8cf9121..00000000
--- a/apps/bitwarden_event_logs/lib/splunklib/binding.py
+++ /dev/null
@@ -1,1577 +0,0 @@
-# Copyright © 2011-2024 Splunk, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"): you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""The **splunklib.binding** module provides a low-level binding interface to the
-`Splunk REST API `_.
-
-This module handles the wire details of calling the REST API, such as
-authentication tokens, prefix paths, URL encoding, and so on. Actual path
-segments, ``GET`` and ``POST`` arguments, and the parsing of responses is left
-to the user.
-
-If you want a friendlier interface to the Splunk REST API, use the
-:mod:`splunklib.client` module.
-"""
-
-import io
-import json
-import logging
-import socket
-import ssl
-import time
-from base64 import b64encode
-from contextlib import contextmanager
-from datetime import datetime
-from functools import wraps
-from io import BytesIO
-from urllib import parse
-from http import client
-from http.cookies import SimpleCookie
-from xml.etree.ElementTree import XML, ParseError
-from .data import record
-from . import __version__
-
-
-logger = logging.getLogger(__name__)
-
-__all__ = [
-    "AuthenticationError",
-    "connect",
-    "Context",
-    "handler",
-    "HTTPError",
-    "UrlEncoded",
-    "_encode",
-    "_make_cookie_header",
-    "_NoAuthenticationToken",
-    "namespace",
-]
-
-SENSITIVE_KEYS = [
-    "Authorization",
-    "Cookie",
-    "action.email.auth_password",
-    "auth",
-    "auth_password",
-    "clear_password",
-    "clientId",
-    "crc-salt",
-    "encr_password",
-    "oldpassword",
-    "passAuth",
-    "password",
-    "session",
-    "suppressionKey",
-    "token",
-]
-
-# If you change these, update the docstring
-# on _authority as well.
-DEFAULT_HOST = "localhost"
-DEFAULT_PORT = "8089"
-DEFAULT_SCHEME = "https"
-
-
-def _log_duration(f):
-    @wraps(f)
-    def new_f(*args, **kwargs):
-        start_time = datetime.now()
-        val = f(*args, **kwargs)
-        end_time = datetime.now()
-        logger.debug("Operation took %s", end_time - start_time)
-        return val
-
-    return new_f
-
-
-def mask_sensitive_data(data):
-    """
-    Masked sensitive fields data for logging purpose
-    """
-    if not isinstance(data, dict):
-        try:
-            data = json.loads(data)
-        except Exception as ex:
-            return data
-
-    # json.loads will return "123"(str) as 123(int), so return the data if it's not 'dict' type
-    if not isinstance(data, dict):
-        return data
-    mdata = {}
-    for k, v in data.items():
-        if k in SENSITIVE_KEYS:
-            mdata[k] = "******"
-        else:
-            mdata[k] = mask_sensitive_data(v)
-    return mdata
-
-
-def _parse_cookies(cookie_str, dictionary):
-    """Tries to parse any key-value pairs of cookies in a string,
-    then updates the the dictionary with any key-value pairs found.
-
-    **Example**::
-
-        dictionary = {}
-        _parse_cookies('my=value', dictionary)
-        # Now the following is True
-        dictionary['my'] == 'value'
-
-    :param cookie_str: A string containing "key=value" pairs from an HTTP "Set-Cookie" header.
-    :type cookie_str: ``str``
-    :param dictionary: A dictionary to update with any found key-value pairs.
-    :type dictionary: ``dict``
-    """
-    parsed_cookie = SimpleCookie(cookie_str)
-    for cookie in parsed_cookie.values():
-        dictionary[cookie.key] = cookie.coded_value
-
-
-def _make_cookie_header(cookies):
-    """
-    Takes a list of 2-tuples of key-value pairs of
-    cookies, and returns a valid HTTP ``Cookie``
-    header.
-
-    **Example**::
-
-        header = _make_cookie_header([("key", "value"), ("key_2", "value_2")])
-        # Now the following is True
-        header == "key=value; key_2=value_2"
-
-    :param cookies: A list of 2-tuples of cookie key-value pairs.
-    :type cookies: ``list`` of 2-tuples
-    :return: ``str` An HTTP header cookie string.
-    :rtype: ``str``
-    """
-    return "; ".join(f"{key}={value}" for key, value in cookies)
-
-
-# Singleton values to eschew None
-class _NoAuthenticationToken:
-    """The value stored in a :class:`Context` or :class:`splunklib.client.Service`
-    class that is not logged in.
-
-    If a ``Context`` or ``Service`` object is created without an authentication
-    token, and there has not yet been a call to the ``login`` method, the token
-    field of the ``Context`` or ``Service`` object is set to
-    ``_NoAuthenticationToken``.
-
-    Likewise, after a ``Context`` or ``Service`` object has been logged out, the
-    token is set to this value again.
-    """
-
-
-class UrlEncoded(str):
-    """This class marks URL-encoded strings.
-    It should be considered an SDK-private implementation detail.
-
-    Manually tracking whether strings are URL encoded can be difficult. Avoid
-    calling ``urllib.quote`` to replace special characters with escapes. When
-    you receive a URL-encoded string, *do* use ``urllib.unquote`` to replace
-    escapes with single characters. Then, wrap any string you want to use as a
-    URL in ``UrlEncoded``. Note that because the ``UrlEncoded`` class is
-    idempotent, making multiple calls to it is OK.
-
-    ``UrlEncoded`` objects are identical to ``str`` objects (including being
-    equal if their contents are equal) except when passed to ``UrlEncoded``
-    again.
-
-    ``UrlEncoded`` removes the ``str`` type support for interpolating values
-    with ``%`` (doing that raises a ``TypeError``). There is no reliable way to
-    encode values this way, so instead, interpolate into a string, quoting by
-    hand, and call ``UrlEncode`` with ``skip_encode=True``.
-
-    **Example**::
-
-        import urllib
-        UrlEncoded(f'{scheme}://{urllib.quote(host)}', skip_encode=True)
-
-    If you append ``str`` strings and ``UrlEncoded`` strings, the result is also
-    URL encoded.
-
-    **Example**::
-
-        UrlEncoded('ab c') + 'de f' == UrlEncoded('ab cde f')
-        'ab c' + UrlEncoded('de f') == UrlEncoded('ab cde f')
-    """
-
-    def __new__(self, val="", skip_encode=False, encode_slash=False):
-        if isinstance(val, UrlEncoded):
-            # Don't urllib.quote something already URL encoded.
-            return val
-        if skip_encode:
-            return str.__new__(self, val)
-        if encode_slash:
-            return str.__new__(self, parse.quote_plus(val))
-        # When subclassing str, just call str.__new__ method
-        # with your class and the value you want to have in the
-        # new string.
-        return str.__new__(self, parse.quote(val))
-
-    def __add__(self, other):
-        """self + other
-
-        If *other* is not a ``UrlEncoded``, URL encode it before
-        adding it.
-        """
-        if isinstance(other, UrlEncoded):
-            return UrlEncoded(str.__add__(self, other), skip_encode=True)
-
-        return UrlEncoded(str.__add__(self, parse.quote(other)), skip_encode=True)
-
-    def __radd__(self, other):
-        """other + self
-
-        If *other* is not a ``UrlEncoded``, URL _encode it before
-        adding it.
-        """
-        if isinstance(other, UrlEncoded):
-            return UrlEncoded(str.__radd__(self, other), skip_encode=True)
-
-        return UrlEncoded(str.__add__(parse.quote(other), self), skip_encode=True)
-
-    def __mod__(self, fields):
-        """Interpolation into ``UrlEncoded``s is disabled.
-
-        If you try to write ``UrlEncoded("%s") % "abc", will get a
-        ``TypeError``.
-        """
-        raise TypeError("Cannot interpolate into a UrlEncoded object.")
-
-    def __repr__(self):
-        return f"UrlEncoded({repr(parse.unquote(str(self)))})"
-
-
-@contextmanager
-def _handle_auth_error(msg):
-    """Handle re-raising HTTP authentication errors as something clearer.
-
-    If an ``HTTPError`` is raised with status 401 (access denied) in
-    the body of this context manager, re-raise it as an
-    ``AuthenticationError`` instead, with *msg* as its message.
-
-    This function adds no round trips to the server.
-
-    :param msg: The message to be raised in ``AuthenticationError``.
-    :type msg: ``str``
-
-    **Example**::
-
-        with _handle_auth_error("Your login failed."):
-             ... # make an HTTP request
-    """
-    try:
-        yield
-    except HTTPError as he:
-        if he.status == 401:
-            raise AuthenticationError(msg, he)
-        else:
-            raise
-
-
-def _authentication(request_fun):
-    """Decorator to handle autologin and authentication errors.
-
-    *request_fun* is a function taking no arguments that needs to
-    be run with this ``Context`` logged into Splunk.
-
-    ``_authentication``'s behavior depends on whether the
-    ``autologin`` field of ``Context`` is set to ``True`` or
-    ``False``. If it's ``False``, then ``_authentication``
-    aborts if the ``Context`` is not logged in, and raises an
-    ``AuthenticationError`` if an ``HTTPError`` of status 401 is
-    raised in *request_fun*. If it's ``True``, then
-    ``_authentication`` will try at all sensible places to
-    log in before issuing the request.
-
-    If ``autologin`` is ``False``, ``_authentication`` makes
-    one roundtrip to the server if the ``Context`` is logged in,
-    or zero if it is not. If ``autologin`` is ``True``, it's less
-    deterministic, and may make at most three roundtrips (though
-    that would be a truly pathological case).
-
-    :param request_fun: A function of no arguments encapsulating
-                        the request to make to the server.
-
-    **Example**::
-
-        import splunklib.binding as binding
-        c = binding.connect(..., autologin=True)
-        c.logout()
-        def f():
-            c.get("/services")
-            return 42
-        print(_authentication(f))
-    """
-
-    @wraps(request_fun)
-    def wrapper(self, *args, **kwargs):
-        if self.token is _NoAuthenticationToken and not self.has_cookies():
-            # Not yet logged in.
-            if self.autologin and self.username and self.password:
-                # This will throw an uncaught
-                # AuthenticationError if it fails.
-                self.login()
-            else:
-                # Try the request anyway without authentication.
-                # Most requests will fail. Some will succeed, such as
-                # 'GET server/info'.
-                with _handle_auth_error("Request aborted: not logged in."):
-                    return request_fun(self, *args, **kwargs)
-        try:
-            # Issue the request
-            return request_fun(self, *args, **kwargs)
-        except HTTPError as he:
-            if he.status == 401 and self.autologin:
-                # Authentication failed. Try logging in, and then
-                # rerunning the request. If either step fails, throw
-                # an AuthenticationError and give up.
-                with _handle_auth_error("Autologin failed."):
-                    self.login()
-                with _handle_auth_error(
-                    "Authentication Failed! If session token is used, it seems to have been expired."
-                ):
-                    return request_fun(self, *args, **kwargs)
-            elif he.status == 401 and not self.autologin:
-                raise AuthenticationError(
-                    "Request failed: Session is not logged in.", he
-                )
-            else:
-                raise
-
-    return wrapper
-
-
-def _authority(scheme=DEFAULT_SCHEME, host=DEFAULT_HOST, port=DEFAULT_PORT):
-    """Construct a URL authority from the given *scheme*, *host*, and *port*.
-
-    Named in accordance with RFC2396_, which defines URLs as::
-
-        ://?
-
-    .. _RFC2396: http://www.ietf.org/rfc/rfc2396.txt
-
-    So ``https://localhost:8000/a/b/b?boris=hilda`` would be parsed as::
-
-        scheme := https
-        authority := localhost:8000
-        path := /a/b/c
-        query := boris=hilda
-
-    :param scheme: URL scheme (the default is "https")
-    :type scheme: "http" or "https"
-    :param host: The host name (the default is "localhost")
-    :type host: string
-    :param port: The port number (the default is 8089)
-    :type port: integer
-    :return: The URL authority.
-    :rtype: UrlEncoded (subclass of ``str``)
-
-    **Example**::
-
-        _authority() == "https://localhost:8089"
-
-        _authority(host="splunk.utopia.net") == "https://splunk.utopia.net:8089"
-
-        _authority(host="2001:0db8:85a3:0000:0000:8a2e:0370:7334") == \
-            "https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8089"
-
-        _authority(scheme="http", host="splunk.utopia.net", port="471") == \
-            "http://splunk.utopia.net:471"
-
-    """
-    # check if host is an IPv6 address and not enclosed in [ ]
-    if ":" in host and not (host.startswith("[") and host.endswith("]")):
-        # IPv6 addresses must be enclosed in [ ] in order to be well
-        # formed.
-        host = "[" + host + "]"
-    return UrlEncoded(f"{scheme}://{host}:{port}", skip_encode=True)
-
-
-# kwargs: sharing, owner, app
-def namespace(sharing=None, owner=None, app=None, **kwargs):
-    """This function constructs a Splunk namespace.
-
-    Every Splunk resource belongs to a namespace. The namespace is specified by
-    the pair of values ``owner`` and ``app`` and is governed by a ``sharing`` mode.
-    The possible values for ``sharing`` are: "user", "app", "global" and "system",
-    which map to the following combinations of ``owner`` and ``app`` values:
-
-        "user"   => {owner}, {app}
-
-        "app"    => nobody, {app}
-
-        "global" => nobody, {app}
-
-        "system" => nobody, system
-
-    "nobody" is a special user name that basically means no user, and "system"
-    is the name reserved for system resources.
-
-    "-" is a wildcard that can be used for both ``owner`` and ``app`` values and
-    refers to all users and all apps, respectively.
-
-    In general, when you specify a namespace you can specify any combination of
-    these three values and the library will reconcile the triple, overriding the
-    provided values as appropriate.
-
-    Finally, if no namespacing is specified the library will make use of the
-    ``/services`` branch of the REST API, which provides a namespaced view of
-    Splunk resources equivelent to using ``owner={currentUser}`` and
-    ``app={defaultApp}``.
-
-    The ``namespace`` function returns a representation of the namespace from
-    reconciling the values you provide. It ignores any keyword arguments other
-    than ``owner``, ``app``, and ``sharing``, so you can provide ``dicts`` of
-    configuration information without first having to extract individual keys.
-
-    :param sharing: The sharing mode (the default is "user").
-    :type sharing: "system", "global", "app", or "user"
-    :param owner: The owner context (the default is "None").
-    :type owner: ``string``
-    :param app: The app context (the default is "None").
-    :type app: ``string``
-    :returns: A :class:`splunklib.data.Record` containing the reconciled
-        namespace.
-
-    **Example**::
-
-        import splunklib.binding as binding
-        n = binding.namespace(sharing="user", owner="boris", app="search")
-        n = binding.namespace(sharing="global", app="search")
-    """
-    if sharing in ["system"]:
-        return record({"sharing": sharing, "owner": "nobody", "app": "system"})
-    if sharing in ["global", "app"]:
-        return record({"sharing": sharing, "owner": "nobody", "app": app})
-    if sharing in ["user", None]:
-        return record({"sharing": sharing, "owner": owner, "app": app})
-    raise ValueError("Invalid value for argument: 'sharing'")
-
-
-class Context:
-    """This class represents a context that encapsulates a splunkd connection.
-
-    The ``Context`` class encapsulates the details of HTTP requests,
-    authentication, a default namespace, and URL prefixes to simplify access to
-    the REST API.
-
-    After creating a ``Context`` object, you must call its :meth:`login`
-    method before you can issue requests to splunkd. Or, use the :func:`connect`
-    function to create an already-authenticated ``Context`` object. You can
-    provide a session token explicitly (the same token can be shared by multiple
-    ``Context`` objects) to provide authentication.
-
-    :param host: The host name (the default is "localhost").
-    :type host: ``string``
-    :param port: The port number (the default is 8089).
-    :type port: ``integer``
-    :param scheme: The scheme for accessing the service (the default is "https").
-    :type scheme: "https" or "http"
-    :param verify: Enable (True) or disable (False) SSL verification for https connections.
-    :type verify: ``Boolean``
-    :param self_signed_certificate: Specifies if self signed certificate is used
-    :type self_signed_certificate: ``Boolean``
-    :param sharing: The sharing mode for the namespace (the default is "user").
-    :type sharing: "global", "system", "app", or "user"
-    :param owner: The owner context of the namespace (optional, the default is "None").
-    :type owner: ``string``
-    :param app: The app context of the namespace (optional, the default is "None").
-    :type app: ``string``
-    :param token: A session token. When provided, you don't need to call :meth:`login`.
-    :type token: ``string``
-    :param cookie: A session cookie. When provided, you don't need to call :meth:`login`.
-        This parameter is only supported for Splunk 6.2+.
-    :type cookie: ``string``
-    :param username: The Splunk account username, which is used to
-        authenticate the Splunk instance.
-    :type username: ``string``
-    :param password: The password for the Splunk account.
-    :type password: ``string``
-    :param splunkToken: Splunk authentication token
-    :type splunkToken: ``string``
-    :param headers: List of extra HTTP headers to send (optional).
-    :type headers: ``list`` of 2-tuples.
-    :param retires: Number of retries for each HTTP connection (optional, the default is 0).
-                    NOTE THAT THIS MAY INCREASE THE NUMBER OF ROUND TRIP CONNECTIONS TO THE SPLUNK SERVER AND BLOCK THE
-                    CURRENT THREAD WHILE RETRYING.
-    :type retries: ``int``
-    :param retryDelay: How long to wait between connection attempts if `retries` > 0 (optional, defaults to 10s).
-    :type retryDelay: ``int`` (in seconds)
-    :param handler: The HTTP request handler (optional).
-    :returns: A ``Context`` instance.
-
-    **Example**::
-
-        import splunklib.binding as binding
-        c = binding.Context(username="boris", password="natasha", ...)
-        c.login()
-        # Or equivalently
-        c = binding.connect(username="boris", password="natasha")
-        # Or if you already have a session token
-        c = binding.Context(token="atg232342aa34324a")
-        # Or if you already have a valid cookie
-        c = binding.Context(cookie="splunkd_8089=...")
-    """
-
-    def __init__(self, handler=None, **kwargs):
-        self.http = HttpLib(
-            handler,
-            kwargs.get("verify", False),
-            key_file=kwargs.get("key_file"),
-            cert_file=kwargs.get("cert_file"),
-            context=kwargs.get("context"),
-            # Default to False for backward compat
-            retries=kwargs.get("retries", 0),
-            retryDelay=kwargs.get("retryDelay", 10),
-        )
-        self.token = kwargs.get("token", _NoAuthenticationToken)
-        if self.token is None:  # In case someone explicitly passes token=None
-            self.token = _NoAuthenticationToken
-        self.scheme = kwargs.get("scheme", DEFAULT_SCHEME)
-        self.host = kwargs.get("host", DEFAULT_HOST)
-        self.port = int(kwargs.get("port", DEFAULT_PORT))
-        self.authority = _authority(self.scheme, self.host, self.port)
-        self.namespace = namespace(**kwargs)
-        self.username = kwargs.get("username", "")
-        self.password = kwargs.get("password", "")
-        self.basic = kwargs.get("basic", False)
-        self.bearerToken = kwargs.get("splunkToken", "")
-        self.autologin = kwargs.get("autologin", False)
-        self.additional_headers = kwargs.get("headers", [])
-        self._self_signed_certificate = kwargs.get("self_signed_certificate", True)
-
-        # Store any cookies in the self.http._cookies dict
-        if "cookie" in kwargs and kwargs["cookie"] not in [
-            None,
-            _NoAuthenticationToken,
-        ]:
-            _parse_cookies(kwargs["cookie"], self.http._cookies)
-
-    def get_cookies(self):
-        """Gets the dictionary of cookies from the ``HttpLib`` member of this instance.
-
-        :return: Dictionary of cookies stored on the ``self.http``.
-        :rtype: ``dict``
-        """
-        return self.http._cookies
-
-    def has_cookies(self):
-        """Returns true if the ``HttpLib`` member of this instance has auth token stored.
-
-        :return: ``True`` if there is auth token present, else ``False``
-        :rtype: ``bool``
-        """
-        auth_token_key = "splunkd_"
-        return any(auth_token_key in key for key in self.get_cookies().keys())
-
-    # Shared per-context request headers
-    @property
-    def _auth_headers(self):
-        """Headers required to authenticate a request.
-
-        Assumes your ``Context`` already has a authentication token or
-        cookie, either provided explicitly or obtained by logging
-        into the Splunk instance.
-
-        :returns: A list of 2-tuples containing key and value
-        """
-        header = []
-        if self.has_cookies():
-            return [("Cookie", _make_cookie_header(list(self.get_cookies().items())))]
-        elif self.basic and (self.username and self.password):
-            token = f"Basic {b64encode(('%s:%s' % (self.username, self.password)).encode('utf-8')).decode('ascii')}"
-        elif self.bearerToken:
-            token = f"Bearer {self.bearerToken}"
-        elif self.token is _NoAuthenticationToken:
-            token = []
-        else:
-            # Ensure the token is properly formatted
-            if self.token.startswith("Splunk "):
-                token = self.token
-            else:
-                token = f"Splunk {self.token}"
-        if token:
-            header.append(("Authorization", token))
-        if self.get_cookies():
-            header.append(
-                ("Cookie", _make_cookie_header(list(self.get_cookies().items())))
-            )
-
-        return header
-
-    def connect(self):
-        """Returns an open connection (socket) to the Splunk instance.
-
-        This method is used for writing bulk events to an index or similar tasks
-        where the overhead of opening a connection multiple times would be
-        prohibitive.
-
-        :returns: A socket.
-
-        **Example**::
-
-            import splunklib.binding as binding
-            c = binding.connect(...)
-            socket = c.connect()
-            socket.write("POST %s HTTP/1.1\\r\\n" % "some/path/to/post/to")
-            socket.write("Host: %s:%s\\r\\n" % (c.host, c.port))
-            socket.write("Accept-Encoding: identity\\r\\n")
-            socket.write("Authorization: %s\\r\\n" % c.token)
-            socket.write("X-Splunk-Input-Mode: Streaming\\r\\n")
-            socket.write("\\r\\n")
-        """
-        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        if self.scheme == "https":
-            context = ssl.create_default_context()
-            context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
-            context.check_hostname = not self._self_signed_certificate
-            context.verify_mode = (
-                ssl.CERT_NONE if self._self_signed_certificate else ssl.CERT_REQUIRED
-            )
-            sock = context.wrap_socket(sock, server_hostname=self.host)
-        sock.connect((socket.gethostbyname(self.host), self.port))
-        return sock
-
-    @_authentication
-    @_log_duration
-    def delete(self, path_segment, owner=None, app=None, sharing=None, **query):
-        """Performs a DELETE operation at the REST path segment with the given
-        namespace and query.
-
-        This method is named to match the HTTP method. ``delete`` makes at least
-        one round trip to the server, one additional round trip for each 303
-        status returned, and at most two additional round trips if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        If *owner*, *app*, and *sharing* are omitted, this method uses the
-        default :class:`Context` namespace. All other keyword arguments are
-        included in the URL as query parameters.
-
-        :raises AuthenticationError: Raised when the ``Context`` object is not
-             logged in.
-        :raises HTTPError: Raised when an error occurred in a GET operation from
-             *path_segment*.
-        :param path_segment: A REST path segment.
-        :type path_segment: ``string``
-        :param owner: The owner context of the namespace (optional).
-        :type owner: ``string``
-        :param app: The app context of the namespace (optional).
-        :type app: ``string``
-        :param sharing: The sharing mode of the namespace (optional).
-        :type sharing: ``string``
-        :param query: All other keyword arguments, which are used as query
-            parameters.
-        :type query: ``string``
-        :return: The response from the server.
-        :rtype: ``dict`` with keys ``body``, ``headers``, ``reason``,
-                and ``status``
-
-        **Example**::
-
-            c = binding.connect(...)
-            c.delete('saved/searches/boris') == \\
-                {'body': ...a response reader object...,
-                 'headers': [('content-length', '1786'),
-                             ('expires', 'Fri, 30 Oct 1998 00:00:00 GMT'),
-                             ('server', 'Splunkd'),
-                             ('connection', 'close'),
-                             ('cache-control', 'no-store, max-age=0, must-revalidate, no-cache'),
-                             ('date', 'Fri, 11 May 2012 16:53:06 GMT'),
-                             ('content-type', 'text/xml; charset=utf-8')],
-                 'reason': 'OK',
-                 'status': 200}
-            c.delete('nonexistant/path') # raises HTTPError
-            c.logout()
-            c.delete('apps/local') # raises AuthenticationError
-        """
-        path = self.authority + self._abspath(
-            path_segment, owner=owner, app=app, sharing=sharing
-        )
-        logger.debug(
-            "DELETE request to %s (body: %s)", path, mask_sensitive_data(query)
-        )
-        response = self.http.delete(path, self._auth_headers, **query)
-        return response
-
-    @_authentication
-    @_log_duration
-    def get(
-        self, path_segment, owner=None, app=None, headers=None, sharing=None, **query
-    ):
-        """Performs a GET operation from the REST path segment with the given
-        namespace and query.
-
-        This method is named to match the HTTP method. ``get`` makes at least
-        one round trip to the server, one additional round trip for each 303
-        status returned, and at most two additional round trips if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        If *owner*, *app*, and *sharing* are omitted, this method uses the
-        default :class:`Context` namespace. All other keyword arguments are
-        included in the URL as query parameters.
-
-        :raises AuthenticationError: Raised when the ``Context`` object is not
-             logged in.
-        :raises HTTPError: Raised when an error occurred in a GET operation from
-             *path_segment*.
-        :param path_segment: A REST path segment.
-        :type path_segment: ``string``
-        :param owner: The owner context of the namespace (optional).
-        :type owner: ``string``
-        :param app: The app context of the namespace (optional).
-        :type app: ``string``
-        :param headers: List of extra HTTP headers to send (optional).
-        :type headers: ``list`` of 2-tuples.
-        :param sharing: The sharing mode of the namespace (optional).
-        :type sharing: ``string``
-        :param query: All other keyword arguments, which are used as query
-            parameters.
-        :type query: ``string``
-        :return: The response from the server.
-        :rtype: ``dict`` with keys ``body``, ``headers``, ``reason``,
-                and ``status``
-
-        **Example**::
-
-            c = binding.connect(...)
-            c.get('apps/local') == \\
-                {'body': ...a response reader object...,
-                 'headers': [('content-length', '26208'),
-                             ('expires', 'Fri, 30 Oct 1998 00:00:00 GMT'),
-                             ('server', 'Splunkd'),
-                             ('connection', 'close'),
-                             ('cache-control', 'no-store, max-age=0, must-revalidate, no-cache'),
-                             ('date', 'Fri, 11 May 2012 16:30:35 GMT'),
-                             ('content-type', 'text/xml; charset=utf-8')],
-                 'reason': 'OK',
-                 'status': 200}
-            c.get('nonexistant/path') # raises HTTPError
-            c.logout()
-            c.get('apps/local') # raises AuthenticationError
-        """
-        if headers is None:
-            headers = []
-
-        path = self.authority + self._abspath(
-            path_segment, owner=owner, app=app, sharing=sharing
-        )
-        logger.debug("GET request to %s (body: %s)", path, mask_sensitive_data(query))
-        all_headers = headers + self.additional_headers + self._auth_headers
-        response = self.http.get(path, all_headers, **query)
-        return response
-
-    @_authentication
-    @_log_duration
-    def post(
-        self, path_segment, owner=None, app=None, sharing=None, headers=None, **query
-    ):
-        """Performs a POST operation from the REST path segment with the given
-        namespace and query.
-
-        This method is named to match the HTTP method. ``post`` makes at least
-        one round trip to the server, one additional round trip for each 303
-        status returned, and at most two additional round trips if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        If *owner*, *app*, and *sharing* are omitted, this method uses the
-        default :class:`Context` namespace. All other keyword arguments are
-        included in the URL as query parameters.
-
-        Some of Splunk's endpoints, such as ``receivers/simple`` and
-        ``receivers/stream``, require unstructured data in the POST body
-        and all metadata passed as GET-style arguments. If you provide
-        a ``body`` argument to ``post``, it will be used as the POST
-        body, and all other keyword arguments will be passed as
-        GET-style arguments in the URL.
-
-        :raises AuthenticationError: Raised when the ``Context`` object is not
-             logged in.
-        :raises HTTPError: Raised when an error occurred in a GET operation from
-             *path_segment*.
-        :param path_segment: A REST path segment.
-        :type path_segment: ``string``
-        :param owner: The owner context of the namespace (optional).
-        :type owner: ``string``
-        :param app: The app context of the namespace (optional).
-        :type app: ``string``
-        :param sharing: The sharing mode of the namespace (optional).
-        :type sharing: ``string``
-        :param headers: List of extra HTTP headers to send (optional).
-        :type headers: ``list`` of 2-tuples.
-        :param query: All other keyword arguments, which are used as query
-            parameters.
-        :param body: Parameters to be used in the post body. If specified,
-            any parameters in the query will be applied to the URL instead of
-            the body. If a dict is supplied, the key-value pairs will be form
-            encoded. If a string is supplied, the body will be passed through
-            in the request unchanged.
-        :type body: ``dict`` or ``str``
-        :return: The response from the server.
-        :rtype: ``dict`` with keys ``body``, ``headers``, ``reason``,
-                and ``status``
-
-        **Example**::
-
-            c = binding.connect(...)
-            c.post('saved/searches', name='boris',
-                   search='search * earliest=-1m | head 1') == \\
-                {'body': ...a response reader object...,
-                 'headers': [('content-length', '10455'),
-                             ('expires', 'Fri, 30 Oct 1998 00:00:00 GMT'),
-                             ('server', 'Splunkd'),
-                             ('connection', 'close'),
-                             ('cache-control', 'no-store, max-age=0, must-revalidate, no-cache'),
-                             ('date', 'Fri, 11 May 2012 16:46:06 GMT'),
-                             ('content-type', 'text/xml; charset=utf-8')],
-                 'reason': 'Created',
-                 'status': 201}
-            c.post('nonexistant/path') # raises HTTPError
-            c.logout()
-            # raises AuthenticationError:
-            c.post('saved/searches', name='boris',
-                   search='search * earliest=-1m | head 1')
-        """
-        if headers is None:
-            headers = []
-
-        path = self.authority + self._abspath(
-            path_segment, owner=owner, app=app, sharing=sharing
-        )
-
-        logger.debug("POST request to %s (body: %s)", path, mask_sensitive_data(query))
-        all_headers = headers + self.additional_headers + self._auth_headers
-        response = self.http.post(path, all_headers, **query)
-        return response
-
-    @_authentication
-    @_log_duration
-    def request(
-        self,
-        path_segment,
-        method="GET",
-        headers=None,
-        body={},
-        owner=None,
-        app=None,
-        sharing=None,
-    ):
-        """Issues an arbitrary HTTP request to the REST path segment.
-
-        This method is named to match ``httplib.request``. This function
-        makes a single round trip to the server.
-
-        If *owner*, *app*, and *sharing* are omitted, this method uses the
-        default :class:`Context` namespace. All other keyword arguments are
-        included in the URL as query parameters.
-
-        :raises AuthenticationError: Raised when the ``Context`` object is not
-             logged in.
-        :raises HTTPError: Raised when an error occurred in a GET operation from
-             *path_segment*.
-        :param path_segment: A REST path segment.
-        :type path_segment: ``string``
-        :param method: The HTTP method to use (optional).
-        :type method: ``string``
-        :param headers: List of extra HTTP headers to send (optional).
-        :type headers: ``list`` of 2-tuples.
-        :param body: Content of the HTTP request (optional).
-        :type body: ``string``
-        :param owner: The owner context of the namespace (optional).
-        :type owner: ``string``
-        :param app: The app context of the namespace (optional).
-        :type app: ``string``
-        :param sharing: The sharing mode of the namespace (optional).
-        :type sharing: ``string``
-        :return: The response from the server.
-        :rtype: ``dict`` with keys ``body``, ``headers``, ``reason``,
-                and ``status``
-
-        **Example**::
-
-            c = binding.connect(...)
-            c.request('saved/searches', method='GET') == \\
-                {'body': ...a response reader object...,
-                 'headers': [('content-length', '46722'),
-                             ('expires', 'Fri, 30 Oct 1998 00:00:00 GMT'),
-                             ('server', 'Splunkd'),
-                             ('connection', 'close'),
-                             ('cache-control', 'no-store, max-age=0, must-revalidate, no-cache'),
-                             ('date', 'Fri, 11 May 2012 17:24:19 GMT'),
-                             ('content-type', 'text/xml; charset=utf-8')],
-                 'reason': 'OK',
-                 'status': 200}
-            c.request('nonexistant/path', method='GET') # raises HTTPError
-            c.logout()
-            c.get('apps/local') # raises AuthenticationError
-        """
-        if headers is None:
-            headers = []
-
-        path = self.authority + self._abspath(
-            path_segment, owner=owner, app=app, sharing=sharing
-        )
-
-        all_headers = headers + self.additional_headers + self._auth_headers
-        logger.debug(
-            "%s request to %s (headers: %s, body: %s)",
-            method,
-            path,
-            str(mask_sensitive_data(dict(all_headers))),
-            mask_sensitive_data(body),
-        )
-        if body:
-            body = _encode(**body)
-
-            if method == "GET":
-                path = path + UrlEncoded("?" + body, skip_encode=True)
-                message = {"method": method, "headers": all_headers}
-            else:
-                message = {"method": method, "headers": all_headers, "body": body}
-        else:
-            message = {"method": method, "headers": all_headers}
-
-        response = self.http.request(path, message)
-
-        return response
-
-    def login(self):
-        """Logs into the Splunk instance referred to by the :class:`Context`
-        object.
-
-        Unless a ``Context`` is created with an explicit authentication token
-        (probably obtained by logging in from a different ``Context`` object)
-        you must call :meth:`login` before you can issue requests.
-        The authentication token obtained from the server is stored in the
-        ``token`` field of the ``Context`` object.
-
-        :raises AuthenticationError: Raised when login fails.
-        :returns: The ``Context`` object, so you can chain calls.
-
-        **Example**::
-
-            import splunklib.binding as binding
-            c = binding.Context(...).login()
-            # Then issue requests...
-        """
-
-        if self.has_cookies() and (not self.username and not self.password):
-            # If we were passed session cookie(s), but no username or
-            # password, then login is a nop, since we're automatically
-            # logged in.
-            return
-
-        if self.token is not _NoAuthenticationToken and (
-            not self.username and not self.password
-        ):
-            # If we were passed a session token, but no username or
-            # password, then login is a nop, since we're automatically
-            # logged in.
-            return
-
-        if self.basic and (self.username and self.password):
-            # Basic auth mode requested, so this method is a nop as long
-            # as credentials were passed in.
-            return
-
-        if self.bearerToken:
-            # Bearer auth mode requested, so this method is a nop as long
-            # as authentication token was passed in.
-            return
-        # Only try to get a token and updated cookie if username & password are specified
-        try:
-            response = self.http.post(
-                self.authority + self._abspath("/services/auth/login"),
-                username=self.username,
-                password=self.password,
-                headers=self.additional_headers,
-                cookie="1",
-            )  # In Splunk 6.2+, passing "cookie=1" will return the "set-cookie" header
-
-            body = response.body.read()
-            session = XML(body).findtext("./sessionKey")
-            self.token = f"Splunk {session}"
-            return self
-        except HTTPError as he:
-            if he.status == 401:
-                raise AuthenticationError("Login failed.", he)
-            else:
-                raise
-
-    def logout(self):
-        """Forgets the current session token, and cookies."""
-        self.token = _NoAuthenticationToken
-        self.http._cookies = {}
-        return self
-
-    def _abspath(self, path_segment, owner=None, app=None, sharing=None):
-        """Qualifies *path_segment* into an absolute path for a URL.
-
-        If *path_segment* is already absolute, returns it unchanged.
-        If *path_segment* is relative, then qualifies it with either
-        the provided namespace arguments or the ``Context``'s default
-        namespace. Any forbidden characters in *path_segment* are URL
-        encoded. This function has no network activity.
-
-        Named to be consistent with RFC2396_.
-
-        .. _RFC2396: http://www.ietf.org/rfc/rfc2396.txt
-
-        :param path_segment: A relative or absolute URL path segment.
-        :type path_segment: ``string``
-        :param owner, app, sharing: Components of a namespace (defaults
-                                    to the ``Context``'s namespace if all
-                                    three are omitted)
-        :type owner, app, sharing: ``string``
-        :return: A ``UrlEncoded`` (a subclass of ``str``).
-        :rtype: ``string``
-
-        **Example**::
-
-            import splunklib.binding as binding
-            c = binding.connect(owner='boris', app='search', sharing='user')
-            c._abspath('/a/b/c') == '/a/b/c'
-            c._abspath('/a/b c/d') == '/a/b%20c/d'
-            c._abspath('apps/local/search') == \
-                '/servicesNS/boris/search/apps/local/search'
-            c._abspath('apps/local/search', sharing='system') == \
-                '/servicesNS/nobody/system/apps/local/search'
-            url = c.authority + c._abspath('apps/local/sharing')
-        """
-        skip_encode = isinstance(path_segment, UrlEncoded)
-        # If path_segment is absolute, escape all forbidden characters
-        # in it and return it.
-        if path_segment.startswith("/"):
-            return UrlEncoded(path_segment, skip_encode=skip_encode)
-
-        # path_segment is relative, so we need a namespace to build an
-        # absolute path.
-        if owner or app or sharing:
-            ns = namespace(owner=owner, app=app, sharing=sharing)
-        else:
-            ns = self.namespace
-
-        # If no app or owner are specified, then use the /services
-        # endpoint. Otherwise, use /servicesNS with the specified
-        # namespace. If only one of app and owner is specified, use
-        # '-' for the other.
-        if ns.app is None and ns.owner is None:
-            return UrlEncoded(f"/services/{path_segment}", skip_encode=skip_encode)
-
-        oname = "nobody" if ns.owner is None else ns.owner
-        aname = "system" if ns.app is None else ns.app
-        path = UrlEncoded(
-            f"/servicesNS/{oname}/{aname}/{path_segment}", skip_encode=skip_encode
-        )
-        return path
-
-
-def connect(**kwargs):
-    """This function returns an authenticated :class:`Context` object.
-
-    This function is a shorthand for calling :meth:`Context.login`.
-
-    This function makes one round trip to the server.
-
-    :param host: The host name (the default is "localhost").
-    :type host: ``string``
-    :param port: The port number (the default is 8089).
-    :type port: ``integer``
-    :param scheme: The scheme for accessing the service (the default is "https").
-    :type scheme: "https" or "http"
-    :param owner: The owner context of the namespace (the default is "None").
-    :type owner: ``string``
-    :param app: The app context of the namespace (the default is "None").
-    :type app: ``string``
-    :param sharing: The sharing mode for the namespace (the default is "user").
-    :type sharing: "global", "system", "app", or "user"
-    :param token: The current session token (optional). Session tokens can be
-        shared across multiple service instances.
-    :type token: ``string``
-    :param cookie: A session cookie. When provided, you don't need to call :meth:`login`.
-        This parameter is only supported for Splunk 6.2+.
-    :type cookie: ``string``
-    :param username: The Splunk account username, which is used to
-        authenticate the Splunk instance.
-    :type username: ``string``
-    :param password: The password for the Splunk account.
-    :type password: ``string``
-    :param headers: List of extra HTTP headers to send (optional).
-    :type headers: ``list`` of 2-tuples.
-    :param autologin: When ``True``, automatically tries to log in again if the
-        session terminates.
-    :type autologin: ``Boolean``
-    :return: An initialized :class:`Context` instance.
-
-    **Example**::
-
-        import splunklib.binding as binding
-        c = binding.connect(...)
-        response = c.get("apps/local")
-    """
-    c = Context(**kwargs)
-    c.login()
-    return c
-
-
-# Note: the error response schema supports multiple messages but we only
-# return the first, although we do return the body so that an exception
-# handler that wants to read multiple messages can do so.
-class HTTPError(Exception):
-    """This exception is raised for HTTP responses that return an error."""
-
-    def __init__(self, response, _message=None):
-        status = response.status
-        reason = response.reason
-        body = response.body.read()
-        try:
-            detail = XML(body).findtext("./messages/msg")
-        except ParseError:
-            detail = body
-        detail_formatted = "" if detail is None else f" -- {detail}"
-        message = f"HTTP {status} {reason}{detail_formatted}"
-        Exception.__init__(self, _message or message)
-        self.status = status
-        self.reason = reason
-        self.headers = response.headers
-        self.body = body
-        self._response = response
-
-
-class AuthenticationError(HTTPError):
-    """Raised when a login request to Splunk fails.
-
-    If your username was unknown or you provided an incorrect password
-    in a call to :meth:`Context.login` or :meth:`splunklib.client.Service.login`,
-    this exception is raised.
-    """
-
-    def __init__(self, message, cause):
-        # Put the body back in the response so that HTTPError's constructor can
-        # read it again.
-        cause._response.body = BytesIO(cause.body)
-
-        HTTPError.__init__(self, cause._response, message)
-
-
-#
-# The HTTP interface used by the Splunk binding layer abstracts the underlying
-# HTTP library using request & response 'messages' which are implemented as
-# dictionaries with the following structure:
-#
-#   # HTTP request message (only method required)
-#   request {
-#       method : str,
-#       headers? : [(str, str)*],
-#       body? : str,
-#   }
-#
-#   # HTTP response message (all keys present)
-#   response {
-#       status : int,
-#       reason : str,
-#       headers : [(str, str)*],
-#       body : file,
-#   }
-#
-
-
-# Encode the given kwargs as a query string. This wrapper will also _encode
-# a list value as a sequence of assignments to the corresponding arg name,
-# for example an argument such as 'foo=[1,2,3]' will be encoded as
-# 'foo=1&foo=2&foo=3'.
-def _encode(**kwargs):
-    items = []
-    for key, value in kwargs.items():
-        if isinstance(value, list):
-            items.extend([(key, item) for item in value])
-        else:
-            items.append((key, value))
-    return parse.urlencode(items)
-
-
-# Crack the given url into (scheme, host, port, path)
-def _spliturl(url):
-    parsed_url = parse.urlparse(url)
-    host = parsed_url.hostname
-    port = parsed_url.port
-    path = (
-        "?".join((parsed_url.path, parsed_url.query))
-        if parsed_url.query
-        else parsed_url.path
-    )
-    # Strip brackets if its an IPv6 address
-    if host.startswith("[") and host.endswith("]"):
-        host = host[1:-1]
-    if port is None:
-        port = DEFAULT_PORT
-    return parsed_url.scheme, host, port, path
-
-
-# Given an HTTP request handler, this wrapper objects provides a related
-# family of convenience methods built using that handler.
-class HttpLib:
-    """A set of convenient methods for making HTTP calls.
-
-    ``HttpLib`` provides a general :meth:`request` method, and :meth:`delete`,
-    :meth:`post`, and :meth:`get` methods for the three HTTP methods that Splunk
-    uses.
-
-    By default, ``HttpLib`` uses Python's built-in ``httplib`` library,
-    but you can replace it by passing your own handling function to the
-    constructor for ``HttpLib``.
-
-    The handling function should have the type:
-
-        ``handler(`url`, `request_dict`) -> response_dict``
-
-    where `url` is the URL to make the request to (including any query and
-    fragment sections) as a dictionary with the following keys:
-
-        - method: The method for the request, typically ``GET``, ``POST``, or ``DELETE``.
-
-        - headers: A list of pairs specifying the HTTP headers (for example: ``[('key': value), ...]``).
-
-        - body: A string containing the body to send with the request (this string
-          should default to '').
-
-    and ``response_dict`` is a dictionary with the following keys:
-
-        - status: An integer containing the HTTP status code (such as 200 or 404).
-
-        - reason: The reason phrase, if any, returned by the server.
-
-        - headers: A list of pairs containing the response headers (for example, ``[('key': value), ...]``).
-
-        - body: A stream-like object supporting ``read(size=None)`` and ``close()``
-          methods to get the body of the response.
-
-    The response dictionary is returned directly by ``HttpLib``'s methods with
-    no further processing. By default, ``HttpLib`` calls the :func:`handler` function
-    to get a handler function.
-
-    If using the default handler, SSL verification can be disabled by passing verify=False.
-    """
-
-    def __init__(
-        self,
-        custom_handler=None,
-        verify=False,
-        key_file=None,
-        cert_file=None,
-        context=None,
-        retries=0,
-        retryDelay=10,
-    ):
-        if custom_handler is None:
-            self.handler = handler(
-                verify=verify, key_file=key_file, cert_file=cert_file, context=context
-            )
-        else:
-            self.handler = custom_handler
-        self._cookies = {}
-        self.retries = retries
-        self.retryDelay = retryDelay
-
-    def delete(self, url, headers=None, **kwargs):
-        """Sends a DELETE request to a URL.
-
-        :param url: The URL.
-        :type url: ``string``
-        :param headers: A list of pairs specifying the headers for the HTTP
-            response (for example, ``[('Content-Type': 'text/cthulhu'), ('Token': 'boris')]``).
-        :type headers: ``list``
-        :param kwargs: Additional keyword arguments (optional). These arguments
-            are interpreted as the query part of the URL. The order of keyword
-            arguments is not preserved in the request, but the keywords and
-            their arguments will be URL encoded.
-        :type kwargs: ``dict``
-        :returns: A dictionary describing the response (see :class:`HttpLib` for
-            its structure).
-        :rtype: ``dict``
-        """
-        if headers is None:
-            headers = []
-        if kwargs:
-            # url is already a UrlEncoded. We have to manually declare
-            # the query to be encoded or it will get automatically URL
-            # encoded by being appended to url.
-            url = url + UrlEncoded("?" + _encode(**kwargs), skip_encode=True)
-        message = {
-            "method": "DELETE",
-            "headers": headers,
-        }
-        return self.request(url, message)
-
-    def get(self, url, headers=None, **kwargs):
-        """Sends a GET request to a URL.
-
-        :param url: The URL.
-        :type url: ``string``
-        :param headers: A list of pairs specifying the headers for the HTTP
-            response (for example, ``[('Content-Type': 'text/cthulhu'), ('Token': 'boris')]``).
-        :type headers: ``list``
-        :param kwargs: Additional keyword arguments (optional). These arguments
-            are interpreted as the query part of the URL. The order of keyword
-            arguments is not preserved in the request, but the keywords and
-            their arguments will be URL encoded.
-        :type kwargs: ``dict``
-        :returns: A dictionary describing the response (see :class:`HttpLib` for
-            its structure).
-        :rtype: ``dict``
-        """
-        if headers is None:
-            headers = []
-        if kwargs:
-            # url is already a UrlEncoded. We have to manually declare
-            # the query to be encoded or it will get automatically URL
-            # encoded by being appended to url.
-            url = url + UrlEncoded("?" + _encode(**kwargs), skip_encode=True)
-        return self.request(url, {"method": "GET", "headers": headers})
-
-    def post(self, url, headers=None, **kwargs):
-        """Sends a POST request to a URL.
-
-        :param url: The URL.
-        :type url: ``string``
-        :param headers: A list of pairs specifying the headers for the HTTP
-            response (for example, ``[('Content-Type': 'text/cthulhu'), ('Token': 'boris')]``).
-        :type headers: ``list``
-        :param kwargs: Additional keyword arguments (optional). If the argument
-            is ``body``, the value is used as the body for the request, and the
-            keywords and their arguments will be URL encoded. If there is no
-            ``body`` keyword argument, all the keyword arguments are encoded
-            into the body of the request in the format ``x-www-form-urlencoded``.
-        :type kwargs: ``dict``
-        :returns: A dictionary describing the response (see :class:`HttpLib` for
-            its structure).
-        :rtype: ``dict``
-        """
-        if headers is None:
-            headers = []
-
-        # We handle GET-style arguments and an unstructured body. This is here
-        # to support the receivers/stream endpoint.
-        if "body" in kwargs:
-            # We only use application/x-www-form-urlencoded if there is no other
-            # Content-Type header present. This can happen in cases where we
-            # send requests as application/json, e.g. for KV Store.
-            if len([x for x in headers if x[0].lower() == "content-type"]) == 0:
-                headers.append(("Content-Type", "application/x-www-form-urlencoded"))
-
-            body = kwargs.pop("body")
-            if isinstance(body, dict):
-                body = _encode(**body).encode("utf-8")
-            if len(kwargs) > 0:
-                url = url + UrlEncoded("?" + _encode(**kwargs), skip_encode=True)
-        else:
-            body = _encode(**kwargs).encode("utf-8")
-        message = {"method": "POST", "headers": headers, "body": body}
-        return self.request(url, message)
-
-    def request(self, url, message, **kwargs):
-        """Issues an HTTP request to a URL.
-
-        :param url: The URL.
-        :type url: ``string``
-        :param message: A dictionary with the format as described in
-            :class:`HttpLib`.
-        :type message: ``dict``
-        :param kwargs: Additional keyword arguments (optional). These arguments
-            are passed unchanged to the handler.
-        :type kwargs: ``dict``
-        :returns: A dictionary describing the response (see :class:`HttpLib` for
-            its structure).
-        :rtype: ``dict``
-        """
-        while True:
-            try:
-                response = self.handler(url, message, **kwargs)
-                break
-            except Exception:
-                if self.retries <= 0:
-                    raise
-                else:
-                    time.sleep(self.retryDelay)
-                    self.retries -= 1
-        response = record(response)
-        if 400 <= response.status:
-            raise HTTPError(response)
-
-        # Update the cookie with any HTTP request
-        # Initially, assume list of 2-tuples
-        key_value_tuples = response.headers
-        # If response.headers is a dict, get the key-value pairs as 2-tuples
-        # this is the case when using urllib2
-        if isinstance(response.headers, dict):
-            key_value_tuples = list(response.headers.items())
-        for key, value in key_value_tuples:
-            if key.lower() == "set-cookie":
-                _parse_cookies(value, self._cookies)
-
-        return response
-
-
-# Converts an httplib response into a file-like object.
-class ResponseReader(io.RawIOBase):
-    """This class provides a file-like interface for :class:`httplib` responses.
-
-    The ``ResponseReader`` class is intended to be a layer to unify the different
-    types of HTTP libraries used with this SDK. This class also provides a
-    preview of the stream and a few useful predicates.
-    """
-
-    # For testing, you can use a StringIO as the argument to
-    # ``ResponseReader`` instead of an ``httplib.HTTPResponse``. It
-    # will work equally well.
-    def __init__(self, response, connection=None):
-        self._response = response
-        self._connection = connection
-        self._buffer = b""
-
-    def __str__(self):
-        return str(self.read(), "UTF-8")
-
-    @property
-    def empty(self):
-        """Indicates whether there is any more data in the response."""
-        return self.peek(1) == b""
-
-    def peek(self, size):
-        """Nondestructively retrieves a given number of characters.
-
-        The next :meth:`read` operation behaves as though this method was never
-        called.
-
-        :param size: The number of characters to retrieve.
-        :type size: ``integer``
-        """
-        c = self.read(size)
-        self._buffer = self._buffer + c
-        return c
-
-    def close(self):
-        """Closes this response."""
-        if self._connection:
-            self._connection.close()
-        self._response.close()
-
-    def read(self, size=None):
-        """Reads a given number of characters from the response.
-
-        :param size: The number of characters to read, or "None" to read the
-            entire response.
-        :type size: ``integer`` or "None"
-
-        """
-        r = self._buffer
-        self._buffer = b""
-        if size is not None:
-            size -= len(r)
-        r = r + self._response.read(size)
-        return r
-
-    def readable(self):
-        """Indicates that the response reader is readable."""
-        return True
-
-    def readinto(self, byte_array):
-        """Read data into a byte array, upto the size of the byte array.
-
-        :param byte_array: A byte array/memory view to pour bytes into.
-        :type byte_array: ``bytearray`` or ``memoryview``
-
-        """
-        max_size = len(byte_array)
-        data = self.read(max_size)
-        bytes_read = len(data)
-        byte_array[:bytes_read] = data
-        return bytes_read
-
-
-def handler(key_file=None, cert_file=None, timeout=None, verify=False, context=None):
-    """This class returns an instance of the default HTTP request handler using
-    the values you provide.
-
-    :param `key_file`: A path to a PEM (Privacy Enhanced Mail) formatted file containing your private key (optional).
-    :type key_file: ``string``
-    :param `cert_file`: A path to a PEM (Privacy Enhanced Mail) formatted file containing a certificate chain file (optional).
-    :type cert_file: ``string``
-    :param `timeout`: The request time-out period, in seconds (optional).
-    :type timeout: ``integer`` or "None"
-    :param `verify`: Set to False to disable SSL verification on https connections.
-    :type verify: ``Boolean``
-    :param `context`: The SSLContext that can is used with the HTTPSConnection when verify=True is enabled and context is specified
-    :type context: ``SSLContext`
-    """
-
-    def connect(scheme, host, port):
-        kwargs = {}
-        if timeout is not None:
-            kwargs["timeout"] = timeout
-        if scheme == "http":
-            return client.HTTPConnection(host, port, **kwargs)
-        if scheme == "https":
-            if key_file is not None:
-                kwargs["key_file"] = key_file
-            if cert_file is not None:
-                kwargs["cert_file"] = cert_file
-
-            if not verify:
-                kwargs["context"] = ssl._create_unverified_context()  # nosemgrep
-            elif context:
-                # verify is True in elif branch and context is not None
-                kwargs["context"] = context
-
-            return client.HTTPSConnection(host, port, **kwargs)
-        raise ValueError(f"unsupported scheme: {scheme}")
-
-    def request(url, message, **kwargs):
-        scheme, host, port, path = _spliturl(url)
-        body = message.get("body", "")
-        head = {
-            "Content-Length": str(len(body)),
-            "Host": host,
-            "User-Agent": "splunk-sdk-python/%s" % __version__,
-            "Accept": "*/*",
-            "Connection": "Close",
-        }  # defaults
-        for key, value in message["headers"]:
-            head[key] = value
-        method = message.get("method", "GET")
-
-        connection = connect(scheme, host, port)
-        is_keepalive = False
-        try:
-            connection.request(method, path, body, head)
-            if timeout is not None:
-                connection.sock.settimeout(timeout)
-            response = connection.getresponse()
-            is_keepalive = (
-                "keep-alive"
-                in response.getheader("connection", default="close").lower()
-            )
-        finally:
-            if not is_keepalive:
-                connection.close()
-
-        return {
-            "status": response.status,
-            "reason": response.reason,
-            "headers": response.getheaders(),
-            "body": ResponseReader(response, connection if is_keepalive else None),
-        }
-
-    return request
diff --git a/apps/bitwarden_event_logs/lib/splunklib/client.py b/apps/bitwarden_event_logs/lib/splunklib/client.py
deleted file mode 100755
index 72cefc26..00000000
--- a/apps/bitwarden_event_logs/lib/splunklib/client.py
+++ /dev/null
@@ -1,4156 +0,0 @@
-# Copyright © 2011-2024 Splunk, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"): you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-# The purpose of this module is to provide a friendlier domain interface to
-# various Splunk endpoints. The approach here is to leverage the binding
-# layer to capture endpoint context and provide objects and methods that
-# offer simplified access their corresponding endpoints. The design avoids
-# caching resource state. From the perspective of this module, the 'policy'
-# for caching resource state belongs in the application or a higher level
-# framework, and its the purpose of this module to provide simplified
-# access to that resource state.
-#
-# A side note, the objects below that provide helper methods for updating eg:
-# Entity state, are written so that they may be used in a fluent style.
-#
-
-"""The **splunklib.client** module provides a Pythonic interface to the
-`Splunk REST API `_,
-allowing you programmatically access Splunk's resources.
-
-**splunklib.client** wraps a Pythonic layer around the wire-level
-binding of the **splunklib.binding** module. The core of the library is the
-:class:`Service` class, which encapsulates a connection to the server, and
-provides access to the various aspects of Splunk's functionality, which are
-exposed via the REST API. Typically you connect to a running Splunk instance
-with the :func:`connect` function::
-
-    import splunklib.client as client
-    service = client.connect(host='localhost', port=8089,
-                       username='admin', password='...')
-    assert isinstance(service, client.Service)
-
-:class:`Service` objects have fields for the various Splunk resources (such as apps,
-jobs, saved searches, inputs, and indexes). All of these fields are
-:class:`Collection` objects::
-
-    appcollection = service.apps
-    my_app = appcollection.create('my_app')
-    my_app = appcollection['my_app']
-    appcollection.delete('my_app')
-
-The individual elements of the collection, in this case *applications*,
-are subclasses of :class:`Entity`. An ``Entity`` object has fields for its
-attributes, and methods that are specific to each kind of entity. For example::
-
-    print(my_app['author'])  # Or: print(my_app.author)
-    my_app.package()  # Creates a compressed package of this application
-"""
-
-import contextlib
-import datetime
-import json
-import logging
-import re
-import socket
-from datetime import datetime, timedelta
-from time import sleep
-from urllib import parse
-
-from . import data
-from .data import record
-from .binding import (
-    AuthenticationError,
-    Context,
-    HTTPError,
-    UrlEncoded,
-    _encode,
-    _make_cookie_header,
-    _NoAuthenticationToken,
-    namespace,
-)
-
-logger = logging.getLogger(__name__)
-
-__all__ = [
-    "connect",
-    "NotSupportedError",
-    "OperationError",
-    "IncomparableException",
-    "Service",
-    "namespace",
-    "AuthenticationError",
-]
-
-PATH_APPS = "apps/local/"
-PATH_CAPABILITIES = "authorization/capabilities/"
-PATH_CONF = "configs/conf-%s/"
-PATH_PROPERTIES = "properties/"
-PATH_DEPLOYMENT_CLIENTS = "deployment/client/"
-PATH_DEPLOYMENT_TENANTS = "deployment/tenants/"
-PATH_DEPLOYMENT_SERVERS = "deployment/server/"
-PATH_DEPLOYMENT_SERVERCLASSES = "deployment/serverclass/"
-PATH_EVENT_TYPES = "saved/eventtypes/"
-PATH_FIRED_ALERTS = "alerts/fired_alerts/"
-PATH_INDEXES = "data/indexes/"
-PATH_INPUTS = "data/inputs/"
-PATH_JOBS = "search/jobs/"
-PATH_JOBS_V2 = "search/v2/jobs/"
-PATH_LOGGER = "/services/server/logger/"
-PATH_MACROS = "configs/conf-macros/"
-PATH_MESSAGES = "messages/"
-PATH_MODULAR_INPUTS = "data/modular-inputs"
-PATH_ROLES = "authorization/roles/"
-PATH_SAVED_SEARCHES = "saved/searches/"
-PATH_STANZA = "configs/conf-%s/%s"  # (file, stanza)
-PATH_USERS = "authentication/users/"
-PATH_RECEIVERS_STREAM = "/services/receivers/stream"
-PATH_RECEIVERS_SIMPLE = "/services/receivers/simple"
-PATH_STORAGE_PASSWORDS = "storage/passwords"
-
-XNAMEF_ATOM = "{http://www.w3.org/2005/Atom}%s"
-XNAME_ENTRY = XNAMEF_ATOM % "entry"
-XNAME_CONTENT = XNAMEF_ATOM % "content"
-
-MATCH_ENTRY_CONTENT = f"{XNAME_ENTRY}/{XNAME_CONTENT}/*"
-
-
-class IllegalOperationException(Exception):
-    """Thrown when an operation is not possible on the Splunk instance that a
-    :class:`Service` object is connected to."""
-
-
-class IncomparableException(Exception):
-    """Thrown when trying to compare objects (using ``==``, ``<``, ``>``, and
-    so on) of a type that doesn't support it."""
-
-
-class AmbiguousReferenceException(ValueError):
-    """Thrown when the name used to fetch an entity matches more than one entity."""
-
-
-class InvalidNameException(Exception):
-    """Thrown when the specified name contains characters that are not allowed
-    in Splunk entity names."""
-
-
-class NoSuchCapability(Exception):
-    """Thrown when the capability that has been referred to doesn't exist."""
-
-
-class OperationError(Exception):
-    """Raised for a failed operation, such as a timeout."""
-
-
-class NotSupportedError(Exception):
-    """Raised for operations that are not supported on a given object."""
-
-
-def _trailing(template, *targets):
-    """Substring of *template* following all *targets*.
-
-    **Example**::
-
-        template = "this is a test of the bunnies."
-        _trailing(template, "is", "est", "the") == " bunnies"
-
-    Each target is matched successively in the string, and the string
-    remaining after the last target is returned. If one of the targets
-    fails to match, a ValueError is raised.
-
-    :param template: Template to extract a trailing string from.
-    :type template: ``string``
-    :param targets: Strings to successively match in *template*.
-    :type targets: list of ``string``s
-    :return: Trailing string after all targets are matched.
-    :rtype: ``string``
-    :raises ValueError: Raised when one of the targets does not match.
-    """
-    s = template
-    for t in targets:
-        n = s.find(t)
-        if n == -1:
-            raise ValueError("Target " + t + " not found in template.")
-        s = s[n + len(t) :]
-    return s
-
-
-# Filter the given state content record according to the given arg list.
-def _filter_content(content, *args):
-    if len(args) > 0:
-        return record((k, content[k]) for k in args)
-    return record(
-        (k, v)
-        for k, v in content.items()
-        if k not in ["eai:acl", "eai:attributes", "type"]
-    )
-
-
-# Construct a resource path from the given base path + resource name
-def _path(base, name):
-    if not base.endswith("/"):
-        base = base + "/"
-    return base + name
-
-
-# Load an atom record from the body of the given response
-# this will ultimately be sent to an xml ElementTree so we
-# should use the xmlcharrefreplace option
-def _load_atom(response, match=None):
-    return data.load(response.body.read().decode("utf-8", "xmlcharrefreplace"), match)
-
-
-# Load an array of atom entries from the body of the given response
-def _load_atom_entries(response):
-    r = _load_atom(response)
-    if "feed" in r:
-        # Need this to handle a random case in the REST API
-        if r.feed.get("totalResults") in [0, "0"]:
-            return []
-        entries = r.feed.get("entry", None)
-        if entries is None:
-            return None
-        return entries if isinstance(entries, list) else [entries]
-    # Unlike most other endpoints, the jobs endpoint does not return
-    # its state wrapped in another element, but at the top level.
-    # For example, in XML, it returns ... instead of
-    # ....
-    entries = r.get("entry", None)
-    if entries is None:
-        return None
-    return entries if isinstance(entries, list) else [entries]
-
-
-# Load the sid from the body of the given response
-def _load_sid(response, output_mode):
-    if output_mode == "json":
-        json_obj = json.loads(response.body.read())
-        return json_obj.get("sid")
-    return _load_atom(response).response.sid
-
-
-# Parse the given atom entry record into a generic entity state record
-def _parse_atom_entry(entry):
-    title = entry.get("title", None)
-
-    elink = entry.get("link", [])
-    elink = elink if isinstance(elink, list) else [elink]
-    links = record((link.rel, link.href) for link in elink)
-
-    # Retrieve entity content values
-    content = entry.get("content", {})
-
-    # Host entry metadata
-    metadata = _parse_atom_metadata(content)
-
-    # Filter some of the noise out of the content record
-    content = record(
-        (k, v) for k, v in content.items() if k not in ["eai:acl", "eai:attributes"]
-    )
-
-    if "type" in content:
-        if isinstance(content["type"], list):
-            content["type"] = [t for t in content["type"] if t != "text/xml"]
-            # Unset type if it was only 'text/xml'
-            if len(content["type"]) == 0:
-                content.pop("type", None)
-            # Flatten 1 element list
-            if len(content["type"]) == 1:
-                content["type"] = content["type"][0]
-        else:
-            content.pop("type", None)
-
-    return record(
-        {
-            "title": title,
-            "links": links,
-            "access": metadata.access,
-            "fields": metadata.fields,
-            "content": content,
-            "updated": entry.get("updated"),
-        }
-    )
-
-
-# Parse the metadata fields out of the given atom entry content record
-def _parse_atom_metadata(content):
-    # Hoist access metadata
-    access = content.get("eai:acl", None)
-
-    # Hoist content metadata (and cleanup some naming)
-    attributes = content.get("eai:attributes", {})
-    fields = record(
-        {
-            "required": attributes.get("requiredFields", []),
-            "optional": attributes.get("optionalFields", []),
-            "wildcard": attributes.get("wildcardFields", []),
-        }
-    )
-
-    return record({"access": access, "fields": fields})
-
-
-# kwargs: scheme, host, port, app, owner, username, password
-def connect(**kwargs):
-    """This function connects and logs in to a Splunk instance.
-
-    This function is a shorthand for :meth:`Service.login`.
-    The ``connect`` function makes one round trip to the server (for logging in).
-
-    :param host: The host name (the default is "localhost").
-    :type host: ``string``
-    :param port: The port number (the default is 8089).
-    :type port: ``integer``
-    :param scheme: The scheme for accessing the service (the default is "https").
-    :type scheme: "https" or "http"
-    :param verify: Enable (True) or disable (False) SSL verification for
-                   https connections. (optional, the default is True)
-    :type verify: ``Boolean``
-    :param `owner`: The owner context of the namespace (optional).
-    :type owner: ``string``
-    :param `app`: The app context of the namespace (optional).
-    :type app: ``string``
-    :param sharing: The sharing mode for the namespace (the default is "user").
-    :type sharing: "global", "system", "app", or "user"
-    :param `token`: The current session token (optional). Session tokens can be
-                    shared across multiple service instances.
-    :type token: ``string``
-    :param cookie: A session cookie. When provided, you don't need to call :meth:`login`.
-        This parameter is only supported for Splunk 6.2+.
-    :type cookie: ``string``
-    :param autologin: When ``True``, automatically tries to log in again if the
-        session terminates.
-    :type autologin: ``boolean``
-    :param `username`: The Splunk account username, which is used to
-                       authenticate the Splunk instance.
-    :type username: ``string``
-    :param `password`: The password for the Splunk account.
-    :type password: ``string``
-    :param retires: Number of retries for each HTTP connection (optional, the default is 0).
-                    NOTE THAT THIS MAY INCREASE THE NUMBER OF ROUND TRIP CONNECTIONS TO THE SPLUNK SERVER.
-    :type retries: ``int``
-    :param retryDelay: How long to wait between connection attempts if `retries` > 0 (optional, defaults to 10s).
-    :type retryDelay: ``int`` (in seconds)
-    :param `context`: The SSLContext that can be used when setting verify=True (optional)
-    :type context: ``SSLContext``
-    :return: An initialized :class:`Service` connection.
-
-    **Example**::
-
-        import splunklib.client as client
-        s = client.connect(...)
-        a = s.apps["my_app"]
-        ...
-    """
-    s = Service(**kwargs)
-    s.login()
-    return s
-
-
-# In preparation for adding Storm support, we added an
-# intermediary class between Service and Context. Storm's
-# API is not going to be the same as enterprise Splunk's
-# API, so we will derive both Service (for enterprise Splunk)
-# and StormService for (Splunk Storm) from _BaseService, and
-# put any shared behavior on it.
-class _BaseService(Context):
-    pass
-
-
-class Service(_BaseService):
-    """A Pythonic binding to Splunk instances.
-
-    A :class:`Service` represents a binding to a Splunk instance on an
-    HTTP or HTTPS port. It handles the details of authentication, wire
-    formats, and wraps the REST API endpoints into something more
-    Pythonic. All of the low-level operations on the instance from
-    :class:`splunklib.binding.Context` are also available in case you need
-    to do something beyond what is provided by this class.
-
-    After creating a ``Service`` object, you must call its :meth:`login`
-    method before you can issue requests to Splunk.
-    Alternately, use the :func:`connect` function to create an already
-    authenticated :class:`Service` object, or provide a session token
-    when creating the :class:`Service` object explicitly (the same
-    token may be shared by multiple :class:`Service` objects).
-
-    :param host: The host name (the default is "localhost").
-    :type host: ``string``
-    :param port: The port number (the default is 8089).
-    :type port: ``integer``
-    :param scheme: The scheme for accessing the service (the default is "https").
-    :type scheme: "https" or "http"
-    :param verify: Enable (True) or disable (False) SSL verification for
-                   https connections. (optional, the default is True)
-    :type verify: ``Boolean``
-    :param `owner`: The owner context of the namespace (optional; use "-" for wildcard).
-    :type owner: ``string``
-    :param `app`: The app context of the namespace (optional; use "-" for wildcard).
-    :type app: ``string``
-    :param `token`: The current session token (optional). Session tokens can be
-                    shared across multiple service instances.
-    :type token: ``string``
-    :param cookie: A session cookie. When provided, you don't need to call :meth:`login`.
-        This parameter is only supported for Splunk 6.2+.
-    :type cookie: ``string``
-    :param `username`: The Splunk account username, which is used to
-                       authenticate the Splunk instance.
-    :type username: ``string``
-    :param `password`: The password, which is used to authenticate the Splunk
-                       instance.
-    :type password: ``string``
-    :param retires: Number of retries for each HTTP connection (optional, the default is 0).
-                    NOTE THAT THIS MAY INCREASE THE NUMBER OF ROUND TRIP CONNECTIONS TO THE SPLUNK SERVER.
-    :type retries: ``int``
-    :param retryDelay: How long to wait between connection attempts if `retries` > 0 (optional, defaults to 10s).
-    :type retryDelay: ``int`` (in seconds)
-    :return: A :class:`Service` instance.
-
-    **Example**::
-
-        import splunklib.client as client
-        s = client.Service(username="boris", password="natasha", ...)
-        s.login()
-        # Or equivalently
-        s = client.connect(username="boris", password="natasha")
-        # Or if you already have a session token
-        s = client.Service(token="atg232342aa34324a")
-        # Or if you already have a valid cookie
-        s = client.Service(cookie="splunkd_8089=...")
-    """
-
-    def __init__(self, **kwargs):
-        super().__init__(**kwargs)
-        self._splunk_version = None
-        self._kvstore_owner = None
-        self._instance_type = None
-
-    @property
-    def apps(self):
-        """Returns the collection of applications that are installed on this instance of Splunk.
-
-        :return: A :class:`Collection` of :class:`Application` entities.
-        """
-        return Collection(self, PATH_APPS, item=Application)
-
-    @property
-    def confs(self):
-        """Returns the collection of configuration files for this Splunk instance.
-
-        :return: A :class:`Configurations` collection of
-            :class:`ConfigurationFile` entities.
-        """
-        return Configurations(self)
-
-    @property
-    def capabilities(self):
-        """Returns the list of system capabilities.
-
-        :return: A ``list`` of capabilities.
-        """
-        response = self.get(PATH_CAPABILITIES)
-        return _load_atom(response, MATCH_ENTRY_CONTENT).capabilities
-
-    @property
-    def event_types(self):
-        """Returns the collection of event types defined in this Splunk instance.
-
-        :return: An :class:`Entity` containing the event types.
-        """
-        return Collection(self, PATH_EVENT_TYPES)
-
-    @property
-    def fired_alerts(self):
-        """Returns the collection of alerts that have been fired on the Splunk
-        instance, grouped by saved search.
-
-        :return: A :class:`Collection` of :class:`AlertGroup` entities.
-        """
-        return Collection(self, PATH_FIRED_ALERTS, item=AlertGroup)
-
-    @property
-    def indexes(self):
-        """Returns the collection of indexes for this Splunk instance.
-
-        :return: An :class:`Indexes` collection of :class:`Index` entities.
-        """
-        return Indexes(self, PATH_INDEXES, item=Index)
-
-    @property
-    def info(self):
-        """Returns the information about this instance of Splunk.
-
-        :return: The system information, as key-value pairs.
-        :rtype: ``dict``
-        """
-        response = self.get("/services/server/info")
-        return _filter_content(_load_atom(response, MATCH_ENTRY_CONTENT))
-
-    def input(self, path, kind=None):
-        """Retrieves an input by path, and optionally kind.
-
-        :return: A :class:`Input` object.
-        """
-        return Input(self, path, kind=kind).refresh()
-
-    @property
-    def inputs(self):
-        """Returns the collection of inputs configured on this Splunk instance.
-
-        :return: An :class:`Inputs` collection of :class:`Input` entities.
-        """
-        return Inputs(self)
-
-    def job(self, sid):
-        """Retrieves a search job by sid.
-
-        :return: A :class:`Job` object.
-        """
-        return Job(self, sid).refresh()
-
-    @property
-    def jobs(self):
-        """Returns the collection of current search jobs.
-
-        :return: A :class:`Jobs` collection of :class:`Job` entities.
-        """
-        return Jobs(self)
-
-    @property
-    def loggers(self):
-        """Returns the collection of logging level categories and their status.
-
-        :return: A :class:`Loggers` collection of logging levels.
-        """
-        return Loggers(self)
-
-    @property
-    def messages(self):
-        """Returns the collection of service messages.
-
-        :return: A :class:`Collection` of :class:`Message` entities.
-        """
-        return Collection(self, PATH_MESSAGES, item=Message)
-
-    @property
-    def modular_input_kinds(self):
-        """Returns the collection of the modular input kinds on this Splunk instance.
-
-        :return: A :class:`ReadOnlyCollection` of :class:`ModularInputKind` entities.
-        """
-        if self.splunk_version >= (5,):
-            return ReadOnlyCollection(self, PATH_MODULAR_INPUTS, item=ModularInputKind)
-        raise IllegalOperationException(
-            "Modular inputs are not supported before Splunk version 5."
-        )
-
-    @property
-    def storage_passwords(self):
-        """Returns the collection of the storage passwords on this Splunk instance.
-
-        :return: A :class:`ReadOnlyCollection` of :class:`StoragePasswords` entities.
-        """
-        return StoragePasswords(self)
-
-    # kwargs: enable_lookups, reload_macros, parse_only, output_mode
-    def parse(self, query, **kwargs):
-        """Parses a search query and returns a semantic map of the search.
-
-        :param query: The search query to parse.
-        :type query: ``string``
-        :param kwargs: Arguments to pass to the ``search/parser`` endpoint
-            (optional). Valid arguments are:
-
-            * "enable_lookups" (``boolean``): If ``True``, performs reverse lookups
-              to expand the search expression.
-
-            * "output_mode" (``string``): The output format (XML or JSON).
-
-            * "parse_only" (``boolean``): If ``True``, disables the expansion of
-              search due to evaluation of subsearches, time term expansion,
-              lookups, tags, eventtypes, and sourcetype alias.
-
-            * "reload_macros" (``boolean``): If ``True``, reloads macro
-              definitions from macros.conf.
-
-        :type kwargs: ``dict``
-        :return: A semantic map of the parsed search query.
-        """
-        if not self.disable_v2_api:
-            return self.post("search/v2/parser", q=query, **kwargs)
-        return self.get("search/parser", q=query, **kwargs)
-
-    def restart(self, timeout=None):
-        """Restarts this Splunk instance.
-
-        The service is unavailable until it has successfully restarted.
-
-        If a *timeout* value is specified, ``restart`` blocks until the service
-        resumes or the timeout period has been exceeded. Otherwise, ``restart`` returns
-        immediately.
-
-        :param timeout: A timeout period, in seconds.
-        :type timeout: ``integer``
-        """
-        msg = {
-            "value": "Restart requested by "
-            + self.username
-            + "via the Splunk SDK for Python"
-        }
-        # This message will be deleted once the server actually restarts.
-        self.messages.create(name="restart_required", **msg)
-        result = self.post("/services/server/control/restart")
-        if timeout is None:
-            return result
-        start = datetime.now()
-        diff = timedelta(seconds=timeout)
-        while datetime.now() - start < diff:
-            try:
-                self.login()
-                if not self.restart_required:
-                    return result
-            except Exception as e:
-                sleep(1)
-        raise Exception("Operation time out.")
-
-    @property
-    def restart_required(self):
-        """Indicates whether splunkd is in a state that requires a restart.
-
-        :return: A ``boolean`` that indicates whether a restart is required.
-
-        """
-        response = self.get("messages").body.read()
-        messages = data.load(response)["feed"]
-        if "entry" not in messages:
-            result = False
-        else:
-            if isinstance(messages["entry"], dict):
-                titles = [messages["entry"]["title"]]
-            else:
-                titles = [x["title"] for x in messages["entry"]]
-            result = "restart_required" in titles
-        return result
-
-    @property
-    def roles(self):
-        """Returns the collection of user roles.
-
-        :return: A :class:`Roles` collection of :class:`Role` entities.
-        """
-        return Roles(self)
-
-    def search(self, query, **kwargs):
-        """Runs a search using a search query and any optional arguments you
-        provide, and returns a `Job` object representing the search.
-
-        :param query: A search query.
-        :type query: ``string``
-        :param kwargs: Arguments for the search (optional):
-
-            * "output_mode" (``string``): Specifies the output format of the
-              results.
-
-            * "earliest_time" (``string``): Specifies the earliest time in the
-              time range to
-              search. The time string can be a UTC time (with fractional
-              seconds), a relative time specifier (to now), or a formatted
-              time string.
-
-            * "latest_time" (``string``): Specifies the latest time in the time
-              range to
-              search. The time string can be a UTC time (with fractional
-              seconds), a relative time specifier (to now), or a formatted
-              time string.
-
-            * "rf" (``string``): Specifies one or more fields to add to the
-              search.
-
-        :type kwargs: ``dict``
-        :rtype: class:`Job`
-        :returns: An object representing the created job.
-        """
-        return self.jobs.create(query, **kwargs)
-
-    @property
-    def saved_searches(self):
-        """Returns the collection of saved searches.
-
-        :return: A :class:`SavedSearches` collection of :class:`SavedSearch`
-            entities.
-        """
-        return SavedSearches(self)
-
-    @property
-    def macros(self):
-        """Returns the collection of macros.
-
-        :return: A :class:`Macros` collection of :class:`Macro`
-            entities.
-        """
-        return Macros(self)
-
-    @property
-    def settings(self):
-        """Returns the configuration settings for this instance of Splunk.
-
-        :return: A :class:`Settings` object containing configuration settings.
-        """
-        return Settings(self)
-
-    @property
-    def splunk_version(self):
-        """Returns the version of the splunkd instance this object is attached
-        to.
-
-        The version is returned as a tuple of the version components as
-        integers (for example, `(4,3,3)` or `(5,)`).
-
-        :return: A ``tuple`` of ``integers``.
-        """
-        if self._splunk_version is None:
-            self._splunk_version = tuple(
-                int(p) for p in self.info["version"].split(".")
-            )
-        return self._splunk_version
-
-    @property
-    def splunk_instance(self):
-        if self._instance_type is None:
-            splunk_info = self.info
-            if hasattr(splunk_info, "instance_type"):
-                self._instance_type = splunk_info["instance_type"]
-            else:
-                self._instance_type = ""
-        return self._instance_type
-
-    @property
-    def disable_v2_api(self):
-        if self.splunk_instance.lower() == "cloud":
-            return self.splunk_version < (9, 0, 2209)
-        return self.splunk_version < (9, 0, 2)
-
-    @property
-    def kvstore_owner(self):
-        """Returns the KVStore owner for this instance of Splunk.
-
-        By default is the kvstore owner is not set, it will return "nobody"
-        :return: A string with the KVStore owner.
-        """
-        if self._kvstore_owner is None:
-            self._kvstore_owner = "nobody"
-        return self._kvstore_owner
-
-    @kvstore_owner.setter
-    def kvstore_owner(self, value):
-        """
-        kvstore is refreshed, when the owner value is changed
-        """
-        self._kvstore_owner = value
-        self.kvstore
-
-    @property
-    def kvstore(self):
-        """Returns the collection of KV Store collections.
-
-        sets the owner for the namespace, before retrieving the KVStore Collection
-
-        :return: A :class:`KVStoreCollections` collection of :class:`KVStoreCollection` entities.
-        """
-        self.namespace["owner"] = self.kvstore_owner
-        return KVStoreCollections(self)
-
-    @property
-    def users(self):
-        """Returns the collection of users.
-
-        :return: A :class:`Users` collection of :class:`User` entities.
-        """
-        return Users(self)
-
-
-class Endpoint:
-    """This class represents individual Splunk resources in the Splunk REST API.
-
-    An ``Endpoint`` object represents a URI, such as ``/services/saved/searches``.
-    This class provides the common functionality of :class:`Collection` and
-    :class:`Entity` (essentially HTTP GET and POST methods).
-    """
-
-    def __init__(self, service, path):
-        self.service = service
-        self.path = path
-
-    def get_api_version(self, path):
-        """Return the API version of the service used in the provided path.
-
-        Args:
-            path (str): A fully-qualified endpoint path (for example, "/services/search/jobs").
-
-        Returns:
-            int: Version of the API (for example, 1)
-        """
-        # Default to v1 if undefined in the path
-        # For example, "/services/search/jobs" is using API v1
-        api_version = 1
-
-        versionSearch = re.search(
-            r"(?:servicesNS\/[^/]+\/[^/]+|services)\/[^/]+\/v(\d+)\/", path
-        )
-        if versionSearch:
-            api_version = int(versionSearch.group(1))
-
-        return api_version
-
-    def get(self, path_segment="", owner=None, app=None, sharing=None, **query):
-        """Performs a GET operation on the path segment relative to this endpoint.
-
-        This method is named to match the HTTP method. This method makes at least
-        one roundtrip to the server, one additional round trip for
-        each 303 status returned, plus at most two additional round
-        trips if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        If *owner*, *app*, and *sharing* are omitted, this method takes a
-        default namespace from the :class:`Service` object for this :class:`Endpoint`.
-        All other keyword arguments are included in the URL as query parameters.
-
-        :raises AuthenticationError: Raised when the ``Service`` is not logged in.
-        :raises HTTPError: Raised when an error in the request occurs.
-        :param path_segment: A path segment relative to this endpoint.
-        :type path_segment: ``string``
-        :param owner: The owner context of the namespace (optional).
-        :type owner: ``string``
-        :param app: The app context of the namespace (optional).
-        :type app: ``string``
-        :param sharing: The sharing mode for the namespace (optional).
-        :type sharing: "global", "system", "app", or "user"
-        :param query: All other keyword arguments, which are used as query
-            parameters.
-        :type query: ``string``
-        :return: The response from the server.
-        :rtype: ``dict`` with keys ``body``, ``headers``, ``reason``,
-                and ``status``
-
-        **Example**::
-
-            import splunklib.client
-            s = client.service(...)
-            apps = s.apps
-            apps.get() == \\
-                {'body': ...a response reader object...,
-                 'headers': [('content-length', '26208'),
-                             ('expires', 'Fri, 30 Oct 1998 00:00:00 GMT'),
-                             ('server', 'Splunkd'),
-                             ('connection', 'close'),
-                             ('cache-control', 'no-store, max-age=0, must-revalidate, no-cache'),
-                             ('date', 'Fri, 11 May 2012 16:30:35 GMT'),
-                             ('content-type', 'text/xml; charset=utf-8')],
-                 'reason': 'OK',
-                 'status': 200}
-            apps.get('nonexistant/path') # raises HTTPError
-            s.logout()
-            apps.get() # raises AuthenticationError
-        """
-        # self.path to the Endpoint is relative in the SDK, so passing
-        # owner, app, sharing, etc. along will produce the correct
-        # namespace in the final request.
-        if path_segment.startswith("/"):
-            path = path_segment
-        else:
-            if not self.path.endswith("/") and path_segment != "":
-                self.path = self.path + "/"
-            path = self.service._abspath(
-                self.path + path_segment, owner=owner, app=app, sharing=sharing
-            )
-        # ^-- This was "%s%s" % (self.path, path_segment).
-        # That doesn't work, because self.path may be UrlEncoded.
-
-        # Get the API version from the path
-        api_version = self.get_api_version(path)
-
-        # Search API v2+ fallback to v1:
-        #   - In v2+, /results_preview, /events and /results do not support search params.
-        #   - Fallback from v2+ to v1 if Splunk Version is < 9.
-        # if api_version >= 2 and ('search' in query and path.endswith(tuple(["results_preview", "events", "results"])) or self.service.splunk_version < (9,)):
-        #     path = path.replace(PATH_JOBS_V2, PATH_JOBS)
-
-        if api_version == 1:
-            if isinstance(path, UrlEncoded):
-                path = UrlEncoded(
-                    path.replace(PATH_JOBS_V2, PATH_JOBS), skip_encode=True
-                )
-            else:
-                path = path.replace(PATH_JOBS_V2, PATH_JOBS)
-
-        return self.service.get(path, owner=owner, app=app, sharing=sharing, **query)
-
-    def post(self, path_segment="", owner=None, app=None, sharing=None, **query):
-        """Performs a POST operation on the path segment relative to this endpoint.
-
-        This method is named to match the HTTP method. This method makes at least
-        one roundtrip to the server, one additional round trip for
-        each 303 status returned, plus at most two additional round trips if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        If *owner*, *app*, and *sharing* are omitted, this method takes a
-        default namespace from the :class:`Service` object for this :class:`Endpoint`.
-        All other keyword arguments are included in the URL as query parameters.
-
-        :raises AuthenticationError: Raised when the ``Service`` is not logged in.
-        :raises HTTPError: Raised when an error in the request occurs.
-        :param path_segment: A path segment relative to this endpoint.
-        :type path_segment: ``string``
-        :param owner: The owner context of the namespace (optional).
-        :type owner: ``string``
-        :param app: The app context of the namespace (optional).
-        :type app: ``string``
-        :param sharing: The sharing mode of the namespace (optional).
-        :type sharing: ``string``
-        :param query: All other keyword arguments, which are used as query
-            parameters.
-        :type query: ``string``
-        :return: The response from the server.
-        :rtype: ``dict`` with keys ``body``, ``headers``, ``reason``,
-                and ``status``
-
-        **Example**::
-
-            import splunklib.client
-            s = client.service(...)
-            apps = s.apps
-            apps.post(name='boris') == \\
-                {'body': ...a response reader object...,
-                 'headers': [('content-length', '2908'),
-                             ('expires', 'Fri, 30 Oct 1998 00:00:00 GMT'),
-                             ('server', 'Splunkd'),
-                             ('connection', 'close'),
-                             ('cache-control', 'no-store, max-age=0, must-revalidate, no-cache'),
-                             ('date', 'Fri, 11 May 2012 18:34:50 GMT'),
-                             ('content-type', 'text/xml; charset=utf-8')],
-                 'reason': 'Created',
-                 'status': 201}
-            apps.get('nonexistant/path') # raises HTTPError
-            s.logout()
-            apps.get() # raises AuthenticationError
-        """
-        if path_segment.startswith("/"):
-            path = path_segment
-        else:
-            if not self.path.endswith("/") and path_segment != "":
-                self.path = self.path + "/"
-            path = self.service._abspath(
-                self.path + path_segment, owner=owner, app=app, sharing=sharing
-            )
-
-        # Get the API version from the path
-        api_version = self.get_api_version(path)
-
-        # Search API v2+ fallback to v1:
-        #   - In v2+, /results_preview, /events and /results do not support search params.
-        #   - Fallback from v2+ to v1 if Splunk Version is < 9.
-        # if api_version >= 2 and ('search' in query and path.endswith(tuple(["results_preview", "events", "results"])) or self.service.splunk_version < (9,)):
-        #     path = path.replace(PATH_JOBS_V2, PATH_JOBS)
-
-        if api_version == 1:
-            if isinstance(path, UrlEncoded):
-                path = UrlEncoded(
-                    path.replace(PATH_JOBS_V2, PATH_JOBS), skip_encode=True
-                )
-            else:
-                path = path.replace(PATH_JOBS_V2, PATH_JOBS)
-
-        return self.service.post(path, owner=owner, app=app, sharing=sharing, **query)
-
-
-# kwargs: path, app, owner, sharing, state
-class Entity(Endpoint):
-    """This class is a base class for Splunk entities in the REST API, such as
-    saved searches, jobs, indexes, and inputs.
-
-    ``Entity`` provides the majority of functionality required by entities.
-    Subclasses only implement the special cases for individual entities.
-    For example for saved searches, the subclass makes fields like ``action.email``,
-    ``alert_type``, and ``search`` available.
-
-    An ``Entity`` is addressed like a dictionary, with a few extensions,
-    so the following all work, for example in saved searches::
-
-        ent['action.email']
-        ent['alert_type']
-        ent['search']
-
-    You can also access the fields as though they were the fields of a Python
-    object, as in::
-
-        ent.alert_type
-        ent.search
-
-    However, because some of the field names are not valid Python identifiers,
-    the dictionary-like syntax is preferable.
-
-    The state of an :class:`Entity` object is cached, so accessing a field
-    does not contact the server. If you think the values on the
-    server have changed, call the :meth:`Entity.refresh` method.
-    """
-
-    # Not every endpoint in the API is an Entity or a Collection. For
-    # example, a saved search at saved/searches/{name} has an additional
-    # method saved/searches/{name}/scheduled_times, but this isn't an
-    # entity in its own right. In these cases, subclasses should
-    # implement a method that uses the get and post methods inherited
-    # from Endpoint, calls the _load_atom function (it's elsewhere in
-    # client.py, but not a method of any object) to read the
-    # information, and returns the extracted data in a Pythonesque form.
-    #
-    # The primary use of subclasses of Entity is to handle specially
-    # named fields in the Entity. If you only need to provide a default
-    # value for an optional field, subclass Entity and define a
-    # dictionary ``defaults``. For instance,::
-    #
-    #     class Hypothetical(Entity):
-    #         defaults = {'anOptionalField': 'foo',
-    #                     'anotherField': 'bar'}
-    #
-    # If you have to do more than provide a default, such as rename or
-    # actually process values, then define a new method with the
-    # ``@property`` decorator.
-    #
-    #     class Hypothetical(Entity):
-    #         @property
-    #         def foobar(self):
-    #             return self.content['foo'] + "-" + self.content["bar"]
-
-    # Subclasses can override defaults the default values for
-    # optional fields. See above.
-    defaults = {}
-
-    def __init__(self, service, path, **kwargs):
-        Endpoint.__init__(self, service, path)
-        self._state = None
-        if not kwargs.get("skip_refresh", False):
-            self.refresh(kwargs.get("state", None))  # "Prefresh"
-
-    def __contains__(self, item):
-        try:
-            self[item]
-            return True
-        except (KeyError, AttributeError):
-            return False
-
-    def __eq__(self, other):
-        """Raises IncomparableException.
-
-        Since Entity objects are snapshots of times on the server, no
-        simple definition of equality will suffice beyond instance
-        equality, and instance equality leads to strange situations
-        such as::
-
-            import splunklib.client as client
-            c = client.connect(...)
-            saved_searches = c.saved_searches
-            x = saved_searches['asearch']
-
-        but then ``x != saved_searches['asearch']``.
-
-        whether or not there was a change on the server. Rather than
-        try to do something fancy, we simply declare that equality is
-        undefined for Entities.
-
-        Makes no roundtrips to the server.
-        """
-        raise IncomparableException(
-            f"Equality is undefined for objects of class {self.__class__.__name__}"
-        )
-
-    def __getattr__(self, key):
-        # Called when an attribute was not found by the normal method. In this
-        # case we try to find it in self.content and then self.defaults.
-        if key in self.state.content:
-            return self.state.content[key]
-        if key in self.defaults:
-            return self.defaults[key]
-        raise AttributeError(key)
-
-    def __getitem__(self, key):
-        # getattr attempts to find a field on the object in the normal way,
-        # then calls __getattr__ if it cannot.
-        return getattr(self, key)
-
-    # Load the Atom entry record from the given response - this is a method
-    # because the "entry" record varies slightly by entity and this allows
-    # for a subclass to override and handle any special cases.
-    def _load_atom_entry(self, response):
-        elem = _load_atom(response, XNAME_ENTRY)
-        if isinstance(elem, list):
-            apps = [ele.entry.content.get("eai:appName") for ele in elem]
-
-            raise AmbiguousReferenceException(
-                f"Fetch from server returned multiple entries for name '{elem[0].entry.title}' in apps {apps}."
-            )
-        return elem.entry
-
-    # Load the entity state record from the given response
-    def _load_state(self, response):
-        entry = self._load_atom_entry(response)
-        return _parse_atom_entry(entry)
-
-    def _run_action(self, path_segment, **kwargs):
-        """Run a method and return the content Record from the returned XML.
-
-        A method is a relative path from an Entity that is not itself
-        an Entity. _run_action assumes that the returned XML is an
-        Atom field containing one Entry, and the contents of Entry is
-        what should be the return value. This is right in enough cases
-        to make this method useful.
-        """
-        response = self.get(path_segment, **kwargs)
-        data = self._load_atom_entry(response)
-        rec = _parse_atom_entry(data)
-        return rec.content
-
-    def _proper_namespace(self, owner=None, app=None, sharing=None):
-        """Produce a namespace sans wildcards for use in entity requests.
-
-        This method tries to fill in the fields of the namespace which are `None`
-        or wildcard (`'-'`) from the entity's namespace. If that fails, it uses
-        the service's namespace.
-
-        :param owner:
-        :param app:
-        :param sharing:
-        :return:
-        """
-        if owner is None and app is None and sharing is None:  # No namespace provided
-            if self._state is not None and "access" in self._state:
-                return (
-                    self._state.access.owner,
-                    self._state.access.app,
-                    self._state.access.sharing,
-                )
-            return (
-                self.service.namespace["owner"],
-                self.service.namespace["app"],
-                self.service.namespace["sharing"],
-            )
-        return owner, app, sharing
-
-    def delete(self):
-        owner, app, sharing = self._proper_namespace()
-        return self.service.delete(self.path, owner=owner, app=app, sharing=sharing)
-
-    def get(self, path_segment="", owner=None, app=None, sharing=None, **query):
-        owner, app, sharing = self._proper_namespace(owner, app, sharing)
-        return super().get(path_segment, owner=owner, app=app, sharing=sharing, **query)
-
-    def post(self, path_segment="", owner=None, app=None, sharing=None, **query):
-        owner, app, sharing = self._proper_namespace(owner, app, sharing)
-        return super().post(
-            path_segment, owner=owner, app=app, sharing=sharing, **query
-        )
-
-    def refresh(self, state=None):
-        """Refreshes the state of this entity.
-
-        If *state* is provided, load it as the new state for this
-        entity. Otherwise, make a roundtrip to the server (by calling
-        the :meth:`read` method of ``self``) to fetch an updated state,
-        plus at most two additional round trips if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        :param state: Entity-specific arguments (optional).
-        :type state: ``dict``
-        :raises EntityDeletedException: Raised if the entity no longer exists on
-            the server.
-
-        **Example**::
-
-            import splunklib.client as client
-            s = client.connect(...)
-            search = s.apps['search']
-            search.refresh()
-        """
-        if state is not None:
-            self._state = state
-        else:
-            self._state = self.read(self.get())
-        return self
-
-    @property
-    def access(self):
-        """Returns the access metadata for this entity.
-
-        :return: A :class:`splunklib.data.Record` object with three keys:
-            ``owner``, ``app``, and ``sharing``.
-        """
-        return self.state.access
-
-    @property
-    def content(self):
-        """Returns the contents of the entity.
-
-        :return: A ``dict`` containing values.
-        """
-        return self.state.content
-
-    def disable(self):
-        """Disables the entity at this endpoint."""
-        self.post("disable")
-        return self
-
-    def enable(self):
-        """Enables the entity at this endpoint."""
-        self.post("enable")
-        return self
-
-    @property
-    def fields(self):
-        """Returns the content metadata for this entity.
-
-        :return: A :class:`splunklib.data.Record` object with three keys:
-            ``required``, ``optional``, and ``wildcard``.
-        """
-        return self.state.fields
-
-    @property
-    def links(self):
-        """Returns a dictionary of related resources.
-
-        :return: A ``dict`` with keys and corresponding URLs.
-        """
-        return self.state.links
-
-    @property
-    def name(self):
-        """Returns the entity name.
-
-        :return: The entity name.
-        :rtype: ``string``
-        """
-        return self.state.title
-
-    def read(self, response):
-        """Reads the current state of the entity from the server."""
-        results = self._load_state(response)
-        # In lower layers of the SDK, we end up trying to URL encode
-        # text to be dispatched via HTTP. However, these links are already
-        # URL encoded when they arrive, and we need to mark them as such.
-        unquoted_links = dict(
-            (k, UrlEncoded(v, skip_encode=True)) for k, v in results["links"].items()
-        )
-        results["links"] = unquoted_links
-        return results
-
-    def reload(self):
-        """Reloads the entity."""
-        self.post("_reload")
-        return self
-
-    def acl_update(self, **kwargs):
-        """To update Access Control List (ACL) properties for an endpoint.
-
-        :param kwargs: Additional entity-specific arguments (required).
-
-            - "owner" (``string``): The Splunk username, such as "admin". A value of "nobody" means no specific user (required).
-
-            - "sharing" (``string``): A mode that indicates how the resource is shared. The sharing mode can be "user", "app", "global", or "system" (required).
-
-        :type kwargs: ``dict``
-
-        **Example**::
-
-            import splunklib.client as client
-            service = client.connect(...)
-            saved_search = service.saved_searches["name"]
-            saved_search.acl_update(sharing="app", owner="nobody", app="search", **{"perms.read": "admin, nobody"})
-        """
-        if "body" not in kwargs:
-            kwargs = {"body": kwargs}
-
-        if "sharing" not in kwargs["body"]:
-            raise ValueError("Required argument 'sharing' is missing.")
-        if "owner" not in kwargs["body"]:
-            raise ValueError("Required argument 'owner' is missing.")
-
-        self.post("acl", **kwargs)
-        self.refresh()
-        return self
-
-    @property
-    def state(self):
-        """Returns the entity's state record.
-
-        :return: A ``dict`` containing fields and metadata for the entity.
-        """
-        if self._state is None:
-            self.refresh()
-        return self._state
-
-    def update(self, **kwargs):
-        """Updates the server with any changes you've made to the current entity
-        along with any additional arguments you specify.
-
-            **Note**: You cannot update the ``name`` field of an entity.
-
-        Many of the fields in the REST API are not valid Python
-        identifiers, which means you cannot pass them as keyword
-        arguments. That is, Python will fail to parse the following::
-
-            # This fails
-            x.update(check-new=False, email.to='boris@utopia.net')
-
-        However, you can always explicitly use a dictionary to pass
-        such keys::
-
-            # This works
-            x.update(**{'check-new': False, 'email.to': 'boris@utopia.net'})
-
-        :param kwargs: Additional entity-specific arguments (optional).
-        :type kwargs: ``dict``
-
-        :return: The entity this method is called on.
-        :rtype: class:`Entity`
-        """
-        # The peculiarity in question: the REST API creates a new
-        # Entity if we pass name in the dictionary, instead of the
-        # expected behavior of updating this Entity. Therefore, we
-        # check for 'name' in kwargs and throw an error if it is
-        # there.
-        if "name" in kwargs:
-            raise IllegalOperationException(
-                "Cannot update the name of an Entity via the REST API."
-            )
-        self.post(**kwargs)
-        return self
-
-
-class ReadOnlyCollection(Endpoint):
-    """This class represents a read-only collection of entities in the Splunk
-    instance.
-    """
-
-    def __init__(self, service, path, item=Entity):
-        Endpoint.__init__(self, service, path)
-        self.item = item  # Item accessor
-        self.null_count = -1
-
-    def __contains__(self, name):
-        """Is there at least one entry called *name* in this collection?
-
-        Makes a single roundtrip to the server, plus at most two more
-        if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-        """
-        try:
-            self[name]
-            return True
-        except KeyError:
-            return False
-        except AmbiguousReferenceException:
-            return True
-
-    def __getitem__(self, key):
-        """Fetch an item named *key* from this collection.
-
-        A name is not a unique identifier in a collection. The unique
-        identifier is a name plus a namespace. For example, there can
-        be a saved search named ``'mysearch'`` with sharing ``'app'``
-        in application ``'search'``, and another with sharing
-        ``'user'`` with owner ``'boris'`` and application
-        ``'search'``. If the ``Collection`` is attached to a
-        ``Service`` that has ``'-'`` (wildcard) as user and app in its
-        namespace, then both of these may be visible under the same
-        name.
-
-        Where there is no conflict, ``__getitem__`` will fetch the
-        entity given just the name. If there is a conflict, and you
-        pass just a name, it will raise a ``ValueError``. In that
-        case, add the namespace as a second argument.
-
-        This function makes a single roundtrip to the server, plus at
-        most two additional round trips if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        :param key: The name to fetch, or a tuple (name, namespace).
-        :return: An :class:`Entity` object.
-        :raises KeyError: Raised if *key* does not exist.
-        :raises ValueError: Raised if no namespace is specified and *key*
-                            does not refer to a unique name.
-
-        **Example**::
-
-            s = client.connect(...)
-            saved_searches = s.saved_searches
-            x1 = saved_searches.create(
-                'mysearch', 'search * | head 1',
-                owner='admin', app='search', sharing='app')
-            x2 = saved_searches.create(
-                'mysearch', 'search * | head 1',
-                owner='admin', app='search', sharing='user')
-            # Raises ValueError:
-            saved_searches['mysearch']
-            # Fetches x1
-            saved_searches[
-                'mysearch',
-                client.namespace(sharing='app', app='search')]
-            # Fetches x2
-            saved_searches[
-                'mysearch',
-                client.namespace(sharing='user', owner='boris', app='search')]
-        """
-        try:
-            if isinstance(key, tuple) and len(key) == 2:
-                # x[a,b] is translated to x.__getitem__( (a,b) ), so we
-                # have to extract values out.
-                key, ns = key
-                key = UrlEncoded(key, encode_slash=True)
-                response = self.get(key, owner=ns.owner, app=ns.app)
-            else:
-                key = UrlEncoded(key, encode_slash=True)
-                response = self.get(key)
-            entries = self._load_list(response)
-            if len(entries) > 1:
-                raise AmbiguousReferenceException(
-                    f"Found multiple entities named '{key}'; please specify a namespace."
-                )
-            if len(entries) == 0:
-                raise KeyError(key)
-            return entries[0]
-        except HTTPError as he:
-            if he.status == 404:  # No entity matching key and namespace.
-                raise KeyError(key)
-            else:
-                raise
-
-    def __iter__(self, **kwargs):
-        """Iterate over the entities in the collection.
-
-        :param kwargs: Additional arguments.
-        :type kwargs: ``dict``
-        :rtype: iterator over entities.
-
-        Implemented to give Collection a listish interface. This
-        function always makes a roundtrip to the server, plus at most
-        two additional round trips if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        **Example**::
-
-            import splunklib.client as client
-            c = client.connect(...)
-            saved_searches = c.saved_searches
-            for entity in saved_searches:
-                print(f"Saved search named {entity.name}")
-        """
-
-        for item in self.iter(**kwargs):
-            yield item
-
-    def __len__(self):
-        """Enable ``len(...)`` for ``Collection`` objects.
-
-        Implemented for consistency with a listish interface. No
-        further failure modes beyond those possible for any method on
-        an Endpoint.
-
-        This function always makes a round trip to the server, plus at
-        most two additional round trips if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        **Example**::
-
-            import splunklib.client as client
-            c = client.connect(...)
-            saved_searches = c.saved_searches
-            n = len(saved_searches)
-        """
-        return len(self.list())
-
-    def _entity_path(self, state):
-        """Calculate the path to an entity to be returned.
-
-        *state* should be the dictionary returned by
-        :func:`_parse_atom_entry`. :func:`_entity_path` extracts the
-        link to this entity from *state*, and strips all the namespace
-        prefixes from it to leave only the relative path of the entity
-        itself, sans namespace.
-
-        :rtype: ``string``
-        :return: an absolute path
-        """
-        # This has been factored out so that it can be easily
-        # overloaded by Configurations, which has to switch its
-        # entities' endpoints from its own properties/ to configs/.
-        raw_path = parse.unquote(state.links.alternate)
-        if "servicesNS/" in raw_path:
-            return _trailing(raw_path, "servicesNS/", "/", "/")
-        if "services/" in raw_path:
-            return _trailing(raw_path, "services/")
-        return raw_path
-
-    def _load_list(self, response):
-        """Converts *response* to a list of entities.
-
-        *response* is assumed to be a :class:`Record` containing an
-        HTTP response, of the form::
-
-            {'status': 200,
-             'headers': [('content-length', '232642'),
-                         ('expires', 'Fri, 30 Oct 1998 00:00:00 GMT'),
-                         ('server', 'Splunkd'),
-                         ('connection', 'close'),
-                         ('cache-control', 'no-store, max-age=0, must-revalidate, no-cache'),
-                         ('date', 'Tue, 29 May 2012 15:27:08 GMT'),
-                         ('content-type', 'text/xml; charset=utf-8')],
-             'reason': 'OK',
-             'body': ...a stream implementing .read()...}
-
-        The ``'body'`` key refers to a stream containing an Atom feed,
-        that is, an XML document with a toplevel element ````,
-        and within that element one or more ```` elements.
-        """
-        # Some subclasses of Collection have to override this because
-        # splunkd returns something that doesn't match
-        # .
-        entries = _load_atom_entries(response)
-        if entries is None:
-            return []
-        entities = []
-        for entry in entries:
-            state = _parse_atom_entry(entry)
-            entity = self.item(self.service, self._entity_path(state), state=state)
-            entities.append(entity)
-
-        return entities
-
-    def itemmeta(self):
-        """Returns metadata for members of the collection.
-
-        Makes a single roundtrip to the server, plus two more at most if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        :return: A :class:`splunklib.data.Record` object containing the metadata.
-
-        **Example**::
-
-            import splunklib.client as client
-            import pprint
-            s = client.connect(...)
-            pprint.pprint(s.apps.itemmeta())
-            {'access': {'app': 'search',
-                                    'can_change_perms': '1',
-                                    'can_list': '1',
-                                    'can_share_app': '1',
-                                    'can_share_global': '1',
-                                    'can_share_user': '1',
-                                    'can_write': '1',
-                                    'modifiable': '1',
-                                    'owner': 'admin',
-                                    'perms': {'read': ['*'], 'write': ['admin']},
-                                    'removable': '0',
-                                    'sharing': 'user'},
-             'fields': {'optional': ['author',
-                                        'configured',
-                                        'description',
-                                        'label',
-                                        'manageable',
-                                        'template',
-                                        'visible'],
-                                        'required': ['name'], 'wildcard': []}}
-        """
-        response = self.get("_new")
-        content = _load_atom(response, MATCH_ENTRY_CONTENT)
-        return _parse_atom_metadata(content)
-
-    def iter(self, offset=0, count=None, pagesize=None, **kwargs):
-        """Iterates over the collection.
-
-        This method is equivalent to the :meth:`list` method, but
-        it returns an iterator and can load a certain number of entities at a
-        time from the server.
-
-        :param offset: The index of the first entity to return (optional).
-        :type offset: ``integer``
-        :param count: The maximum number of entities to return (optional).
-        :type count: ``integer``
-        :param pagesize: The number of entities to load (optional).
-        :type pagesize: ``integer``
-        :param kwargs: Additional arguments (optional):
-
-            - "search" (``string``): The search query to filter responses.
-
-            - "sort_dir" (``string``): The direction to sort returned items:
-              "asc" or "desc".
-
-            - "sort_key" (``string``): The field to use for sorting (optional).
-
-            - "sort_mode" (``string``): The collating sequence for sorting
-              returned items: "auto", "alpha", "alpha_case", or "num".
-
-        :type kwargs: ``dict``
-
-        **Example**::
-
-            import splunklib.client as client
-            s = client.connect(...)
-            for saved_search in s.saved_searches.iter(pagesize=10):
-                # Loads 10 saved searches at a time from the
-                # server.
-                ...
-        """
-        assert pagesize is None or pagesize > 0
-        if count is None:
-            count = self.null_count
-        fetched = 0
-        while count == self.null_count or fetched < count:
-            response = self.get(count=pagesize or count, offset=offset, **kwargs)
-            items = self._load_list(response)
-            N = len(items)
-            fetched += N
-            for item in items:
-                yield item
-            if pagesize is None or N < pagesize:
-                break
-            offset += N
-            logger.debug(
-                "pagesize=%d, fetched=%d, offset=%d, N=%d, kwargs=%s",
-                pagesize,
-                fetched,
-                offset,
-                N,
-                kwargs,
-            )
-
-    # kwargs: count, offset, search, sort_dir, sort_key, sort_mode
-    def list(self, count=None, **kwargs):
-        """Retrieves a list of entities in this collection.
-
-        The entire collection is loaded at once and is returned as a list. This
-        function makes a single roundtrip to the server, plus at most two more if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-        There is no caching--every call makes at least one round trip.
-
-        :param count: The maximum number of entities to return (optional).
-        :type count: ``integer``
-        :param kwargs: Additional arguments (optional):
-
-            - "offset" (``integer``): The offset of the first item to return.
-
-            - "search" (``string``): The search query to filter responses.
-
-            - "sort_dir" (``string``): The direction to sort returned items:
-              "asc" or "desc".
-
-            - "sort_key" (``string``): The field to use for sorting (optional).
-
-            - "sort_mode" (``string``): The collating sequence for sorting
-              returned items: "auto", "alpha", "alpha_case", or "num".
-
-        :type kwargs: ``dict``
-        :return: A ``list`` of entities.
-        """
-        # response = self.get(count=count, **kwargs)
-        # return self._load_list(response)
-        return list(self.iter(count=count, **kwargs))
-
-
-class Collection(ReadOnlyCollection):
-    """A collection of entities.
-
-    Splunk provides a number of different collections of distinct
-    entity types: applications, saved searches, fired alerts, and a
-    number of others. Each particular type is available separately
-    from the Splunk instance, and the entities of that type are
-    returned in a :class:`Collection`.
-
-    The interface for :class:`Collection` does not quite match either
-    ``list`` or ``dict`` in Python, because there are enough semantic
-    mismatches with either to make its behavior surprising. A unique
-    element in a :class:`Collection` is defined by a string giving its
-    name plus namespace (although the namespace is optional if the name is
-    unique).
-
-    **Example**::
-
-        import splunklib.client as client
-        service = client.connect(...)
-        mycollection = service.saved_searches
-        mysearch = mycollection['my_search', client.namespace(owner='boris', app='natasha', sharing='user')]
-        # Or if there is only one search visible named 'my_search'
-        mysearch = mycollection['my_search']
-
-    Similarly, ``name`` in ``mycollection`` works as you might expect (though
-    you cannot currently pass a namespace to the ``in`` operator), as does
-    ``len(mycollection)``.
-
-    However, as an aggregate, :class:`Collection` behaves more like a
-    list. If you iterate over a :class:`Collection`, you get an
-    iterator over the entities, not the names and namespaces.
-
-    **Example**::
-
-        for entity in mycollection:
-            assert isinstance(entity, client.Entity)
-
-    Use the :meth:`create` and :meth:`delete` methods to create and delete
-    entities in this collection. To view the access control list and other
-    metadata of the collection, use the :meth:`ReadOnlyCollection.itemmeta` method.
-
-    :class:`Collection` does no caching. Each call makes at least one
-    round trip to the server to fetch data.
-    """
-
-    def create(self, name, **params):
-        """Creates a new entity in this collection.
-
-        This function makes either one or two roundtrips to the
-        server, depending on the type of entities in this
-        collection, plus at most two more if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        :param name: The name of the entity to create.
-        :type name: ``string``
-        :param namespace: A namespace, as created by the :func:`splunklib.binding.namespace`
-            function (optional).  You can also set ``owner``, ``app``, and
-            ``sharing`` in ``params``.
-        :type namespace: A :class:`splunklib.data.Record` object with keys ``owner``, ``app``,
-            and ``sharing``.
-        :param params: Additional entity-specific arguments (optional).
-        :type params: ``dict``
-        :return: The new entity.
-        :rtype: A subclass of :class:`Entity`, chosen by :meth:`Collection.self.item`.
-
-        **Example**::
-
-            import splunklib.client as client
-            s = client.connect(...)
-            applications = s.apps
-            new_app = applications.create("my_fake_app")
-        """
-        if not isinstance(name, str):
-            raise InvalidNameException(f"{name} is not a valid name for an entity.")
-        if "namespace" in params:
-            namespace = params.pop("namespace")
-            params["owner"] = namespace.owner
-            params["app"] = namespace.app
-            params["sharing"] = namespace.sharing
-        response = self.post(name=name, **params)
-        atom = _load_atom(response, XNAME_ENTRY)
-        if atom is None:
-            # This endpoint doesn't return the content of the new
-            # item. We have to go fetch it ourselves.
-            return self[name]
-        entry = atom.entry
-        state = _parse_atom_entry(entry)
-        entity = self.item(self.service, self._entity_path(state), state=state)
-        return entity
-
-    def delete(self, name, **params):
-        """Deletes a specified entity from the collection.
-
-        :param name: The name of the entity to delete.
-        :type name: ``string``
-        :return: The collection.
-        :rtype: ``self``
-
-        This method is implemented for consistency with the REST API's DELETE
-        method.
-
-        If there is no *name* entity on the server, a ``KeyError`` is
-        thrown. This function always makes a roundtrip to the server.
-
-        **Example**::
-
-            import splunklib.client as client
-            c = client.connect(...)
-            saved_searches = c.saved_searches
-            saved_searches.create('my_saved_search',
-                                  'search * | head 1')
-            assert 'my_saved_search' in saved_searches
-            saved_searches.delete('my_saved_search')
-            assert 'my_saved_search' not in saved_searches
-        """
-        name = UrlEncoded(name, encode_slash=True)
-        if "namespace" in params:
-            namespace = params.pop("namespace")
-            params["owner"] = namespace.owner
-            params["app"] = namespace.app
-            params["sharing"] = namespace.sharing
-        try:
-            self.service.delete(_path(self.path, name), **params)
-        except HTTPError as he:
-            # An HTTPError with status code 404 means that the entity
-            # has already been deleted, and we reraise it as a
-            # KeyError.
-            if he.status == 404:
-                raise KeyError(f"No such entity {name}")
-            else:
-                raise
-        return self
-
-    def get(self, name="", owner=None, app=None, sharing=None, **query):
-        """Performs a GET request to the server on the collection.
-
-        If *owner*, *app*, and *sharing* are omitted, this method takes a
-        default namespace from the :class:`Service` object for this :class:`Endpoint`.
-        All other keyword arguments are included in the URL as query parameters.
-
-        :raises AuthenticationError: Raised when the ``Service`` is not logged in.
-        :raises HTTPError: Raised when an error in the request occurs.
-        :param path_segment: A path segment relative to this endpoint.
-        :type path_segment: ``string``
-        :param owner: The owner context of the namespace (optional).
-        :type owner: ``string``
-        :param app: The app context of the namespace (optional).
-        :type app: ``string``
-        :param sharing: The sharing mode for the namespace (optional).
-        :type sharing: "global", "system", "app", or "user"
-        :param query: All other keyword arguments, which are used as query
-            parameters.
-        :type query: ``string``
-        :return: The response from the server.
-        :rtype: ``dict`` with keys ``body``, ``headers``, ``reason``,
-                and ``status``
-
-        **Example**::
-
-            import splunklib.client
-            s = client.service(...)
-            saved_searches = s.saved_searches
-            saved_searches.get("my/saved/search") == \\
-                {'body': ...a response reader object...,
-                 'headers': [('content-length', '26208'),
-                             ('expires', 'Fri, 30 Oct 1998 00:00:00 GMT'),
-                             ('server', 'Splunkd'),
-                             ('connection', 'close'),
-                             ('cache-control', 'no-store, max-age=0, must-revalidate, no-cache'),
-                             ('date', 'Fri, 11 May 2012 16:30:35 GMT'),
-                             ('content-type', 'text/xml; charset=utf-8')],
-                 'reason': 'OK',
-                 'status': 200}
-            saved_searches.get('nonexistant/search') # raises HTTPError
-            s.logout()
-            saved_searches.get() # raises AuthenticationError
-
-        """
-        name = UrlEncoded(name, encode_slash=True)
-        return super().get(name, owner, app, sharing, **query)
-
-
-class ConfigurationFile(Collection):
-    """This class contains all of the stanzas from one configuration file."""
-
-    # __init__'s arguments must match those of an Entity, not a
-    # Collection, since it is being created as the elements of a
-    # Configurations, which is a Collection subclass.
-    def __init__(self, service, path, **kwargs):
-        Collection.__init__(self, service, path, item=Stanza)
-        self.name = kwargs["state"]["title"]
-
-
-class Configurations(Collection):
-    """This class provides access to the configuration files from this Splunk
-    instance. Retrieve this collection using :meth:`Service.confs`.
-
-    Splunk's configuration is divided into files, and each file into
-    stanzas. This collection is unusual in that the values in it are
-    themselves collections of :class:`ConfigurationFile` objects.
-    """
-
-    def __init__(self, service):
-        Collection.__init__(self, service, PATH_PROPERTIES, item=ConfigurationFile)
-        if self.service.namespace.owner == "-" or self.service.namespace.app == "-":
-            raise ValueError("Configurations cannot have wildcards in namespace.")
-
-    def __getitem__(self, key):
-        # The superclass implementation is designed for collections that contain
-        # entities. This collection (Configurations) contains collections
-        # (ConfigurationFile).
-        #
-        # The configurations endpoint returns multiple entities when we ask for a single file.
-        # This screws up the default implementation of __getitem__ from Collection, which thinks
-        # that multiple entities means a name collision, so we have to override it here.
-        try:
-            self.get(key)
-            return ConfigurationFile(
-                self.service, PATH_CONF % key, state={"title": key}
-            )
-        except HTTPError as he:
-            if he.status == 404:  # No entity matching key
-                raise KeyError(key)
-            else:
-                raise
-
-    def __contains__(self, key):
-        # configs/conf-{name} never returns a 404. We have to post to properties/{name}
-        # in order to find out if a configuration exists.
-        try:
-            self.get(key)
-            return True
-        except HTTPError as he:
-            if he.status == 404:  # No entity matching key
-                return False
-            raise
-
-    def create(self, name):
-        """Creates a configuration file named *name*.
-
-        If there is already a configuration file with that name,
-        the existing file is returned.
-
-        :param name: The name of the configuration file.
-        :type name: ``string``
-
-        :return: The :class:`ConfigurationFile` object.
-        """
-        # This has to be overridden to handle the plumbing of creating
-        # a ConfigurationFile (which is a Collection) instead of some
-        # Entity.
-        if not isinstance(name, str):
-            raise ValueError(f"Invalid name: {repr(name)}")
-        response = self.post(__conf=name)
-        if response.status == 303:
-            return self[name]
-        if response.status == 201:
-            return ConfigurationFile(
-                self.service, PATH_CONF % name, item=Stanza, state={"title": name}
-            )
-        raise ValueError(
-            f"Unexpected status code {response.status} returned from creating a stanza"
-        )
-
-    def delete(self, key):
-        """Raises `IllegalOperationException`."""
-        raise IllegalOperationException(
-            "Cannot delete configuration files from the REST API."
-        )
-
-    def _entity_path(self, state):
-        # Overridden to make all the ConfigurationFile objects
-        # returned refer to the configs/ path instead of the
-        # properties/ path used by Configrations.
-        return PATH_CONF % state["title"]
-
-
-class Stanza(Entity):
-    """This class contains a single configuration stanza."""
-
-    def submit(self, stanza):
-        """Adds keys to the current configuration stanza as a
-        dictionary of key-value pairs.
-
-        :param stanza: A dictionary of key-value pairs for the stanza.
-        :type stanza: ``dict``
-        :return: The :class:`Stanza` object.
-        """
-        body = _encode(**stanza)
-        self.service.post(self.path, body=body)
-        return self
-
-    def __len__(self):
-        # The stanza endpoint returns all the keys at the same level in the XML as the eai information
-        # and 'disabled', so to get an accurate length, we have to filter those out and have just
-        # the stanza keys.
-        return len(
-            [
-                x
-                for x in self._state.content.keys()
-                if not x.startswith("eai") and x != "disabled"
-            ]
-        )
-
-
-class StoragePassword(Entity):
-    """This class contains a storage password."""
-
-    def __init__(self, service, path, **kwargs):
-        state = kwargs.get("state", None)
-        kwargs["skip_refresh"] = kwargs.get("skip_refresh", state is not None)
-        super().__init__(service, path, **kwargs)
-        self._state = state
-
-    @property
-    def clear_password(self):
-        return self.content.get("clear_password")
-
-    @property
-    def encrypted_password(self):
-        return self.content.get("encr_password")
-
-    @property
-    def realm(self):
-        return self.content.get("realm")
-
-    @property
-    def username(self):
-        return self.content.get("username")
-
-
-class StoragePasswords(Collection):
-    """This class provides access to the storage passwords from this Splunk
-    instance. Retrieve this collection using :meth:`Service.storage_passwords`.
-    """
-
-    def __init__(self, service):
-        if service.namespace.owner == "-" or service.namespace.app == "-":
-            raise ValueError("StoragePasswords cannot have wildcards in namespace.")
-        super().__init__(service, PATH_STORAGE_PASSWORDS, item=StoragePassword)
-
-    def create(self, password, username, realm=None):
-        """Creates a storage password.
-
-        A `StoragePassword` can be identified by , or by : if the
-        optional realm parameter is also provided.
-
-        :param password: The password for the credentials - this is the only part of the credentials that will be stored securely.
-        :type name: ``string``
-        :param username: The username for the credentials.
-        :type name: ``string``
-        :param realm: The credential realm. (optional)
-        :type name: ``string``
-
-        :return: The :class:`StoragePassword` object created.
-        """
-        if not isinstance(username, str):
-            raise ValueError(f"Invalid name: {repr(username)}")
-
-        if realm is None:
-            response = self.post(password=password, name=username)
-        else:
-            response = self.post(password=password, realm=realm, name=username)
-
-        if response.status != 201:
-            raise ValueError(
-                f"Unexpected status code {response.status} returned from creating a stanza"
-            )
-
-        entries = _load_atom_entries(response)
-        state = _parse_atom_entry(entries[0])
-        storage_password = StoragePassword(
-            self.service, self._entity_path(state), state=state, skip_refresh=True
-        )
-
-        return storage_password
-
-    def delete(self, username, realm=None):
-        """Delete a storage password by username and/or realm.
-
-        The identifier can be passed in through the username parameter as
-         or :, but the preferred way is by
-        passing in the username and realm parameters.
-
-        :param username: The username for the credentials, or : if the realm parameter is omitted.
-        :type name: ``string``
-        :param realm: The credential realm. (optional)
-        :type name: ``string``
-        :return: The `StoragePassword` collection.
-        :rtype: ``self``
-        """
-        if realm is None:
-            # This case makes the username optional, so
-            # the full name can be passed in as realm.
-            # Assume it's already encoded.
-            name = username
-        else:
-            # Encode each component separately
-            name = (
-                UrlEncoded(realm, encode_slash=True)
-                + ":"
-                + UrlEncoded(username, encode_slash=True)
-            )
-
-        # Append the : expected at the end of the name
-        if name[-1] != ":":
-            name = name + ":"
-        return Collection.delete(self, name)
-
-
-class AlertGroup(Entity):
-    """This class represents a group of fired alerts for a saved search. Access
-    it using the :meth:`alerts` property."""
-
-    def __init__(self, service, path, **kwargs):
-        Entity.__init__(self, service, path, **kwargs)
-
-    def __len__(self):
-        return self.count
-
-    @property
-    def alerts(self):
-        """Returns a collection of triggered alerts.
-
-        :return: A :class:`Collection` of triggered alerts.
-        """
-        return Collection(self.service, self.path)
-
-    @property
-    def count(self):
-        """Returns the count of triggered alerts.
-
-        :return: The triggered alert count.
-        :rtype: ``integer``
-        """
-        return int(self.content.get("triggered_alert_count", 0))
-
-
-class Indexes(Collection):
-    """This class contains the collection of indexes in this Splunk instance.
-    Retrieve this collection using :meth:`Service.indexes`.
-    """
-
-    def get_default(self):
-        """Returns the name of the default index.
-
-        :return: The name of the default index.
-
-        """
-        index = self["_audit"]
-        return index["defaultDatabase"]
-
-    def delete(self, name):
-        """Deletes a given index.
-
-        **Note**: This method is only supported in Splunk 5.0 and later.
-
-        :param name: The name of the index to delete.
-        :type name: ``string``
-        """
-        if self.service.splunk_version >= (5,):
-            Collection.delete(self, name)
-        else:
-            raise IllegalOperationException(
-                "Deleting indexes via the REST API is "
-                "not supported before Splunk version 5."
-            )
-
-
-class Index(Entity):
-    """This class represents an index and provides different operations, such as
-    cleaning the index, writing to the index, and so forth."""
-
-    def __init__(self, service, path, **kwargs):
-        Entity.__init__(self, service, path, **kwargs)
-
-    def attach(self, host=None, source=None, sourcetype=None):
-        """Opens a stream (a writable socket) for writing events to the index.
-
-        :param host: The host value for events written to the stream.
-        :type host: ``string``
-        :param source: The source value for events written to the stream.
-        :type source: ``string``
-        :param sourcetype: The sourcetype value for events written to the
-            stream.
-        :type sourcetype: ``string``
-
-        :return: A writable socket.
-        """
-        args = {"index": self.name}
-        if host is not None:
-            args["host"] = host
-        if source is not None:
-            args["source"] = source
-        if sourcetype is not None:
-            args["sourcetype"] = sourcetype
-        path = UrlEncoded(
-            PATH_RECEIVERS_STREAM + "?" + parse.urlencode(args), skip_encode=True
-        )
-
-        cookie_header = (
-            self.service.token
-            if self.service.token is _NoAuthenticationToken
-            else self.service.token.replace("Splunk ", "")
-        )
-        cookie_or_auth_header = f"Authorization: Splunk {cookie_header}\r\n"
-
-        # If we have cookie(s), use them instead of "Authorization: ..."
-        if self.service.has_cookies():
-            cookie_header = _make_cookie_header(self.service.get_cookies().items())
-            cookie_or_auth_header = f"Cookie: {cookie_header}\r\n"
-
-        # Since we need to stream to the index connection, we have to keep
-        # the connection open and use the Splunk extension headers to note
-        # the input mode
-        sock = self.service.connect()
-        headers = [
-            f"POST {str(self.service._abspath(path))} HTTP/1.1\r\n".encode("utf-8"),
-            f"Host: {self.service.host}:{int(self.service.port)}\r\n".encode("utf-8"),
-            b"Accept-Encoding: identity\r\n",
-            cookie_or_auth_header.encode("utf-8"),
-            b"X-Splunk-Input-Mode: Streaming\r\n",
-            b"\r\n",
-        ]
-
-        for h in headers:
-            sock.write(h)
-        return sock
-
-    @contextlib.contextmanager
-    def attached_socket(self, *args, **kwargs):
-        """Opens a raw socket in a ``with`` block to write data to Splunk.
-
-        The arguments are identical to those for :meth:`attach`. The socket is
-        automatically closed at the end of the ``with`` block, even if an
-        exception is raised in the block.
-
-        :param host: The host value for events written to the stream.
-        :type host: ``string``
-        :param source: The source value for events written to the stream.
-        :type source: ``string``
-        :param sourcetype: The sourcetype value for events written to the
-            stream.
-        :type sourcetype: ``string``
-
-        :returns: Nothing.
-
-        **Example**::
-
-            import splunklib.client as client
-            s = client.connect(...)
-            index = s.indexes['some_index']
-            with index.attached_socket(sourcetype='test') as sock:
-                sock.send('Test event\\r\\n')
-
-        """
-        try:
-            sock = self.attach(*args, **kwargs)
-            yield sock
-        finally:
-            sock.shutdown(socket.SHUT_RDWR)
-            sock.close()
-
-    def clean(self, timeout=60):
-        """Deletes the contents of the index.
-
-        This method blocks until the index is empty, because it needs to restore
-        values at the end of the operation.
-
-        :param timeout: The time-out period for the operation, in seconds (the
-            default is 60).
-        :type timeout: ``integer``
-
-        :return: The :class:`Index`.
-        """
-        self.refresh()
-
-        tds = self["maxTotalDataSizeMB"]
-        ftp = self["frozenTimePeriodInSecs"]
-        was_disabled_initially = self.disabled
-        try:
-            if not was_disabled_initially and self.service.splunk_version < (5,):
-                # Need to disable the index first on Splunk 4.x,
-                # but it doesn't work to disable it on 5.0.
-                self.disable()
-            self.update(maxTotalDataSizeMB=1, frozenTimePeriodInSecs=1)
-            self.roll_hot_buckets()
-
-            # Wait until event count goes to 0.
-            start = datetime.now()
-            diff = timedelta(seconds=timeout)
-            while self.content.totalEventCount != "0" and datetime.now() < start + diff:
-                sleep(1)
-                self.refresh()
-
-            if self.content.totalEventCount != "0":
-                raise OperationError(
-                    f"Cleaning index {self.name} took longer than {timeout} seconds; timing out."
-                )
-        finally:
-            # Restore original values
-            self.update(maxTotalDataSizeMB=tds, frozenTimePeriodInSecs=ftp)
-            if not was_disabled_initially and self.service.splunk_version < (5,):
-                # Re-enable the index if it was originally enabled and we messed with it.
-                self.enable()
-
-        return self
-
-    def roll_hot_buckets(self):
-        """Performs rolling hot buckets for this index.
-
-        :return: The :class:`Index`.
-        """
-        self.post("roll-hot-buckets")
-        return self
-
-    def submit(self, event, host=None, source=None, sourcetype=None):
-        """Submits a single event to the index using ``HTTP POST``.
-
-        :param event: The event to submit.
-        :type event: ``string``
-        :param `host`: The host value of the event.
-        :type host: ``string``
-        :param `source`: The source value of the event.
-        :type source: ``string``
-        :param `sourcetype`: The sourcetype value of the event.
-        :type sourcetype: ``string``
-
-        :return: The :class:`Index`.
-        """
-        args = {"index": self.name}
-        if host is not None:
-            args["host"] = host
-        if source is not None:
-            args["source"] = source
-        if sourcetype is not None:
-            args["sourcetype"] = sourcetype
-
-        self.service.post(PATH_RECEIVERS_SIMPLE, body=event, **args)
-        return self
-
-    # kwargs: host, host_regex, host_segment, rename-source, sourcetype
-    def upload(self, filename, **kwargs):
-        """Uploads a file for immediate indexing.
-
-        **Note**: The file must be locally accessible from the server.
-
-        :param filename: The name of the file to upload. The file can be a
-            plain, compressed, or archived file.
-        :type filename: ``string``
-        :param kwargs: Additional arguments (optional). For more about the
-            available parameters, see `Index parameters `_ on Splunk Developer Portal.
-        :type kwargs: ``dict``
-
-        :return: The :class:`Index`.
-        """
-        kwargs["index"] = self.name
-        path = "data/inputs/oneshot"
-        self.service.post(path, name=filename, **kwargs)
-        return self
-
-
-class Input(Entity):
-    """This class represents a Splunk input. This class is the base for all
-    typed input classes and is also used when the client does not recognize an
-    input kind.
-    """
-
-    def __init__(self, service, path, kind=None, **kwargs):
-        # kind can be omitted (in which case it is inferred from the path)
-        # Otherwise, valid values are the paths from data/inputs ("udp",
-        # "monitor", "tcp/raw"), or two special cases: "tcp" (which is "tcp/raw")
-        # and "splunktcp" (which is "tcp/cooked").
-        Entity.__init__(self, service, path, **kwargs)
-        if kind is None:
-            path_segments = path.split("/")
-            i = path_segments.index("inputs") + 1
-            if path_segments[i] == "tcp":
-                self.kind = path_segments[i] + "/" + path_segments[i + 1]
-            else:
-                self.kind = path_segments[i]
-        else:
-            self.kind = kind
-
-        # Handle old input kind names.
-        if self.kind == "tcp":
-            self.kind = "tcp/raw"
-        if self.kind == "splunktcp":
-            self.kind = "tcp/cooked"
-
-    def update(self, **kwargs):
-        """Updates the server with any changes you've made to the current input
-        along with any additional arguments you specify.
-
-        :param kwargs: Additional arguments (optional). For more about the
-            available parameters, see `Input parameters `_ on Splunk Developer Portal.
-        :type kwargs: ``dict``
-
-        :return: The input this method was called on.
-        :rtype: class:`Input`
-        """
-        # UDP and TCP inputs require special handling due to their restrictToHost
-        # field. For all other inputs kinds, we can dispatch to the superclass method.
-        if self.kind not in ["tcp", "splunktcp", "tcp/raw", "tcp/cooked", "udp"]:
-            return super().update(**kwargs)
-        else:
-            # The behavior of restrictToHost is inconsistent across input kinds and versions of Splunk.
-            # In Splunk 4.x, the name of the entity is only the port, independent of the value of
-            # restrictToHost. In Splunk 5.0 this changed so the name will be of the form :.
-            # In 5.0 and 5.0.1, if you don't supply the restrictToHost value on every update, it will
-            # remove the host restriction from the input. As of 5.0.2 you simply can't change restrictToHost
-            # on an existing input.
-
-            # The logic to handle all these cases:
-            # - Throw an exception if the user tries to set restrictToHost on an existing input
-            #   for *any* version of Splunk.
-            # - Set the existing restrictToHost value on the update args internally so we don't
-            #   cause it to change in Splunk 5.0 and 5.0.1.
-            to_update = kwargs.copy()
-
-            if "restrictToHost" in kwargs:
-                raise IllegalOperationException(
-                    "Cannot set restrictToHost on an existing input with the SDK."
-                )
-            if "restrictToHost" in self._state.content and self.kind != "udp":
-                to_update["restrictToHost"] = self._state.content["restrictToHost"]
-
-            # Do the actual update operation.
-            return super().update(**to_update)
-
-
-# Inputs is a "kinded" collection, which is a heterogenous collection where
-# each item is tagged with a kind, that provides a single merged view of all
-# input kinds.
-class Inputs(Collection):
-    """This class represents a collection of inputs. The collection is
-    heterogeneous and each member of the collection contains a *kind* property
-    that indicates the specific type of input.
-    Retrieve this collection using :meth:`Service.inputs`."""
-
-    def __init__(self, service, kindmap=None):
-        Collection.__init__(self, service, PATH_INPUTS, item=Input)
-
-    def __getitem__(self, key):
-        # The key needed to retrieve the input needs it's parenthesis to be URL encoded
-        # based on the REST API for input
-        # 
-        if isinstance(key, tuple) and len(key) == 2:
-            # Fetch a single kind
-            key, kind = key
-            key = UrlEncoded(key, encode_slash=True)
-            try:
-                response = self.get(self.kindpath(kind) + "/" + key)
-                entries = self._load_list(response)
-                if len(entries) > 1:
-                    raise AmbiguousReferenceException(
-                        f"Found multiple inputs of kind {kind} named {key}."
-                    )
-                if len(entries) == 0:
-                    raise KeyError((key, kind))
-                return entries[0]
-            except HTTPError as he:
-                if he.status == 404:  # No entity matching kind and key
-                    raise KeyError((key, kind))
-                else:
-                    raise
-        else:
-            # Iterate over all the kinds looking for matches.
-            kind = None
-            candidate = None
-            key = UrlEncoded(key, encode_slash=True)
-            for kind in self.kinds:
-                try:
-                    response = self.get(kind + "/" + key)
-                    entries = self._load_list(response)
-                    if len(entries) > 1:
-                        raise AmbiguousReferenceException(
-                            f"Found multiple inputs of kind {kind} named {key}."
-                        )
-                    if len(entries) == 0:
-                        pass
-                    else:
-                        if (
-                            candidate is not None
-                        ):  # Already found at least one candidate
-                            raise AmbiguousReferenceException(
-                                f"Found multiple inputs named {key}, please specify a kind"
-                            )
-                        candidate = entries[0]
-                except HTTPError as he:
-                    if he.status == 404:
-                        pass  # Just carry on to the next kind.
-                    else:
-                        raise
-            if candidate is None:
-                raise KeyError(key)  # Never found a match.
-            return candidate
-
-    def __contains__(self, key):
-        if isinstance(key, tuple) and len(key) == 2:
-            # If we specify a kind, this will shortcut properly
-            try:
-                self.__getitem__(key)
-                return True
-            except KeyError:
-                return False
-        else:
-            # Without a kind, we want to minimize the number of round trips to the server, so we
-            # reimplement some of the behavior of __getitem__ in order to be able to stop searching
-            # on the first hit.
-            for kind in self.kinds:
-                try:
-                    response = self.get(self.kindpath(kind) + "/" + key)
-                    entries = self._load_list(response)
-                    if len(entries) > 0:
-                        return True
-                except HTTPError as he:
-                    if he.status == 404:
-                        pass  # Just carry on to the next kind.
-                    else:
-                        raise
-            return False
-
-    def create(self, name, kind, **kwargs):
-        """Creates an input of a specific kind in this collection, with any
-        arguments you specify.
-
-        :param `name`: The input name.
-        :type name: ``string``
-        :param `kind`: The kind of input:
-
-            - "ad": Active Directory
-
-            - "monitor": Files and directories
-
-            - "registry": Windows Registry
-
-            - "script": Scripts
-
-            - "splunktcp": TCP, processed
-
-            - "tcp": TCP, unprocessed
-
-            - "udp": UDP
-
-            - "win-event-log-collections": Windows event log
-
-            - "win-perfmon": Performance monitoring
-
-            - "win-wmi-collections": WMI
-
-        :type kind: ``string``
-        :param `kwargs`: Additional arguments (optional). For more about the
-            available parameters, see `Input parameters `_ on Splunk Developer Portal.
-
-        :type kwargs: ``dict``
-
-        :return: The new :class:`Input`.
-        """
-        kindpath = self.kindpath(kind)
-        self.post(kindpath, name=name, **kwargs)
-
-        # If we created an input with restrictToHost set, then
-        # its path will be :, not just ,
-        # and we have to adjust accordingly.
-
-        # Url encodes the name of the entity.
-        name = UrlEncoded(name, encode_slash=True)
-        path = _path(
-            self.path + kindpath,
-            f"{kwargs['restrictToHost']}:{name}"
-            if "restrictToHost" in kwargs
-            else name,
-        )
-        return Input(self.service, path, kind)
-
-    def delete(self, name, kind=None):
-        """Removes an input from the collection.
-
-        :param `kind`: The kind of input:
-
-            - "ad": Active Directory
-
-            - "monitor": Files and directories
-
-            - "registry": Windows Registry
-
-            - "script": Scripts
-
-            - "splunktcp": TCP, processed
-
-            - "tcp": TCP, unprocessed
-
-            - "udp": UDP
-
-            - "win-event-log-collections": Windows event log
-
-            - "win-perfmon": Performance monitoring
-
-            - "win-wmi-collections": WMI
-
-        :type kind: ``string``
-        :param name: The name of the input to remove.
-        :type name: ``string``
-
-        :return: The :class:`Inputs` collection.
-        """
-        if kind is None:
-            self.service.delete(self[name].path)
-        else:
-            self.service.delete(self[name, kind].path)
-        return self
-
-    def itemmeta(self, kind):
-        """Returns metadata for the members of a given kind.
-
-        :param `kind`: The kind of input:
-
-            - "ad": Active Directory
-
-            - "monitor": Files and directories
-
-            - "registry": Windows Registry
-
-            - "script": Scripts
-
-            - "splunktcp": TCP, processed
-
-            - "tcp": TCP, unprocessed
-
-            - "udp": UDP
-
-            - "win-event-log-collections": Windows event log
-
-            - "win-perfmon": Performance monitoring
-
-            - "win-wmi-collections": WMI
-
-        :type kind: ``string``
-
-        :return: The metadata.
-        :rtype: class:``splunklib.data.Record``
-        """
-        response = self.get(f"{self._kindmap[kind]}/_new")
-        content = _load_atom(response, MATCH_ENTRY_CONTENT)
-        return _parse_atom_metadata(content)
-
-    def _get_kind_list(self, subpath=None):
-        if subpath is None:
-            subpath = []
-
-        kinds = []
-        response = self.get("/".join(subpath))
-        content = _load_atom_entries(response)
-        for entry in content:
-            this_subpath = subpath + [entry.title]
-            # The "all" endpoint doesn't work yet.
-            # The "tcp/ssl" endpoint is not a real input collection.
-            if entry.title == "all" or this_subpath == ["tcp", "ssl"]:
-                continue
-            if "create" in [x.rel for x in entry.link]:
-                path = "/".join(subpath + [entry.title])
-                kinds.append(path)
-            else:
-                subkinds = self._get_kind_list(subpath + [entry.title])
-                kinds.extend(subkinds)
-        return kinds
-
-    @property
-    def kinds(self):
-        """Returns the input kinds on this Splunk instance.
-
-        :return: The list of input kinds.
-        :rtype: ``list``
-        """
-        return self._get_kind_list()
-
-    def kindpath(self, kind):
-        """Returns a path to the resources for a given input kind.
-
-        :param `kind`: The kind of input:
-
-            - "ad": Active Directory
-
-            - "monitor": Files and directories
-
-            - "registry": Windows Registry
-
-            - "script": Scripts
-
-            - "splunktcp": TCP, processed
-
-            - "tcp": TCP, unprocessed
-
-            - "udp": UDP
-
-            - "win-event-log-collections": Windows event log
-
-            - "win-perfmon": Performance monitoring
-
-            - "win-wmi-collections": WMI
-
-        :type kind: ``string``
-
-        :return: The relative endpoint path.
-        :rtype: ``string``
-        """
-        if kind == "tcp":
-            return UrlEncoded("tcp/raw", skip_encode=True)
-        if kind == "splunktcp":
-            return UrlEncoded("tcp/cooked", skip_encode=True)
-        return UrlEncoded(kind, skip_encode=True)
-
-    def list(self, *kinds, **kwargs):
-        """Returns a list of inputs that are in the :class:`Inputs` collection.
-        You can also filter by one or more input kinds.
-
-        This function iterates over all possible inputs, regardless of any arguments you
-        specify. Because the :class:`Inputs` collection is the union of all the inputs of each
-        kind, this method implements parameters such as "count", "search", and so
-        on at the Python level once all the data has been fetched. The exception
-        is when you specify a single input kind, and then this method makes a single request
-        with the usual semantics for parameters.
-
-        :param kinds: The input kinds to return (optional).
-
-            - "ad": Active Directory
-
-            - "monitor": Files and directories
-
-            - "registry": Windows Registry
-
-            - "script": Scripts
-
-            - "splunktcp": TCP, processed
-
-            - "tcp": TCP, unprocessed
-
-            - "udp": UDP
-
-            - "win-event-log-collections": Windows event log
-
-            - "win-perfmon": Performance monitoring
-
-            - "win-wmi-collections": WMI
-
-        :type kinds: ``string``
-        :param kwargs: Additional arguments (optional):
-
-            - "count" (``integer``): The maximum number of items to return.
-
-            - "offset" (``integer``): The offset of the first item to return.
-
-            - "search" (``string``): The search query to filter responses.
-
-            - "sort_dir" (``string``): The direction to sort returned items:
-              "asc" or "desc".
-
-            - "sort_key" (``string``): The field to use for sorting (optional).
-
-            - "sort_mode" (``string``): The collating sequence for sorting
-              returned items: "auto", "alpha", "alpha_case", or "num".
-
-        :type kwargs: ``dict``
-
-        :return: A list of input kinds.
-        :rtype: ``list``
-        """
-        if len(kinds) == 0:
-            kinds = self.kinds
-        if len(kinds) == 1:
-            kind = kinds[0]
-            logger.debug("Inputs.list taking short circuit branch for single kind.")
-            path = self.kindpath(kind)
-            logger.debug("Path for inputs: %s", path)
-            try:
-                path = UrlEncoded(path, skip_encode=True)
-                response = self.get(path, **kwargs)
-            except HTTPError as he:
-                if he.status == 404:  # No inputs of this kind
-                    return []
-            entities = []
-            entries = _load_atom_entries(response)
-            if entries is None:
-                return []  # No inputs in a collection comes back with no feed or entry in the XML
-            for entry in entries:
-                state = _parse_atom_entry(entry)
-                # Unquote the URL, since all URL encoded in the SDK
-                # should be of type UrlEncoded, and all str should not
-                # be URL encoded.
-                path = parse.unquote(state.links.alternate)
-                entity = Input(self.service, path, kind, state=state)
-                entities.append(entity)
-            return entities
-
-        search = kwargs.get("search", "*")
-
-        entities = []
-        for kind in kinds:
-            response = None
-            try:
-                kind = UrlEncoded(kind, skip_encode=True)
-                response = self.get(self.kindpath(kind), search=search)
-            except HTTPError as e:
-                if e.status == 404:
-                    continue  # No inputs of this kind
-                else:
-                    raise
-
-            entries = _load_atom_entries(response)
-            if entries is None:
-                continue  # No inputs to process
-            for entry in entries:
-                state = _parse_atom_entry(entry)
-                # Unquote the URL, since all URL encoded in the SDK
-                # should be of type UrlEncoded, and all str should not
-                # be URL encoded.
-                path = parse.unquote(state.links.alternate)
-                entity = Input(self.service, path, kind, state=state)
-                entities.append(entity)
-        if "offset" in kwargs:
-            entities = entities[kwargs["offset"] :]
-        if "count" in kwargs:
-            entities = entities[: kwargs["count"]]
-        if kwargs.get("sort_mode", None) == "alpha":
-            sort_field = kwargs.get("sort_field", "name")
-            if sort_field == "name":
-                f = lambda x: x.name.lower()
-            else:
-                f = lambda x: x[sort_field].lower()
-            entities = sorted(entities, key=f)
-        if kwargs.get("sort_mode", None) == "alpha_case":
-            sort_field = kwargs.get("sort_field", "name")
-            if sort_field == "name":
-                f = lambda x: x.name
-            else:
-                f = lambda x: x[sort_field]
-            entities = sorted(entities, key=f)
-        if kwargs.get("sort_dir", "asc") == "desc":
-            entities = list(reversed(entities))
-        return entities
-
-    def __iter__(self, **kwargs):
-        for item in self.iter(**kwargs):
-            yield item
-
-    def iter(self, **kwargs):
-        """Iterates over the collection of inputs.
-
-        :param kwargs: Additional arguments (optional):
-
-            - "count" (``integer``): The maximum number of items to return.
-
-            - "offset" (``integer``): The offset of the first item to return.
-
-            - "search" (``string``): The search query to filter responses.
-
-            - "sort_dir" (``string``): The direction to sort returned items:
-              "asc" or "desc".
-
-            - "sort_key" (``string``): The field to use for sorting (optional).
-
-            - "sort_mode" (``string``): The collating sequence for sorting
-              returned items: "auto", "alpha", "alpha_case", or "num".
-
-        :type kwargs: ``dict``
-        """
-        for item in self.list(**kwargs):
-            yield item
-
-    def oneshot(self, path, **kwargs):
-        """Creates a oneshot data input, which is an upload of a single file
-        for one-time indexing.
-
-        :param path: The path and filename.
-        :type path: ``string``
-        :param kwargs: Additional arguments (optional). For more about the
-            available parameters, see `Input parameters `_ on Splunk Developer Portal.
-        :type kwargs: ``dict``
-        """
-        self.post("oneshot", name=path, **kwargs)
-
-
-class Job(Entity):
-    """This class represents a search job."""
-
-    def __init__(self, service, sid, **kwargs):
-        # Default to v2 in Splunk Version 9+
-        path = "{path}{sid}"
-        # Formatting path based on the Splunk Version
-        if service.disable_v2_api:
-            path = path.format(path=PATH_JOBS, sid=sid)
-        else:
-            path = path.format(path=PATH_JOBS_V2, sid=sid)
-
-        Entity.__init__(self, service, path, skip_refresh=True, **kwargs)
-        self.sid = sid
-
-    # The Job entry record is returned at the root of the response
-    def _load_atom_entry(self, response):
-        return _load_atom(response).entry
-
-    def cancel(self):
-        """Stops the current search and deletes the results cache.
-
-        :return: The :class:`Job`.
-        """
-        try:
-            self.post("control", action="cancel")
-        except HTTPError as he:
-            if he.status == 404:
-                # The job has already been cancelled, so
-                # cancelling it twice is a nop.
-                pass
-            else:
-                raise
-        return self
-
-    def disable_preview(self):
-        """Disables preview for this job.
-
-        :return: The :class:`Job`.
-        """
-        self.post("control", action="disablepreview")
-        return self
-
-    def enable_preview(self):
-        """Enables preview for this job.
-
-        **Note**: Enabling preview might slow search considerably.
-
-        :return: The :class:`Job`.
-        """
-        self.post("control", action="enablepreview")
-        return self
-
-    def events(self, **kwargs):
-        """Returns a streaming handle to this job's events.
-
-        :param kwargs: Additional parameters (optional). For a list of valid
-            parameters, see `GET search/jobs/{search_id}/events
-            `_
-            in the REST API documentation.
-        :type kwargs: ``dict``
-
-        :return: The ``InputStream`` IO handle to this job's events.
-        """
-        kwargs["segmentation"] = kwargs.get("segmentation", "none")
-
-        # Search API v1(GET) and v2(POST)
-        if self.service.disable_v2_api:
-            return self.get("events", **kwargs).body
-        return self.post("events", **kwargs).body
-
-    def finalize(self):
-        """Stops the job and provides intermediate results for retrieval.
-
-        :return: The :class:`Job`.
-        """
-        self.post("control", action="finalize")
-        return self
-
-    def is_done(self):
-        """Indicates whether this job finished running.
-
-        :return: ``True`` if the job is done, ``False`` if not.
-        :rtype: ``boolean``
-        """
-        if not self.is_ready():
-            return False
-        done = self._state.content["isDone"] == "1"
-        return done
-
-    def is_ready(self):
-        """Indicates whether this job is ready for querying.
-
-        :return: ``True`` if the job is ready, ``False`` if not.
-        :rtype: ``boolean``
-
-        """
-        response = self.get()
-        if response.status == 204:
-            return False
-        self._state = self.read(response)
-        ready = self._state.content["dispatchState"] not in ["QUEUED", "PARSING"]
-        return ready
-
-    @property
-    def name(self):
-        """Returns the name of the search job, which is the search ID (SID).
-
-        :return: The search ID.
-        :rtype: ``string``
-        """
-        return self.sid
-
-    def pause(self):
-        """Suspends the current search.
-
-        :return: The :class:`Job`.
-        """
-        self.post("control", action="pause")
-        return self
-
-    def results(self, **query_params):
-        """Returns a streaming handle to this job's search results. To get a nice, Pythonic iterator, pass the handle
-        to :class:`splunklib.results.JSONResultsReader` along with the query param "output_mode='json'", as in::
-
-            import splunklib.client as client
-            import splunklib.results as results
-            from time import sleep
-            service = client.connect(...)
-            job = service.jobs.create("search * | head 5")
-            while not job.is_done():
-                sleep(.2)
-            rr = results.JSONResultsReader(job.results(output_mode='json'))
-            for result in rr:
-                if isinstance(result, results.Message):
-                    # Diagnostic messages may be returned in the results
-                    print(f'{result.type}: {result.message}')
-                elif isinstance(result, dict):
-                    # Normal events are returned as dicts
-                    print(result)
-            assert rr.is_preview == False
-
-        Results are not available until the job has finished. If called on
-        an unfinished job, the result is an empty event set.
-
-        This method makes a single roundtrip
-        to the server, plus at most two additional round trips if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        :param query_params: Additional parameters (optional). For a list of valid
-            parameters, see `GET search/jobs/{search_id}/results
-            `_.
-        :type query_params: ``dict``
-
-        :return: The ``InputStream`` IO handle to this job's results.
-        """
-        query_params["segmentation"] = query_params.get("segmentation", "none")
-
-        # Search API v1(GET) and v2(POST)
-        if self.service.disable_v2_api:
-            return self.get("results", **query_params).body
-        return self.post("results", **query_params).body
-
-    def preview(self, **query_params):
-        """Returns a streaming handle to this job's preview search results.
-
-        Unlike :class:`splunklib.results.JSONResultsReader`along with the query param "output_mode='json'",
-        which requires a job to be finished to return any results, the ``preview`` method returns any results that
-        have been generated so far, whether the job is running or not. The returned search results are the raw data
-        from the server. Pass the handle returned to :class:`splunklib.results.JSONResultsReader` to get a nice,
-        Pythonic iterator over objects, as in::
-
-            import splunklib.client as client
-            import splunklib.results as results
-            service = client.connect(...)
-            job = service.jobs.create("search * | head 5")
-            rr = results.JSONResultsReader(job.preview(output_mode='json'))
-            for result in rr:
-                if isinstance(result, results.Message):
-                    # Diagnostic messages may be returned in the results
-                    print(f'{result.type}: {result.message}')
-                elif isinstance(result, dict):
-                    # Normal events are returned as dicts
-                    print(result)
-            if rr.is_preview:
-                print("Preview of a running search job.")
-            else:
-                print("Job is finished. Results are final.")
-
-        This method makes one roundtrip to the server, plus at most
-        two more if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        :param query_params: Additional parameters (optional). For a list of valid
-            parameters, see `GET search/jobs/{search_id}/results_preview
-            `_
-            in the REST API documentation.
-        :type query_params: ``dict``
-
-        :return: The ``InputStream`` IO handle to this job's preview results.
-        """
-        query_params["segmentation"] = query_params.get("segmentation", "none")
-
-        # Search API v1(GET) and v2(POST)
-        if self.service.disable_v2_api:
-            return self.get("results_preview", **query_params).body
-        return self.post("results_preview", **query_params).body
-
-    def searchlog(self, **kwargs):
-        """Returns a streaming handle to this job's search log.
-
-        :param `kwargs`: Additional parameters (optional). For a list of valid
-            parameters, see `GET search/jobs/{search_id}/search.log
-            `_
-            in the REST API documentation.
-        :type kwargs: ``dict``
-
-        :return: The ``InputStream`` IO handle to this job's search log.
-        """
-        return self.get("search.log", **kwargs).body
-
-    def set_priority(self, value):
-        """Sets this job's search priority in the range of 0-10.
-
-        Higher numbers indicate higher priority. Unless splunkd is
-        running as *root*, you can only decrease the priority of a running job.
-
-        :param `value`: The search priority.
-        :type value: ``integer``
-
-        :return: The :class:`Job`.
-        """
-        self.post("control", action="setpriority", priority=value)
-        return self
-
-    def summary(self, **kwargs):
-        """Returns a streaming handle to this job's summary.
-
-        :param `kwargs`: Additional parameters (optional). For a list of valid
-            parameters, see `GET search/jobs/{search_id}/summary
-            `_
-            in the REST API documentation.
-        :type kwargs: ``dict``
-
-        :return: The ``InputStream`` IO handle to this job's summary.
-        """
-        return self.get("summary", **kwargs).body
-
-    def timeline(self, **kwargs):
-        """Returns a streaming handle to this job's timeline results.
-
-        :param `kwargs`: Additional timeline arguments (optional). For a list of valid
-            parameters, see `GET search/jobs/{search_id}/timeline
-            `_
-            in the REST API documentation.
-        :type kwargs: ``dict``
-
-        :return: The ``InputStream`` IO handle to this job's timeline.
-        """
-        return self.get("timeline", **kwargs).body
-
-    def touch(self):
-        """Extends the expiration time of the search to the current time (now) plus
-        the time-to-live (ttl) value.
-
-        :return: The :class:`Job`.
-        """
-        self.post("control", action="touch")
-        return self
-
-    def set_ttl(self, value):
-        """Set the job's time-to-live (ttl) value, which is the time before the
-        search job expires and is still available.
-
-        :param `value`: The ttl value, in seconds.
-        :type value: ``integer``
-
-        :return: The :class:`Job`.
-        """
-        self.post("control", action="setttl", ttl=value)
-        return self
-
-    def unpause(self):
-        """Resumes the current search, if paused.
-
-        :return: The :class:`Job`.
-        """
-        self.post("control", action="unpause")
-        return self
-
-
-class Jobs(Collection):
-    """This class represents a collection of search jobs. Retrieve this
-    collection using :meth:`Service.jobs`."""
-
-    def __init__(self, service):
-        # Splunk 9 introduces the v2 endpoint
-        if not service.disable_v2_api:
-            path = PATH_JOBS_V2
-        else:
-            path = PATH_JOBS
-        Collection.__init__(self, service, path, item=Job)
-        # The count value to say list all the contents of this
-        # Collection is 0, not -1 as it is on most.
-        self.null_count = 0
-
-    def _load_list(self, response):
-        # Overridden because Job takes a sid instead of a path.
-        entries = _load_atom_entries(response)
-        if entries is None:
-            return []
-        entities = []
-        for entry in entries:
-            state = _parse_atom_entry(entry)
-            entity = self.item(self.service, entry["content"]["sid"], state=state)
-            entities.append(entity)
-        return entities
-
-    def create(self, query, **kwargs):
-        """Creates a search using a search query and any additional parameters
-        you provide.
-
-        :param query: The search query.
-        :type query: ``string``
-        :param kwargs: Additiona parameters (optional). For a list of available
-            parameters, see `Search job parameters
-            `_
-            on Splunk Developer Portal.
-        :type kwargs: ``dict``
-
-        :return: The :class:`Job`.
-        """
-        if kwargs.get("exec_mode", None) == "oneshot":
-            raise TypeError(
-                "Cannot specify exec_mode=oneshot; use the oneshot method instead."
-            )
-        response = self.post(search=query, **kwargs)
-        sid = _load_sid(response, kwargs.get("output_mode", None))
-        return Job(self.service, sid)
-
-    def export(self, query, **params):
-        """Runs a search and immediately starts streaming preview events. This method returns a streaming handle to
-        this job's events as an XML document from the server. To parse this stream into usable Python objects,
-        pass the handle to :class:`splunklib.results.JSONResultsReader` along with the query param
-        "output_mode='json'"::
-
-            import splunklib.client as client
-            import splunklib.results as results
-            service = client.connect(...)
-            rr = results.JSONResultsReader(service.jobs.export("search * | head 5",output_mode='json'))
-            for result in rr:
-                if isinstance(result, results.Message):
-                    # Diagnostic messages may be returned in the results
-                    print(f'{result.type}: {result.message}')
-                elif isinstance(result, dict):
-                    # Normal events are returned as dicts
-                    print(result)
-            assert rr.is_preview == False
-
-        Running an export search is more efficient as it streams the results
-        directly to you, rather than having to write them out to disk and make
-        them available later. As soon as results are ready, you will receive
-        them.
-
-        The ``export`` method makes a single roundtrip to the server (as opposed
-        to two for :meth:`create` followed by :meth:`preview`), plus at most two
-        more if the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        :raises `ValueError`: Raised for invalid queries.
-        :param query: The search query.
-        :type query: ``string``
-        :param params: Additional arguments (optional). For a list of valid
-            parameters, see `GET search/jobs/export
-            `_
-            in the REST API documentation.
-        :type params: ``dict``
-
-        :return: The ``InputStream`` IO handle to raw XML returned from the server.
-        """
-        if "exec_mode" in params:
-            raise TypeError("Cannot specify an exec_mode to export.")
-        params["segmentation"] = params.get("segmentation", "none")
-        return self.post(path_segment="export", search=query, **params).body
-
-    def itemmeta(self):
-        """There is no metadata available for class:``Jobs``.
-
-        Any call to this method raises a class:``NotSupportedError``.
-
-        :raises: class:``NotSupportedError``
-        """
-        raise NotSupportedError()
-
-    def oneshot(self, query, **params):
-        """Run a oneshot search and returns a streaming handle to the results.
-
-        The ``InputStream`` object streams fragments from the server. To parse this stream into usable Python
-        objects, pass the handle to :class:`splunklib.results.JSONResultsReader` along with the query param
-        "output_mode='json'" ::
-
-            import splunklib.client as client
-            import splunklib.results as results
-            service = client.connect(...)
-            rr = results.JSONResultsReader(service.jobs.oneshot("search * | head 5",output_mode='json'))
-            for result in rr:
-                if isinstance(result, results.Message):
-                    # Diagnostic messages may be returned in the results
-                    print(f'{result.type}: {result.message}')
-                elif isinstance(result, dict):
-                    # Normal events are returned as dicts
-                    print(result)
-            assert rr.is_preview == False
-
-        The ``oneshot`` method makes a single roundtrip to the server (as opposed
-        to two for :meth:`create` followed by :meth:`results`), plus at most two more
-        if the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        :raises ValueError: Raised for invalid queries.
-
-        :param query: The search query.
-        :type query: ``string``
-        :param params: Additional arguments (optional):
-
-            - "output_mode": Specifies the output format of the results (XML,
-              JSON, or CSV).
-
-            - "earliest_time": Specifies the earliest time in the time range to
-              search. The time string can be a UTC time (with fractional seconds),
-              a relative time specifier (to now), or a formatted time string.
-
-            - "latest_time": Specifies the latest time in the time range to
-              search. The time string can be a UTC time (with fractional seconds),
-              a relative time specifier (to now), or a formatted time string.
-
-            - "rf": Specifies one or more fields to add to the search.
-
-        :type params: ``dict``
-
-        :return: The ``InputStream`` IO handle to raw XML returned from the server.
-        """
-        if "exec_mode" in params:
-            raise TypeError("Cannot specify an exec_mode to oneshot.")
-        params["segmentation"] = params.get("segmentation", "none")
-        return self.post(search=query, exec_mode="oneshot", **params).body
-
-
-class Loggers(Collection):
-    """This class represents a collection of service logging categories.
-    Retrieve this collection using :meth:`Service.loggers`."""
-
-    def __init__(self, service):
-        Collection.__init__(self, service, PATH_LOGGER)
-
-    def itemmeta(self):
-        """There is no metadata available for class:``Loggers``.
-
-        Any call to this method raises a class:``NotSupportedError``.
-
-        :raises: class:``NotSupportedError``
-        """
-        raise NotSupportedError()
-
-
-class Message(Entity):
-    def __init__(self, service, path, **kwargs):
-        Entity.__init__(self, service, path, **kwargs)
-
-    @property
-    def value(self):
-        """Returns the message value.
-
-        :return: The message value.
-        :rtype: ``string``
-        """
-        return self[self.name]
-
-
-class ModularInputKind(Entity):
-    """This class contains the different types of modular inputs. Retrieve this
-    collection using :meth:`Service.modular_input_kinds`.
-    """
-
-    def __contains__(self, name):
-        args = self.state.content["endpoints"]["args"]
-        if name in args:
-            return True
-        return Entity.__contains__(self, name)
-
-    def __getitem__(self, name):
-        args = self.state.content["endpoint"]["args"]
-        if name in args:
-            return args["item"]
-        return Entity.__getitem__(self, name)
-
-    @property
-    def arguments(self):
-        """A dictionary of all the arguments supported by this modular input kind.
-
-        The keys in the dictionary are the names of the arguments. The values are
-        another dictionary giving the metadata about that argument. The possible
-        keys in that dictionary are ``"title"``, ``"description"``, ``"required_on_create``",
-        ``"required_on_edit"``, ``"data_type"``. Each value is a string. It should be one
-        of ``"true"`` or ``"false"`` for ``"required_on_create"`` and ``"required_on_edit"``,
-        and one of ``"boolean"``, ``"string"``, or ``"number``" for ``"data_type"``.
-
-        :return: A dictionary describing the arguments this modular input kind takes.
-        :rtype: ``dict``
-        """
-        return self.state.content["endpoint"]["args"]
-
-    def update(self, **kwargs):
-        """Raises an error. Modular input kinds are read only."""
-        raise IllegalOperationException(
-            "Modular input kinds cannot be updated via the REST API."
-        )
-
-
-class SavedSearch(Entity):
-    """This class represents a saved search."""
-
-    def __init__(self, service, path, **kwargs):
-        Entity.__init__(self, service, path, **kwargs)
-
-    def acknowledge(self):
-        """Acknowledges the suppression of alerts from this saved search and
-        resumes alerting.
-
-        :return: The :class:`SavedSearch`.
-        """
-        self.post("acknowledge")
-        return self
-
-    @property
-    def alert_count(self):
-        """Returns the number of alerts fired by this saved search.
-
-        :return: The number of alerts fired by this saved search.
-        :rtype: ``integer``
-        """
-        return int(self._state.content.get("triggered_alert_count", 0))
-
-    def dispatch(self, **kwargs):
-        """Runs the saved search and returns the resulting search job.
-
-        :param `kwargs`: Additional dispatch arguments (optional). For details,
-                         see the `POST saved/searches/{name}/dispatch
-                         `_
-                         endpoint in the REST API documentation.
-        :type kwargs: ``dict``
-        :return: The :class:`Job`.
-        """
-        response = self.post("dispatch", **kwargs)
-        sid = _load_sid(response, kwargs.get("output_mode", None))
-        return Job(self.service, sid)
-
-    @property
-    def fired_alerts(self):
-        """Returns the collection of fired alerts (a fired alert group)
-        corresponding to this saved search's alerts.
-
-        :raises IllegalOperationException: Raised when the search is not scheduled.
-
-        :return: A collection of fired alerts.
-        :rtype: :class:`AlertGroup`
-        """
-        if self["is_scheduled"] == "0":
-            raise IllegalOperationException(
-                "Unscheduled saved searches have no alerts."
-            )
-        c = Collection(
-            self.service,
-            self.service._abspath(
-                PATH_FIRED_ALERTS + self.name,
-                owner=self._state.access.owner,
-                app=self._state.access.app,
-                sharing=self._state.access.sharing,
-            ),
-            item=AlertGroup,
-        )
-        return c
-
-    def history(self, **kwargs):
-        """Returns a list of search jobs corresponding to this saved search.
-
-        :param `kwargs`: Additional arguments (optional).
-        :type kwargs: ``dict``
-
-        :return: A list of :class:`Job` objects.
-        """
-        response = self.get("history", **kwargs)
-        entries = _load_atom_entries(response)
-        if entries is None:
-            return []
-        jobs = []
-        for entry in entries:
-            job = Job(self.service, entry.title)
-            jobs.append(job)
-        return jobs
-
-    def update(self, search=None, **kwargs):
-        """Updates the server with any changes you've made to the current saved
-        search along with any additional arguments you specify.
-
-        :param `search`: The search query (optional).
-        :type search: ``string``
-        :param `kwargs`: Additional arguments (optional). For a list of available
-            parameters, see `Saved search parameters
-            `_
-            on Splunk Developer Portal.
-        :type kwargs: ``dict``
-
-        :return: The :class:`SavedSearch`.
-        """
-        # Updates to a saved search *require* that the search string be
-        # passed, so we pass the current search string if a value wasn't
-        # provided by the caller.
-        if search is None:
-            search = self.content.search
-        Entity.update(self, search=search, **kwargs)
-        return self
-
-    def scheduled_times(self, earliest_time="now", latest_time="+1h"):
-        """Returns the times when this search is scheduled to run.
-
-        By default this method returns the times in the next hour. For different
-        time ranges, set *earliest_time* and *latest_time*. For example,
-        for all times in the last day use "earliest_time=-1d" and
-        "latest_time=now".
-
-        :param earliest_time: The earliest time.
-        :type earliest_time: ``string``
-        :param latest_time: The latest time.
-        :type latest_time: ``string``
-
-        :return: The list of search times.
-        """
-        response = self.get(
-            "scheduled_times", earliest_time=earliest_time, latest_time=latest_time
-        )
-        data = self._load_atom_entry(response)
-        rec = _parse_atom_entry(data)
-        times = [datetime.fromtimestamp(int(t)) for t in rec.content.scheduled_times]
-        return times
-
-    def suppress(self, expiration):
-        """Skips any scheduled runs of this search in the next *expiration*
-        number of seconds.
-
-        :param expiration: The expiration period, in seconds.
-        :type expiration: ``integer``
-
-        :return: The :class:`SavedSearch`.
-        """
-        self.post("suppress", expiration=expiration)
-        return self
-
-    @property
-    def suppressed(self):
-        """Returns the number of seconds that this search is blocked from running
-        (possibly 0).
-
-        :return: The number of seconds.
-        :rtype: ``integer``
-        """
-        r = self._run_action("suppress")
-        if r.suppressed == "1":
-            return int(r.expiration)
-        return 0
-
-    def unsuppress(self):
-        """Cancels suppression and makes this search run as scheduled.
-
-        :return: The :class:`SavedSearch`.
-        """
-        self.post("suppress", expiration="0")
-        return self
-
-
-class SavedSearches(Collection):
-    """This class represents a collection of saved searches. Retrieve this
-    collection using :meth:`Service.saved_searches`."""
-
-    def __init__(self, service):
-        Collection.__init__(self, service, PATH_SAVED_SEARCHES, item=SavedSearch)
-
-    def create(self, name, search, **kwargs):
-        """Creates a saved search.
-
-        :param name: The name for the saved search.
-        :type name: ``string``
-        :param search: The search query.
-        :type search: ``string``
-        :param kwargs: Additional arguments (optional). For a list of available
-            parameters, see `Saved search parameters
-            `_
-            on Splunk Developer Portal.
-        :type kwargs: ``dict``
-        :return: The :class:`SavedSearches` collection.
-        """
-        return Collection.create(self, name, search=search, **kwargs)
-
-
-class Macro(Entity):
-    """This class represents a search macro."""
-
-    def __init__(self, service, path, **kwargs):
-        Entity.__init__(self, service, path, **kwargs)
-
-    @property
-    def args(self):
-        """Returns the macro arguments.
-        :return: The macro arguments.
-        :rtype: ``string``
-        """
-        return self._state.content.get("args", "")
-
-    @property
-    def definition(self):
-        """Returns the macro definition.
-        :return: The macro definition.
-        :rtype: ``string``
-        """
-        return self._state.content.get("definition", "")
-
-    @property
-    def errormsg(self):
-        """Returns the validation error message for the macro.
-        :return: The validation error message for the macro.
-        :rtype: ``string``
-        """
-        return self._state.content.get("errormsg", "")
-
-    @property
-    def iseval(self):
-        """Returns the eval-based definition status of the macro.
-        :return: The iseval value for the macro.
-        :rtype: ``string``
-        """
-        return self._state.content.get("iseval", "0")
-
-    def update(self, definition=None, **kwargs):
-        """Updates the server with any changes you've made to the current macro
-        along with any additional arguments you specify.
-        :param `definition`: The macro definition (optional).
-        :type definition: ``string``
-        :param `kwargs`: Additional arguments (optional). Available parameters are:
-            'disabled', 'iseval', 'validation', and 'errormsg'.
-        :type kwargs: ``dict``
-        :return: The :class:`Macro`.
-        """
-        # Updates to a macro *require* that the definition be
-        # passed, so we pass the current definition if a value wasn't
-        # provided by the caller.
-        if definition is None:
-            definition = self.content.definition
-        Entity.update(self, definition=definition, **kwargs)
-        return self
-
-    @property
-    def validation(self):
-        """Returns the validation expression for the macro.
-        :return: The validation expression for the macro.
-        :rtype: ``string``
-        """
-        return self._state.content.get("validation", "")
-
-
-class Macros(Collection):
-    """This class represents a collection of macros. Retrieve this
-    collection using :meth:`Service.macros`."""
-
-    def __init__(self, service):
-        Collection.__init__(self, service, PATH_MACROS, item=Macro)
-
-    def create(self, name, definition, **kwargs):
-        """Creates a macro.
-        :param name: The name for the macro.
-        :type name: ``string``
-        :param definition: The macro definition.
-        :type definition: ``string``
-        :param kwargs: Additional arguments (optional). Available parameters are:
-            'disabled', 'iseval', 'validation', and 'errormsg'.
-        :type kwargs: ``dict``
-        :return: The :class:`Macros` collection.
-        """
-        return Collection.create(self, name, definition=definition, **kwargs)
-
-
-class Settings(Entity):
-    """This class represents configuration settings for a Splunk service.
-    Retrieve this collection using :meth:`Service.settings`."""
-
-    def __init__(self, service, **kwargs):
-        Entity.__init__(self, service, "/services/server/settings", **kwargs)
-
-    # Updates on the settings endpoint are POSTed to server/settings/settings.
-    def update(self, **kwargs):
-        """Updates the settings on the server using the arguments you provide.
-
-        :param kwargs: Additional arguments. For a list of valid arguments, see
-            `POST server/settings/{name}
-            `_
-            in the REST API documentation.
-        :type kwargs: ``dict``
-        :return: The :class:`Settings` collection.
-        """
-        self.service.post("/services/server/settings/settings", **kwargs)
-        return self
-
-
-class User(Entity):
-    """This class represents a Splunk user."""
-
-    @property
-    def role_entities(self):
-        """Returns a list of roles assigned to this user.
-
-        :return: The list of roles.
-        :rtype: ``list``
-        """
-        all_role_names = [r.name for r in self.service.roles.list()]
-        return [
-            self.service.roles[name]
-            for name in self.content.roles
-            if name in all_role_names
-        ]
-
-
-# Splunk automatically lowercases new user names so we need to match that
-# behavior here to ensure that the subsequent member lookup works correctly.
-class Users(Collection):
-    """This class represents the collection of Splunk users for this instance of
-    Splunk. Retrieve this collection using :meth:`Service.users`.
-    """
-
-    def __init__(self, service):
-        Collection.__init__(self, service, PATH_USERS, item=User)
-
-    def __getitem__(self, key):
-        return Collection.__getitem__(self, key.lower())
-
-    def __contains__(self, name):
-        return Collection.__contains__(self, name.lower())
-
-    def create(self, username, password, roles, **params):
-        """Creates a new user.
-
-        This function makes two roundtrips to the server, plus at most
-        two more if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        :param username: The username.
-        :type username: ``string``
-        :param password: The password.
-        :type password: ``string``
-        :param roles: A single role or list of roles for the user.
-        :type roles: ``string`` or  ``list``
-        :param params: Additional arguments (optional). For a list of available
-            parameters, see `User authentication parameters
-            `_
-            on Splunk Developer Portal.
-        :type params: ``dict``
-
-        :return: The new user.
-        :rtype: :class:`User`
-
-        **Example**::
-
-            import splunklib.client as client
-            c = client.connect(...)
-            users = c.users
-            boris = users.create("boris", "securepassword", roles="user")
-            hilda = users.create("hilda", "anotherpassword", roles=["user","power"])
-        """
-        if not isinstance(username, str):
-            raise ValueError(f"Invalid username: {str(username)}")
-        username = username.lower()
-        self.post(name=username, password=password, roles=roles, **params)
-        # splunkd doesn't return the user in the POST response body,
-        # so we have to make a second round trip to fetch it.
-        response = self.get(username)
-        entry = _load_atom(response, XNAME_ENTRY).entry
-        state = _parse_atom_entry(entry)
-        entity = self.item(
-            self.service, parse.unquote(state.links.alternate), state=state
-        )
-        return entity
-
-    def delete(self, name):
-        """Deletes the user and returns the resulting collection of users.
-
-        :param name: The name of the user to delete.
-        :type name: ``string``
-
-        :return:
-        :rtype: :class:`Users`
-        """
-        return Collection.delete(self, name.lower())
-
-
-class Role(Entity):
-    """This class represents a user role."""
-
-    def grant(self, *capabilities_to_grant):
-        """Grants additional capabilities to this role.
-
-        :param capabilities_to_grant: Zero or more capabilities to grant this
-            role. For a list of capabilities, see
-            `Capabilities `_
-            on Splunk Developer Portal.
-        :type capabilities_to_grant: ``string`` or ``list``
-        :return: The :class:`Role`.
-
-        **Example**::
-
-            service = client.connect(...)
-            role = service.roles['somerole']
-            role.grant('change_own_password', 'search')
-        """
-        possible_capabilities = self.service.capabilities
-        for capability in capabilities_to_grant:
-            if capability not in possible_capabilities:
-                raise NoSuchCapability(capability)
-        new_capabilities = self["capabilities"] + list(capabilities_to_grant)
-        self.post(capabilities=new_capabilities)
-        return self
-
-    def revoke(self, *capabilities_to_revoke):
-        """Revokes zero or more capabilities from this role.
-
-        :param capabilities_to_revoke: Zero or more capabilities to grant this
-            role. For a list of capabilities, see
-            `Capabilities `_
-            on Splunk Developer Portal.
-        :type capabilities_to_revoke: ``string`` or ``list``
-
-        :return: The :class:`Role`.
-
-        **Example**::
-
-            service = client.connect(...)
-            role = service.roles['somerole']
-            role.revoke('change_own_password', 'search')
-        """
-        possible_capabilities = self.service.capabilities
-        for capability in capabilities_to_revoke:
-            if capability not in possible_capabilities:
-                raise NoSuchCapability(capability)
-        old_capabilities = self["capabilities"]
-        new_capabilities = []
-        for c in old_capabilities:
-            if c not in capabilities_to_revoke:
-                new_capabilities.append(c)
-        if not new_capabilities:
-            new_capabilities = ""  # Empty lists don't get passed in the body, so we have to force an empty argument.
-        self.post(capabilities=new_capabilities)
-        return self
-
-
-class Roles(Collection):
-    """This class represents the collection of roles in the Splunk instance.
-    Retrieve this collection using :meth:`Service.roles`."""
-
-    def __init__(self, service):
-        Collection.__init__(self, service, PATH_ROLES, item=Role)
-
-    def __getitem__(self, key):
-        return Collection.__getitem__(self, key.lower())
-
-    def __contains__(self, name):
-        return Collection.__contains__(self, name.lower())
-
-    def create(self, name, **params):
-        """Creates a new role.
-
-        This function makes two roundtrips to the server, plus at most
-        two more if
-        the ``autologin`` field of :func:`connect` is set to ``True``.
-
-        :param name: Name for the role.
-        :type name: ``string``
-        :param params: Additional arguments (optional). For a list of available
-            parameters, see `Roles parameters
-            `_
-            on Splunk Developer Portal.
-        :type params: ``dict``
-
-        :return: The new role.
-        :rtype: :class:`Role`
-
-        **Example**::
-
-            import splunklib.client as client
-            c = client.connect(...)
-            roles = c.roles
-            paltry = roles.create("paltry", imported_roles="user", defaultApp="search")
-        """
-        if not isinstance(name, str):
-            raise ValueError(f"Invalid role name: {str(name)}")
-        name = name.lower()
-        self.post(name=name, **params)
-        # splunkd doesn't return the user in the POST response body,
-        # so we have to make a second round trip to fetch it.
-        response = self.get(name)
-        entry = _load_atom(response, XNAME_ENTRY).entry
-        state = _parse_atom_entry(entry)
-        entity = self.item(
-            self.service, parse.unquote(state.links.alternate), state=state
-        )
-        return entity
-
-    def delete(self, name):
-        """Deletes the role and returns the resulting collection of roles.
-
-        :param name: The name of the role to delete.
-        :type name: ``string``
-
-        :rtype: The :class:`Roles`
-        """
-        return Collection.delete(self, name.lower())
-
-
-class Application(Entity):
-    """Represents a locally-installed Splunk app."""
-
-    @property
-    def setupInfo(self):
-        """Returns the setup information for the app.
-
-        :return: The setup information.
-        """
-        return self.content.get("eai:setup", None)
-
-    def package(self):
-        """Creates a compressed package of the app for archiving."""
-        return self._run_action("package")
-
-    def updateInfo(self):
-        """Returns any update information that is available for the app."""
-        return self._run_action("update")
-
-
-class KVStoreCollections(Collection):
-    def __init__(self, service):
-        Collection.__init__(
-            self, service, "storage/collections/config", item=KVStoreCollection
-        )
-
-    def __getitem__(self, item):
-        res = Collection.__getitem__(self, item)
-        for k, v in res.content.items():
-            if "accelerated_fields" in k:
-                res.content[k] = json.loads(v)
-        return res
-
-    def create(self, name, accelerated_fields={}, fields={}, **kwargs):
-        """Creates a KV Store Collection.
-
-        :param name: name of collection to create
-        :type name: ``string``
-        :param accelerated_fields: dictionary of accelerated_fields definitions
-        :type accelerated_fields: ``dict``
-        :param fields: dictionary of field definitions
-        :type fields: ``dict``
-        :param kwargs: a dictionary of additional parameters specifying indexes and field definitions
-        :type kwargs: ``dict``
-
-        :return: Result of POST request
-        """
-        for k, v in accelerated_fields.items():
-            if isinstance(v, dict):
-                v = json.dumps(v)
-            kwargs["accelerated_fields." + k] = v
-        for k, v in fields.items():
-            kwargs["field." + k] = v
-        return self.post(name=name, **kwargs)
-
-
-class KVStoreCollection(Entity):
-    @property
-    def data(self):
-        """Returns data object for this Collection.
-
-        :rtype: :class:`KVStoreCollectionData`
-        """
-        return KVStoreCollectionData(self)
-
-    def update_accelerated_field(self, name, value):
-        """Changes the definition of a KV Store accelerated_field.
-
-        :param name: name of accelerated_fields to change
-        :type name: ``string``
-        :param value: new accelerated_fields definition
-        :type value: ``dict``
-
-        :return: Result of POST request
-        """
-        kwargs = {}
-        kwargs["accelerated_fields." + name] = (
-            json.dumps(value) if isinstance(value, dict) else value
-        )
-        return self.post(**kwargs)
-
-    def update_field(self, name, value):
-        """Changes the definition of a KV Store field.
-
-        :param name: name of field to change
-        :type name: ``string``
-        :param value: new field definition
-        :type value: ``string``
-
-        :return: Result of POST request
-        """
-        kwargs = {}
-        kwargs["field." + name] = value
-        return self.post(**kwargs)
-
-
-class KVStoreCollectionData:
-    """This class represents the data endpoint for a KVStoreCollection.
-
-    Retrieve using :meth:`KVStoreCollection.data`
-    """
-
-    JSON_HEADER = [("Content-Type", "application/json")]
-
-    def __init__(self, collection):
-        self.service = collection.service
-        self.collection = collection
-        self.owner, self.app, self.sharing = collection._proper_namespace()
-        self.path = (
-            "storage/collections/data/"
-            + UrlEncoded(self.collection.name, encode_slash=True)
-            + "/"
-        )
-
-    def _get(self, url, **kwargs):
-        return self.service.get(
-            self.path + url,
-            owner=self.owner,
-            app=self.app,
-            sharing=self.sharing,
-            **kwargs,
-        )
-
-    def _post(self, url, **kwargs):
-        return self.service.post(
-            self.path + url,
-            owner=self.owner,
-            app=self.app,
-            sharing=self.sharing,
-            **kwargs,
-        )
-
-    def _delete(self, url, **kwargs):
-        return self.service.delete(
-            self.path + url,
-            owner=self.owner,
-            app=self.app,
-            sharing=self.sharing,
-            **kwargs,
-        )
-
-    def query(self, **query):
-        """
-        Gets the results of query, with optional parameters sort, limit, skip, and fields.
-
-        :param query: Optional parameters. Valid options are sort, limit, skip, and fields
-        :type query: ``dict``
-
-        :return: Array of documents retrieved by query.
-        :rtype: ``array``
-        """
-
-        for key, value in query.items():
-            if isinstance(query[key], dict):
-                query[key] = json.dumps(value)
-
-        return json.loads(self._get("", **query).body.read().decode("utf-8"))
-
-    def query_by_id(self, id):
-        """
-        Returns object with _id = id.
-
-        :param id: Value for ID. If not a string will be coerced to string.
-        :type id: ``string``
-
-        :return: Document with id
-        :rtype: ``dict``
-        """
-        return json.loads(
-            self._get(UrlEncoded(str(id), encode_slash=True))
-            .body.read()
-            .decode("utf-8")
-        )
-
-    def insert(self, data):
-        """
-        Inserts item into this collection. An _id field will be generated if not assigned in the data.
-
-        :param data: Document to insert
-        :type data: ``string``
-
-        :return: _id of inserted object
-        :rtype: ``dict``
-        """
-        if isinstance(data, dict):
-            data = json.dumps(data)
-        return json.loads(
-            self._post("", headers=KVStoreCollectionData.JSON_HEADER, body=data)
-            .body.read()
-            .decode("utf-8")
-        )
-
-    def delete(self, query=None):
-        """
-        Deletes all data in collection if query is absent. Otherwise, deletes all data matched by query.
-
-        :param query: Query to select documents to delete
-        :type query: ``string``
-
-        :return: Result of DELETE request
-        """
-        return self._delete("", **({"query": query}) if query else {})
-
-    def delete_by_id(self, id):
-        """
-        Deletes document that has _id = id.
-
-        :param id: id of document to delete
-        :type id: ``string``
-
-        :return: Result of DELETE request
-        """
-        return self._delete(UrlEncoded(str(id), encode_slash=True))
-
-    def update(self, id, data):
-        """
-        Replaces document with _id = id with data.
-
-        :param id: _id of document to update
-        :type id: ``string``
-        :param data: the new document to insert
-        :type data: ``string``
-
-        :return: id of replaced document
-        :rtype: ``dict``
-        """
-        if isinstance(data, dict):
-            data = json.dumps(data)
-        return json.loads(
-            self._post(
-                UrlEncoded(str(id), encode_slash=True),
-                headers=KVStoreCollectionData.JSON_HEADER,
-                body=data,
-            )
-            .body.read()
-            .decode("utf-8")
-        )
-
-    def batch_find(self, *dbqueries):
-        """
-        Returns array of results from queries dbqueries.
-
-        :param dbqueries: Array of individual queries as dictionaries
-        :type dbqueries: ``array`` of ``dict``
-
-        :return: Results of each query
-        :rtype: ``array`` of ``array``
-        """
-        if len(dbqueries) < 1:
-            raise Exception("Must have at least one query.")
-
-        data = json.dumps(dbqueries)
-
-        return json.loads(
-            self._post(
-                "batch_find", headers=KVStoreCollectionData.JSON_HEADER, body=data
-            )
-            .body.read()
-            .decode("utf-8")
-        )
-
-    def batch_save(self, *documents):
-        """
-        Inserts or updates every document specified in documents.
-
-        :param documents: Array of documents to save as dictionaries
-        :type documents: ``array`` of ``dict``
-
-        :return: Results of update operation as overall stats
-        :rtype: ``dict``
-        """
-        if len(documents) < 1:
-            raise Exception("Must have at least one document.")
-
-        data = json.dumps(documents)
-
-        return json.loads(
-            self._post(
-                "batch_save", headers=KVStoreCollectionData.JSON_HEADER, body=data
-            )
-            .body.read()
-            .decode("utf-8")
-        )
diff --git a/apps/bitwarden_event_logs/lib/splunklib/data.py b/apps/bitwarden_event_logs/lib/splunklib/data.py
deleted file mode 100755
index 1f026ed8..00000000
--- a/apps/bitwarden_event_logs/lib/splunklib/data.py
+++ /dev/null
@@ -1,281 +0,0 @@
-# Copyright © 2011-2024 Splunk, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"): you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""The **splunklib.data** module reads the responses from splunkd in Atom Feed
-format, which is the format used by most of the REST API.
-"""
-
-from xml.etree.ElementTree import XML
-
-__all__ = ["load", "record"]
-
-# LNAME refers to element names without namespaces; XNAME is the same
-# name, but with an XML namespace.
-LNAME_DICT = "dict"
-LNAME_ITEM = "item"
-LNAME_KEY = "key"
-LNAME_LIST = "list"
-
-XNAMEF_REST = "{http://dev.splunk.com/ns/rest}%s"
-XNAME_DICT = XNAMEF_REST % LNAME_DICT
-XNAME_ITEM = XNAMEF_REST % LNAME_ITEM
-XNAME_KEY = XNAMEF_REST % LNAME_KEY
-XNAME_LIST = XNAMEF_REST % LNAME_LIST
-
-
-# Some responses don't use namespaces (eg: search/parse) so we look for
-# both the extended and local versions of the following names.
-
-
-def isdict(name):
-    return name in (XNAME_DICT, LNAME_DICT)
-
-
-def isitem(name):
-    return name in (XNAME_ITEM, LNAME_ITEM)
-
-
-def iskey(name):
-    return name in (XNAME_KEY, LNAME_KEY)
-
-
-def islist(name):
-    return name in (XNAME_LIST, LNAME_LIST)
-
-
-def hasattrs(element):
-    return len(element.attrib) > 0
-
-
-def localname(xname):
-    rcurly = xname.find("}")
-    return xname if rcurly == -1 else xname[rcurly + 1 :]
-
-
-def load(text, match=None):
-    """This function reads a string that contains the XML of an Atom Feed, then
-    returns the
-    data in a native Python structure (a ``dict`` or ``list``). If you also
-    provide a tag name or path to match, only the matching sub-elements are
-    loaded.
-
-    :param text: The XML text to load.
-    :type text: ``string``
-    :param match: A tag name or path to match (optional).
-    :type match: ``string``
-    """
-    if text is None:
-        return None
-    text = text.strip()
-    if len(text) == 0:
-        return None
-    nametable = {"namespaces": [], "names": {}}
-
-    root = XML(text)
-    items = [root] if match is None else root.findall(match)
-    count = len(items)
-    if count == 0:
-        return None
-    if count == 1:
-        return load_root(items[0], nametable)
-    return [load_root(item, nametable) for item in items]
-
-
-# Load the attributes of the given element.
-def load_attrs(element):
-    if not hasattrs(element):
-        return None
-    attrs = record()
-    for key, value in element.attrib.items():
-        attrs[key] = value
-    return attrs
-
-
-# Parse a  element and return a Python dict
-def load_dict(element, nametable=None):
-    value = record()
-    children = list(element)
-    for child in children:
-        assert iskey(child.tag)
-        name = child.attrib["name"]
-        value[name] = load_value(child, nametable)
-    return value
-
-
-# Loads the given elements attrs & value into single merged dict.
-def load_elem(element, nametable=None):
-    name = localname(element.tag)
-    attrs = load_attrs(element)
-    value = load_value(element, nametable)
-    if attrs is None:
-        return name, value
-    if value is None:
-        return name, attrs
-    # If value is simple, merge into attrs dict using special key
-    if isinstance(value, str):
-        attrs["$text"] = value
-        return name, attrs
-    # Both attrs & value are complex, so merge the two dicts, resolving collisions.
-    collision_keys = []
-    for key, val in attrs.items():
-        if key in value and key in collision_keys:
-            value[key].append(val)
-        elif key in value and key not in collision_keys:
-            value[key] = [value[key], val]
-            collision_keys.append(key)
-        else:
-            value[key] = val
-    return name, value
-
-
-# Parse a  element and return a Python list
-def load_list(element, nametable=None):
-    assert islist(element.tag)
-    value = []
-    children = list(element)
-    for child in children:
-        assert isitem(child.tag)
-        value.append(load_value(child, nametable))
-    return value
-
-
-# Load the given root element.
-def load_root(element, nametable=None):
-    tag = element.tag
-    if isdict(tag):
-        return load_dict(element, nametable)
-    if islist(tag):
-        return load_list(element, nametable)
-    k, v = load_elem(element, nametable)
-    return Record.fromkv(k, v)
-
-
-# Load the children of the given element.
-def load_value(element, nametable=None):
-    children = list(element)
-    count = len(children)
-
-    # No children, assume a simple text value
-    if count == 0:
-        text = element.text
-        if text is None:
-            return None
-
-        if len(text.strip()) == 0:
-            return None
-        return text
-
-    # Look for the special case of a single well-known structure
-    if count == 1:
-        child = children[0]
-        tag = child.tag
-        if isdict(tag):
-            return load_dict(child, nametable)
-        if islist(tag):
-            return load_list(child, nametable)
-
-    value = record()
-    for child in children:
-        name, item = load_elem(child, nametable)
-        # If we have seen this name before, promote the value to a list
-        if name in value:
-            current = value[name]
-            if not isinstance(current, list):
-                value[name] = [current]
-            value[name].append(item)
-        else:
-            value[name] = item
-
-    return value
-
-
-# A generic utility that enables "dot" access to dicts
-class Record(dict):
-    """This generic utility class enables dot access to members of a Python
-    dictionary.
-
-    Any key that is also a valid Python identifier can be retrieved as a field.
-    So, for an instance of ``Record`` called ``r``, ``r.key`` is equivalent to
-    ``r['key']``. A key such as ``invalid-key`` or ``invalid.key`` cannot be
-    retrieved as a field, because ``-`` and ``.`` are not allowed in
-    identifiers.
-
-    Keys of the form ``a.b.c`` are very natural to write in Python as fields. If
-    a group of keys shares a prefix ending in ``.``, you can retrieve keys as a
-    nested dictionary by calling only the prefix. For example, if ``r`` contains
-    keys ``'foo'``, ``'bar.baz'``, and ``'bar.qux'``, ``r.bar`` returns a record
-    with the keys ``baz`` and ``qux``. If a key contains multiple ``.``, each
-    one is placed into a nested dictionary, so you can write ``r.bar.qux`` or
-    ``r['bar.qux']`` interchangeably.
-    """
-
-    sep = "."
-
-    def __call__(self, *args):
-        if len(args) == 0:
-            return self
-        return Record((key, self[key]) for key in args)
-
-    def __getattr__(self, name):
-        try:
-            return self[name]
-        except KeyError:
-            raise AttributeError(name)
-
-    def __delattr__(self, name):
-        del self[name]
-
-    def __setattr__(self, name, value):
-        self[name] = value
-
-    @staticmethod
-    def fromkv(k, v):
-        result = record()
-        result[k] = v
-        return result
-
-    def __getitem__(self, key):
-        if key in self:
-            return dict.__getitem__(self, key)
-        key += self.sep
-        result = record()
-        for k, v in self.items():
-            if not k.startswith(key):
-                continue
-            suffix = k[len(key) :]
-            if "." in suffix:
-                ks = suffix.split(self.sep)
-                z = result
-                for x in ks[:-1]:
-                    if x not in z:
-                        z[x] = record()
-                    z = z[x]
-                z[ks[-1]] = v
-            else:
-                result[suffix] = v
-        if len(result) == 0:
-            raise KeyError(f"No key or prefix: {key}")
-        return result
-
-
-def record(value=None):
-    """This function returns a :class:`Record` instance constructed with an
-    initial value that you provide.
-
-    :param value: An initial record value.
-    :type value: ``dict``
-    """
-    if value is None:
-        value = {}
-    return Record(value)
diff --git a/apps/bitwarden_event_logs/lib/splunklib/modularinput/__init__.py b/apps/bitwarden_event_logs/lib/splunklib/modularinput/__init__.py
deleted file mode 100755
index 987d1f95..00000000
--- a/apps/bitwarden_event_logs/lib/splunklib/modularinput/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""The following imports allow these classes to be imported via
-the splunklib.modularinput package like so:
-
-from splunklib.modularinput import *
-"""
-
-from .argument import Argument
-from .event import Event
-from .event_writer import EventWriter
-from .input_definition import InputDefinition
-from .scheme import Scheme
-from .script import Script
-from .validation_definition import ValidationDefinition
diff --git a/apps/bitwarden_event_logs/lib/splunklib/modularinput/argument.py b/apps/bitwarden_event_logs/lib/splunklib/modularinput/argument.py
deleted file mode 100755
index 99203ca2..00000000
--- a/apps/bitwarden_event_logs/lib/splunklib/modularinput/argument.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# Copyright © 2011-2024 Splunk, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"): you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import xml.etree.ElementTree as ET
-
-
-class Argument:
-    """Class representing an argument to a modular input kind.
-
-    ``Argument`` is meant to be used with ``Scheme`` to generate an XML
-    definition of the modular input kind that Splunk understands.
-
-    ``name`` is the only required parameter for the constructor.
-
-        **Example with least parameters**::
-
-            arg1 = Argument(name="arg1")
-
-        **Example with all parameters**::
-
-            arg2 = Argument(
-                name="arg2",
-                description="This is an argument with lots of parameters",
-                validation="is_pos_int('some_name')",
-                data_type=Argument.data_type_number,
-                required_on_edit=True,
-                required_on_create=True
-            )
-    """
-
-    # Constant values, do not change.
-    # These should be used for setting the value of an Argument object's data_type field.
-    data_type_boolean = "BOOLEAN"
-    data_type_number = "NUMBER"
-    data_type_string = "STRING"
-
-    def __init__(
-        self,
-        name,
-        description=None,
-        validation=None,
-        data_type=data_type_string,
-        required_on_edit=False,
-        required_on_create=False,
-        title=None,
-    ):
-        """
-        :param name: ``string``, identifier for this argument in Splunk.
-        :param description: ``string``, human-readable description of the argument.
-        :param validation: ``string`` specifying how the argument should be validated, if using internal validation.
-               If using external validation, this will be ignored.
-        :param data_type: ``string``, data type of this field; use the class constants.
-               "data_type_boolean", "data_type_number", or "data_type_string".
-        :param required_on_edit: ``Boolean``, whether this arg is required when editing an existing modular input of this kind.
-        :param required_on_create: ``Boolean``, whether this arg is required when creating a modular input of this kind.
-        :param title: ``String``, a human-readable title for the argument.
-        """
-        self.name = name
-        self.description = description
-        self.validation = validation
-        self.data_type = data_type
-        self.required_on_edit = required_on_edit
-        self.required_on_create = required_on_create
-        self.title = title
-
-    def add_to_document(self, parent):
-        """Adds an ``Argument`` object to this ElementTree document.
-
-        Adds an  subelement to the parent element, typically 
-        and sets up its subelements with their respective text.
-
-        :param parent: An ``ET.Element`` to be the parent of a new  subelement
-        :returns: An ``ET.Element`` object representing this argument.
-        """
-        arg = ET.SubElement(parent, "arg")
-        arg.set("name", self.name)
-
-        if self.title is not None:
-            ET.SubElement(arg, "title").text = self.title
-
-        if self.description is not None:
-            ET.SubElement(arg, "description").text = self.description
-
-        if self.validation is not None:
-            ET.SubElement(arg, "validation").text = self.validation
-
-        # add all other subelements to this Argument, represented by (tag, text)
-        subelements = [
-            ("data_type", self.data_type),
-            ("required_on_edit", self.required_on_edit),
-            ("required_on_create", self.required_on_create),
-        ]
-
-        for name, value in subelements:
-            ET.SubElement(arg, name).text = str(value).lower()
-
-        return arg
diff --git a/apps/bitwarden_event_logs/lib/splunklib/modularinput/event.py b/apps/bitwarden_event_logs/lib/splunklib/modularinput/event.py
deleted file mode 100755
index 4d243c75..00000000
--- a/apps/bitwarden_event_logs/lib/splunklib/modularinput/event.py
+++ /dev/null
@@ -1,124 +0,0 @@
-# Copyright © 2011-2024 Splunk, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"): you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from io import TextIOBase
-import xml.etree.ElementTree as ET
-
-from ..utils import ensure_str
-
-
-class Event:
-    """Represents an event or fragment of an event to be written by this modular input to Splunk.
-
-    To write an input to a stream, call the ``write_to`` function, passing in a stream.
-    """
-
-    def __init__(
-        self,
-        data=None,
-        stanza=None,
-        time=None,
-        host=None,
-        index=None,
-        source=None,
-        sourcetype=None,
-        done=True,
-        unbroken=True,
-    ):
-        """There are no required parameters for constructing an Event
-
-        **Example with minimal configuration**::
-
-            my_event = Event(
-                data="This is a test of my new event.",
-                stanza="myStanzaName",
-                time="%.3f" % 1372187084.000
-            )
-
-        **Example with full configuration**::
-
-            excellent_event = Event(
-                data="This is a test of my excellent event.",
-                stanza="excellenceOnly",
-                time="%.3f" % 1372274622.493,
-                host="localhost",
-                index="main",
-                source="Splunk",
-                sourcetype="misc",
-                done=True,
-                unbroken=True
-            )
-
-        :param data: ``string``, the event's text.
-        :param stanza: ``string``, name of the input this event should be sent to.
-        :param time: ``float``, time in seconds, including up to 3 decimal places to represent milliseconds.
-        :param host: ``string``, the event's host, ex: localhost.
-        :param index: ``string``, the index this event is specified to write to, or None if default index.
-        :param source: ``string``, the source of this event, or None to have Splunk guess.
-        :param sourcetype: ``string``, source type currently set on this event, or None to have Splunk guess.
-        :param done: ``boolean``, is this a complete ``Event``? False if an ``Event`` fragment.
-        :param unbroken: ``boolean``, Is this event completely encapsulated in this ``Event`` object?
-        """
-        self.data = data
-        self.done = done
-        self.host = host
-        self.index = index
-        self.source = source
-        self.sourceType = sourcetype
-        self.stanza = stanza
-        self.time = time
-        self.unbroken = unbroken
-
-    def write_to(self, stream):
-        """Write an XML representation of self, an ``Event`` object, to the given stream.
-
-        The ``Event`` object will only be written if its data field is defined,
-        otherwise a ``ValueError`` is raised.
-
-        :param stream: stream to write XML to.
-        """
-        if self.data is None:
-            raise ValueError(
-                "Events must have at least the data field set to be written to XML."
-            )
-
-        event = ET.Element("event")
-        if self.stanza is not None:
-            event.set("stanza", self.stanza)
-        event.set("unbroken", str(int(self.unbroken)))
-
-        # if a time isn't set, let Splunk guess by not creating a