From 1e407e34e5ec41da9714b0deaf09707fbca47f39 Mon Sep 17 00:00:00 2001
From: yu-i-i
Date: Mon, 9 Dec 2024 06:18:51 +0100
Subject: [PATCH] Update README.md
---
README.md | 675 +++++++++++++++++++++++++++++++++++++++++++--
doc/screenshot.png | Bin 601370 -> 1080606 bytes
2 files changed, 659 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
index 7e15159eb9..2dd7ab63d0 100644
--- a/README.md
+++ b/README.md
@@ -14,30 +14,676 @@
License
-
+
- Figure 1: A screenshot of a project being edited in Overleaf Community Edition.
+ Figure 1: A screenshot of a project being edited in Overleaf Extended Community Edition.
## Community Edition
-[Overleaf](https://www.overleaf.com) is an open-source online real-time collaborative LaTeX editor. We run a hosted version at [www.overleaf.com](https://www.overleaf.com), but you can also run your own local version, and contribute to the development of Overleaf.
+[Overleaf](https://www.overleaf.com) is an open-source online real-time collaborative LaTeX editor. Overleaf runs a hosted version at [www.overleaf.com](https://www.overleaf.com), but you can also run your own local version, and contribute to the development of Overleaf.
+
+## Extended Community Edition
+
+The present "extended" version of Overleaf CE includes:
+
+- Sandboxed Compiles with TeX Live image selection
+- LDAP authentication
+- SAML authentication
+- Real-time track changes and comments
+- Autocomplete of reference keys
+- Symbol Palette
## Enterprise
-If you want help installing and maintaining Overleaf in your lab or workplace, we offer an officially supported version called [Overleaf Server Pro](https://www.overleaf.com/for/enterprises). It also includes more features for security (SSO with LDAP or SAML), administration and collaboration (e.g. tracked changes). [Find out more!](https://www.overleaf.com/for/enterprises)
-
-## Keeping up to date
-
-Sign up to the [mailing list](https://mailchi.mp/overleaf.com/community-edition-and-server-pro) to get updates on Overleaf releases and development.
+If you want help installing and maintaining Overleaf in your lab or workplace, Overleaf offers an officially supported version called [Overleaf Server Pro](https://www.overleaf.com/for/enterprises).
## Installation
-We have detailed installation instructions in the [Overleaf Toolkit](https://github.com/overleaf/toolkit/).
+Detailed installation instructions can be found in the [Overleaf Toolkit](https://github.com/overleaf/toolkit/).
+To run a custom image, add a file named docker-compose.override.yml with the following or similar content into the `overleaf-toolkit/config directory`:
-## Upgrading
+```yml
+---
+version: '2.2'
+services:
+ sharelatex:
+ image: sharelatex/sharelatex:ext-ce
+ volumes:
+ - ../config/certs:/overleaf/certs
+```
+Here, the attached volume provides convenient access for the container to the certificates needed for SAML or LDAP authentication.
-If you are upgrading from a previous version of Overleaf, please see the [Release Notes section on the Wiki](https://github.com/overleaf/overleaf/wiki#release-notes) for all of the versions between your current version and the version you are upgrading to.
+If you want to build a Docker image of the extended CE based on the upstream v5.2.1 codebase, you can check out the corresponding tag by running:
+```
+git checkout v5.2.1-ext
+```
+Alternatively, you can download a prebuilt image from Docker Hub:
+```
+docker pull overleafcep/sharelatex:5.2.1-ext
+```
+Make sure to update the image name in overleaf-toolkit/config/docker-compose.override.yml accordingly.
+
+## Sandboxed Compiles
+
+To enable sandboxed compiles (also known as "Sibling containers"), set the following configuration options in `overleaf-toolkit/config/overleaf.rc`:
+
+```
+SERVER_PRO=true
+SIBLING_CONTAINERS_ENABLED=true
+```
+
+The following environment variables are used to specify which TeX Live images to use for sandboxed compiles:
+
+- `ALL_TEX_LIVE_DOCKER_IMAGES` **(required)**
+ * A comma-separated list of TeX Live images to use. These images will be downloaded or updated.
+ To skip downloading the images, set `SIBLING_CONTAINERS_PULL=false` in `config/overleaf.rc`.
+- `ALL_TEX_LIVE_DOCKER_IMAGE_NAMES`
+ * A comma-separated list of friendly names for the images. If omitted, the version name will be used (e.g., `latest-full`).
+- `TEX_LIVE_DOCKER_IMAGE` **(required)**
+ * The default TeX Live image that will be used for compiling new projects. The environment variable `ALL_TEX_LIVE_DOCKER_IMAGES` must include this image.
+
+Users can select the image for their project in the project menu.
+
+Here is an example where the default TeX Live image is `latest-full` from Docker Hub, but the `TL2023-historic` image can be used for older projects:
+```
+ALL_TEX_LIVE_DOCKER_IMAGES=texlive/texlive:latest-full, texlive/texlive:TL2023-historic
+ALL_TEX_LIVE_DOCKER_IMAGE_NAMES=TeXLive 2024, TeXLive 2023
+TEX_LIVE_DOCKER_IMAGE=texlive/texlive:latest-full
+```
+For additional details refer to
+[Server Pro: Sandboxed Compiles](https://github.com/overleaf/overleaf/wiki/Server-Pro:-Sandboxed-Compiles) and
+[Toolkit: Sandboxed Compiles](https://github.com/overleaf/toolkit/blob/master/doc/sandboxed-compiles.md).
+
+
+Sample variables.env file
+
+```
+OVERLEAF_APP_NAME="Our Overleaf Instance"
+
+ENABLED_LINKED_FILE_TYPES=project_file,project_output_file
+
+# Enables Thumbnail generation using ImageMagick
+ENABLE_CONVERSIONS=true
+
+# Disables email confirmation requirement
+EMAIL_CONFIRMATION_DISABLED=true
+
+## Nginx
+# NGINX_WORKER_PROCESSES=4
+# NGINX_WORKER_CONNECTIONS=768
+
+## Set for TLS via nginx-proxy
+# OVERLEAF_BEHIND_PROXY=true
+# OVERLEAF_SECURE_COOKIE=true
+
+OVERLEAF_SITE_URL=http://my-overleaf-instance.com
+OVERLEAF_NAV_TITLE=Our Overleaf Instance
+# OVERLEAF_HEADER_IMAGE_URL=http://somewhere.com/mylogo.png
+OVERLEAF_ADMIN_EMAIL=support@example.com
+
+OVERLEAF_LEFT_FOOTER=[{"text": "Contact your support team", "url": "mailto:support@example.com"}]
+OVERLEAF_RIGHT_FOOTER=[{"text":"Hello, I am on the Right", "url":"https://github.com/yu-i-i/overleaf-cep"}]
+
+OVERLEAF_EMAIL_FROM_ADDRESS=team@example.com
+OVERLEAF_EMAIL_SMTP_HOST=smtp.example.com
+OVERLEAF_EMAIL_SMTP_PORT=587
+OVERLEAF_EMAIL_SMTP_SECURE=false
+# OVERLEAF_EMAIL_SMTP_USER=
+# OVERLEAF_EMAIL_SMTP_PASS=
+# OVERLEAF_EMAIL_SMTP_NAME=
+OVERLEAF_EMAIL_SMTP_LOGGER=false
+OVERLEAF_EMAIL_SMTP_TLS_REJECT_UNAUTH=true
+OVERLEAF_EMAIL_SMTP_IGNORE_TLS=false
+OVERLEAF_CUSTOM_EMAIL_FOOTER=This system is run by department x
+
+OVERLEAF_PROXY_LEARN=true
+NAV_HIDE_POWERED_BY=true
+
+########################
+## Sandboxed Compiles ##
+########################
+
+ALL_TEX_LIVE_DOCKER_IMAGES=texlive/texlive:latest-full, texlive/texlive:TL2023-historic
+ALL_TEX_LIVE_DOCKER_IMAGE_NAMES=TeXLive 2024, TeXLive 2023
+TEX_LIVE_DOCKER_IMAGE=texlive/texlive:latest-full
+```
+
+
+## Authentication Methods
+
+The following authentication methods are supported: Local authentication, LDAP authentication, and SAML authentication. Local authentication is always active.
+To enable LDAP or SAML authentication, the environment variable `EXTERNAL_AUTH` must be set to `ldap` or `saml`, respectively.
+
+
+Local Authentication
+
+Password of local users stored in the MongoDB database. An admin user can create a new local user. For details, visit the
+[wiki of Overleaf project](https://github.com/overleaf/overleaf/wiki/Creating-and-managing-users).
+
+It is possible to enforce password restrictions on local users:
+
+
+* `OVERLEAF_PASSWORD_VALIDATION_MIN_LENGTH`: The minimum length required
+
+* `OVERLEAF_PASSWORD_VALIDATION_MAX_LENGTH`: The maximum length allowed
+
+* `OVERLEAF_PASSWORD_VALIDATION_PATTERN`: is used to validate password strength
+
+ - `abc123` – password requires 3 letters and 3 numbers and be at least 6 characters long
+ - `aA` – password requires lower and uppercase letters and be at least 2 characters long
+ - `ab$3` – it must contain letters, digits and symbols and be at least 4 characters long
+ - There are 4 groups of characters: letters, UPPERcase letters, digits, symbols. Anything that is neither a letter nor a digit is considered to be a symbol.
+
+
+
+
+LDAP Authentication
+
+Internally, Overleaf LDAP uses the [passport-ldapauth](https://github.com/vesse/passport-ldapauth) library. Most of these configuration options are passed through to the `server` config object which is used to configure `passport-ldapauth`. If you are having issues configuring LDAP, it is worth reading the README for `passport-ldapauth` to understand the configuration it expects.
+
+#### Environment Variables
+
+- `OVERLEAF_LDAP_URL` **(required)**
+ * URL of the LDAP server.
+
+ - Example: `ldaps://ldap.example.com:636` (LDAP over SSL)
+ - Example: `ldap://ldap.example.com:389` (unencrypted or STARTTLS, if configured).
+
+- `OVERLEAF_LDAP_EMAIL_ATT`
+ * The email attribute returned by the LDAP server, default `mail`. Each LDAP user must have at least one email address.
+ If multiple addresses are provided, only the first one will be used.
+
+- `OVERLEAF_LDAP_FIRST_NAME_ATT`
+ * The property name holding the first name of the user which is used in the application, usually `givenName`.
+
+- `OVERLEAF_LDAP_LAST_NAME_ATT`
+ * The property name holding the family name of the user which is used in the application, usually `sn`.
+
+- `OVERLEAF_LDAP_NAME_ATT`
+ * The property name holding the full name of the user, usually `cn`. If either of the two previous variables is not defined,
+ the first and/or last name of the user is extracted from this variable. Otherwise, it is not used.
+
+- `OVERLEAF_LDAP_PLACEHOLDER`
+ * The placeholder for the login form, defaults to `Username`.
+
+- `OVERLEAF_LDAP_UPDATE_USER_DETAILS_ON_LOGIN`
+ * If set to `true`, updates the LDAP user `first_name` and `last_name` field on login, and turn off the user details form on the `/user/settings`
+ page for LDAP users. Otherwise, details will be fetched only on first login.
+
+- `OVERLEAF_LDAP_BIND_DN`
+ * The distinguished name of the LDAP user that should be used for the LDAP connection
+ (this user should be able to search/list accounts on the LDAP server),
+ e.g., `cn=ldap_reader,dc=example,dc=com`. If not defined, anonymous binding is used.
+
+- `OVERLEAF_LDAP_BIND_CREDENTIALS`
+ * Password for `OVERLEAF_LDAP_BIND_DN`.
+
+- `OVERLEAF_LDAP_BIND_PROPERTY`
+ * Property of the user to bind against the client, defaults to `dn`.
+
+- `OVERLEAF_LDAP_SEARCH_BASE` **(required)**
+ * The base DN from which to search for users. E.g., `ou=people,dc=example,dc=com`.
+
+- `OVERLEAF_LDAP_SEARCH_FILTER`
+ * LDAP search filter with which to find a user. Use the literal '{{username}}' to have the given username be interpolated in for the LDAP search.
+
+ - Example: `(|(uid={{username}})(mail={{username}}))` (user can login with email or with login name).
+ - Example: `(sAMAccountName={{username}})` (Active Directory).
+
+- `OVERLEAF_LDAP_SEARCH_SCOPE`
+ * The scope of the search can be `base`, `one`, or `sub` (default).
+
+- `OVERLEAF_LDAP_SEARCH_ATTRIBUTES`
+ * JSON array of attributes to fetch from the LDAP server, e.g., `["uid", "mail", "givenName", "sn"]`.
+ By default, all attributes are fetched.
+
+- `OVERLEAF_LDAP_STARTTLS`
+ * If `true`, LDAP over TLS is used.
+
+- `OVERLEAF_LDAP_TLS_OPTS_CA_PATH`
+ * Path to the file containing the CA certificate used to verify the LDAP server's SSL/TLS certificate. If there are multiple certificates, then
+ it can be a JSON array of paths to the certificates. The files must be accessible to the docker container.
+
+ - Example (one certificate): `/overleaf/certs/ldap_ca_cert.pem`
+ - Example (multiple certificates): `["/overleaf/certs/ldap_ca_cert1.pem", "/overleaf/certs/ldap_ca_cert2.pem"]`
+
+- `OVERLEAF_LDAP_TLS_OPTS_REJECT_UNAUTH`
+ * If `true`, the server certificate is verified against the list of supplied CAs.
+
+- `OVERLEAF_LDAP_CACHE`
+ * If `true`, then up to 100 credentials at a time will be cached for 5 minutes.
+
+- `OVERLEAF_LDAP_TIMEOUT`
+ * How long the client should let operations live for before timing out, ms (Default: Infinity).
+
+- `OVERLEAF_LDAP_CONNECT_TIMEOUT`
+ * How long the client should wait before timing out on TCP connections, ms (Default: OS default).
+
+- `OVERLEAF_LDAP_IS_ADMIN_ATT` and `OVERLEAF_LDAP_IS_ADMIN_ATT_VALUE`
+ * When both environment variables are set, the login process updates `user.isAdmin = true` if the LDAP profile contains the attribute specified by
+ `OVERLEAF_LDAP_IS_ADMIN_ATT` and its value either matches `OVERLEAF_LDAP_IS_ADMIN_ATT_VALUE` or is an array containing `OVERLEAF_LDAP_IS_ADMIN_ATT_VALUE`,
+ otherwise `user.isAdmin` is set to `false`. If either of these variables is not set, then the admin status is only set to `true` during admin user
+ creation in Launchpad.
+
+The following five variables are used to configure how user contacts are retrieved from the LDAP server.
+
+- `OVERLEAF_LDAP_CONTACTS_FILTER`
+ * The filter used to search for users in the LDAP server to be loaded into contacts. The placeholder '{{userProperty}}' within the filter is replaced with the value of
+ the property specified by `OVERLEAF_LDAP_CONTACTS_PROPERTY` from the LDAP user initiating the search. If not defined, no users are retrieved from the LDAP server into contacts.
+
+- `OVERLEAF_LDAP_CONTACTS_SEARCH_BASE`
+ * Specifies the base DN from which to start searching for the contacts. Defaults to `OVERLEAF_LDAP_SEARCH_BASE`.
+
+- `OVERLEAF_LDAP_CONTACTS_SEARCH_SCOPE`
+ * The scope of the search can be `base`, `one`, or `sub` (default).
+
+- `OVERLEAF_LDAP_CONTACTS_PROPERTY`
+ * Specifies the property of the user object that will replace the '{{userProperty}}' placeholder in the `OVERLEAF_LDAP_CONTACTS_FILTER`.
+
+- `OVERLEAF_LDAP_CONTACTS_NON_LDAP_VALUE`
+ * Specifies the value of the `OVERLEAF_LDAP_CONTACTS_PROPERTY` if the search is initiated by a non-LDAP user. If this variable is not defined, the resulting filter
+ will match nothing. The value `*` can be used as a wildcard.
+
+
+Example
+
+ OVERLEAF_LDAP_CONTACTS_FILTER=(gidNumber={{userProperty}})
+ OVERLEAF_LDAP_CONTACTS_PROPERTY=gidNumber
+ OVERLEAF_LDAP_CONTACTS_NON_LDAP_VALUE=1000
+
+The above example results in loading into the contacts of the current LDAP user all LDAP users who have the same UNIX `gid`. Non-LDAP users will have all LDAP users with UNIX `gid=1000` in their contacts.
+
+
+
+
+
+Sample variables.env file
+
+```
+OVERLEAF_APP_NAME="Our Overleaf Instance"
+
+ENABLED_LINKED_FILE_TYPES=project_file,project_output_file
+
+# Enables Thumbnail generation using ImageMagick
+ENABLE_CONVERSIONS=true
+
+# Disables email confirmation requirement
+EMAIL_CONFIRMATION_DISABLED=true
+
+## Nginx
+# NGINX_WORKER_PROCESSES=4
+# NGINX_WORKER_CONNECTIONS=768
+
+## Set for TLS via nginx-proxy
+# OVERLEAF_BEHIND_PROXY=true
+# OVERLEAF_SECURE_COOKIE=true
+
+OVERLEAF_SITE_URL=http://my-overleaf-instance.com
+OVERLEAF_NAV_TITLE=Our Overleaf Instance
+# OVERLEAF_HEADER_IMAGE_URL=http://somewhere.com/mylogo.png
+OVERLEAF_ADMIN_EMAIL=support@example.com
+
+OVERLEAF_LEFT_FOOTER=[{"text": "Contact your support team", "url": "mailto:support@example.com"}]
+OVERLEAF_RIGHT_FOOTER=[{"text":"Hello, I am on the Right", "url":"https://github.com/yu-i-i/overleaf-cep"}]
+
+OVERLEAF_EMAIL_FROM_ADDRESS=team@example.com
+OVERLEAF_EMAIL_SMTP_HOST=smtp.example.com
+OVERLEAF_EMAIL_SMTP_PORT=587
+OVERLEAF_EMAIL_SMTP_SECURE=false
+# OVERLEAF_EMAIL_SMTP_USER=
+# OVERLEAF_EMAIL_SMTP_PASS=
+# OVERLEAF_EMAIL_SMTP_NAME=
+OVERLEAF_EMAIL_SMTP_LOGGER=false
+OVERLEAF_EMAIL_SMTP_TLS_REJECT_UNAUTH=true
+OVERLEAF_EMAIL_SMTP_IGNORE_TLS=false
+OVERLEAF_CUSTOM_EMAIL_FOOTER=This system is run by department x
+
+OVERLEAF_PROXY_LEARN=true
+NAV_HIDE_POWERED_BY=true
+
+#################
+## LDAP for CE ##
+#################
+
+EXTERNAL_AUTH=ldap
+OVERLEAF_LDAP_URL=ldap://ldap.example.com:389
+OVERLEAF_LDAP_STARTTLS=true
+OVERLEAF_LDAP_TLS_OPTS_CA_PATH=/overleaf/certs/ldap_ca_cert.pem
+OVERLEAF_LDAP_SEARCH_BASE=ou=people,dc=example,dc=com
+OVERLEAF_LDAP_SEARCH_FILTER=(|(uid={{username}})(mail={{username}}))
+OVERLEAF_LDAP_BIND_DN=cn=ldap_reader,dc=example,dc=com
+OVERLEAF_LDAP_BIND_CREDENTIALS=GoodNewsEveryone
+OVERLEAF_LDAP_EMAIL_ATT=mail
+OVERLEAF_LDAP_FIRST_NAME_ATT=givenName
+OVERLEAF_LDAP_LAST_NAME_ATT=sn
+# OVERLEAF_LDAP_NAME_ATT=cn
+OVERLEAF_LDAP_SEARCH_ATTRIBUTES=["uid", "sn", "givenName", "mail"]
+
+OVERLEAF_LDAP_UPDATE_USER_DETAILS_ON_LOGIN=true
+
+OVERLEAF_LDAP_PLACEHOLDER='Username or email address'
+
+OVERLEAF_LDAP_IS_ADMIN_ATT=mail
+OVERLEAF_LDAP_IS_ADMIN_ATT_VALUE=admin@example.com
+
+OVERLEAF_LDAP_CONTACTS_FILTER=(gidNumber={{userProperty}})
+OVERLEAF_LDAP_CONTACTS_PROPERTY=gidNumber
+OVERLEAF_LDAP_CONTACTS_NON_LDAP_VALUE='*'
+```
+
+
+
+Deprecated variables
+
+**These variables will be removed soon**, use `OVERLEAF_LDAP_IS_ADMIN_ATT` and `OVERLEAF_LDAP_IS_ADMIN_ATT_VALUE` instead.
+
+The following variables are used to determine if the user has admin rights.
+Please note: the user gains admin status if the search result is not empty, not when the user is explicitly included in the search results.
+
+- `OVERLEAF_LDAP_ADMIN_SEARCH_BASE`
+ * Specifies the base DN from which to start searching for the admin group. If this variable is defined,
+ `OVERLEAF_LDAP_ADMIN_SEARCH_FILTER` must also be defined for the search to function properly.
+
+- `OVERLEAF_LDAP_ADMIN_SEARCH_FILTER`
+ * Defines the LDAP search filter used to identify the admin group. The placeholder `{{dn}}` within the filter
+ is replaced with the value of the property specified by `OVERLEAF_LDAP_ADMIN_DN_PROPERTY`. The placeholder `{{username}}` is also supported.
+
+- `OVERLEAF_LDAP_ADMIN_DN_PROPERTY`
+ * Specifies the property of the user object that will replace the '{{dn}}' placeholder
+ in the `OVERLEAF_LDAP_ADMIN_SEARCH_FILTER`, defaults to `dn`.
+
+- `OVERLEAF_LDAP_ADMIN_SEARCH_SCOPE`
+ * The scope of the LDAP search can be `base`, `one`, or `sub` (default)
+
+
+Example
+
+In the following example admins are members of a group `admins`, the objectClass of the entry `admins` is `groupOfNames`:
+
+ OVERLEAF_LDAP_ADMIN_SEARCH_BASE='cn=admins,ou=group,dc=example,dc=com'
+ OVERLEAF_LDAP_ADMIN_SEARCH_FILTER='(member={{dn}})'
+
+In the following example admins are members of a group 'admins', the objectClass of the entry `admins` is `posixGroup`:
+
+ OVERLEAF_LDAP_ADMIN_SEARCH_BASE='cn=admins,ou=group,dc=example,dc=com'
+ OVERLEAF_LDAP_ADMIN_SEARCH_FILTER='(memberUid={{username}})'
+
+In the following example admins are users with UNIX gid=1234:
+
+ OVERLEAF_LDAP_ADMIN_SEARCH_BASE='ou=people,dc=example,dc=com'
+ OVERLEAF_LDAP_ADMIN_SEARCH_FILTER='(&(gidNumber=1234)(uid={{username}}))'
+
+In the following example admin is the user with `uid=someuser`:
+
+ OVERLEAF_LDAP_ADMIN_SEARCH_BASE='ou=people,dc=example,dc=com'
+ OVERLEAF_LDAP_ADMIN_SEARCH_FILTER='(&(uid=someuser)(uid={{username}}))'
+
+The filter
+
+ OVERLEAF_LDAP_ADMIN_SEARCH_FILTER='(uid=someuser)'
+
+where `someuser` is the uid of an existing user, will always produce a non-empty search result.
+As a result, **every user will be granted admin rights**, not just `someuser`, as one might expect.
+
+
+
+
+
+
+SAML Authentication
+
+Internally, Overleaf SAML module uses the [passport-saml](https://github.com/node-saml/passport-saml) library, most of the following
+configuration options are passed through to `passport-saml`. If you are having issues configuring SAML, it is worth reading the README
+for `passport-saml` to get a feel for the configuration it expects.
+
+#### Environment Variables
+
+- `OVERLEAF_SAML_IDENTITY_SERVICE_NAME`
+ * Display name for the identity service, used on the login page (default: `Login with SAML IdP`).
+
+- `OVERLEAF_SAML_EMAIL_FIELD`
+ * Name of the Email field in user profile, default to 'nameID'.
+
+- `OVERLEAF_SAML_FIRST_NAME_FIELD`
+ * Name of the firstName field in user profile, default to 'givenName'.
+
+- `OVERLEAF_SAML_LAST_NAME_FIELD`
+ * Name of the lastName field in user profile, default to 'lastName'
+
+- `OVERLEAF_SAML_UPDATE_USER_DETAILS_ON_LOGIN`
+ * If set to `true`, updates the user `first_name` and `last_name` field on login,
+ and turn off the user details form on `/user/settings` page.
+
+- `OVERLEAF_SAML_ENTRYPOINT` **(required)**
+ * Entrypoint URL for the SAML identity service.
+
+ - Example: `https://idp.example.com/simplesaml/saml2/idp/SSOService.php`
+ - Azure Example: `https://login.microsoftonline.com/8b26b46a-6dd3-45c7-a104-f883f4db1f6b/saml2`
+
+- `OVERLEAF_SAML_CALLBACK_URL` **(required)**
+ * Callback URL for Overleaf service. Should be the full URL of the `/saml/login/callback` path.
+
+ - Example: `https://my-overleaf-instance.com/saml/login/callback`
+
+- `OVERLEAF_SAML_ISSUER` **(required)**
+ * The Issuer name.
+
+- `OVERLEAF_SAML_AUDIENCE`
+ * Expected saml response Audience, defaults to value of `OVERLEAF_SAML_ISSUER`.
+
+- `OVERLEAF_SAML_IDP_CERT` **(required)**
+ * Path to a file containing the Identity Provider's public certificate, used to validate the signatures of incoming SAML responses. If the Identity Provider has multiple valid signing certificates, then
+ it can be a JSON array of paths to the certificates.
+
+ - Example (one certificate): `/overleaf/certs/idp_cert.pem`
+ - Example (multiple certificates): `["/overleaf/certs/idp_cert.pem", "/overleaf/certs/idp_cert_old.pem"]`
+
+- `OVERLEAF_SAML_PUBLIC_CERT`
+ * Path to a file containing public signing certificate used to embed in auth requests in order for the IdP to validate the signatures of the incoming SAML Request. It's required when setting up the [metadata endpoint](#metadata-for-the-identity-provider)
+ when the strategy is configured with a `OVERLEAF_SAML_PRIVATE_KEY`. A JSON array of paths to certificates can be provided to support certificate rotation. When supplying an array of certificates, the first entry in the array should match the
+ current `OVERLEAF_SAML_PRIVATE_KEY`. Additional entries in the array can be used to publish upcoming certificates to IdPs before changing the `OVERLEAF_SAML_PRIVATE_KEY`.
+
+- `OVERLEAF_SAML_PRIVATE_KEY`
+ * Path to a file containing a PEM-formatted private key matching the `OVERLEAF_SAML_PUBLIC_CERT` used to sign auth requests sent by passport-saml.
+
+- `OVERLEAF_SAML_DECRYPTION_CERT`
+ * Path to a file containing public certificate, used for the [metadata endpoint](#metadata-for-the-identity-provider).
+
+- `OVERLEAF_SAML_DECRYPTION_PVK`
+ * Path to a file containing private key matching the `OVERLEAF_SAML_DECRYPTION_CERT` that will be used to attempt to decrypt any encrypted assertions that are received.
+
+- `OVERLEAF_SAML_SIGNATURE_ALGORITHM`
+ * Optionally set the signature algorithm for signing requests,
+ valid values are 'sha1' (default), 'sha256' (prefered), 'sha512' (most secure, check if your IdP supports it).
+
+- `OVERLEAF_SAML_ADDITIONAL_PARAMS`
+ * JSON dictionary of additional query params to add to all requests.
+
+- `OVERLEAF_SAML_ADDITIONAL_AUTHORIZE_PARAMS`
+ * JSON dictionary of additional query params to add to 'authorize' requests.
+
+ - Example: `{"some_key": "some_value"}`
+
+- `OVERLEAF_SAML_IDENTIFIER_FORMAT`
+ * Name identifier format to request from identity provider (default: `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`).
+
+- `OVERLEAF_SAML_ACCEPTED_CLOCK_SKEW_MS`
+ * Time in milliseconds of skew that is acceptable between client and server when checking OnBefore and NotOnOrAfter assertion
+ condition validity timestamps. Setting to -1 will disable checking these conditions entirely. Default is 0.
+
+- `OVERLEAF_SAML_ATTRIBUTE_CONSUMING_SERVICE_INDEX`
+ * `AttributeConsumingServiceIndex` attribute to add to AuthnRequest to instruct the IdP which attribute set to attach
+ to the response ([link](http://blog.aniljohn.com/2014/01/data-minimization-front-channel-saml-attribute-requests.html)).
+
+- `OVERLEAF_SAML_AUTHN_CONTEXT`
+ * JSON array of name identifier format values to request auth context. Default: `["urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"]`.
+
+- `OVERLEAF_SAML_FORCE_AUTHN`
+ * If `true`, the initial SAML request from the service provider specifies that the IdP should force re-authentication of the user,
+ even if they possess a valid session.
+
+- `OVERLEAF_SAML_DISABLE_REQUESTED_AUTHN_CONTEXT`
+ * If `true`, do not request a specific auth context. For example, you can this this to `true` to allow additional contexts such as password-less logins (`urn:oasis:names:tc:SAML:2.0:ac:classes:X509`). Support for additional contexts is dependant on your IdP.
+
+- `OVERLEAF_SAML_AUTHN_REQUEST_BINDING`
+ * If set to `HTTP-POST`, will request authentication from IdP via HTTP POST binding, otherwise defaults to HTTP-Redirect.
+
+- `OVERLEAF_SAML_VALIDATE_IN_RESPONSE_TO`
+ * If `always`, then InResponseTo will be validated from incoming SAML responses.
+ * If `never`, then InResponseTo won't be validated (default).
+ * If `ifPresent`, then InResponseTo will only be validated if present in the incoming SAML response.
+
+- `OVERLEAF_SAML_REQUEST_ID_EXPIRATION_PERIOD_MS`
+ * Defines the expiration time when a Request ID generated for a SAML request will not be valid if seen
+ in a SAML response in the `InResponseTo` field. Default: 28800000 (8 hours).
+
+- `OVERLEAF_SAML_LOGOUT_URL`
+ * base address to call with logout requests (default: `entryPoint`).
+
+ - Example: `https://idp.example.com/simplesaml/saml2/idp/SingleLogoutService.php`
+
+- `OVERLEAF_SAML_LOGOUT_CALLBACK_URL`
+ * Callback URL for IdP initiated logout. Should be the full URL of the `/saml/logot/callback` path.
+ With this value the `Location` attribute in the `SingleLogoutService` elements in the generated service provider metadata is populated with this value.
+
+ - Example: `https://my-overleaf-instance.com/saml/logout/callback`
+
+- `OVERLEAF_SAML_ADDITIONAL_LOGOUT_PARAMS`
+ * JSON dictionary of additional query params to add to 'logout' requests.
+
+
+- `OVERLEAF_SAML_IS_ADMIN_FIELD` and `OVERLEAF_SAML_IS_ADMIN_FIELD_VALUE`
+ * When both environment variables are set, the login process updates `user.isAdmin = true` if the profile returned by the SAML IdP contains the attribute specified by
+ `OVERLEAF_SAML_IS_ADMIN_FIELD` and its value either matches `OVERLEAF_SAML_IS_ADMIN_FIELD_VALUE` or is an array containing `OVERLEAF_SAML_IS_ADMIN_FIELD_VALUE`,
+ otherwise `user.isAdmin` is set to `false`. If either of these variables is not set, then the admin status is only set to `true` during admin user.
+ creation in Launchpad.
+
+#### Metadata for the Identity Provider
+
+The current version of Overleaf CE includes and endpoint to retrieve Service Provider Metadata: `http://my-overleaf-instance.com/saml/meta`
+
+The Identity Provider will need to be configured to recognize the Overleaf server as a "Service Provider". Consult the documentation for your SAML server for instructions on how to do this.
+
+Below is an example of appropriate Service Provider metadata:
+
+
+ol-meta.xml
+
+```
+
+
+
+
+
+
+ MII...
+[skipped]
+
+
+
+
+
+
+
+ MII...
+[skipped]
+
+
+
+
+
+
+
+
+
+ urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
+
+
+
+
+```
+
+
+Note the certificates, `AssertionConsumerService.Location`, `SingleLogoutService.Location` and `EntityDescriptor.entityID`
+and set as appropriate in your IdP configuration, or send the metadata file to the IdP admin.
+
+
+Sample variables.env file
+
+```
+OVERLEAF_APP_NAME="Our Overleaf Instance"
+
+ENABLED_LINKED_FILE_TYPES=project_file,project_output_file
+
+# Enables Thumbnail generation using ImageMagick
+ENABLE_CONVERSIONS=true
+
+# Disables email confirmation requirement
+EMAIL_CONFIRMATION_DISABLED=true
+
+## Nginx
+# NGINX_WORKER_PROCESSES=4
+# NGINX_WORKER_CONNECTIONS=768
+
+## Set for TLS via nginx-proxy
+# OVERLEAF_BEHIND_PROXY=true
+# OVERLEAF_SECURE_COOKIE=true
+
+OVERLEAF_SITE_URL=http://my-overleaf-instance.com
+OVERLEAF_NAV_TITLE=Our Overleaf Instance
+# OVERLEAF_HEADER_IMAGE_URL=http://somewhere.com/mylogo.png
+OVERLEAF_ADMIN_EMAIL=support@example.com
+
+OVERLEAF_LEFT_FOOTER=[{"text": "Contact your support team", "url": "mailto:support@example.com"}]
+OVERLEAF_RIGHT_FOOTER=[{"text":"Hello, I am on the Right", "url":"https://github.com/yu-i-i/overleaf-cep"}]
+
+OVERLEAF_EMAIL_FROM_ADDRESS=team@example.com
+OVERLEAF_EMAIL_SMTP_HOST=smtp.example.com
+OVERLEAF_EMAIL_SMTP_PORT=587
+OVERLEAF_EMAIL_SMTP_SECURE=false
+# OVERLEAF_EMAIL_SMTP_USER=
+# OVERLEAF_EMAIL_SMTP_PASS=
+# OVERLEAF_EMAIL_SMTP_NAME=
+OVERLEAF_EMAIL_SMTP_LOGGER=false
+OVERLEAF_EMAIL_SMTP_TLS_REJECT_UNAUTH=true
+OVERLEAF_EMAIL_SMTP_IGNORE_TLS=false
+OVERLEAF_CUSTOM_EMAIL_FOOTER=This system is run by department x
+
+OVERLEAF_PROXY_LEARN=true
+NAV_HIDE_POWERED_BY=true
+
+#################
+## SAML for CE ##
+#################
+
+EXTERNAL_AUTH=saml
+OVERLEAF_SAML_IDENTITY_SERVICE_NAME='Login with My IdP'
+OVERLEAF_SAML_EMAIL_FIELD=mail
+OVERLEAF_SAML_FIRST_NAME_FIELD=givenName
+OVERLEAF_SAML_LAST_NAME_FIELD=sn
+OVERLEAF_SAML_ENTRYPOINT=https://idp.example.com/simplesamlphp/saml2/idp/SSOService.php
+OVERLEAF_SAML_CALLBACK_URL=https://my-overleaf-instance.com/saml/login/callback
+OVERLEAF_SAML_LOGOUT_URL=https://idp.example.com/simplesamlphp/saml2/idp/SingleLogoutService.php
+OVERLEAF_SAML_LOGOUT_CALLBACK_URL=https://my-overleaf-instance.com/saml/logout/callback
+OVERLEAF_SAML_ISSUER=MyOverleaf
+OVERLEAF_SAML_IDP_CERT=/overleaf/certs/idp_cert.pem
+OVERLEAF_SAML_PUBLIC_CERT=/overleaf/certs/myol_cert.pem
+OVERLEAF_SAML_PRIVATE_KEY=/overleaf/certs/myol_key.pem
+OVERLEAF_SAML_DECRYPTION_CERT=/overleaf/certs/myol_decr_cert.pem
+OVERLEAF_SAML_DECRYPTION_PVK=/overleaf/certs/myol_decr_key.pem
+OVERLEAF_SAML_IS_ADMIN_FIELD=mail
+OVERLEAF_SAML_IS_ADMIN_FIELD_VALUE=overleaf.admin@example.com
+```
+
+
## Overleaf Docker Image
@@ -60,14 +706,11 @@ in which to run the Overleaf services. Baseimage uses the `runit` service
manager to manage services, and we add our init-scripts from the `server-ce/runit`
folder.
-
-## Contributing
-
-Please see the [CONTRIBUTING](CONTRIBUTING.md) file for information on contributing to the development of Overleaf.
-
## Authors
[The Overleaf Team](https://www.overleaf.com/about)
+
+Extensions for CE by: [yu-i-i](https://github.com/yu-i-i/overleaf-cep)
## License
diff --git a/doc/screenshot.png b/doc/screenshot.png
index 1c1f339630b048780aed1e692290dada8aa23307..92633192a51ec83a2e16a0b41d2f4f0d7a392cf9 100644
GIT binary patch
literal 1080606
zcmZ5{by!sG*7uMOjiN9#gObwSEg(pPbW3-4r!asqbc1wvcd4{=mvju>@$Kh4=l$b+
za}9Y7>^=9s*IK{YpOqD5a4<=;laK?guhdk?QLcT+-IHqWx|??!$^6(+w5?D?fzuO9
zc@u8IQQOG;U8!G%&k~;1R6Uk2QS(_obj1sX@fM8S9|`}4Z=(GX|2ECVM2sO1P95q<
z3x?|08}bw25oL`uK3@TO{b_@!;nB!=6EZzPn{30arJp#UL|EK_9$gA_B0g+
z8oJu?J2lW4D)s+9{K3|NFLG;n(q^Klrt3=!bvK1PbCWP^4Ty
zjLAG8F)ns7aRN2g(4E^7A50K>piN~wdSIaVPqF79P&os)7&intDj3NKy%1d<1$2%5
zrmTY!1O~CE5Ldo5BRQ5ZR8_{Qn3Bp>7Q@ye!4~U0RtqFiu6^Wb#{?ZK91pATUT1`!
zkr#!iqM#nD)uJ1rVqWg_2k@{DnEpYPofDx=h!j9p*M`GBeQQW2alm2krzJf*m&*OU62n?D+4an#SqIdiO8`
zLQ@VrWd{YCUsQ0Tf!v|s;Otueo|rjclU-|wo~K1d8g60icKBSi=ZXX<5e>L#?>H#-vl38HuZ?fxoBxqr|k4
z`5Uwq?q&OP+Aum_%G0(2?)lBOxxkD352l!@vS4l;e5%kd{iI{ZyUlAFPkm#QjSpCY
zy+%rcX*V=H1UFTm!fwwbH+XI{4k2-+;ifT<1Ky_{eH1>KdGPr{Dlq-)P<%Nkw%^K(
z1lYE|TL4RvBt86pcRw|?KL@>a>a-;Cxtt^b*Mk1VWFu$zcGE?|eoFeR+vJ9v%qAe_<`_7tGn5
zp;FrKp?*QC#)@x)+*nEWD$Cp9wLjZ!uG_7-&|F(6yR^;cKQ5Aw
ztY~(T&_D(Yl`w$>sFoeantQH^Rn+BD>YTcR$zzLRKo9XJ<4GuW%>r-y=^oOF
zQvB#>Rg2g%+>P7{xT%}+P;Vw`pG3bLyZZq9_{{}3t9D%OZ4nGV7{8l;fFmRnzn?F|
zkL`i(|GQl4bZ9dvB%rL6Kx*~p)?lMO4rxvlO9lGCaP$V&1&vWFM<@z=C#Vy|-uWR!
z;6t5#q-{QG?VMH7$CiA~n(&1c1`1hjv-4QV&s(B?q7!?KuTHfUSM2FZAE7R1+C)WZ)cg!#HW^L7L+Fcl$OR%`p}@v
z541INOs}akN9XDlFraB9rf|$UTDWt6(ns$&xYOx(n+JrZ=i(Akjm_J4QvdU~|0Ev5
zX>dl0`Au1Y9wMjU2M(t-0#8Yy1X5q5oO%r22C?*NAGmUnD(~n`i;*(oIM=B$e0&*+
zB;hV?tZavk^!^tM(ipl_h^Ee0Z%J3#E)YIuV>(Fem&ZH7Tj6XIL^e{OWesAziYcboU_(X)V}V
z%S@wq2g?_`=s0a?A3yJa4<8$fLqGcS3hxWvMdMnY5qb7&|l+=@n{mJ9`oI
z1@=3K8uor=%rvZ#CJf0B7GvlNHFl(++G!n|{-keFfd{kgOG)geiUL+zg+X6#3Bsqv7$AY|es}Fc2#vg#Bd*%@
zKR3MdCUhRpl1yoo0_+j4hh5%A6p9
zPkqLc#zvj|tk|ait+YqcCtm_(SabGYMF}gE_ImD@@>`xpP0nIh24$&rvNR@Aj%Huq
zm59uz6x|kYEd(Z|VM({~z+Xz>(_o>YsJ!k+4wptUQ-5w+Ti*l%t+*X(eem`l
zdLg798a)=8J>I>}2qtDbw6Vr|*Qxv>{2PYij|6FyJgB8YBu_Y!8~v5D*B)2_dnbJ_
zYJ)Fhn^+XzVXY=a~vt$?{P
z8_?lYI1Y#8{a{X0emf=?@?z+;yK}3aBgIk@68JGRC;|FP&!#Ul3*KDL8j6F%&x~3K
zSJi5D)XuK^1XKAPLe#T*v(_S?3!m8Nd{Yg?n
z$)nrx-#$w*!GqX~9lxsb$*-O<5B~ndQE#_lmV!@>{pymS6?m_@-Tio{ew2|_O!9KX
zsNzh7l6BKpezwN8gr-AyyH%o|dtX&`62bMDy`yt!DPY*f|ZX=vDG<~Yb8%Cg0
z`{RC6hgydjXu2X%B0QFu(|n^prhK3Fdl415dd`+389O+Oife-%1q4(~<|r1lQv0L^
zRJ-j(Kfi9KD?~ABUgJroDtA&@YbTgF>M~MSj$lu7nQ=SOnveFH@WjsTv;)2P96CMk
zrZ3c_j1HQ=3X!5t7~Lix_;p8-L45+&lzVmS_n%hP%SxCwI$~a93|a341@QK;4Vl-Z
zx!f-e7}p~1_#$t1)smE1QK@pm4U)`QvBOR{7)W0H+vDy(QTbCvM@?|oC8Ngm#YB2-
zCAFi(313GVm@P>hGZ|rPfyKeMlSp)7Sqcp|!|>m?QbsYS)#vTGq5ipzuA-G8KN
z^i3hyNVJXUJjpZeEioF{;`_VG`o~OSCI59zNt~)A*er|n@P8;hdjra)&pA#*n%u$a1qmF?7
zK%_P>(nzFoC2=F|Z5b9L=Ml$Vh9@0n5k32c5rkJH`NQ<|w0DN4
zp58$-iy}srR1$FXsHjlaBfbc)!Ld2S&A
zdE(;zpYaz6cO=oq=t1j>*@aPmOjr`--@HH*lxInd9@vnxI^ZmnL>FK6qOebzp1*pK
zqF(dLK->Z20u0UDN}HLQGA8Qghe=f2jRr-KZVLe?YHSIsW*UU_(NE}*puh+~V>&@R
zV&Lr|w>D3qa_&ZhWr&(O9N3WE>mXDM*GkS+@gN)nZEbB;)nK)c+}zys4eJfzf;)V%
z+qYj62K}bFAZ-x^DU_+sda_8HatW~Zm4JLSLBbiMQ^8QF%hC>Ao=y+@N!wH
z+G4YzV-d0>3;VcxdEEem?*+yHNY7&_#-aU&mPQY}aDgHLruf^R#D?uuFC#}B-3Oxj
z{_D*Pj68LHeSIe<_KZNj0zR40XJU-;zk!N$iy|ub6q}x!%A44&G`^7*$t-}=zWB_B
zeRdd3YOo_E;$L$)&S1k1V7Uw1V78>M4iUXA
z%+5tY8vyaCQ522-%Wgy&Ubr(BIuCX#-hS$QB=0wH^unUg7jwb)%`Hi=(^A{t60>?y
zJaSiesMj8V#LG-UNE#PH!feOF1ey{ufZfQ-c?TLlD%;DCCSB|0HxIPr~qf<$a~
zs_u+nWa_%HH-@RNCmk1%F%yR0(4){|OOk}{=D6l%zJ}eoX$vN!qUh{XZIepW_Q1yz
zvU#eQhJ{2&?Gyu%gV?}mL=ur~;9B-C@uwY&-L`O|2a$
z(Es69_2&9oOPSg_qg4qLr2mg
z#C?7@$D?<1x6*zw9n7GXU#e9Vtjb7_)l+HI^p1`JiW)OSkDIfqgabEdp|hO
z2pb=nUdtL~sin4}ytH+HgaLjk#kAE-fg}me7F(}3g(0JenCcJ2ohRMMv#bcBr53*TRH5{5-wvABfC6(EFR2e~3ssK}<>L_oVNPmG
zw*4mXASld|hJjm}bOa22L*b!QZ#(zn{dYZuo&N|UV1uD&yoJ!{
z5SO75eNz@s{;2c*J;PML@`!x&1P7Qnuc`Tim-a+)F(WkeV<&@#u~^`qG6%AIk5nw;
zZW3hLJ8TYD{q;#zP?0B9;mr$Aw)O6ht;n~JijP@W#4RE`T<#z9)Sa3w$Fd|rM!SFF
z@)gr{)W5agpAHJTTb6KvI^hggLT5vqFiZ)^_M$8xK*4i7gfmC)+T&s(bwk?3!Cw^%
zRDgNEaCX|HhYNBfK_x-e6EYur)YG#0GPr3{6*^5qrzAAW+5bb8A#Ho^Z5wEzw!EAr
z`NO(8h=}VeO!#DM|_I=bKxr
zxPO@MbziW}obva+O&!mvpgrdKP^a;gQJdd{e$$O^z48D_pqq=@U-$2cm*V;r#DYPMQ%j
zTeDpucze!2pQk_5Se*4c-N0+@ux`>wVf$^FVJ~xv{aa
zzJA(-Y=UzPGp1yS*mS2I)@Rb6WXnSu-M1GJ9hy`3+>8(#hbq*_2rU+BV{Pr2_W4p~
zpnia57Z_SQokXUq
zrnbR{YdswL2)xn{$IHwazXbW6T875IvT>)uirsXB=GM`Ug9J7
z2W}j|50w3QNVq_`SzPeM#N4Q)(U#ba#&R2g3tfYZU^#FOMF^eF*L3lAoS-(#FBUNF
z5x7{7GfU!I@Nj~exa3GB;%=4-K;&sVUIs!G1FKjEp#V;?D|&kNtC>EM?ghr^sBS_Y
zoX3bBs^8*9F5vp}WPoy|+H9hK^y=Q|Q5V6aeY!T39Ou&S%lfh#Q&OX{jfjKU5eJE+
zxyr+s3ELfmf#!&t;uIvtFl=69$%Na(_BGNtE~?L@NiP<#73!0U=U!>q--7WrrUk#onX!
zU!VZ*^tl}bk~6hUI^$b?y1`R+RR@_eHu?mX3;w1g%x<%kV%8zxnUy-+IENh`m&J=|
zLE-pEn&DMAbbiBWE(~#}kiymVcIpFdh-Q7GwGpdan>3@cKsuwUxU9G!p~F=54OW0p
zyApyTv(#Xrl<8vfAlV|_NoU8W9`s6r`YZjL5wQ?giigsFr*1a`>eQ82`I-^Szl3w0PGZ_)qUhXefXrj0tLIgxpTiJ^
z>*0-(U;8%*!k3Qe<4tqPSrxgq+kh^q8=Hp{=vOEv&-%uw=
zKPe)e?<`z3((eAu&KSI>$3$hta9dmMd7e^KKel@3acn=Mz(u0r%rDV!V&)u8vEKzvBlHO%^E|TCnFc!$_7eH|as-<|LJ%cl&R=
zjQ|SD!q;3Q}(mmCqky7xIs
zHc`3~?VpqY$W$B0+Q
zZmj0Cbx$x20%I8x8H7aZgH{&g>^}p)n|Is!(`M1ZvgCcWGu0qdA+qFs-u4)t$}Kja
zxb#-wYHz$mX}kQ{`ObKYW(7*K`+l9BZXV*UNw2)Hun^xlX6u#2&+keiOPHl!@a@+p#(1DRN$>SclRuZEyx7Uf$@xHQs!bS9pEKLGkp3VZ;wae~$-sn~1R(8!
zOS@5ii%;KOPYfSVi9nuP$rk3rDRq8#?gLI7b9#OnJ0`DfF_?S0qy|j~4(bBuHexA|8v6u=r2yIk(U-9mWg
zi|QXg&bwomoq~YL%|`0OnxVin*!=@q#*NRnlNFM`$jzS~JDPGaSu^@jr~SPe7(H>6
z0X6V!?0EbS3}K{(vKRfi!ngYWj%k{ZTrt=DRnT)8(Z)CU!wh`OeQN`wW*uyrxG`^T
zd?|=x)*N}h%BpK>ZrJDa`8Y5SMg1#mUtd8%4E6}a>GdHbI{9OS_wA$RN0w5B=W*su
z?;1JaD!K8Ib7Y>4xjg!MIwgKedpL#xZWA%QC9NLo40IWO>&G$~85#u5Mu0ChyBkOw
zu4=?c`NbB5KcaiBL;HQd5%E|+;i$)<@4S6L?7zd18~p=cQDFNn&1pA0D;_hi=N;^r
zZ_OWqUz95Oo`BBE1sW4YV9%a#wy39&z`oVXR9ds?V?h0NtpAfW=Vz(l{`IN&`0i>@
z;By@~;~yi5HVd!zBpJOV@$IzjHs1#OB@_0$AKw)P)_OPmRs#0Rc$N4!;p&Wi5TrnL
z#(Zvwa+xk-0-%+-as0Qlrg1pFH!~fNb@EpfIz0)j9rcGv=6gQ;>z&nEC_)lckHk{diXc6zpUq}X#5Yr11
zJ_{6MG=ULa>yXeE!jTw%#%}a(oXpS9udn|}Ng;9VjWCYfr>!e@NRuchACWd{r#vcB
z#dP7RzlR=$jRf|mzh3KX
zOM&)7Ymv+L2m$Q}>R#MDCOutadY+MKJ+IApO+9w&h5C7~vn@1n$NQ53rBoifow00V
ztxT76xxDIRA=4qZ2ZRhOnU1(n|ZIkU1%iMTXP-P>0azW}=~W8NaD%IYa@}jj#Hv5!+7`o4(=LHdr@Q
zvj70=!y~f>VT^fweSPhQnQ;d6&QV9VZFS#}TWH-YYDNV%=4~os`gSOvJk_WP?-mTV
zeH%UJnzqw~?dEGAE*FSEKY}IvveRR%KNv&B{ws|E1ZD=!jDna%edJM_faN%qxWdr;#BxI0S(YP2@R(~(~%5#cdk!$y}
z7DT%t?#T6i>V?CC;8#v|a9L8kGYvF9Hf*SB9r|OVFCOjdeEk1q0R+C>D1-1MUvXUC
z)R$T4bE>M2VRR=Ol~cDHnh!`Y($JI>k=TK0(xT?~nt@9hMhy?54t-PF$TbhTwijbS
zle?TOi0BtlZ{RP8kB{HY`CDr>AyDs7V?I2eHz@K0UhgnbuX#lQM*^W5ck=TZL1<82
zGnd=ckBq)b!3svPqBV_}2Q3p4=`Ty<({N=v1*zMhaARKA~c
z_i7-`ClAXC2NtaUjdQuR^`Le_G1YhG8%jdj%2Aj$o6LjVqFyK~bn=Z!m9Ge;$rmT8RCqj>
zUCLja!Q*4$@tYtH4?8<%Z-4eg6iu@ATnKMa4kKvwQ>Vd11!M-~PqpzYXTDg+oV_cQ
zOI3^divYOmq9^qG7gY@Vpz$4XKwGr*N>DZ7ez(Z8sJ>7iQ{++W*=|^P`%zO<2F$?B
z{I0^{jFoQ-#P%?VAh&ZBWcquH
zAeP)0>~u(nR2U`;PJ}89JN!-iVYh$3E4-G50V7u&e-RKtw9Hg&6c}C-5t*82!N0Lf
zfMtnS$3shS07+A)VL5_RY{0JPCTQbBCmyru!*Wx^0SuN^yL{mHz&&%hGjBit_s;w3
z$ZrjeNcjHe#?>Zm^C7>~YDVKrubM0F;UaGD-uKkPnBQ>f~wpNxTTR!F3{i
z*XM+6|L8kDmk0L;HLNO_@L<(q1d`w5<-uZ|jc78jgTYGsGq(O_4@9&3;qU$OmaT`Y
z6~mgX??7Sbg3T8$!!Jt8TaE-wvGb1q$g_^5-(iP$;7g1N)irn{Pusl-g=IRPWj?yL
z!MkpV^cFiDGWRQO`u5CQZSgDM!+mtp?%um9ly{=cvR
zYBgD?B17)>a@%(xmfRR}xih}82tcW)`?JBp!EuE^o76GHvCCXVaCRX3M}7S^0AkU|
zCopMOf9eWGGYojB`^ScPK`!w04C?f+koWvaU`Q-VNBC;DRIH=H(YQas*d6@zxZ+M%75YBzM(v#G6Z*$#u5;`RZ}2x8_?=<6(1Zfq@`HwieSH
zD^p?r!Jb3|XDgNFPg`X*v4Y-_hp8MH%}0NpyxjkMzgpolyI$RRCuZOBm>}cOD*Ea;
zM_JEp89_n9S*PD@_9s&O8O7~nol>p+@(UXk$B`!@`QAKus01{dFJ2B%yxfZ|dmyg6
ze@+%%Mg$(tC+^O7Wx!A|Y>2!TT-g+cge(?9wX@W6^$sXn-|OR}r4~jU08sWsYGMnr
zltxUhIq5Wr;@^QGj!O*Ly#!iZ4DdNOQ&%V8$eQ-fXX8-;eV)
zR6<#;;wM_hC?wT)TOU9oRS0i@rX~w`{ob1@No3OT-76}<6*xHNUG{u^yteFfbnCl8
z$E*XV`~C}n@2zJef{6CJOLC7z6}>b$+V8JrGHRSRf3Ni@X}9~{#PB{^o#iWy3L=EC
zLB#CqrEdEl>uqLmV_y2mrwo`UVx~#8*7Nk(MZ3rcjg$Ns?}yNK*4tUt!c!b+WBSMR
zVMg|j4r6TCK(LAvbnG{CpzB*Umcu*}5VE^10(iw$hXU%BBO<=`WYMrLS
zh%y`&B*5-RO|Pd*wdtr!s;f$$yAlM$>iCVmKuZ_&a4;ya73$l?9cy{f_>zrJZt|EBu->LsOF~
zEkJPsu}PPco!#Xt{Lx935|ZAt>$^~yk$VdwaWO$X2C1XNhCiErm1lWWh`>F>j7DK2
zCk2rW5cAk3O|yBO{?%iN2qOlF8;{-mo4g+{Q@Cy1M{A1)6PSJ0Znkv}Cy-%#Q!N7%
zO2Y=tw!dsD+J)|G)x=W2z8+0JS#`}bK3Vq=xn4z?JXcwgW*xT|L@A3Sw5lDL1aYSj
zeDUwZSSm0(!(!#zj~;ChVc%yb4wZ}*c3Na^P;9>o0*1wO!6+1{Z8}s%k(0)Wh)i0u
zPPD#|Id>+>T3V6@ltj_V$;qJrC
z?K0Vd#So~x+yE9u8a^~dquDX28r{mx&mO#V*Zc7vC4P+BAE4cwABZhDCi#FWZh*+y`FG$57kP<#uDdiu8LsP2sDU7@;0Ah!$8F*`
zA;GJr0&`IebPC_&F7XibY|z6-Hr>B%=*e$&en_Gf9oLnSkx^0P=9AoR8ox__EV-c5
zdT*+IvlUPQfSh9o)Wq>xkCSaE35x+__4Jnncf7>KCp~Wr9Dd6fEM`DiN7A#j=;ReVel+wAAbWajcx(j>E;|yq@N;*myE7L+JVKmMq#Y^=K+%ms(U&R8f%1al9TKScPw9
z)r@&y#HrW)=;-}B%FZJpou)AQ9RBU@cp4BnbZX>B?7oLqB5nFsh5k33zr#cZ{FQDq
zKAC=hlV={;i$^1&hj#(zTRF~_^DTZ?9OR-o4@h_7-fJZYEJsu=b}OQ(afZaW{qfTE
z$AKfihs~K0{_Dk%7QFlO^f-Yok@WNg1--i&a$I}7ya>dM;M!@=9a$@Ry?Q`hx+-Jx
zh)>f~UpL1>l^(B5OsuvGL
zHSS_xfhH}3(Kh)azI}VakcW*dqorfhWyi3If+sWv$bkTpIyh|D#-sF)ntmZhnhOl+
zi?xX8r}F|*@5_Ue2+{jEl}F-&^pvuaCX@4cL)&G(o00d!zvT$nQz6{9f6l%;Z7(%!
z6VYr0q@UF$jv6>F|HKpVd}_ZtTJ~7^*iTBc+?99S^i>xN}~ZLLzDB+s|akN<10-)AW=%dkYq;5lHoWwOc=4?
zkScWENYLPSHkBKY;WV55Y(?1Z)bHv8sleYP29Kq+7Jl7ISGoI9M1@wn>#sXRd)sA=
z!uFFnD%!6|fqj@7QEP+aS@=cvwwfG+aSM;UxY3enZ9-a*>c#jFhdK_5zM5gCnmou(
zyEPjYg+oHgwIjnL4d5&>e9utG2*1UUrBNtj9+*4$>uJ71I4=KIRfmxCM58FV`%YIt
zEfS-GE@5e&yA=W*Nn1ck6TV&8vJ!3}q$b%Yr1lz>u#X{C*s
zB~3r9S+(rii;=>uB#jI1^_~jZ>+O6p66M|~iJW+v1fm$@Bnn*%NI-IfL3Y>AdIK?0
zCK)l3fF@R~Aqy_Sdygl~Vu|m4C|HYzygwa~;89cm`q(?dMczgs==@;(VIwXa|P^N!ST3pU3F~
zS0r*voA?&Dr)gM_s_(!U{c+YPd9tu`j^I06^;LKC+l0ENJL9
zrSWtxmiF@?BuoKf7xe1@-0(nCyl07
z=bNvxWB_*2*#|&k>*c(SB{9B)?R@QSb_4|pul*v@GqU4uEY?poa~K4)r8;%LuO0v{
zHCzAii!QVE@pj+P|0WOU79Vg)xOP@U@DvLs08Z}>tO6mcfu6Fh%Chj?LCrHnX;svbM{uUcfWc
z?~<5>oSes2D~>|=_u!z@Ibrx(1f@Tp#YkFnbF&n65YhwypwA9+MhO2i0!|P{;Mt;C
zX%Dq`wwbYI3$`m&8P3MF({PfmBp&wn6W?OV1X@`N{oK0l9-iSb$a6DPo7n5)268z}
zSD0c*?Z%#rX+b1#yRFE|!SD^1?Nn7&b-x=^KlkQHmt#C0Nb@32d(V{hbiH#Z
zlaW4EFFBw{bC~IWu?tw#q90$1W?w-g&M6!b1aTR{=l9~z$j6P(E{19
z0Xo(UnCbu=#-{D
z?&IZR8ijCk+x2>MJ+sJ->rzF4-v^Flq5aaDbtjwk-V^ym7X2pgiy~m={DejfC38ND
zp5c!TO9)2D|9XmMIp5NC$ffxRUTdL%_Wm5JW-^8G1m583$PZS#AIz%26$N80fjR)J
z!xQl_vEVP0)%sqN6K4x1%!N@(c*F96r<0!jf_KR|U?{1-xB
z$3g&=ccy&labqBEpcrP5kVl&Kn?Fl+
zySc!E5O+>=gtCS<`Wkf`Nv7zzZl*h9P$2zt>30QKDjg^NPBIkyh57mUel30u%~pCX
z?sn+s`}}TuelA-=>7&~VM=R!&g=ePhsn0P%jBw+f5@qDTzCKMuyI-3e@a|h28{${(
z2sItn$#p8B)M46hP9VQIvqVFuo4%O4FX&0`SCUuDXCM(~!sulES|3a!5~1;^KpwH(
z@=>u(VZ!Lch82HUP(mjJ_}#A~0p=+kLdI>YSI8i<(i~GCIV*bZ;>&sb(X&b=RpcZb
zAW@V$s+B+!`sL4cdxz)Rv#UjyIQFg9uiNhXf3$x){s}!%mCKt9ce9BTxs61@BRd}A
z9BnKo4X*@9&7sDWmIFQ=gpJd?;qr!3uyagfxlETA&MhUo#1h#%_xNkB^BTqGAy
z;Qx$#nm`s)JH4*`Z$pH$n?K0QY{Addn40%RtT>3ME>yU
z<{+=_ESuwM=UPuhuE#%}lY-;ZPk^6f_@4gy{rmTLt_-F7tnrO+`xg^wa8Yq_HPe15
zfudHe24o6l1ocU2qa*{ocRtb?PuGg0c&AI^#9nkN0UY0RT&cp
zxj&5(t9Lrh5sa*u@>_u_?d}>kVoBMIK=Tb(D*;dPEKNU52V$d%SpE0Q8h{h$v7Rgh
z;%t^>|8a~$o&`Ky%(!d~X#*RXC9$Nq7|4YXvvl?rLz0Y%XgvR$BfOKv)Loi)*mHjq
zlUevy(|nz_ynIAZUfG?)Fh
zQ|20kA0N|rzWASeG`vECdCsG+Ij(K{lFQ}6NgI*4(GQ3nM7>sQ;%>5R&fNHUb@dY5
z#VLKxoj40Vbll|&UNYFEE>>tWUsw2E?tLXkuZ88ItCJo7dHVzszaNVWdG}Ch);x*s
za=#{tNawg%^Fbg~rt=!TcITN>c{X`Gj?|rYf>3z;S{{dK5En)U+QPB>Uz?(sirT
zM*sTyx-CztVgYd&AdUF|i9bMSC^tK)uI5;%$8s8-vvqfHgAP=eye)xbx9?jq%gaTv
zHm(Lge=U73oQ3y#^{!mic-2dq!SsWW0cD+DAzaIHt-G1GYz>gtgs&E{M))>b0VdsY
zHd6E_96!so`^S6T_FL=wUX17jCVoUPRuX=)o+5E2)8JVvtwIVI7jXNU
z@Vl!^_x7womQ%$VJgG7KzMH?}3vEYIc`J$qTmZ@BAE|wzL6cdp5#Nkg&*3Ul;O|e0
zjvCsFCuABYZD5z{giH&7k>#4Em3343Z~m%L`a1UOI<&bQcRd3%WJMr0W>{P@nC`VT
zN0;Gw+OJ^9Y}lUTb(YZINo437VFNekO&J=sIwA2PPa
zBy@Jw*OcQ28u%}@Bdj0epm{O;lwWETNg{sD@IP)#)z#IMGbjOt@5Zp(O$TrRgIIaK
zkkVdA&I@0*3@K2RmYzT^xpkkgUCtC6DgTEt45(8=5IQzQ45Ol`9Ej$>u15-V!J@~C
zkEQummt4wW#9u|Lkg6ZhlWA~$C(rqK9|`^9BAmsv?JXge{lXM~GBKKof#F2Rp@H-!
zn8r>AOYY6`}Ns8Pe%nevGrn*U8-yyy(Ygsn#QnIwgO{Xh#ikJbzB
zKolTd6Re`E8y$8nCog|OR8w5M2ei1p?3?S8jfGk(g1CVNV59>Z{$hV-G=)1FzuIy<
z$M14(8|Z+Bl}1R=H>tyzK;B*pXJbm!(C@HrhHqQH#a$s!wW9U(ch0+LvVq;1ij~JZ
zgc8HyWRcp_<3mYF38DodGULWP7&WkQxX^$Ao`3S>olF5gggfBT7ux#;D*0#ke7~aO
z@%{|R+0+4O>7O4uQScTUonFUcjiUz5V5bXuv~Oql9P4yLT!y)4jKmM6sM*ba!+~2#
z=Ie!l-U(Re$($DDT2en1Fkg#Qkn8%OCs
zSrw4{1v)i&p!^b}R%IovZfm`#tsS;!yO{YL$a;^`|>c!!Z0IKd+H{
zJfd5C64UBGZgyu|J`Ok)e0%H9w>`5A3@`oN+Uxt;%iefqpErE;BMtVt&7;#S)mrm5
z2rp)Q{_Txny?39=13Dp5K|+Q0!^lANi0IimK`bd_mu`)_Laf&}0uy${$Zvnfgip&~
z3|0yA#+3{gmy`h9Mn_ZAqZ@;+cDX?#nvj{X!6B8y%(=o~NrD(?yl#7wMGY(Nq|n~_
zL%`S@O+Ir4CjG{JNEl_B=lW+rm%Uj(s{mRwNof9$AH8Q1BTdtcU?I6(K!17wgxKqL
zL{nD+v+mf>NN!GgGx&=UG-&OQAAfJQGYx?)8j3*>iqB~w5}bq2B5>uGsj8!`O&q$l
zS5jfnV4n_!siq8Xv9BrE3@5phSvbVx0t^)hGy}0Z>gTzWd-HYsZZi)-E?KC1d%k+O
zTI%Y5`4j;PhLn}x51jg2x%Xitp9{^nZK1xGa~4>HOr3dd!A^^+u4N{LOS~(-E{jeB
zz#H5RC$(<`V9bAz6L@>o3$XXEw^ALj#emfr%l-UzkH=xzw-f2vb&xcQ4aPV(|LW`~(a~@AWI69)K&EP@zsm6y3lpW4>DUNV1WDJY>ytdRY=Hzs8dAN`V
zuhKdIxM%Bn)F7Q=8kcc*sIGleoAZ-Xh??AiS1=WdjERGHh19
zo{moOOMt`vIul~pALPvWURPgVUsxE4|Lts1oiTp+FEN2m1YC7Zi|?_bsHnn2yS|3p03*!ZM1qB>v=pl>CgG@739vt5uHm9PIKIm0%$Bvoy
zG<)z|Cl0CeO48V+f3{d7Q?{t7GDgK10^Fb>@{nlg@6{XmT+_g7vm1|aVB^G=M^{~a
zGF!3_s4=E!O-)T8H@9+CC2htS?|sroG*hb0>3{DzazmhWPxDpQNHqt^@x@8Ao&h*$
z9|O2I=c@p3tN&^CxWA2R$1eO2RiKn=C=`hExr}gI%0b4%NpL1D%VJb?2+RUiJNJS~
zu)ER-OZ^LJ@V|X{CCHx2@jR3^3OxI?pFNI0SclaPZ}rfDRK!4hdPc#laYo
zW((}43`)CrFVz=&b}afKDYJHiYlMl?rbE9Y?R6&^B%G
zSAau*mdcj4_}2~(;I%{w4_{vbV#xJ&{aPZK4gmM+k0Aw=f0w4TX@Re@5L2eXKROmQ
z+G#woeI_x3N?1_fA9#83=hXrn6QEak!63wTTCVu(c)6x>U7(3q^zn80iWsV?0ZjkS
zcBMVtC6<;*k2?%eZ`^}knt%(knJ%@ODc8TdJS1Y$!Vk~h_5yG!>$MGio(!2&?`l^_
zb~XpLfaU2;>js~tepi(YkSGPVGfSf6T-&Oj0bs4o*V#<$x{72XW~*}H&OPBc<@?rU
z0Q+5Uwx7sXII+$KNGot(pH`(&mvIDn!mxSA!=)~hLhQt`76!2>*PhjXrEl7B(0d)-
zYK@64VW*ofXXTZ*5#;?)NI8&nTC9$7yj|l}gH$6#OFTN#X|3j%&g*
z$XMlw16@l9XO=v3ErM(ScJ#BvjbvQm^)MgD9b`<1%&Brn~H!$Ntmr8F}7Y
zjjHv~#8K_eyg;|Q6{d0nuhTJtv${Gjq%t23rW=#tdrd=N7i|#SQl`?&D`*S6w%Cnx
z&cr#uG@vm2zbwF*%UW|7lI3s_ZMayQ)c)aG@c|n)#zv^B1ViOmB6N!rV7?Bsm1_y9
z{TF*vI3QG_O@&m2_OtTf>X+9d1Q*CEz_^U#TaN^=XlMO;yreADQ6rq*
z{5eh^zHKgW>!+cw;yYn$-`-KW?k)B~Ha7L)tST>?0WK6urP{UN&_RwWE<`b-L$sH>
zYPWJlY??MRL(;WJ6{y156UK*gGEj0(Ddb?(GWuktd?O*(*3cPTVzz6v`q7Hr=
zS^*=EVZME?*-jsob1u?JY>~ze!5$m)yIS%9ls_|V|C`N3O7ER)849mAc>JB`O{0EC
zN>ArXbhPs;_glP!)vW-=DSzy$E9ki8_ISEoe)HboY<{M!ZL4FuxozLRaa@aUJz>j=ghqMV7lm%
zaaQV|poD1XusC5-`Nm;X!pUA|y?!Ye;5Jy+knT3Ejr=9?6^UR=(;)Ic$+P*o8Q{ht
zw?lUyHVD0O>y$O~PxSf)L(6Y(nojz4Gyfk=XB`z)xV7=2haM0lg&`CKq>=6xDP@q7
zZV*Je8-^}PX%LX^?(Pn0>23y){Epwfm$mqhnKhhw&yMH$?S1ZZ>Hamu3T!RhW9Y^?
z+z~@UJE3v?fe{E6%O&ZQ_oDSvbgh*Oi6$jm4@VI`X
zybDk8>bDUfDz7v&@GE+y{`etyyPHFOUElZ9!fi^C*CIP3R()D>vT`o;Z=S_1FvNNf
z)D3DgWq>G9lF(Yo7z*j^?(WuSAJ@X(KhU;ZEfQu8Lb$
zHClzW#cx=KKA>&00-b2a<7NIRKXC`hCxU{vRI8?N^~7qx0&U6`h~iP6hen~z2l%QD
zI1l^?-q~_@uy~Ba%Nq~CLI7mzF1?#hl60Wvn*~zD98dzpuiRC#@D!cEy^bQDk{F>D?|6-UMOT+|Mu9T~7q7
zcy0uLYP}C2@xIHW9+9D8yO0#X7?I#GpF%%=%20k9I?%mjU~}6VqD!iG`g(zz=*hp_
zcHy7#=psBEud;G^pgk0F6MEo%x;VyXdBkSJ$YQ2LPC@~fuvMw>(fp?5bmZ_lF(KO2
z%xsE2CCNO)X~Du|FQi{9)QCjFq~8w0N!r5!EyzozvA^BR_ul`Qfk#6mO)QNG`qgU@
zgB#8P3|Jgth@5&W0bZ@>(}if$QLSFf)5FtsV(aD4Ujwj%Ip_ESW;_)NsY;fn
z<>T&dHC3V^o&YudS*f!=fZMRuJ$H;(Q;G%b2bYrzkMTW+bgv~lfNT<=B}LiM`|3Lh
zp3eDLry26&-RqG`1Kjup*`up>QcK=X4_0<41g?NQ{>24WXs2g)u)zqBN`up(i9$-xzE>^ZvM8O
z2a^pA4G=#bRTxZ{FO=4IYqX+^;{z8f+2X5gp)pmdc$XaT%4yIXyT4gIVs>#%;Gmd6
zcu)S5j@|r1jcDs`c9@dD9{mj0KcYT<-yI0T%qiYLAK1F_;)D;lA{RpcWW7=Tom87T
zcf`!64DXJ>GM66abVRY)XMlF;6Gpr?(M&M;`!C#v0KbB(e@CM{Hgka3(#r8xacVxf
zLA~gweo(8W%vD)cG~w^Nal4PL8rRml9ej1e;3;X&87~+IkYs>5UoYK?_e;qbk}Ww
z-u}8^k>7ID!*+~t6MgzSwh9!nrkXLYHJ_&x|UAD106b9y6NpVsbEB+I0Jv+FERm$Vx)sWS?
zRzwLGAgKMjH!ZI}#sEeLtrP_dR1@vb(CrX{h^dEOg
z#ZQU@pl+?YW%=}IxC*KEfPZ>W(MNTc)F-rESXBDKD>R4H&AAjD@dpp>2fFoVqZM<{rFVi)ol{vCj5
z9Y?P^(wfa!JzjfjTKHuWr}lq=S2}Ft_p6CK-7~$_yQ{Rh)q8x~yTyl*oJhCntb>z#
z1h$ee56a!Pw}92M@O5^D;j%%n(5;cJ=c*Ca#qP=KhA^_6MBN77No_te@8+p@cqv
zTB0^`3k$gw+fDI0tVnfK#PVp+?T)-!%R7>)!u
z{7+yX_VrGuSo|+Mr1c~;Q`3V4_?kHn`K^zqBMJH
z5xJ@FXkppA4g$*F3tS6FwSLpo58fgPW+wSlf4f9oMyHL>_bx)6ZE&Ox}Bnto5hb3i?LYASBkPrZMczl*|)2&{#CERC+BW9xM
zB=ExVu!?1u=_aC9(8&D&3#L!pUl3QXH+4+HLVy@*mW(U${X1p&*V~_Vd&0
zSPoD-<#)t+FK^3U#?#)D+f|kK*f{by7l>VQ?`0?iH27iVKB4V#)R`3nN_$QVl4CvZ
z)aB!xO#y>Mo-&@!lD(gF@}~wWC0=uaPLsMKlai9eHiU*k7}~yCS{7yydtV=4r(Rs2
z%)qys$2>|43!!{X4cGT^$`X{o>bJmx*)xrDqKsv{{X&*p@26{T(WB}qs)yYf>f7<)
z$1T0bt>&?GK&6F9@cr>Y5qUg|5?#ZT<>>mCeVbW;D)jb21i6rzXeY
zyo!SDO)Ux-Y)jZG)auWl)L#t>gkOV!87~2Re!XBW$3$I
zu^^P-;m}O92}qr~=dp=G|4Q45FkJ_rGjI?{gB7Wh8U2e*V?a>SY7ie%56_O&DTBML
zdS3tY$;ifBdNs|`5OEpz#+H`*Nk)+kz%U5#TAldesdxQu`=vUuDKpuO<$i5PP86Wy
z#)DETpnkVdc3)UrxvB-^uPs3H_PpPq2C9i`Jx|1pd~5+-mJqqsQIz-nhMDkzCIChN
z-_74GHg8wJiJ%714qz54vF&d8WOmYYkWPiIcG>0tf1+4kQS778=U=RV8F6O&Fl(D;
z*GskvR2&3nd&=GdT;4}kdKW9yj?=0~PIv#ZJ3wienwp*qJpu3h7a%>DI!l!To#2DR
zJpLvBt=*j_ny=%*WJG2leeWtgv^81L#}ks4(?E<#-;AfV#D%ts+odXzU2$|!ndkuw
zEkM%if+H{vYxfi-N&pe1{BZKa*6lC{-?NAM{!C`q+vsSEChPY+=l6$Ze2_^Dg_S9L
zfJ!5uQ;?gAatCQ!=0^zf2!=8Ao1AE2Z)iRD7
z#PdYd+@JUZW#<;mBz%I?V$fpzcBb%irkc&mMWz?xtEDcDlWasyANA%mi`ILja;3{>
za$eEGx==v0DJdyTL+3T#PQ5(9y953Nz+&Y6D)Zxzad#)!=Q?^MlgHktkyV{OKuDaX
zDdi7hKln<+{8Wgf?d|P>1TxuF)({oi&~_GK+q|7ZVbg+8k09B9T}Js=XbkpYOzWVf
z47(04N7={4#r5pjvq0(u7eIy$C3HL?)~cC}?Qr`_IA6$wDfVP>#Qt3+D0E({@-IzL
z#$c7Pt7-UaNd$1RTGw#B&(5N}4_&=4@36(jKzdj#mz##D-CUuVgNjqH}qCY3H8F|E}v9?fFr+^%8WlN&vc^U|gC
zjEn=?&3p@%j<&0svX;%*vKp-c{+;FrN3(mNNq_KOwz&op4UNCdhc(jYoCBC~y)H@Q!BTFEcsl6b7Y*o+6un9&hEICD%qr=QNmZ+N5Oz$=&`9
zt-)u&6ayodTi5(ambOp<_=Pb7S;}n|Qm*Evx1ku)dx3~t2~gwmx-SOR_yxC#SBD%@
z)obO|{{@`=G>{J!{alouT@Nt;mhE6Nq@D&a2(1CG4-U2o}N2$oKP
zQD%Rc%~_2gP-%JD0Xk&cwR@ZMq&x${t>qtL0u)t)7fV`2k!b=SYV>}tR5jkrE_CQ;
z9tX=PlIXgu0W@0r?R35f5YCu~&b3!>XPw*bK1aAtGtadAfQM$^?8=I|4ZhC*m!O6A
z3vz%^02I2mOD-D`w~pitjQ7GsAF;)$2?%hhz8mH=l4&t+(^3EJmuE=31nLH^&}^XE
zy8{wE(55XG*ZiA)14?jUwDzCQO0Ymodp;56b(x@TGm)+q6zC>0BKJ=V_$LT_#%P3h
zB(`o%c6WuP{|(05#5k}meHHgCO4RkmlJkHwTk>!3+oKHE#4j%?FqT`HkAbU+R#aut
zgn6IX=Da39cArB+>74Degl|v%ILI)2ZI(TdixnRbnu;CoEY(f}(V*Xv`~!+XWTE;p
zzLh?O7+}I6kwzG;mPp94YCl2UK`QNPNFYBNws>|j|8|^Vq>vD#3S@jdtb#&P%uFm|
zeo8)cW2+805;a5v6}kTdk`yXDl|sPu7S4n7r#K=u35is^szQfyhI&+dJd?JnCimo@
z-Igj8sItyCN$JcjW8&ry(&T0QR-K2lB4q=&s(#C)pu8Ye
z?RLP7_cpS!5+oT~NI2ijG%){B*JHnYZ#0O;;(NPF4>EK!+m)159F!EOLj*!r_+E>p
zXVHh8sh<0cKum>E(?`}(102J1n`uDK7-92~)F7*pF7rZ&N)Xve5^Ri{jbH&>H5UjN
zsUI1%*}&V2hwkr4@pj4cx~%N>@wya%BJ@`6^}xOaQV`kbJvg=k9EuD#^&skCbc|0P
zibcc}V$I4R#wVM`aB{prp0iqoMHBrhM&!>?M9-qTA~jDji8IeyiDJ5?+s-K3&c>eZ
z$NDHQ_~=zC>m-^FX2-m?nDty&?^g2j8HFfg+_=6vJfj}$-T52a@X%bXNdx}pKWMgj
zc`6dDj$X%R)|fguIU)8R&^4pxwXGuThFQYFnFVe3z5JhU2YY^97h^@?hwx!{`dZ<+
z>OTnlfzr-KU$5ZF?l*4>^R_$wt5Y3MICY+<{?y?ce32W^fFWFfB6{5a)aC{V3Cu^*($Z=wO=L>{|EVK*Y86lM
z0tl0O7WhBq1(&1?ZMV;lLhT!Xjhu#bVt(EIs8k@@L^0NqSl!d6F`=E!Hsnmv$6#KY
zg2t@5llOIV*JkWBuQ*=@6W05mO{aEmzWqv7k^&@#knxXH?oz4rb1U{k?@7gsdkl29
z%o)EWFqav4ia~vTKSQ}R)JLW0=ZN!xx*(%}#R2Qfv@_Cy3990lCjjs%sWV(||jIONnI6w?PmjM3SV{e1r9HCfzuiMuYoS|^l4jsZn(
z@YD4NAhm-YSE`h5HW?mA_)lMk1@JkExDZu3p$c%74uefs>;=Eo
zm(#^R{6oc8L)Be=?cz2x2Wcl$?JHi%Q~%D@0}a`SzyB)U3SEF&Q(->x7O0Ck?`
z$J`pTPeGYKFFZh2AenmFaD6vVaq#IjZyVxAqHZ2lq
zsWaQz)+%{UuxXM2xB^7*yrA@WMDyga+kbA22;n8X;F|rJy9Qd9SzE88KPOMW%f{n=P3e`7>Ku(+w$rc2H`=TOqJ|jZK`GbjygbYU_
z0`qwUpvnPzl-qs$4p5OT(8Bdy|9(w;10lUy(E}_9`(@ptc>0)^*_{f-sp=pCFeo9Y
zW~Mp#?nKY~F0F0f5kr;8Reie*lLiNgZpl-31aCvSo{Rqy&R1o@8lp}6?ZJ^(7jQ#r#o4h8J00UIQMFj7Pc{mvk`ca5d_<#zF1l92s+t!6e->;F4TBuK{
zuRn(|ErVgk-{Orix4zW^=pad(!vuq<>q;3wDpw10kZz_anc3IbmPF(bX^*<=#l=X1
z>0B==^ePyy6P=yCSwls*suE77P&IHb{+Sq7rMf?A*TqHWn36#%X8o+3zSq_lD?6?$
zmibbfI>U!8*Q32Ad;h|(sQd?9I)eAGAiLd$NSq|EX?EgOzGo6?QY=nIQGyPZ=P%nRSJ{iG@-%%
zj?2kE!c$ndM2tWDe2#lSo@{BK2RL`6F*OLYLJ(ZQZ}3JPwIN}1GNbr#@1MF1w2@Qk
zK>N!4_ZHaR(RMkh090i*JE=@AjB+LK=pwQ|{r42U2_y4Qzqvp0K5O&7s?zp)U=ClF
zS-pN%OFMjF^Ia-Xtv6Zydv@@9zR(;(3F4|KdNtU0v7Vn__zBKh9ePO*3JW>Kj+}}<
zZG*&+*#}#w{dz**LZayU{j{NCw{l`&zJPF4BvfQzKB5|Jo%6jY^_j}&q`s7T^t6Bk
z`JC^mRTR{z{C{&v9=Coxt^=(=^GhNEdXTsn0XjF4=BHcBu13VcTcMk%r<*7s%fU=?
z=wTJ6MmWLosPUQYggys8&zq)?z-+lrs|Eyc(68AnPPgJ0zY16;9ocK?ZCq`?`eL@Z%XUqE
z=S_`(aFpX`O}^L06_hTIuf^~eiu_!*D&5UkN&7*e;1ImN#AwS6qfe0=WcVK>!?mAk>3ZV7>$7(8%Q8ory=KDe-QuU|Q&V*R}!+JA%7Q6nxo%DcnH
zLgu2$E2JrVSKf<;X!AO%lt7pzX
zb0J?J^=pzck<=veEGlH8*aUNPaKKUk(aV3Y&xB~Em0_3wsy#!zCk8d0I+wiI!^ndnRl_Mph|Hn
zKQ-8Cx_gUmEd8@*AML)Qj%iJgy02Q+RBy_|U_6m+=iY1}pYi8UI$w2<#Fo^a_UGs4
zfqAO~#482{;y&eAdeqk*KPLjvi6kANCkSwEWUhMTo5E&-zO$vJ)Ucdp7CyLr>9YK`
zDQ{6>6vyn{A5V}ER9~kWtzBUDhj#i;>##iAH+Ul#Y>Q`2VS-*HiA&0?ASU8$QT0HnUbM2I%B5@Mr2mE^Z7;46qv+rKdg?!#@RfeP**F~D9+{Bxqka2M
zVRV8VKkw4S7?&ha&4eMj|Dt&-R*3mM(T{Gl=WyCe0vec!=JS^c@f<7!L(m
zYxe7~cNzODT}pO=6jWYofAn?SoXi!^}NQlEl<%wX@@u&$Cnn2-$^-WK&T
z2?yjhc`c|0%$F>c&IpGLC+izv9>(sxByet8R?6=hmI8^H?D4qTef##IW&KM^i@k7{
z!ZCHn3kh=PQxidJT0&`gBIy>GY!rM@K*ND
zHY7-2-?2RECO}!p_bjrqAh|3GdV$=EP0I~@k^W!Pci@E5ss%wN=zUcVb&Jns418O}
z>D)8kzVKb#I0rgBgHPY
z^s<`T)e~m@Wy>1N_;&K@lC^DurtZB@08zphN!&lHtd8zW7z~Rai+ulg2upYF-Vn5l
zaKrk*+*mSFJ6l-H#l@U!6Rygq4I8TFcxN!1QCu<^3crvDrXy`pFJ=vuSXB8$q82U~
zkojet`oqSb|8%h>?dJL<54%09L!2yQGK#jgbr_gv@Q%Q&R#ZAvR1iI6Mv=-8Pr`@A
zCmkgKBCBegEi{xSWsyo`Lfpi7@iXKzgac%b6HOC6;PB0+^oJB4nJ-5`=6X+WLpGEB
zNgSj6!W%t~Fp}KcmA&|20y3mw`vjCumk~iv6ESwW%-mkZ+I7yk-GTb%AgD{K8EaH<
zt_&%f92^N05{*`qs5b9|1jXU1ufsK~iNFDwBvTlLW}DY&r62$=cY3-odyp7RM;nth
zBrBzvtoZ&tk#q$xOQn?mlT|Unq_-IA_6iGpYG?=!YqjdeQ91T&tQXg4Y1Lx?QjlG{
z?vP>Us@^6&%W4u_5O(Z|38JNMr|lLh{$Ut?gmAk%s>^sK8;TRd{nL4PWaKsUubjgu
z*mlXT+N5K?;pk&Q|4uet3Cqyl-d=KYawW?m;9DjLg_GCMC|wlmV=}@~EmCe(LNfBV
z3%Gma9-``O*64!&vJ~Dmn_n_2kk@q9)6-rkQ6C=ey7OdfS8ZoH9vqvYOTjF+e@2;V
zx#+){m@Vcvf4D`^pj!P>+WV3{7>tigcCk{c_)aU6ayMH-d>=OcHlsXNZ3Qj7zdRMq
z4>Vge($7XC7F5A}@-YWV8d978v2Ckd45|HR8XJ3QHPvU!%g&MPiOZ+1S+51!#+8^a
zb|IbC3M&>r&Q`;p@&Wu?`DnLA2{ZSJYw3iNW~slL7?f8cw&NjwMnh1oCKKgs;&%#3D022p^0T977w
zW3=}-$FZm9ywPr=E1sanbrTOL(E4~P)_vfB9na~1ZYSa+cEDc%|5Y`>Rfzt;biu{nQ)=Aim(=r
zcA3tZE!M8XBXHhlP-($>^Fnqx{`xp}KCPvxx_h;@sc$5*)me>8rRNWfaA}SuKiK;_
z9ac7|JpDfW>b<3!pnCOC186F_4jcX_v_5j?l$g@(wcmzDAyq4G*`2Zeg4703>gJJE<%Xs~H0iaU
znT{kQQrV&oCr^MT6SX(_Qy=PRGJe>mIlELFx|s`yfutZipbu$g`a|?&%eT$Xb2W0x@@xPOFzzonO
zYNXUz4SkQu$xt>+t+-8*x~L9Uf?USZl=D=O!VGXY=N{iM%;B*rHw)fXkv)yv*xpuE
z2v1~KSSMP`@dlw0;p~@Sk;tZyG?8%kR+tzD8Hn?D6{2NvwswR4a^rX9008C9ckO|&
z+ak%4mY47U{@g(?$wWwjP>}fyUn%QHlgdlAyO%>jzNjE%PAI6-Kuo`BOiKKHDnFaP
zc#wmwcsq?Dqt@Dp`xyF*7&`yWck^|%IJ6SnaC8C)rWjG~{KwzEf-vK6l&ilVVQ1A@
zt>th~792FT0}7Y3;od^Hki|3gQ_%9R_|-#(sJ+97d$???)hVmeUJZm!YH-hDkwfX(@jlD=N=VaoBZH)XiCB456{)La93}!xMr34K
z_RXcRLIc@dS_f`Uf?s~55OJd4!L!PE**D?q(k$=IiNqHa9(-S}5ff?XcVm$dfIBl&
zmC#AYYS3dmZ64-hCZy2=d}ADQk2p3g`AeOC@l2s5Ub#_HwH6Z{GoV02IYy=#yS
zaI$a^>VRBAN)l7S!U7eOLMQW`r#N`-Av`!}Fma6giAGax$C-kpk`*n>QV099#eIyl
zCM1fnwz1qkR68Rv(o6Uat7FSG&6poDXgg~o>elyVkTdfaVV!eyHs<07_ghEhlc(jS
z$Ddsc3YW^LDgTL#KUNm+N>P`-W;kP@f4*iKxatqmb`8TH@O(u`uh0Fw9RxXrOv^xM
z+p~VyM1wn^NbIyjlB-5b+hxl&Po<1c&oNVB=P#?E>>tqbzQg%A6MR^zpr0f-*XQB$
ziQliIaic*r8mN-U=pbKQ6t~P+On9-KxfCgZbU$g>-L#iD`T&TGNURcq+7HDdJR-Om
zj@>z#^z$@?Ncs0>*^x5EKV$EOkAvCg4Pz)_n%4JZgqUzKxL9Mmw&YbzCk=Hn;_sh6
zs;UhQ1Tvld-43xIbA;fp9Tz&9znL!|t1s_?1L%*(?*e2St@sa8)s*{A4uRyh-;x_}
zNNcg#Y^s{9pY%Nrk0jH=h@HCRo~L(UuZ@OP@m-nTyZ+Fw_36DXV2dI7j6%{}D#gmr
z_Ul10&uQujU;9p$Q&z!127Em1VcYA?_4wn_+PaKu(vWIVEzYJ?(0NPMv*9+zu326`
zY>vx@KyaKkL(|(28XV(+;X6%OEOhU!v883gD+dk?6v~PIbJ{3e?Vpem^fZ2VGI(W6
z7P3)Lh(%I37!X1?S1hpoXFh>C2}{xIV#h
zrJ}2wBE2hrT^BVVs|0*JO<-g{ZzUqg&XN`0R|TFrfdP`bT$#HqV5ZK{JimWYV08Dm=Wz(ITeW70mDPqz-Zd)hZQlSL?0L%
zWcBRI>Qy$RI2Si0{A>jS9f?-bSS*p)BVhBQh|?#Uhk!N+fmetc!0g{JxAvizphC9N|;l}I+R
zW|$Y>3WpTtv}`bV74}scHWDSe8SWQ$@5P~k=;`Eh7Z=v0#uFI8-;jf*9P*C9^7ZNfu
zzNacpx4}}yczgo6;Bot7Q}%Oor^SsYb9Vvl&4Hg3LY&K8TTTZ~er
z9gO0`uuj7&lOw01uzrY`1MMP__CyBd&ROeIL+c+VvD6hy{nQD?*on~5=8r!rn5z;2
z=GKb4QFx6yO^PsD>OBARC)$*3Y`qu`=CFaiU(nF}tU=K+=a_L;OTLqurmF0*cfq&@
zZf=c*g?y3MH04`$QKA+VI}+eg{xp{r_nlO~%gthT)GN3gU4a)zsm(`3c165(xR6A&
zIMV9Y`Muh*_O_L=*wRcZ
zBgc?qHdGE+pKTT0jj`tA$cdMI6+(XW)6Bsy=lx8{^T9Pc-UxT9TPWT1{$CiZMytfD
z&9-F5EP|uUBo0hq7f3ukYYjm05@4DD0sMlBczfr|@6{|r#4gSbiUnxJ65y`&xglez
zT;WVTB#=P9l(GBLPT;<~hM5O(_)7zbzC;(H<*Om}i|S-F_v`uv-kdbIXVj((xI3yw
z?k9>27W-_h8;(m{#T?B7y0a}P$k;Rld*?OK^ZeibtPbeqrO%AU*{kr8zSciO3WG!R
zajCeF=n7E6%_c7UQ59qaX#!7Z6x2OhF?9AD9tH-|zZ|rB$o7O8&U6IYv<%
zQj=v3NoFjO#_crNE1}XEwXlEks?U5A$CZO!TvJ=fBsDDxPw8mrOZt515dbIc{?tLL
zAeVdg!%mmax=>xfT!$BohaYT1&Fc~dKB>^`1?(_FeSn{Wz
z=^mkA)a^koye=cKVX>op(;#-iDh}tp?Euqb6Mrs=KA|{OXcObOfZB?_FVs&8m4%Xt
zNX~jQi@e2c<@3sruTNnA3A`5=46>u_Ytb!Z8RCm1;IOD^TDCbA5-6y0Rj0Spf)PW(
zDE?50k54A}&pSc1=cwX%$bR4ev0o6t9VzuU(fQr?G(q+6eb+4>Lh(8O|TooF0QHe+~Q{m
z!#+0$B$Nlq&_J9Wr`s46#5f!m*$zMa7{E{U>7z7(u?!s;DI`EF+zCB$kdISEl5r{S
zn2kl}SEwc&Sa)DYDTS(K(Zs|oUdR!C#!NfYWqepT_>&f{?K(W1n)jM((^dCCSyojC
zM(oS-<%)IJ-=8(GT^u4;9~njNZ5qWfRDY@|z9mW2L%S{sMfwKN`>wj(6;r>Hl51Ll
z!I#^y3g@}`vO?=|xEzb6!so$;y`e3K_YT&RH}x}HtV-IN2@LYx!&0OHo?w%ho}knU
zb1=w{ohwnA;9KNp?zfk&UT=Ei9i9h+0HGoWk$`EINA{!Qz02UcLDXEc^
zPk*G#x*vQvo#4~78(c1&=<;$wLk6q8x*&KU$6)&Rw`Gu)bs;Agt#5@mDiWE6+Jyre
zqOEcsp!i-8cIT04v9h$FnT^>f9G^xGzVVw+^_T|DHdR{EIO1A_`CLG0euA1A>L;!G
zI-AN5q6%KuIn*h>2Q~y0*T_!}ULciKBglevu|Qx5R+7FL9h9aEB!(_VR18Hwy^AJK
zga#Jify6Z$Zv1Mb*!H3+&O2a{9(oIGR~{Zg&(r4ph9T0b={ult%a``{%T9uy9cVOM
zyatj&ADYQ^Rn>cw7~f5DzhOQ}l?)P3=Qm1x>s1?;!A=OuuAt=BMr}C5zoyhy>z1`2
zh>tG2sk9&E|CsQz!Z-q#hTYwYj$okDI`@;rBF^p0B1M2^rE3*%KZ)oF^|$QMwgODA
zxPgsGp~HU@Rp0Z4wlXF00YzVxkS>OVindDfE8N-OX`v-AUr|N_n{sZn7)k_#`l>I5
z`VQJC=`I{yWwLZfcVs=bL9^u`^V(Gt&vPPaQh<@%FTh^KfBxEa+tY*KN%O}fY2(Ue
zGNP9tW6jw;he__E>pP1S%eMepD6Kkta%Ham$512RD2hBpl_=h%q2Jiz`9*M-!{#&@
zI$Z@nGMM?xX?VW)Zoj4whvD929PNhQS}FiEf@#7V+O*leVebmkg`m>p7~z@t^HWqo2&%-!98#?sU^z382B
z*&N{5?iKbYl5$-1Z_S?PcgfEwZ9wR$FSBz^a9=Yk&>!MCOIqcJz$J)AMwUMgvp!cO
zP}SU4C3*?yxvF)Gj-zBohGxI3^hK&
zh{-NnIY)8NSDyHey_-*`z>BNbP-=*pLv3HmZ+en-R=yOnzz-(`
zmrq#)LW;SJ-svsQ`uU;7pp?XS5{jv`KTCnMV?Rr#4=F4J=@U?ihFcuQkUu#__%3so
zUe!EOzEoxgOM(ddN?9&UlTLbGfmyl@0c2Hi#F3<|hGo$OQ4+)aG9?4g&Fi%env4^+
z`C$(gi7Z%vT(f?pK_4O(R^IZ$HLAF!k_-8sce%8y9UTqbKmaW0Z?ALkB~6(nP+)
znwGIlU@p`>1a$UW_Ig?y3ETk^Kop9jAGkomsY$0%{CLs=Cz7@(iP!*)BNpa$z7s~-$#Y{dtUo)d+ZE#Ea0^{*clRa*|FPotIX&OL
zqugaDrKbb4Q58I{>4~n7gNbdI$4xe}UFDl`?yAB{^(kKCcPlUh`$
zq8?}|cGA6TQCtyE((o%d*boYr4fAh)O7un~=C^K6lCs35OY%%=9Kv526anD)G
zLZK3)KAAYGI|hyxgoegQggX3(x&_!)P-
z*RNkJ)N0ZuEWS`ez8%X=>;QGsl1&4fsq$~A&lVV+uurffj#|MMLsmr6a_zb*Q5UM}
zEc8t6oZ+Jr(oVUD?RNA
zS&628dgN_0*;CZ?&0LN7f!)k+*30}-8gdT2J`W@J77WQ;49EJ@#@{-LF2pl&l+O|=
zvxRPzDQ`o$i$91-ZGaKa@ABa4M8!zvww+|9yVFIkS?#FiLM;R{U9ihO`TBv&+rzXm6bBW^o{oM
zx%H>Ysu%@O2NKPMii+y+mpuu@o)nXu2X18C5=4kr9O?JbvW2ghi`2%B5lbrA&g@VW
z)CqDjzZ|=f1umKT6&U%V;5`zmrLz_QSClvj2nq_eSnex7ZYtwxv^=dgZ^4?p;v8#+
znBkO{=%+Jfo)5%jH*vrw4+zLvrrf>>T<>;A;+XwE7JyR@xbb64_!OO{F~#>tp|sLiL)Q->KbO=37xUysv?sSVZvozZ)E3_Gh1O{
zXTp7;&&c!*^r4zAdcWNYxocS-+QuIh+95s=+;SkuVm1C2M>JJj59emJgQ}19##e;c}u%`J+qagFbLQ
zQg@t{F;BkTc$e9c>1-pc%1s?e1C14fD&Q<#?&u!Z$@NU;a=gi*=F>~|Sc;iC>MLMF
zLpDd{7aQfwNNbh;6A=KW>%@wzJg(=2`79}XcUnh%R;l`1g@_A=iib8V#|4vFO{bSn
zxW)`rF*SQzDx&|yStj%ePTwwn*l#G(4{3B<_mnC~N+-V{mbAlD-V=q4
zW||NS6{Jtxn>q^zi%U?RdXKXB3Ur4GQ>>sl=t
zV_JRgnybsMs6JqbXHNNvdj1`-y*+S_{|o)1>|&sqg56Rs>Tixp>f`59N#F0sIDQlC
z9{Z*hCRhH-ZRuJ1&ETij=CpbzYYcyJLRl#tqMm;f_+EeG?SE{CbG(riBSprJ#tAfu
zzZ*aVm0&llZ3eZK#vBYVBx_u>O!u+w+;9~#x0p}kp=r9$ehR!e{3lnC|~iU
z6lZ`3`L2^Qnh=5YEmk~i
z2-0UCs=J-LLG#T-&8UtoJ_QDJhf$(LHWMP8@B0!TFA{K_M{93gv4y@8qyHJNHX{73
zhRfJ{D_O1dbtI=$)N^xoSN^b|`VexH-AB6_^eQYUg`*c81oEhhvixwY`2n7p~n(=E%Yc#xmEI{Z@B-
z?ZhA$`A`x6xOTpv?(A`YX>6+{Vo~G*0-^fh3>9k!@A`ff+RSFP3}3sRY#rUF={do+1}@SsSP7Jc
z&bsxQwuB#(JT{qHj{9igSn?2#cjjdtjU->%Ox^3!nI@jSU(pP37NBPY`)d07?ctbc
z%9f{SVp6LLIQGVQuqgYPs_ieVEz1PEr2vnJA}&PtEi-&%&yAnbZ-#G-u_wIOT52Q{%~)ehOo!oMLRt}19pU-xOBbt`
zB9T+~^vwHlIww>8KHiNQh^PxxU$jhNrLh>Nl{JS{PxXgnm2|cB`{b*(JCBS>y-{mR
zt~*AN5=zNeezledLFQ44WyIaaq}=}NdsMEpGH~uM8cNJVBRU+y-)@T~FK2&fewizO
z;m@^ftYbzwmMWgNjFJ2Xn^h=Bq3QVJ!DATL>dUCV#6ri)3zR-&oDpS|8QXd*_2gRqg_DF}R;(jLgMM)X&tg%l!^A<_ZjD!x1Yo9*T-QnH)qxxO0G
z6lSwBSXHgCDQ+2tl9d0W>8zuo?7BWYq$45>J%j>7hbS#wLrRx)cS}mQbax{$NJ~qD
zARwJXmoz-IbbYtqTJOKQ7K=P*pWoj5x?Cnk#@=s4+c(bB%c@6Dt$JO{`;5=d;V6%HtTZ-|$jW8V58STVCP?T8583SvF?$zAzZ$
zwg63L1}W>$4%^Ao78E3bg9}Rfnp7ve@R$ezjjQ2J%w4O&|N;3~6bQ
z(f!D`CsUDD7efbg*UC^8|E3TA*0k(*R~RQ~Hnt;V+1Y-zw8yvDSJt`TO(dm@{z)N8
ziy*sBF7OH+eNYNg*wrjY7XdON6d$Qj7NvoAk-a$(lsWrD(y^8&a-N`Zb#Hy&(aI1>7NR
zO3KpxtrD-}g~w3eq~gzz0xoSMIIYyXzT4W`zIYzCJ}z0lcT~*9iwa+TgJs~GzTbI_
zi7OR!sj0@IYFQh2KT>?7pu|ZCjabal_<7
zn3dg6*thWb^iUZ*CO8?+kV8{HD>WPl1_VO_WZ;8$;|38f2DUUXusEDuCb5XR7b3pG
zlznwL12QpFtQ!skF~Z~nUTlvT{+I{?_;1~rMV}0`ql(bqMY={RYRrhi5hNc`10Y(q
z7@$a*u+A#aPe5?L<@dRGLh1gX
z4gt`}QVp=5Mhggd&+!%2Sd#gRQH;I73)Jpsm4v8$kcLSL8fqO=y$v5=`LQ3sfHW;o
ziDKg|zB%60!j;{FHXl}lt64G`vb7fd(zxlbyHqM_ehQu+a$b=_P|hp9m1CkqAn4C!
zwIJ`Dx%%K^w25SgnPMgy*fH<4?M+V56SZchi=`CaA8Oilc`;5fV&F>(qB5jrw#eB}
z8oX}s<1)$m6ZnR4iGP1cTLNUxocUr+*HQMdvY$Y-OLH7YlP
z5S-75QgJ|!g#t;yPgR^K9n>ipUh%K24;e^^(IkriR?7I#0I21PLsn&f|EzkCs&yoL
z0TsR{Wl0*Vm^enzPjOfgVR%3|QZ7UV{XJlS%SR8*518`?O+>cYCUOxGqtjuB42H=R
zRVZYiAO3vLDZa3&h0+BHZYUMUUSUBG4M?EtW96=5BVt0wi{)Wo@h%1ChaAV5guc&??lQD&mO=#FJ%t<)d7*knol@q-;Q-r(5|eR*eFk
z7_e!hh{rCCPMpBnaPfUO(LEJ~nkt}xxDj7cE}g(O=se&Xh|*r6VMBZKxN-54Z_&|z
z$MCTr9N*RiJdWuPk$L^VWU79$0zGV3gNIB}A^-b;M=c8Ocp$=4d}aoj{>vvRnqH_%
z%Sxf0Fj;o7V&u-Z1${1y_iHx=hDU6yfDXnF3Sfi>&egt6n1H@OW&f^mu#%XS#Zu#T9+A^kXFVFk_*zdlD^V!9Qxof=hA83YRBFZ
z5+;~!$EAZxl$D=y`qPZ7(0Mc=AO2gNY(HNa?VD6c{Yzn+@!o;xig*kv8Hc1nUa`5k
z-u?m9VIvuGxfJ_;gfqAzFlJ;CJG1h$>!}6^)pvGSe$9Fwu8LWf^*q
z6m~il)g6L|NP9vo;5j^ys@|duwhSAfmV)07gehIGl~Mvyz#+EIdlA3CJuH4czm)v%
zlUV%RXHuTMs((`GeCp9%z3cJZ>v1zlym+`&)}CA%^<1wESY~?R
z9qqUJR4Aw$!XdDpZdqz;qo70WN!c)YNFmkb-aa^4&&&eJHRyP4KM6r)R;9>@ub*W9
z4wL-$o&%r#1&F!W)C}*PR6let;=bFOOsy~wc)!(U9oU>Oo?w1`?bT9A@Oat(US?<)Zd-3sTC^4rHmq$yl$ne
zclK!&sH9Tkq2zpI>M)Z5II$>9wekXWn4)k3!TlX?+=|=>B5G=fEeV)qfU!}QLcb-M6Dc))E{$?m^Q6pS2
zRuizTyfU!ef)%F1K9nJ-)f2SAc@GtIJ2@_F6&aCwzr){1oh$kO-I#s2C&6Uo*r)x)
z<k{8C!yr-@g=L>>LuE8inm0vnbEKMI==
zyrC^anN@f3$~k>k&wL8N6-piYz4I38OKr^Eum!Vs4_Mt|#_DH$n;0o=<3B3N7cH~)
zX{7`!HtBMPb>%qlB1Z*y6WyCv3G;U{j*K+;ss||gAwGu(cC6Kz3m77a+s1=#@rgxF
zDPv3#>>se21{6P<`qzm}Epvui@yu4EHGAIGq}y=wQc&ZL(O
zl7W4-)=M>4n5qCM%z)hE!OxKC!1t9Y1v&Y_Rms9WVz?r?tPBezkfR8&z)DlU4-A9S
zY4@(Lua}x#GK>MFPV2H?XLT|R#WdQ5ZK$@TO46t>hWH=g%`>-2B%&rXGDN1h)MUG?
zEO|1V5jB!aT2pSuEr-@R6VbCi4kZw`8VQA(cCIQVhVUV*|Jam7T+R7j`2ifZsOOULi$A#e?md5dc798r2MNQuK@Djz+e
zbD%eHE*PRbOIL8#@jS4O)fh8DD^;N+$%8+qg)KsTN*#$9rVi;Ec9H7G>?yM*%d&z`
z>quUPlgVNRKMoA&;XMyrlu5eE4PP+T0Jck-+CPjo)5?OnbaXXR!i%iS8eU_EfyNKr
z4{A-exfB*7&y{dz12V$T1U;(g3!sJJjKyFL-EY$H1+UZ5P#!D}g7tnkZ~&Gi4%
zy2|ZQ!SYSqh>8v-Werye7+wO_8Aw=;{MWKwM1+LrucqRzPv2|9-gM|8w`7_)+1UeG
zHTSykeStE%$`;881A3>ggIi;>Kx1Mh~JNZox>p-e|oO2hrMmRmfG||Zu$#w7i=(A0-dvya9=uE&(b!gkeA+@bl$7Yt6W!r
zg`t01NQpqo$5tP@^23>()Ip;5ktnCp_#ZShWD|R#4M^m|x>Gu>Y}O;b__z*<xqO8m&;^q+SC^9Gf!qz_3oK=OX7-X4N;XY#hD`(*tD=^}l
zvjPy{SakSWyv+N(m`5z>ix65S9NP14UD>rM|6!?(RVl0bj-gIdYJ9J^qV33s>AzPd6;=mh;^c?{1N?7MWUk2L@)_k{e+PXNpNrd
zz_X5ZFaZ1?nf_j1sv)JIs9@f%0>Y>CIi&fJN~a>;S(XSRQCA=+z&DeXPo+hs5Cu=0
zXVA+EFsbIGnp-E)!ZDAd1k1Jc)Z%D!$|%gVw@tz97Mdlp{59@^&cAoDZjEEL|VG80zefq!T*gpA+UoI7YD1
zvR@IQQ;Abc6%&FRB6UDTDs^$1q?ji%(JF*VsEa*j2Crvt16ZdAS2<;M7a)@H;P7Or
za7Y&TYNhiJfXv`EGl`xM5Iu5h(dhwr=>EX3zt4SPiQlfoe#ys&=!_|@7b`@P6G!kk
z0e5jQz@8~AEFAsV%^Pkq?OH3BOYg=_n*u5vc_Dg9aj}|Cwd!wwKb+2SJy(?d#1I>o
zHgQSF5twUDzA(vUUkT6Bg4tvu$Wpaa?Z;*JTY!ZRCXLi$Dy8|NG7i;pe-_RCyd42z?vkeEbDu1z_|gZJ
zuz`HpG_GzpIQdD^aRS`;^EwI&Q}I80cQ;}M9G=iF$@j{D_x0ZWd8ZS=g#ts%U8C(M
z2XAwk8lZ&2r#^WNg>6@IrP>}Vv`Fu`aQkN{UEU05Ay}_z<1+aUbW+Vn`9KarpA^c<
zhAwy5ow^2C->{vUS+0os)EKS?d$dm)ghMP<@1xnR&Hzms|E#ir3~Rj9
zELS_9%jMGf4gUd58}Io~_P)7k|C^o>%zT*_(F^;#dit|&yvL$oEBnLjnlcf-0k52i
zm4VB}r{%EKCqyoaDgK(%&(h;4q~FuCS@)=BjgtgC8-7{uXZ@j^|fH!(W2nk+1P+
zX#&^C={`A>gk!UTz5RL)4BPh-@lfVAe%<+Awk2F;f36iH(u*!oC?PP}q)L@PL5nb`
zD9yb7?@iNpO`6bPT)$6zpHI$rau?AJbsi!=cJ7;3zb{zLt3V*ti~XIp2ov0fi$=b*
zsDa<*XwcGv2P%_>kozQuPvSx*PY;71(pKyAVytpXOV_Ey<)Z|#kOXRP=kAXUo+f*m
zmaNY4WDedvP8mMlvwSpYtTp_Qiat*FY&-x$<76DIY4sdGNztiv-)Wouc){bmedT)3
z18YWs21&17&=wU!78>LtWlgpA^{y2o%m4J+h5I{dbUxV{*%HI!1E)y)-p71yYdI}P
zAdu|Lecz{*S*qefEYJD9@2Qj!pf~4TU#i`wl>A!6>fk%F3IP^VJm%m_#_t_CtFYG1NVTEi1WqdqIX2&CvaFo^=`kNH9wal}M;PPTHrW2tHG53(
zb~dj*zV$pTk9AfEh8G>?SNsD&cmv{VwY=MDfD-Mwv-A%N!li&g#5{A&_^q};V4f1j
zj44-JP<7BJZC*izQ@#M*pegaB4(chBo%8`1;0%Ca_r;~pBYQu^)MrX@0HePCPe&Ap
zo12QTp5j`FpFva|0KQJYS^YfT|E?tA%FB)Sv7BRqE&wTzA7BJ`-n9<_0JTgtMLu)D
zzh{0p$>m1PSgcaIz*k8`)wtU{;iZM_gI2OiPYm`!(OgoAHJ1NOj2~as(YlPr#KgS%
z)N9=Nup9$dPfclX&t&;N+GrawR?)yV^p%@_sFshW{ohsRfBT;&`z?U}d5btBfKm4}=UDG{XUij{2PF{(3$%7Znf){m!;3Hxg^33m5sblXj=%n;+Ndmx6z_6
z#fa6xd*(k7P>VYm%BXuDXOwj
z@DEYgQQP_D-O<&bbK!@Z&LvNer7j%`m@@!?e%u7e4O`_ni+*>932TOrJE6eWUm{3f
z7?b9yoV!Avkn@bAB~%nOE(<
zp=+%PuFh*8IWWIWaEV2$NBIg+)=W!s+;zSiiIwoGYRveu9JN1OE>;7-LJ)Cab6n-!
z`3BZSeAfoqcxCCr&x$CX`Asy+>j3c^fU)CMnq1WU71G
zEYS>PpV4NmSA$`{=wkyhv#{kt8O`9_0c2e!I5~=8;fUKLfc)EY)OzInc(YTj*T6p#
zxkl4F$At$f@K{zn%EX$v4GlmpF?wm
zF^Js!US0mo2@~c)^X1<+I`m#S&z(;v=A?0oPEfZ^@P-wnevF!u6gK$OTdwqeuNUDi
zr3+ieu``tiwkK&7rd|O~u=Ssz_`yi#>wNXBY1qO7M0_)zF=~(vcvSpOr1My92&!ib
z(|~+O3MWwY0*+~EY3Z2BKB($@Vc`y^$F_e2+$dtldw|sj$jtpZ79Cm}PHEAJOyT&&
z%IK1CXo~99Qj-awTZ+S#$d^~Fyjk>S`|!V6fRghuq22u8vsh9bhD+byFNSJ+=bc**
zxa1KfJwjJPKb*IiEs#24q>59lHi8@+9R82@!~zZsX_+c~nK|@_>|pO>J~{o_N?R`7
zw^cDH5S8lLECG)rS6QbF_ixEIG^HVo_PdHq7^1^%7AAUdGyZBuVbiil{|TKPFlCIH
zw!Lz_V>T>uRC?A9V3mcv_S)sqbu8wVw5~xrA93_MAIy8iRtb>A^Gb04?-vwr#xP;2
zyGu)lITc2v4n@cUKFyH
zp5*h$^tF%tYW>r?^zkVcT6O>vwIH_b)90(a&dVO)sTb^F>_Aj!!j+>(i|h$Zffsuc
z2=TJd5=T^UClsBnAWGpl3NkS&a@60kCgqdG3LCv>KcqL?WoxwLLW#9CrQa2?mcDb9
zP0Zh2D^NwSk;C>EhErm|qkFNHpJG(!_F~*=Z+?b}^g&iHGH@&XoVK_v4PSRt`fRf&
zWugX0dd0G%Y-~EAs@d1JMFjHpDpG-dq4#3v_CEQ5de7K{yS`ezg|@x8WZepD5t5IP|C~~lrHGV
zFuT{We(D9Jm`*~SKms;c8y)-+83K6^x8>Cm`*ty;rymm?9Rm3h>{q=@y8sf6_5-T0
z0-5NH?Cj~BpM2HRQ)=hU)|sqBCeaJu_zGzp{rh#V7Hq3&CuR+=4#s@8If1)~&idlW
zqtkn=-EjPXZs@809)Jrz3>hAsQC!WLRs$E}YrM|$oMWH!L`Oo&bsyiZ$7gMSh^oEr
z7FWJDTvnZ~TuHSiZ4k)XL?s+ePbX6s<0WeKD$`#^#4_5upbq!aY3s=|{?Ou~TWxr~Cx-(twud%j8t-q5
zrQ3Y3X3aqUK5I&yzPo|uA9#f9#y+kTF428_>i>SpqZDKt$!a+ZB0ctXoj@npH-4*D
z8dVsxABfd6_)aTF;o=#5>A-b}zE*rY-lBz)OyM~)HvnU)SmgfEW;PB(w%|zXaVI(v
zp1`GmU!-i+HCFd)sa}9y7DtEEY*5g$u2Rvr=UMFSX4Y(oF`u?aB+g8(gnDT%#b4jd
z^a|5t>%p=#;$TFcjZJ2s)yu&0wORu)gUN|MwYL7Xv$11_WqnXBTB-<@P4YDB_Wtv$
zwrhb^z+QQPvvif8kdR=kzvbz5wR|NE2qIdKTD&t6=GwdpDLb#W^OLEA5U23`h8Pu~
zlc^FJ&F*%X*jq0Uf5jfMrUxY@Jr%|YBjSW6L38Tol%u+V(MI-mgMUhe@`IMy!_+OK
zBn4tz%wq8z_p@47fgGF!o<8ibnciOXgv*tvH9&0H31}+({}50PoyT6iR-sn4>&6?C
zD`g!L2eU`A%fSzo4kD}^S2h6WtL|BfcM+gV3F0KyrNU;hQ_DOJkZ
zYgL&tFuaud@RAyI7y5zcrt8_tTbRt!o&~PpXT$1Q8gqcLTTYPn*b|H^`~#?SsbTu62bQohrKF@lKg!Bz*+Ji5muKQhG9_6t4|%OV7&@L*H5AhIg@?b%YS^l65RZ8y?HxRtNBbNvbWjAq#^8#$t~$LR
zK38Ybt1*#0xj)%Y;a&NgrIh2MnMivKAm~;eV?F5hzI;M@E0CoNFrDq+R
zwm%?FW!|sXpzj?)v^8I+!jvoj4RshrLBr!h=i?Bd=Znb%u!V}B$0CmXfsX>{0tl^P
zsKD+_l`VW`MHD^T!iUAVo7~jmCw39Gw(YrKI{?+|yia+717N9vpX_(*Oa)$DpPvy=
zPJjSVULFUXE1%F>SXek0P@t%kPj48yXPqWlU0iy!&4hj7V=U;K5&prYP(n{%2XidT
z%pfu%^n~#>A*_kn^sc|+`da;pBm$Ijk?d9ab&(kM$CNiszFg6j9A3il9utQj>Zr70scdJuQ{E)-#L(D&Bbk;%qPBQ?iF0v*=^**kY
z&A3_Z^uH-iGboc02_(TYF)FOI^)Z<;jT0gcOh!OI`}UYZWZ60
zHs{O&IOK-#X}9H$K)2eb_fgVHPlhV3rP{WOaZNtwNIV;{r#}Vm$oYJ#gxh1{8OeZY3&h)FuPyScrE5N{>jjbf{cJ~nb8{ic$BO`^XdSU{1Z;<3T}`N(IdyK(4XQCRYd?+nE0xZcg(|;RClGB
z=w8d&66h1n&{cIE+pPlXDW~BnpKrE*x=jzRzXP)UD
zDvdw|Nfd@8BqU2khOlFXQETXUs2bMbIn?bLBj910k=p4QbY+?|X6?Jx;aaBY8KkLf
z`uyD7z)AMeu3<(K_@OTW@9HFkwLn4Jl~TR%-#ayHlkMR{4UGt}Y?)R71T3blF>6i;
zE0{=7)aI@?uy3(k;5^K@WSq(j2U0TYvK7zGm&8mCvi+5wq~cVeWNx-6(8A0wXRz}X
zft>}J%cBC7BGfsXs5O(
z9Q`Y@{$Yl%#~-lPf%D7z7Yh#1tI10LkEV>zWxK+lePQ7*dxEgFq-3tulReXK*+c-o
zjh*UUE(MoCCWgW;hEd`2kDGW#CeA*t
zW)*Ijc~xR5<{2&xGlR{y^;058dcJ^zNz4$O32z=`1G`)oIF+MkxRfX8vVX`05_vX!A>*C*CF67?92zgSP8`
z--h$7xQtA#to&Z6wA4=Z-p2`n2pAkIUOD1BGBZRRT#A8`Pb~dTN?f!sybHg6LJtom
zn*7awhiyH?S4zz@J*rSCuR`kYxG8YQ^U=?T(d=K0Mzd>hbA435maO-%9%Gggfzf<7
z|He^VEbvy7zO`hw!J`tS`Ej~B1@6TPU?}ObwE!78Ve|8k|F$wc3nd?Wx@J%W-j`oJ
z+P7Ttgl0Ro>;;59yf0_+(w;C>@JNqyWL07MIA30w)@u?FY|xk%=FR{KkUmb_t34va
z>tRm{-*1`VZ)XJ+Xi^Vl5(dr#FPd)WL~>sjR0^5!e4ImJ7o7{hsrV3YHw1;DLC)A(
zj{=zPZxQ4SrDa`p_{7v)|9K7*j*(^DA(stfAWDx*(vE&7M^Y})ev7Y~I`^u!u#I3u
zL=HvX4;sEDq8^h{oSwt;?!Q|iO4)~760yG3tA+d)#?5S&efxts7MGJFIU{|)fdE(6
zHibKPF1TZBeX+xN%iIkYbMD73M^<>6pjDYMy295eLjLggDmcPd4gTg24MbdD@$#DX
z-1XNaeI*r<#HH0fnja$R<*!$E+h%rONoQB=WGq#_c1ZTvHdmj`35<<$N;Djq3zc|ro4QTDzPkW}4_$8$(#_Crf<
zduV^lWRyORKZ~Ub%#ext4!Z3Eaq;kY8KBQQ(KL;H7^1+*LoOb2jI_5d*!9<|ITmO?MW6s3<~-NR>4CH3~J=jUxQ{8u6|Cs
zIR+YJG&IZWPS?O0as&8BPgcSpxpzyi3@-L*fEA($_9$I^!w+fXIAIoO6Ti6>!h)G%
zb3r6*bGsoPPd&iEacN4e&J6-HLdRGi2cVf4lt8gDWgT*^I!aZO=4szPd#Ff~>Tg$E
z$;*D1`u=k=7}eTD^jnp!xZRdq7UK0`40bsRK7GUldL|e~pbU&BOd0S3lW_Myv}4jR
zA-kNcvCJ5=T%e{Ij3~1&;5Igstwb?HkDOqTa=fV+3AV*H7NQ7&=-7UtR9knKC`{=n
zZ9ppMTS|^n_pRxCNWe>?1puaQXm12mNr_CB#$l8|if@IYF#7{xE$)g0HZ_ocvadEa
zdbn*hf#YFLx6`P*?f0WmFt#4-4+OA`TzJ81O@0B#XnNqR#NZlJ@=WH#h9)DT__zTE
zggWuL7Sosfl0vMGKaOr&$QtJ!UVC@s1Bsm3+c1gBi`$ek)hUdHgjsXh~kbCG(
zsRP_UK?Qo$6eq`~p)|33hW8=hUf;6eyl+
zEWl}WsX6H6-0)spH|pn*gyZKN7a(mM{Rd1g_nO<=p85Va7S>NI``%=V3j}DR
zbUx8eBWB58VPl5Z#5`9}RCI6o1qf&Tf#wXvXk%Z~?nlmx6k7XB(R0;W2H{B)rJDNcSd7q&sOi14;-F4
z{(~OfGTOwCVx0)GuI}LCIIg3g$`uZjEieLYWtlgs4>PZ_8
zuaIu-&Rc_kd4zArg7Jg+&u|$|U>u+8`OnHp@hC#uWyGA)*cFed>)}EJ&=jNgs&sRG
zjkgFa(LPtlvixL;SC7Orw$NO-Plrq+G+sHrh5;%Oo8^8mQZPCQO|C9KkV`MlJ5~7VDt)LEhLIR4+%`X=`=e+*&F1X*i
zAFdk>b003=R&@`KzCmEBy@W4VK7u(&_C-($O%QoG_&x9QTRPWx^hhI_$6K1{04v4vSrK$=ceZF`no0g?jjLhNk
zco^+SAxY_y&oF^HKYoC`f<}%(0;xT8zk@fN)ZC%$^>4N4_@IO?T55c)q$>Re_oPv+
zUECL@5?k=zaF~6m48#6<