From 6197558a38f5afbb74f138be59b52e705c99bf1e Mon Sep 17 00:00:00 2001
From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com>
Date: Sat, 28 Mar 2026 21:08:48 +0530
Subject: [PATCH 01/13] fix(validation): add input validation for resource
limit fields
---
.../Project/Shared/ResourceLimits.php | 44 ++++++++++++++-----
1 file changed, 32 insertions(+), 12 deletions(-)
diff --git a/app/Livewire/Project/Shared/ResourceLimits.php b/app/Livewire/Project/Shared/ResourceLimits.php
index 0b3840289..8a14dc10c 100644
--- a/app/Livewire/Project/Shared/ResourceLimits.php
+++ b/app/Livewire/Project/Shared/ResourceLimits.php
@@ -3,6 +3,7 @@
namespace App\Livewire\Project\Shared;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
+use Illuminate\Validation\ValidationException;
use Livewire\Component;
class ResourceLimits extends Component
@@ -16,24 +17,24 @@ class ResourceLimits extends Component
public ?string $limitsCpuset = null;
- public ?int $limitsCpuShares = null;
+ public mixed $limitsCpuShares = null;
public string $limitsMemory;
public string $limitsMemorySwap;
- public int $limitsMemorySwappiness;
+ public mixed $limitsMemorySwappiness = 0;
public string $limitsMemoryReservation;
protected $rules = [
- 'limitsMemory' => 'required|string',
- 'limitsMemorySwap' => 'required|string',
+ 'limitsMemory' => ['required', 'string', 'regex:/^(0|\d+[bBkKmMgG])$/'],
+ 'limitsMemorySwap' => ['required', 'string', 'regex:/^(0|\d+[bBkKmMgG])$/'],
'limitsMemorySwappiness' => 'required|integer|min:0|max:100',
- 'limitsMemoryReservation' => 'required|string',
- 'limitsCpus' => 'nullable',
- 'limitsCpuset' => 'nullable',
- 'limitsCpuShares' => 'nullable',
+ 'limitsMemoryReservation' => ['required', 'string', 'regex:/^(0|\d+[bBkKmMgG])$/'],
+ 'limitsCpus' => ['nullable', 'regex:/^\d*\.?\d+$/'],
+ 'limitsCpuset' => ['nullable', 'regex:/^\d+([,-]\d+)*$/'],
+ 'limitsCpuShares' => 'nullable|integer|min:0',
];
protected $validationAttributes = [
@@ -46,6 +47,19 @@ class ResourceLimits extends Component
'limitsCpuShares' => 'cpu shares',
];
+ protected $messages = [
+ 'limitsMemory.regex' => 'Maximum Memory Limit must be a number followed by a unit (b, k, m, g). Example: 256m, 1g. Use 0 for unlimited.',
+ 'limitsMemorySwap.regex' => 'Maximum Swap Limit must be a number followed by a unit (b, k, m, g). Example: 256m, 1g. Use 0 for unlimited.',
+ 'limitsMemoryReservation.regex' => 'Soft Memory Limit must be a number followed by a unit (b, k, m, g). Example: 256m, 1g. Use 0 for unlimited.',
+ 'limitsCpus.regex' => 'Number of CPUs must be a number (integer or decimal). Example: 0.5, 2.',
+ 'limitsCpuset.regex' => 'CPU sets must be a comma-separated list of CPU numbers or ranges. Example: 0-2 or 0,1,3.',
+ 'limitsMemorySwappiness.integer' => 'Swappiness must be a whole number between 0 and 100.',
+ 'limitsMemorySwappiness.min' => 'Swappiness must be between 0 and 100.',
+ 'limitsMemorySwappiness.max' => 'Swappiness must be between 0 and 100.',
+ 'limitsCpuShares.integer' => 'CPU Weight must be a whole number.',
+ 'limitsCpuShares.min' => 'CPU Weight must be a positive number.',
+ ];
+
/**
* Sync data between component properties and model
*
@@ -57,10 +71,10 @@ private function syncData(bool $toModel = false): void
// Sync TO model (before save)
$this->resource->limits_cpus = $this->limitsCpus;
$this->resource->limits_cpuset = $this->limitsCpuset;
- $this->resource->limits_cpu_shares = $this->limitsCpuShares;
+ $this->resource->limits_cpu_shares = (int) $this->limitsCpuShares;
$this->resource->limits_memory = $this->limitsMemory;
$this->resource->limits_memory_swap = $this->limitsMemorySwap;
- $this->resource->limits_memory_swappiness = $this->limitsMemorySwappiness;
+ $this->resource->limits_memory_swappiness = (int) $this->limitsMemorySwappiness;
$this->resource->limits_memory_reservation = $this->limitsMemoryReservation;
} else {
// Sync FROM model (on load/refresh)
@@ -91,7 +105,7 @@ public function submit()
if (! $this->limitsMemorySwap) {
$this->limitsMemorySwap = '0';
}
- if (is_null($this->limitsMemorySwappiness)) {
+ if ($this->limitsMemorySwappiness === '' || is_null($this->limitsMemorySwappiness)) {
$this->limitsMemorySwappiness = 60;
}
if (! $this->limitsMemoryReservation) {
@@ -103,7 +117,7 @@ public function submit()
if ($this->limitsCpuset === '') {
$this->limitsCpuset = null;
}
- if (is_null($this->limitsCpuShares)) {
+ if ($this->limitsCpuShares === '' || is_null($this->limitsCpuShares)) {
$this->limitsCpuShares = 1024;
}
@@ -112,6 +126,12 @@ public function submit()
$this->syncData(true);
$this->resource->save();
$this->dispatch('success', 'Resource limits updated.');
+ } catch (ValidationException $e) {
+ foreach ($e->validator->errors()->all() as $message) {
+ $this->dispatch('error', $message);
+ }
+
+ return;
} catch (\Throwable $e) {
return handleError($e, $this);
}
From 407b6df7440d90f324a578ee0b0ebd10cae1da6a Mon Sep 17 00:00:00 2001
From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com>
Date: Sat, 28 Mar 2026 22:30:17 +0530
Subject: [PATCH 02/13] fix(validation): add IP validation for custom DNS
servers input
---
app/Livewire/Settings/Advanced.php | 4 ++--
app/Rules/ValidDnsServers.php | 35 ++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+), 2 deletions(-)
create mode 100644 app/Rules/ValidDnsServers.php
diff --git a/app/Livewire/Settings/Advanced.php b/app/Livewire/Settings/Advanced.php
index ad478273f..f4b57ae20 100644
--- a/app/Livewire/Settings/Advanced.php
+++ b/app/Livewire/Settings/Advanced.php
@@ -3,6 +3,7 @@
namespace App\Livewire\Settings;
use App\Models\InstanceSettings;
+use App\Rules\ValidDnsServers;
use App\Rules\ValidIpOrCidr;
use Livewire\Attributes\Validate;
use Livewire\Component;
@@ -20,7 +21,6 @@ class Advanced extends Component
#[Validate('boolean')]
public bool $is_dns_validation_enabled;
- #[Validate('nullable|string')]
public ?string $custom_dns_servers = null;
#[Validate('boolean')]
@@ -43,7 +43,7 @@ public function rules()
'is_registration_enabled' => 'boolean',
'do_not_track' => 'boolean',
'is_dns_validation_enabled' => 'boolean',
- 'custom_dns_servers' => 'nullable|string',
+ 'custom_dns_servers' => ['nullable', 'string', new ValidDnsServers],
'is_api_enabled' => 'boolean',
'allowed_ips' => ['nullable', 'string', new ValidIpOrCidr],
'is_sponsorship_popup_enabled' => 'boolean',
diff --git a/app/Rules/ValidDnsServers.php b/app/Rules/ValidDnsServers.php
new file mode 100644
index 000000000..e3bbd048f
--- /dev/null
+++ b/app/Rules/ValidDnsServers.php
@@ -0,0 +1,35 @@
+
Date: Sat, 28 Mar 2026 23:23:25 +0530
Subject: [PATCH 03/13] fix(validation): add input validation for port exposes
and port mappings fields
---
app/Livewire/Project/Application/General.php | 12 ++++++++--
.../Project/Database/Clickhouse/General.php | 6 ++++-
.../Project/Database/Dragonfly/General.php | 6 ++++-
.../Project/Database/Keydb/General.php | 6 ++++-
.../Project/Database/Mariadb/General.php | 6 ++++-
.../Project/Database/Mongodb/General.php | 6 ++++-
.../Project/Database/Mysql/General.php | 6 ++++-
.../Project/Database/Postgresql/General.php | 6 ++++-
.../Project/Database/Redis/General.php | 6 ++++-
app/Support/ValidationPatterns.php | 24 +++++++++++++++++++
10 files changed, 74 insertions(+), 10 deletions(-)
diff --git a/app/Livewire/Project/Application/General.php b/app/Livewire/Project/Application/General.php
index 5c186af70..3e78c1732 100644
--- a/app/Livewire/Project/Application/General.php
+++ b/app/Livewire/Project/Application/General.php
@@ -153,8 +153,8 @@ protected function rules(): array
'staticImage' => 'required',
'baseDirectory' => array_merge(['required'], array_slice(ValidationPatterns::directoryPathRules(), 1)),
'publishDirectory' => ValidationPatterns::directoryPathRules(),
- 'portsExposes' => 'required',
- 'portsMappings' => 'nullable',
+ 'portsExposes' => ['required', 'string', 'regex:/^(\d+)(,\d+)*$/'],
+ 'portsMappings' => ValidationPatterns::portMappingRules(),
'customNetworkAliases' => 'nullable',
'dockerfile' => 'nullable',
'dockerRegistryImageName' => 'nullable',
@@ -209,6 +209,8 @@ protected function messages(): array
'staticImage.required' => 'The Static Image field is required.',
'baseDirectory.required' => 'The Base Directory field is required.',
'portsExposes.required' => 'The Exposed Ports field is required.',
+ 'portsExposes.regex' => 'Ports exposes must be a comma-separated list of port numbers (e.g. 3000,3001).',
+ ...ValidationPatterns::portMappingMessages(),
'isStatic.required' => 'The Static setting is required.',
'isStatic.boolean' => 'The Static setting must be true or false.',
'isSpa.required' => 'The SPA setting is required.',
@@ -752,6 +754,12 @@ public function submit($showToaster = true)
$this->authorize('update', $this->application);
$this->resetErrorBag();
+
+ $this->portsExposes = str($this->portsExposes)->replace(' ', '')->trim()->toString();
+ if ($this->portsMappings) {
+ $this->portsMappings = str($this->portsMappings)->replace(' ', '')->trim()->toString();
+ }
+
$this->validate();
$oldPortsExposes = $this->application->ports_exposes;
diff --git a/app/Livewire/Project/Database/Clickhouse/General.php b/app/Livewire/Project/Database/Clickhouse/General.php
index 9de75c1c5..0913ca797 100644
--- a/app/Livewire/Project/Database/Clickhouse/General.php
+++ b/app/Livewire/Project/Database/Clickhouse/General.php
@@ -79,7 +79,7 @@ protected function rules(): array
'clickhouseAdminUser' => 'required|string',
'clickhouseAdminPassword' => 'required|string',
'image' => 'required|string',
- 'portsMappings' => 'nullable|string',
+ 'portsMappings' => ValidationPatterns::portMappingRules(),
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicPortTimeout' => 'nullable|integer|min:1',
@@ -94,6 +94,7 @@ protected function messages(): array
{
return array_merge(
ValidationPatterns::combinedMessages(),
+ ValidationPatterns::portMappingMessages(),
[
'clickhouseAdminUser.required' => 'The Admin User field is required.',
'clickhouseAdminUser.string' => 'The Admin User must be a string.',
@@ -207,6 +208,9 @@ public function submit()
try {
$this->authorize('update', $this->database);
+ if ($this->portsMappings) {
+ $this->portsMappings = str($this->portsMappings)->replace(' ', '')->trim()->toString();
+ }
if (str($this->publicPort)->isEmpty()) {
$this->publicPort = null;
}
diff --git a/app/Livewire/Project/Database/Dragonfly/General.php b/app/Livewire/Project/Database/Dragonfly/General.php
index d35e57a9d..23503bd98 100644
--- a/app/Livewire/Project/Database/Dragonfly/General.php
+++ b/app/Livewire/Project/Database/Dragonfly/General.php
@@ -90,7 +90,7 @@ protected function rules(): array
'description' => ValidationPatterns::descriptionRules(),
'dragonflyPassword' => 'required|string',
'image' => 'required|string',
- 'portsMappings' => 'nullable|string',
+ 'portsMappings' => ValidationPatterns::portMappingRules(),
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicPortTimeout' => 'nullable|integer|min:1',
@@ -106,6 +106,7 @@ protected function messages(): array
{
return array_merge(
ValidationPatterns::combinedMessages(),
+ ValidationPatterns::portMappingMessages(),
[
'dragonflyPassword.required' => 'The Dragonfly Password field is required.',
'dragonflyPassword.string' => 'The Dragonfly Password must be a string.',
@@ -217,6 +218,9 @@ public function submit()
try {
$this->authorize('update', $this->database);
+ if ($this->portsMappings) {
+ $this->portsMappings = str($this->portsMappings)->replace(' ', '')->trim()->toString();
+ }
if (str($this->publicPort)->isEmpty()) {
$this->publicPort = null;
}
diff --git a/app/Livewire/Project/Database/Keydb/General.php b/app/Livewire/Project/Database/Keydb/General.php
index adb4ccb5f..ff9dc19ad 100644
--- a/app/Livewire/Project/Database/Keydb/General.php
+++ b/app/Livewire/Project/Database/Keydb/General.php
@@ -93,7 +93,7 @@ protected function rules(): array
'keydbConf' => 'nullable|string',
'keydbPassword' => 'required|string',
'image' => 'required|string',
- 'portsMappings' => 'nullable|string',
+ 'portsMappings' => ValidationPatterns::portMappingRules(),
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicPortTimeout' => 'nullable|integer|min:1',
@@ -111,6 +111,7 @@ protected function messages(): array
{
return array_merge(
ValidationPatterns::combinedMessages(),
+ ValidationPatterns::portMappingMessages(),
[
'keydbPassword.required' => 'The KeyDB Password field is required.',
'keydbPassword.string' => 'The KeyDB Password must be a string.',
@@ -224,6 +225,9 @@ public function submit()
try {
$this->authorize('manageEnvironment', $this->database);
+ if ($this->portsMappings) {
+ $this->portsMappings = str($this->portsMappings)->replace(' ', '')->trim()->toString();
+ }
if (str($this->publicPort)->isEmpty()) {
$this->publicPort = null;
}
diff --git a/app/Livewire/Project/Database/Mariadb/General.php b/app/Livewire/Project/Database/Mariadb/General.php
index 14240c82d..a9ac47b97 100644
--- a/app/Livewire/Project/Database/Mariadb/General.php
+++ b/app/Livewire/Project/Database/Mariadb/General.php
@@ -78,7 +78,7 @@ protected function rules(): array
'mariadbDatabase' => 'required',
'mariadbConf' => 'nullable',
'image' => 'required',
- 'portsMappings' => 'nullable',
+ 'portsMappings' => ValidationPatterns::portMappingRules(),
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicPortTimeout' => 'nullable|integer|min:1',
@@ -92,6 +92,7 @@ protected function messages(): array
{
return array_merge(
ValidationPatterns::combinedMessages(),
+ ValidationPatterns::portMappingMessages(),
[
'name.required' => 'The Name field is required.',
'mariadbRootPassword.required' => 'The Root Password field is required.',
@@ -213,6 +214,9 @@ public function submit()
try {
$this->authorize('update', $this->database);
+ if ($this->portsMappings) {
+ $this->portsMappings = str($this->portsMappings)->replace(' ', '')->trim()->toString();
+ }
if (str($this->publicPort)->isEmpty()) {
$this->publicPort = null;
}
diff --git a/app/Livewire/Project/Database/Mongodb/General.php b/app/Livewire/Project/Database/Mongodb/General.php
index 11419ec71..2b6538edf 100644
--- a/app/Livewire/Project/Database/Mongodb/General.php
+++ b/app/Livewire/Project/Database/Mongodb/General.php
@@ -77,7 +77,7 @@ protected function rules(): array
'mongoInitdbRootPassword' => 'required',
'mongoInitdbDatabase' => 'required',
'image' => 'required',
- 'portsMappings' => 'nullable',
+ 'portsMappings' => ValidationPatterns::portMappingRules(),
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicPortTimeout' => 'nullable|integer|min:1',
@@ -92,6 +92,7 @@ protected function messages(): array
{
return array_merge(
ValidationPatterns::combinedMessages(),
+ ValidationPatterns::portMappingMessages(),
[
'name.required' => 'The Name field is required.',
'mongoInitdbRootUsername.required' => 'The Root Username field is required.',
@@ -213,6 +214,9 @@ public function submit()
try {
$this->authorize('update', $this->database);
+ if ($this->portsMappings) {
+ $this->portsMappings = str($this->portsMappings)->replace(' ', '')->trim()->toString();
+ }
if (str($this->publicPort)->isEmpty()) {
$this->publicPort = null;
}
diff --git a/app/Livewire/Project/Database/Mysql/General.php b/app/Livewire/Project/Database/Mysql/General.php
index 4f0f5eb19..f3c554522 100644
--- a/app/Livewire/Project/Database/Mysql/General.php
+++ b/app/Livewire/Project/Database/Mysql/General.php
@@ -80,7 +80,7 @@ protected function rules(): array
'mysqlDatabase' => 'required',
'mysqlConf' => 'nullable',
'image' => 'required',
- 'portsMappings' => 'nullable',
+ 'portsMappings' => ValidationPatterns::portMappingRules(),
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicPortTimeout' => 'nullable|integer|min:1',
@@ -95,6 +95,7 @@ protected function messages(): array
{
return array_merge(
ValidationPatterns::combinedMessages(),
+ ValidationPatterns::portMappingMessages(),
[
'name.required' => 'The Name field is required.',
'mysqlRootPassword.required' => 'The Root Password field is required.',
@@ -220,6 +221,9 @@ public function submit()
try {
$this->authorize('update', $this->database);
+ if ($this->portsMappings) {
+ $this->portsMappings = str($this->portsMappings)->replace(' ', '')->trim()->toString();
+ }
if (str($this->publicPort)->isEmpty()) {
$this->publicPort = null;
}
diff --git a/app/Livewire/Project/Database/Postgresql/General.php b/app/Livewire/Project/Database/Postgresql/General.php
index 4e044672b..7a4ff057e 100644
--- a/app/Livewire/Project/Database/Postgresql/General.php
+++ b/app/Livewire/Project/Database/Postgresql/General.php
@@ -92,7 +92,7 @@ protected function rules(): array
'postgresConf' => 'nullable',
'initScripts' => 'nullable',
'image' => 'required',
- 'portsMappings' => 'nullable',
+ 'portsMappings' => ValidationPatterns::portMappingRules(),
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicPortTimeout' => 'nullable|integer|min:1',
@@ -107,6 +107,7 @@ protected function messages(): array
{
return array_merge(
ValidationPatterns::combinedMessages(),
+ ValidationPatterns::portMappingMessages(),
[
'name.required' => 'The Name field is required.',
'postgresUser.required' => 'The Postgres User field is required.',
@@ -456,6 +457,9 @@ public function submit()
try {
$this->authorize('update', $this->database);
+ if ($this->portsMappings) {
+ $this->portsMappings = str($this->portsMappings)->replace(' ', '')->trim()->toString();
+ }
if (str($this->publicPort)->isEmpty()) {
$this->publicPort = null;
}
diff --git a/app/Livewire/Project/Database/Redis/General.php b/app/Livewire/Project/Database/Redis/General.php
index ebe2f3ba0..a1a22ab8b 100644
--- a/app/Livewire/Project/Database/Redis/General.php
+++ b/app/Livewire/Project/Database/Redis/General.php
@@ -73,7 +73,7 @@ protected function rules(): array
'description' => ValidationPatterns::descriptionRules(),
'redisConf' => 'nullable',
'image' => 'required',
- 'portsMappings' => 'nullable',
+ 'portsMappings' => ValidationPatterns::portMappingRules(),
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicPortTimeout' => 'nullable|integer|min:1',
@@ -89,6 +89,7 @@ protected function messages(): array
{
return array_merge(
ValidationPatterns::combinedMessages(),
+ ValidationPatterns::portMappingMessages(),
[
'name.required' => 'The Name field is required.',
'image.required' => 'The Docker Image field is required.',
@@ -201,6 +202,9 @@ public function submit()
try {
$this->authorize('manageEnvironment', $this->database);
+ if ($this->portsMappings) {
+ $this->portsMappings = str($this->portsMappings)->replace(' ', '')->trim()->toString();
+ }
$this->syncData(true);
if (version_compare($this->redisVersion, '6.0', '>=')) {
diff --git a/app/Support/ValidationPatterns.php b/app/Support/ValidationPatterns.php
index 7084b4cc2..5d53076ea 100644
--- a/app/Support/ValidationPatterns.php
+++ b/app/Support/ValidationPatterns.php
@@ -194,6 +194,12 @@ public static function volumeNameMessages(string $field = 'name'): array
];
}
+ /**
+ * Pattern for port mappings (e.g. 3000:3000, 8080:80, 8000-8010:8000-8010)
+ * Each entry requires host:container format, where each side can be a number or a range (number-number)
+ */
+ public const PORT_MAPPINGS_PATTERN = '/^(\d+(-\d+)?:\d+(-\d+)?)(,\d+(-\d+)?:\d+(-\d+)?)*$/';
+
/**
* Get validation rules for container name fields
*/
@@ -202,6 +208,24 @@ public static function containerNameRules(int $maxLength = 255): array
return ['string', 'max:'.$maxLength, 'regex:'.self::CONTAINER_NAME_PATTERN];
}
+ /**
+ * Get validation rules for port mapping fields
+ */
+ public static function portMappingRules(): array
+ {
+ return ['nullable', 'string', 'regex:'.self::PORT_MAPPINGS_PATTERN];
+ }
+
+ /**
+ * Get validation messages for port mapping fields
+ */
+ public static function portMappingMessages(string $field = 'portsMappings'): array
+ {
+ return [
+ "{$field}.regex" => 'Port mappings must be a comma-separated list of port pairs or ranges (e.g. 3000:3000,8080:80,8000-8010:8000-8010).',
+ ];
+ }
+
/**
* Check if a string is a valid Docker container name.
*/
From 73258c317e3d79aefb90924d5319ddc54209eebc Mon Sep 17 00:00:00 2001
From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com>
Date: Sun, 29 Mar 2026 00:34:32 +0530
Subject: [PATCH 04/13] fix(validation): add URL validation for proxy redirect
input
---
app/Livewire/Server/Proxy.php | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/app/Livewire/Server/Proxy.php b/app/Livewire/Server/Proxy.php
index d5f30fca0..c2d8205ef 100644
--- a/app/Livewire/Server/Proxy.php
+++ b/app/Livewire/Server/Proxy.php
@@ -6,6 +6,7 @@
use App\Actions\Proxy\SaveProxyConfiguration;
use App\Enums\ProxyTypes;
use App\Models\Server;
+use App\Rules\SafeExternalUrl;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Component;
@@ -41,9 +42,13 @@ public function getListeners()
];
}
- protected $rules = [
- 'generateExactLabels' => 'required|boolean',
- ];
+ protected function rules()
+ {
+ return [
+ 'generateExactLabels' => 'required|boolean',
+ 'redirectUrl' => ['nullable', new SafeExternalUrl],
+ ];
+ }
public function mount()
{
@@ -147,6 +152,7 @@ public function submit()
{
try {
$this->authorize('update', $this->server);
+ $this->validate();
SaveProxyConfiguration::run($this->server, $this->proxySettings);
$this->server->proxy->redirect_url = $this->redirectUrl;
$this->server->save();
From c52a199120d2d06e2a473305734643f2bd66ead1 Mon Sep 17 00:00:00 2001
From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com>
Date: Sun, 29 Mar 2026 01:14:08 +0530
Subject: [PATCH 05/13] fix(validation): add input validation for server
advanced settings page
---
app/Http/Controllers/Api/ServersController.php | 18 +++++++++++++++++-
app/Livewire/Server/Advanced.php | 16 ++++++++--------
.../views/livewire/server/advanced.blade.php | 4 ++++
3 files changed, 29 insertions(+), 9 deletions(-)
diff --git a/app/Http/Controllers/Api/ServersController.php b/app/Http/Controllers/Api/ServersController.php
index 2ef95ce8b..930879d80 100644
--- a/app/Http/Controllers/Api/ServersController.php
+++ b/app/Http/Controllers/Api/ServersController.php
@@ -598,6 +598,11 @@ public function create_server(Request $request)
'is_build_server' => ['type' => 'boolean', 'description' => 'Is build server.'],
'instant_validate' => ['type' => 'boolean', 'description' => 'Instant validate.'],
'proxy_type' => ['type' => 'string', 'enum' => ['traefik', 'caddy', 'none'], 'description' => 'The proxy type.'],
+ 'concurrent_builds' => ['type' => 'integer', 'description' => 'Number of concurrent builds.'],
+ 'dynamic_timeout' => ['type' => 'integer', 'description' => 'Deployment timeout in seconds.'],
+ 'deployment_queue_limit' => ['type' => 'integer', 'description' => 'Maximum number of queued deployments.'],
+ 'server_disk_usage_notification_threshold' => ['type' => 'integer', 'description' => 'Server disk usage notification threshold (%).'],
+ 'server_disk_usage_check_frequency' => ['type' => 'string', 'description' => 'Cron expression for disk usage check frequency.'],
],
),
),
@@ -634,7 +639,7 @@ public function create_server(Request $request)
)]
public function update_server(Request $request)
{
- $allowedFields = ['name', 'description', 'ip', 'port', 'user', 'private_key_uuid', 'is_build_server', 'instant_validate', 'proxy_type'];
+ $allowedFields = ['name', 'description', 'ip', 'port', 'user', 'private_key_uuid', 'is_build_server', 'instant_validate', 'proxy_type', 'concurrent_builds', 'dynamic_timeout', 'deployment_queue_limit', 'server_disk_usage_notification_threshold', 'server_disk_usage_check_frequency'];
$teamId = getTeamIdFromToken();
if (is_null($teamId)) {
@@ -655,6 +660,11 @@ public function update_server(Request $request)
'is_build_server' => 'boolean|nullable',
'instant_validate' => 'boolean|nullable',
'proxy_type' => 'string|nullable',
+ 'concurrent_builds' => 'integer|nullable|min:1',
+ 'dynamic_timeout' => 'integer|nullable|min:1',
+ 'deployment_queue_limit' => 'integer|nullable|min:1',
+ 'server_disk_usage_notification_threshold' => 'integer|nullable|min:1|max:100',
+ 'server_disk_usage_check_frequency' => 'string|nullable',
]);
$extraFields = array_diff(array_keys($request->all()), $allowedFields);
@@ -691,6 +701,12 @@ public function update_server(Request $request)
'is_build_server' => $request->is_build_server,
]);
}
+
+ $advancedSettings = $request->only(['concurrent_builds', 'dynamic_timeout', 'deployment_queue_limit', 'server_disk_usage_notification_threshold', 'server_disk_usage_check_frequency']);
+ if (! empty($advancedSettings)) {
+ $server->settings()->update(array_filter($advancedSettings, fn ($value) => ! is_null($value)));
+ }
+
if ($request->instant_validate) {
ValidateServer::dispatch($server);
}
diff --git a/app/Livewire/Server/Advanced.php b/app/Livewire/Server/Advanced.php
index dba1b4903..0e1a9a325 100644
--- a/app/Livewire/Server/Advanced.php
+++ b/app/Livewire/Server/Advanced.php
@@ -15,17 +15,17 @@ class Advanced extends Component
#[Validate(['string'])]
public string $serverDiskUsageCheckFrequency = '0 23 * * *';
- #[Validate(['integer', 'min:1', 'max:99'])]
- public int $serverDiskUsageNotificationThreshold = 50;
+ #[Validate(['required', 'integer', 'min:1', 'max:99'])]
+ public ?int $serverDiskUsageNotificationThreshold = 50;
- #[Validate(['integer', 'min:1'])]
- public int $concurrentBuilds = 1;
+ #[Validate(['required', 'integer', 'min:1'])]
+ public ?int $concurrentBuilds = 1;
- #[Validate(['integer', 'min:1'])]
- public int $dynamicTimeout = 1;
+ #[Validate(['required', 'integer', 'min:1'])]
+ public ?int $dynamicTimeout = 1;
- #[Validate(['integer', 'min:1'])]
- public int $deploymentQueueLimit = 25;
+ #[Validate(['required', 'integer', 'min:1'])]
+ public ?int $deploymentQueueLimit = 25;
public function mount(string $server_uuid)
{
diff --git a/resources/views/livewire/server/advanced.blade.php b/resources/views/livewire/server/advanced.blade.php
index 33086aea1..f6610c1d5 100644
--- a/resources/views/livewire/server/advanced.blade.php
+++ b/resources/views/livewire/server/advanced.blade.php
@@ -22,6 +22,7 @@
id="serverDiskUsageCheckFrequency" label="Disk usage check frequency" required
helper="Cron expression for disk usage check frequency.
You can use every_minute, hourly, daily, weekly, monthly, yearly.
Default is every night at 11:00 PM." />
nHS$$!CxdI(>Av-s#P~#34=@ud(qTuebMJ(LRL{Ho0d$`D-$lrec3Ma z4!8Fgg|!uhdewN?nAjR z) |ngTBj~L2x`|8*so;p+<|V8%8ga zURwD?A+=q};e&J~vWpx9`)D`d8CyA_+g_U*?ESXb(%EYyy=K`!YWy@^Znjs(Nu&v9 z4IL*eC65{aqa@DZ16m>#)pweb`Gs2vM^7%J;UZZ&Gt4UO85V3BV(y|_DRI9WRoz#( z(s=Irv_aS!)hbTiwg{+^E `RUbV5n^SC=AB5WKz8rw9VB)(&c*T4oxS=jFA$6$tH3u+(!CyUf9i z^!v5hm$1|=T+0~Sory_NBxQ1<0oa3@oBk _ps^`aps_v^pslDgM$4laU&eMop2b; oO(iW&WXXB%gC=BHuSoAGApA?JsvA{?n>nDvu=vSP^@g9&64zy6~i{8u5zcP z>w%NK2N{q12{)8?^yI1&LJFp)1TC la;If3n(2}TM=6xq>57j| z6$Vf*?APTGrF*En#Cys_J-3kT^YtYHR^2HYswGthVRn|tv?Bq{lFkZ;_$4*-y~Y1w_#6ba)RbVX6K$2rEGcXY2rbhwC$NptK^ h}l$DD>7F-DPpnTyel{rF!kcA?N1z>K>ixxRM?SRxVxU%68 z*1;%QssW)%-ujipM&n|3U{TnaYlBVMcR-Vl88$1zG~roIBoE6?%B~V-F(tOxL^%wi zQbbX_ysRsLDvn%y*2%sQQiPG+C8S6uNKy%n<|VxV6xFej;sa2ijI$~7ZPT925(=~A z4gg-hN_2Y=`~`Ybb`5I}FMRdypHO%u9Y*-?Rn87j{I5j%1wOwip&Dks WE~hRZGh1f-%DnEc0rK&%h+M348y>TgT?NuRjvOVQuMT>Qn6a|} zB1|Yp9t;uzh!2T=J}o1www(30QspWgSFbUtX6<)$38}QPo_Pf^$ ?)IdUPr312do#{F`*uk6In7JE?zp@^Y~+N&`J=F}msQkv#;)~A^mThjdCH89 zr+3WR-|B>Tm@?ATu6$VJc`0lL2|Fv{8lW&Z3;_xZ*g-`45F L7d!Bfr3po%?z{5HQz#uEwx;@NYS`>R^eM?t@SqA zOkkUx_Si2~hD_OV6)0A!T%{Uy8Z~Rx;h@8g>2lI(XPtKu0)Xqvp>VRc7Mz2o5<~`b zV7@RHQmUL(s7M!Z;$RlLY&tgyf*X*Gtb}Q(21acp2ehTMv&qm+{lUkiy<~93fOdgI z$RRFCAAuo?XqIg{iz*c>6?sOKIj2IE8g*k9v388Blze^hCuPe_M;s_i otT4Vzy&t5!79ivP+)8E4kA+wytffJY9HopZ)mPlJz za}B9dM=t|0`Snv{3_3(fkU}-8k(n3e*N@2tFfI+F4ST9}_Kc)r4Y*(3)%1fixoG~u zf6@BG_Gt1UXC!llhe}He^4fz;_ZL8JY294+d)P+LeuX(M_k0=p-Zl7OAb=1eh#`UW zY*_|1s6#_M(Nih!lj%*Sx?CdP^fY|K7=aNQkr5k-k>Z|0|FS;?pjn8?Zg+fQcEs4R zPMu9-j-|8y#Pm}!?Y-D`PDd?uAVwWLo!zzOALrGsuVKg8@lyMp!|ib|p5OjAcYdd- zD{@uw$l~b}J=Fr%G|Ix+$m#d_L78g{MI#6o?p?TEhkpyTW@~NGnx#!cYi1rEi)bby zHTrVmnP8jn#t#tMm>i)@5T>S21}_HFU6U2ecLjsbMUUY0R>LgvQp1`gC>s{zu}~P3 z+j5sFBeCexnr??7z1pRzaRi1geYH 9@uz`4Y #T!-awM%xyyEckL#L~E7XcJPbr*^U+ALQ_)LTD>Dw6Lc kFz)mvL7}f9b8LrN0;r)(EuN5u;RQc^;;c;Y$apZ)qs&EchTxQUF;3*U=p$5i=$2C$XJfmR zdLI=4cc)7TrbmK9Y3D}H6kFxN@spE%lI!%g5OB70vY(ghUW2Q^J ^Ub6P=l>#@`lI_>Lm P3;0PoNT^=x49G*ZVkttLfoxx `$ZPWmN4mH(QSA84X)aJIdwT7X71Eu5}`QNOmy#?1| z){FXu7W7Lk>NR=vy1aTrOJiI2wiq4%2m-RtUP$Zdu|yrgqZiWK)I({Mn+zLB=)35N zs!Egg8@_oBYUV<&fMh~77eI_5j6w}POt8X93)){Z+AIDO>j+2~Y$JsX9p(X$V+luc zDp?WM5kUfJ9OATIZPR`u*EvvZoaLxULqG#WeUBIn@XtD{LUIHC=|3S^E XH6<9j}zLf6Z2HNayFj&OCLu^5>GK04;w7`o%Xt`{|O^R z7 `j+YEDD@%_SDqAvfywO<6_8A)98s{(V9 z t97OJZRTkre7K6(vH zrTmKQ+fkj6B+rDW`%mtfKB=R=nyNk`ry89H{%Yv~Nw^3f4*U%j(g72M`~RhXGYq5N zHk!5Y$^4V$7v_l7`XumV^GW>0zClEzwVoH>bt8ABv^$%nXUP88h7Y}xsgewmBHe9R z{#7f(&T~#vg tXCuPYCjnn4D~^S&beYJs`!T-$C `|OZel#lHE zZ!icPtm)+EUOFD(``p@NbI9KKlfLz>hxPs9?+9t3i;tZ%@G$h(G5yXS{CXn@0=~v~ zWF1Z^e5!(%PFVQS{WZJ?xF-LZ-tahjatAPRWdngZIOTxq=C4DbiQ%OW0REE2{-H){ z5>4tXLo;$v>}PLlqzytb9fvapTG$S%lE-VW++20tsMXm7nzalMJ^hOuo_meSTOTO% z$ye%Tal$3U{We2Pb}z&fTOg*{1~J`sh#7W36xj(;Y!}2VyCG)V12NBDi23$GEU+J9 zp$8xqc@W|_pNDARD-icM2&q2@)Ict%!8}ky`3OF?+C5OF+UhWrneKB0${hc46v|xp zI|f}tgKeu8y2gguULABz4cAmXbj^*VY9n+ljkcpr(6u(!&Nf5W)_A+x0$qC(?QSb{ z9UW;;4KS*2pvG#dhM |11{S<*s(E>)q&Px4PY(2~F1I&-}RxWGl2M;%Pf=su|HQ z3b)(3MG^twT18q9Sr)fjlPXiLQk_PEW!xzHe-4dpYkN(p+R@H-wYxndx&5~cViCTR zb)#&QkM*NsY#5cJYE+M!p)J84g5lSV7$_ZkX8|h+Jdw4yYK;QeOa<0HP8n1u3%8v^ zCzBZ$r+eC)3CEyztbRz?b(lNBb#VjSneGC2k-NlQ=0>?I+;#2-x5BM;TioOBsreZ{ z`*So#7cL>gyU)ir&zHE_q=sJGWU_I-w34WOKgaS)h4oSimCEG4D&Gmc5F>tdP&y_D z-}$m1%6osBJMatG?{5XbOgupB%jD%B){Ad1&}(|1+TIHKo*%r9M}JMtUB*iZgKRm2 zTaIsfX|^-IIi=7^mBQ-27+>t3@N~Vtt);yFzWh>K5Pa>WPVybtKVtc%qjviXjw8?5 z@foR+ynkKK!535tf-l4u;zW$)zN|@8`#7eDAeiE9zH4XdZrDG@VGtX2g5`Aq^F#>K zTDNW%2rh(eT$q8L>UUD__NgxIdYxm5(&Z9tITD3S@OmJ-9tT+92*k>*dU>e4&!6+t z{Y>R{BreKK>?%fXk;)U7_ASe{p^?KsS;INBza#{%#WlEHkD%?@M?+{&)@1hn@qGjI zKJ#?r{sK>)G92$+=5{#Z;9%-gPpo4wc#XFtH2qAK;1a-jt~+gzZ-65> kPX#T>VMsbRb$20;Zp sxrPeeet`T2Owta{YUpq%8D%4^w&qVPnlcEDPJL7ag(PCq zl+_{6!A6;SDO(<8Npwc{>7K>udeqXTz9-Mo)=h5jlY4)ka@gN%pVGemDRSp!@8f!g z;6sUXp7qP*;7tE%+SD0cdhdQ=x$=9dl-F(w6aPv@{reI^o*9SAdLDB6b=BE=wb~wn zm)nbz&aIt0?=5e8qK-V(*AOC3DMIdR(nEvbbQ@Zq*RTJiLC8qAUA5>`-Plu8&hqks zbB*8dgTqLiV(CZL5I(_mQ!%(AX-k3)`c!{yViREN#}so A&`vkX{0I6a_1{+^DPmZ zCkeMphA87%KaU!4ntu9NULTc0mIf8r=N(hujADNC? faIJ zOo1J&g@+4Ux?rT_dWnpuI8gfC^+utzI(ih}bMstu`y2*wWA@w1a=N3Kg&;S=Y{j_p z2!f}yyvI_f{933#ML+QPGJrgUiT~XKnC{tpSNbV77#&5?u&y=vAIz0Nx7Y?4+(RBM zVZ&K}A6|k(t_^X$mdE`sETW$Oht>c2!sGK8oTK*#@ACiK0Q6zj?+l>e%O3#Q*l_^# z%mzW^!Ge5&+ NXMJ0%D2UsV;L(BNCGvpb*8p*h*B7lRN0DbkBm(%t*mXT7!jYEAT2+& zF}@+-pGg!D5Na4;j1_he^su8tk1;dW>~+LF#b>7Z6E8=xa{WqnRH9y^3JSF~(@9yC z>~!1zw@|rXd9D2O?;<8mnLcy!DSm%Fun*3EzbD^H0)QSJ$lcmARijC}sF3V}KWDp# zo%3<7C+R7ZnG=HKo-W-o{_vwA_)szGPKirhx|*uFS}bq*Dp;GfH5;F+Vx3kKF-H+^ z&nWR2Ih24sBP?H86H{Xydt`#wr?nL+)z77eJw-c=d33*vn`D_JMY>G!{ArOG+x7fi zkwaO%zx3T!zdH6Sf2e8C#`Acz%Y#WT?(_d8e=KtbjDC?C{kh}naigdBxzT@Lg0l$o zgmZK2v^o5s$4&L03o_r8BtZ_PKYyh=?IZ)|(y1<)bEmKDe_Ppqc8z|D>8E`mB%1v! zco0K^asU9{toq-6c)kAYq%X3eXDN99eqVie+q?31ejb40VITtlZuSmGTG###wW}vO zUwYdB)V@PCG($Ha=z7$l!!gJKXZBfapYb&A-@%*X@pw9(k2mAvV8a~tv@{cdmeBIF zB7nxx$^i7{FZ=g%W}b(N^t%}NekHQBK)*T<96Z1M7Xil4OD-+BvgF#58zOuG-y8X~ z8)Fga8T?T?LWi(z=;lg8+?8H-x&QETYWQO7TUhgtGERjWA{JI|m>Fi9XR#&1{VU2_ zY&HKEDMhI=)oQei4=wd^e7*mtoQL{+^9M^t1=O&_8bwM~sn#fMl+nhTV3PT+vRH*> zy<2s%ec$b|y~#_KAVrk0@`a!4Lci!KMabEq9j<@^ZSU0E!E-}n|90=T?`?_#%PbTb zqe!VTd^%!MYCeI21T)kqPJ~G7t(ZtyM=Vvk47D~D&j*jZ^wm3G^!k}5^s{hJER|~+ z*E*t8lV*Jejdq!)y3%A*ERm%WE#IPeOxt%R_yyZV-7e|yD}7h=xoV_5unB-;`C#IA zW6cM*3c;&|;MoH3&j=(ufo!3(!5;xK6T&$V$r&~h@!W{zN+L3;JW1zGLtbR^Whe%T z(b-TWNx=wXBPfP#aoAZLJ3`nVm;EKOF9CbwQ&Jv<<&c($;&Le{o1$b?R6t#&)N8Gr z_9|#=J*!&5?$S`;1)qwrHxK6I#7sPr+k}!Pv%ikc>a-b=C@hhLN5IJhG>*<>jZup< zG1%ky{)j+~I5zw}d_m$;UcnKXC^QaFAd-0)4hfQF=%Wr6I_MD;5*Cq=^o2>w$Z2Y6 z>*(qk85)?|*h-P@M9oaCN`JbsiM70}hCU TC@n%U^RC)>~TL5hZ(%v#UqR`q>`U-&` zjfBEjQ#kR3B1%kV60%Dtw@mWNB0niPWzg6f8d^ y+MGaz~Vo@xAI<`?%IxZI5Hhc$aLG z8ubO v8o_@)*^c@uS8UrBdE#t<9WE)kLB({zifr8{gPl;@Gv+1Xk>H!qUA0(!v$Ad z^N3q+csI+;GGIG=HCrXK@Org^FJT8aLVhS``9mDL(g|rW@UCKD~-snf@ zXafj +Dv=AsDoQXs~|$Mh0wlA=v?+xX2c0l>A9E#; _uS{)dlkL+x1n%a4GSB11)+&$U5;6!j}oKjeMCJX_bUVxAvfeG6HXl#eo>x)1Z zgqrntpun6TCyR{+Mishz@Y;aGgdn7`f!0&t9x~inb>OibM(2j;d*3-ablgyE &Ly# z@ewkiZ&!xHIt&z^MxRjiWaNh*lmV<)=4?a4A??FMFJM5?hb}OSc&QOLX&&qd+2XK zYQM@MGkp#*Xs_y>jE$z=+N0>E*XrGi6W)4zkT12NO2;{dB;mc^`JMj&bjLddilC~F zW?L~HtvtSu-~dK6XvEKf)n*`uy}iAc#xYXRvh;TEG1o)Uy>D|O_O2EO%D|>giQ6jf zbYFWCj~iQX^-xaj lRkVo+vnT!C#m zkK?09iN-`!MQOoEez%kE3_qv|@MLH7o8M2#117#9xHl5t9LFf6eI<)1(TPYP# mx36xUpAE3h)yC;bexpQ>}&F?px_ITdcB05a%t- zLr$k+`&Daz`%~LYBZPI@;`)=MbFH& ~A!CU-Hy_TDS!Z{vQond29K~e9G?M4c-SzkY z!7fLeLlLoagTir0Y}2^M4yUi zQ#T6TR6Na-G&SM9w&x=n2>89MLP~AVz#$Ju)E`tp57Ys7vv kK5ulW zSskdG9n@DO?{F*W42+7QIJKZb!8aXUK|L5)65V^36*rl|TB(_U ftc zvLN@B1E%YK2F77+V5pV5Gx1yfYsmr0->BaSMky&>qk!SbV}3}0B@45cW5tUbflkNU z4^dEta!MZwd6K3ZIdNZJvM>zmOFsy5l%9r{+6)CQWD6-78_4L=x*JL$o#;%+PHH#p zK@#$Q$~$HXyT5r8a*(H-xYY;LR9M_e8C4Fo>K*o(k;$1}^g$ZD!vpuy_fFS(AH^_@ zknf;G A&x9+Xo_r zEI!_i9Y~BQL$Z%L%^{+od?Rif7yb*Q;P=yRL{59)IN^aa{7s(}2@ln~zTZNhXEXi7 z@(1zY5+QCgiWd%V3rbN^<%fcy*^~65xuGCsseqP-#kwR|BH@4?hUqGRf)q1G&F1%( z_Q>OzE-|?qiy`8u(mc%%??);flh=Z*Fgv=RZgy6XR05JiUj9Ze6%0fciw?#yQY!Gn zQpiHyib=>BD8m7Yy;&5@B$ *tE Y!z^xa&$4%3wKZ;%>FHPpCtW_Q%`6n%8_#=r6Imbfc z#Yg_Nffv}0zPI?3uwx{C%MW$=gJUpIBV{W0R@v>XW*3S;U7)`5IrVD4$vCu=gcb4Q zr*dTvtEv3hvbxm66U;XW2}1`pu;9K=w#>7cz@t)CJs=!;Gj?npEWbl8(i0~Nd`jbF zHEey=8H??+=49yCvZnyXDruos7fI(`3390hC|tso7e-tTzHp4dUdKWX`pP%E6d5w- zZHzf}MgLfRxgQ{?KLR_P cw|RWG^|bP$me{e4~|!7NW)AHHL<=|@DqU>0T~?S zUn7qy+bL~3V~c#+v&%YQAXMNvq TY^u| z;MjIYmp!Z*S*$x1x7w3Qe%5%;ncH=`LGb}Q{Nn;>DGpZD636%{PE4s=p^A+q^I-+k z5jM0oSBoQB{^CU8`NBK=AJI~%)3+Fvox_@e#}m3^XjloWWV+1*#!z&UsAA4s4fZrt z9r~mU^gEF!>T7NUsC!O427546Nds4$uoP;Y2!Qq5{ql4@hoSE4v#>`@VFdZ`xw)>8 zgA^I;kg|b+1UXMkA>UZV;%<#u>|*?%Gg~w+4N{4+ttzal7RBAqP=IqfsCjWQS|A ztSFrcrTbLq-utnHSZ !_f=P-TbGK?ax zWkvT6bOV_oMW1BxK`Y_uH6Aq>FvCgO6&=o`yB-HMKVV)w{I3Dgsy$VLwG4LK^W*P1 z1KFd8Q=a&BL99h$&52YaX8>y(VN_}SVWY7R15Ig{R}IhfXK);!yK&2cB$)%l{ 4v4+I JGbW3A00!|gnPlS7dWEjCJHQWhk?LDzG$L`FU{ zU`7S+;i&NWBXbAAv@|;){icICn9Ug?uORuG hC*%{ zY-U|f@(|FxtbMdIL(4XWbfGyp60+pFa%qPyz6R- 9IJ1Pg0#=R?YT+w=4hX8GAoy&T&M~*L?qy zzrkOhVeo;jCEskcJu#@fvaN221~w`zela`38~`WDwKe{_cy9@dT8kX<3zouP=EQ Ox4$NZc)rtFiRgCJCg^outrlg#aO;i z*JX8a7}@8n%mc;JLQCyaj0*Tp7ZtlO?YM<$-tgWh9OqL!z(EkRF*Vd$iI4XwL;Gl~ z4>R*Jk=Id8C3{O=BMu+ba$A3#t|tRiQ65T#dS(0DPNivqx_88K)@`iK4Rq|hMf(w( zN$5KTLu6o4kS*Q_t|3h$H2jx)e#n1Np-}|3W04K+@3Q}OT$?MSv;r(;i-d_xCgbPp z`VF9}JKNuOCV&K_hK~noFUXheZ$zyRJRfw*);=Wk3==-%7^^8)I-r(NS|GDM5{HRK zbiK6xd6!yth~v*5!{nMWH1>sgD7UQ7C)Du3DtZiP`Z4ohIq%jz4@~wWf(%gh`Gnuq zgab`$BN`P{J2{u(+t{4o^*xxWI^1sgD~M+!$pvjRx&)*c)APXJvjA*MfqJMNjf@~U zIM_LE*2CN%j=w^k9v%ugzrX(tRq;8zuO(aWCN8`ci?QwORsCKfk`@47SOQ%?sWf zL#cPiizrz2aO^IC!ljZRUiKZQjd>WgZjZa!%huC6XUcu6p+BgWwX;(3UJD3_U@+7B zp!zmmx<;9uTkW42C-ixghE0HZ?@#vas+B5kfOM{}>8w`Ufv~K_X#;=-dGgc`%m2;& zX5Ig+|BqoH`)@a_4N|%SRj zTrXt|Gl(u<4od$Cr>!OIxz1t@@8t-rUo2~pb;|_f$1FO(sS9}KO@16*$B&(9!kxC^ zInHmaMYERP%aKEj-^wfKBaevy4kZnSz-|%VrXgX Beo~!{l-mC=IkL-r)b}`__MEC}z2EEE&l^R$3ASOm+1; zz@b5lvDl=yCqo@ FF*mX+p*n&~+bxLyR*?6~6r3@xf;Mn@Cb8u+!C$;( 59{ z-6YmSZ!ngEj*OFadoXR|w$=?fsIB3*#ogujY*$6Y$NVjaXMPZB2Q^vYI#`Rd(4FGR zIlb^6LKzCcnp{pFu)4_&94(GeNQQ)CY-~p15^ 5h5S$*pcTr^JzZE5(>;=rZ}OQHr}i{;i5Py;rf0e z>3fs K+(Ughutba<93Ux(Z?Y^UHZO 9 zY2or7cm3}PG?}(d_<<{+RD@r+Iz7YOck)`TZQY%@56^$%7Neb*16SFad#^zC4}L#h zWRAivQ&g=#Kfbih7p}Ar;6$<3o5(d5n>9RobMQ5ar`#cb46*O&V#87OvmW)?EC%zv zA2s-H+2~JQ*ZYO^-al@M>ki97PxP?W_OB^)n%~&a2(Y^UPpESn?*We~8n_e%?J{H< z(Uhgia^q!_%yvWVUea>yj0K0Lyt4k3dkQp5qCKtG*aJh1rQe=_oqn|Y;_3?dHa=3* z-tTyzk@m^M6jETMhFs(kG&{WbAT;|{ZarDXwo$*Ndl(gxadRg_ONI+|rZB>RYEOVX z&hb}R&Av)=Q1y-vQW&; UZIE;cqhbmd*$BY}doM!q=F}C69v LxNSfrDyi {+Huc5~)X)HT41byCW#$bT zwVB})Huig 9jcF}F4G$;?@JO7@- z7TwvE69oBor%SG6X2VnXK#Cb5+1@Frety7s9G&0kAIA6fdT7{NEsjzDY9&DZp+Z%a z1?O63b1F_nvVgGrR%5Mny#4<+RX8q1?T)Pzd@B#!vp!!+ldB}BlEo)zg&NT#k_Euz z#WZeL-Rz-x8ek@gm8ZUfDyPq%aY8A_L&b?bf4JAnW^ukk(oH%uFqX!jt9 _~tr)ZfXvP7AAcE99U|mDggX8dH^2F(mJ_lvb#;{r}E7XmzkXRX3hi86~}# zSyZZbP2Ndu70mGfv^W5mzi9Hx<_@hi=q)(mp*-c9W^caD!b1D$kMrP7$2fEJZq)Ji z%%DCr%h7K2xO$mcOJT|=S#oxo!%uFJRFsqG19KYG96-+a9*WOv*_;=hx;)8zBhT!# zfFs+vbQv}W#^uXcEKU)(FG#A|+nPK1(6RZLtHMu&9ISg@Z&hQh(x~M^E%mn3{(q *42^if+%74+6x9eG81VTpQ`J`bKh-TDS_2uYGq8H7| zNHryI*W+0_TLWZ!t2O0nsDri{l9&}FI>^dVpfX2=Wm$E28tak3Y@Y4?_^fn!Y;~eF zT5ewO@ sCj%z4XcXDCYjn;P7p5jz6Tb-SS}5le8U_SnsVm{Xh3dvboe#wf( zl1hyv}R%0SX*=fqG8Y zc?zRdB2b6cHxNNt>zg74Ubi?EEy5dx{;2kwg13B$B{Ih{$ztN2Cm~yd-qJa?geGr8 zV9c=@# eO+c`C? zfTyfk;Rw?nHHA8F=PBH!{C_+9Tm=s)ZhQW<7x OKg8?pT$|!Cs2Y6Wro&e z_2lBc(AXZy?@ta4?G )RJTFITqzY$xwzD^Bo@a7Sk N~8+l#X{`Egw* WJs5a_&9^2-Gu0#hodY+~b!TX1kJdjo*}B-MwrJcT;o(Y_a>@^fsiJ#_eWH zlhR|r0~af*ckCZ3P~=fTEVEW=(%+D87>ERI_5dbblTMVb9)Iq)yJE40h#(I?vc3`s z)cb|C9OzEDoZeR(E3AtKyM{K@)W~Zyqk%v@fC#>UIic^w2=K$jN>c87dc2+uxGfF4 zY|db$h-fS@@_O2v%#OtJ7_wg>#|{+pgHdz9ChwseX+=-S1|;eUPJM|56JZR%73VLE z;P)#FT>D1_QMApDcPymw^9|8Z)NKu7vNh>M`RWj6H~LKSOy$AI_f97FFU1w_n1Bkn z;n+1P&;C_%&jCedz3mX%u`raMj|+{8dL2 )Ri3d2p^ Y1 zNkCP{`HyZI ^R`J@6pk}_% zZ?NZwDK$^M E&YXFh1ZfumU34~g$ zL@7yZbt*Eric86SeqowAf(4%W8yzbF5pWlqyLX zWInUQmg+W8R43$UF9_l13!E@itiysXW9?~*h;icF4p>zO+nn)!EpYtQ(mR+IrawCw zqfz3ArCq4Ab*VMD0jc(jsOgoVX)+xTojx xrwL)n)aXEC+=X? z6@S!a4}5uBt(5Gihop%G`lb43YZGeKk4FH8`XNhdus0EOu#w^((unriY_F1UW7AQm z%Zr7!fh7@hAllH=QT_L0@C54{7OD{?!O-!dM}^@I)NXzI`2>ssl%GyDcMr9Hj{j9; zPcysp?7vxxF>E2jRbtBG6$vqw=ALT)Ep|>a(23>5@2skh-@;kqwM$0orGMncx+lf_ zId>r#e1fD{(OtD+X170%&WXdai5{WgNRpec$AzK@O$`i+pO`~uhSii-%mj*v!fH!9 zS?RGqJ4lQRQ7e`bAPVc|;g!7lCR!179C2Q^X@PF5Alq@vWGrTxY{%&^9_VgJ2f9$b zM MDmCnfVD750jup^x(3hV60Ta qv8-IyltQ{| zO>d|8*t^$857@=XUaU1EY7=j|2H 9cThhp5nO}pKCOb9sg7DZ3h{ZUD2!)0WWFnDJ1~`8r`DDe-^ZXnk zQ6sLqZ~sECklRBBSqhG^&Y*>|A%P(60Bq=kziK~1)hC~X#t|S>LHk`&bU$q}fe;Sm z4KP5UMlNeuFMa#L9q;tRUo!f)07ILK8e`2$dO8xKsS+8VJ_i93J~*qWv7QpH(Hijl zP~FYJOdVoRbTqT9_hX{TpK^~#@KWN8T^~T2e@s)ot2HW;FLyF#dCC@JowPmRkfQ<# zrgs8s70s o zp3ubc_c=tPaY^(IBZ1_NW%(#keiSC1j5E@e6ln;TyEsXw)F)i!Wo}Nw>1@jV;?)is zB2hwtlmaoT{ji2&bh*&&47UZfPZ$O2!@_csmoq)7qq fboq-t%9K9Qf#u)1NSR>W;QvO7wjM{+7PYHz(9#gZChU}YjdQ8&U7S}EY& zwdYIhd_D oAQcotv zx`Gy;-Q{Jx4wl2LRpUbVB)G#{IP=RDN%(SZv2fq97ZZ91tj!EP;_2wT$WA|kFk^9# zCpbj`0cRFXXo%~lYo;aRs8jmlZP!I8s8K=7EAP(Q@n0(twjbHiT>l30a@-$qknk`` z-+SE0Bz@gDcQTY;X4nx9iw=teCfK0Z&D2K@O5c6&B?I9E@(NBG@nK`wirK1CdK2%( z>{b{z8=A3#MtUTPx>#4u^VMzif2*NCX)x<$i=EHFJyhPz`z-#XF#TWYF=QWDBFN!a z{^5<~R>Fa9A4TFT7t}ApQfqSN8S`tavjd+~Tq?xe$l@Ev7jvS3tOzw^7zUrcp n~X3fggE0DtE-bcuHtcb~&WrZEMsHaq=DF zed3toJoQ4dry)yDe31iQxKN(aQ7@~{Ut;#~Ene2;c2Q2(6g%Z6wYVif23a4{U7yce zmg=+A(ft-U4H*O;TK*)b&+jhs8f@mqJ}Y3Td7B>U)+#^B=0_q>FBcoLJ*Mc*UcJqe z5Rfv?)?ZwgsRx@A)s>&|{WpFw(H&6L=ftL%hQLasy|{nlJyz0B@*g+ZxjuhJJL#Z$ zaR|_efcri6Rk0XTe{zUD8N>M7TC)CDX8vq!&9(&E!iS$CPl2O4E>{f2k1tZ~2uE&v z365tG#DB&sP3{J@p^==!(`1F(AQ@58tarta15z_uYrInlcvue0d-T)isp8RCG*caA zj{&whKiC?RXM)>lAKW%*Y?*C1MKffUP<*pg#oFTB{ =p^^7JmWE zJ%rE5^+!Wn?Dt EWNL5L^QB#!ez{q4 z=0=67y!#?A<|N&=x*;uH6U7=076lseP5Wn*D`TT6$NphCe{mY+gB?vguPVXKK1+o; zs?tTBmGM%?t4cz4K`{B#Dr61<*5gu=A31#{c`!xX^yrz>qJfJzHBW6tVV_5euM4l0 zuIcM9UHQI4;H>TMi@xH%57d?$!+A=$k*49ML3Q}N`oS^J`1vDtZT%b38)1&a =^^Z^QVmgZ?p+-}$x`QC5H72J9F|1f|BwaR zOw89GuClN=G_1it?PtZ?zt72}BKMde3fu0q0sG$O_PME*2RB+bicih>5F{+O{G*j! zETEy `{3c-pGcRjjD;3KEI%qYJ2*4@o%6$=+CcufI*yaM`o&S7}AON zzF9Se5F@!25JgP?zG<~S?ftVBL{OOH?1xa3{Bq%rT~>NaW2)thE4Eu3T!fVFCUEE% zik~ipsy|%9wnfM0MA#^Z7Q1OM;xi9+xcy-~7)~aFEUrN1qJS9|P^bV1@R!+!AYr61 z$9yu*=cF3Q`iCM9dtH?|^UV9{ZT>HX_Q#a1paNe_Cr-Zv6?oqP_9;QhCE)Um&ZNJ2 zhTe2~kSxmg4pi5wuCfQWS^U>!L4Gn?BilS-J;COV3;<0$%h_|g&Q=}aZk=wOYeJ@; z38Sxqpc~sFOBF)#xq@U5@hRDvXKALhh9g4fMgr>`Oyui^<_4Rwv|Q&^TX73M#}LVf zX)w909 1Cz|Ezai4xZhAWp{_LaHShOAH#86pcS<9LXf;>?|;zf=M2!CIR#yVPR;Z(F)SN) zjV2OI{X_60$jGVxChiMqNR(}Eros)O9HQ8Z0$&!Jf#7rdbJg_p1ZYS9un#3l)V4Z- zGKju{oC#d36Wsmufwwg&TC~RS>E-$arhKfH)BQaHW~IOSw;~%$Ejzv^lrPgzMuUd- z_0d}+_k;p68HDZu_qObu@=m!g>!$|ZL@qFzrf;YlZVvnUU9H91U2d}t;1OhAGFHUj z`#U*uof+58M}9#4<`y59akKS-0Eb1Tl+5smlKhB)1b*X@bX?p?F_7)3!$VJ?(ETJ{ z9to5_GPef^JKd-Mp+3Tyk;B3D+ii*ruuyfV4qGVuT7Oj#C!+!PA3;6Vy9;#*4IE(` zasw7xy=F9ZShlSYosm1~J_4R(VYn2OVkvQ4GsVU Us-!W@v?W?U$M3)OMGS7^?QHG(Q}xS2H5wEMRS==# z``Q>?=4kdf; MVvuu_6RDT{gt_vwaCZVU)FbdjwlhJJ6p|gMCS0&g4!I^Cy$*HB zfU)r0C#3RSe)zSMB$@F{t(VF465CBezQrC9#Q!)wmwtLqbn5u=nZM_p=IFOHNVtxQ z4DnS7UfbMcYxc;ms7UvriYj*b*Dlu97p@4r4taa=@t?)Q$L6i~-hQBkVpT#H>i;k5 z?gd}R-qBx*2a4&=r@-APU7%4mg1Rr)FYrM&LPX7riv@@OvEG^BbTzp*P9al30_}p{ zlZH_yeDt7CY0IA7rcK|=F4@R9#;=xNe?*U<4ba%a$ui#&b`p*#XSG)pfJG{$)MRa+ zwU@egLt Y928!Nb7$tr7yB8I6H3Byduia hl-HD6*ZNc8w(lV-bc~h>y=r%Lox@)36>??h(SVFNC*vNc=Yb|LA1kiu0uF z9rbj5{%Y9a^h8*{LFmIIT17yXpZ46b0#R1y|2zG0b$Ex%*6;N?2l|}A1IOh1pzZAm zmA4{=Jy_VCkX!uk@U@S01O-Jg&H5aP(S3bvk&*0#?R`|pwRFJYjgqlsm}X+Q&M#4V z^?Hfls{p5Rsh=*Jg9S6l1DNJ-zH#|3erF1hapWp3+UN;3wD}hozeGo2Hfy5U;C8nd zED0M%1>QD_TAXSNdRoGlYRM>BkKnE_&4d}+h0`jYw4JcojTj6=IBXO};Cfx&4}4q4 zAH*Ofh{e>2K?nK!CK!r|OWb#Qk={&(?eR*~vq`aD4_u*}I@9jSP H TAm z4Y(6RNFsR|H;BsMisD-$ZjLAS&Q;zX{G%-Qoes9kT5II}A-324>87A?! Y6XO z7Uh-Y_Ht!}U)d~{skxUmlYzfxdAkI)(F7LAa=|rz&2OZCS^ti$gfP(`rMc`xqdaaK z?01!Ie_k)OopOi!z&R+g7S5{?uNM*|iOUFSaxC?uF7i${$BTM`7*zeyJx)KQgsw0wg5&DT<04C;VCrY`p)3K% zvmW!t7O{B)43Y#(i79^Em$;6G8j{YcHo{?Z-1YGFxF-aczr>9n5h+2;gGRicxHO9$ z$7N-;Xj$IvfQ(CA_m_M90<`&kZO-FO)&HS)c7D)r_WSYsn)B&o3K@$=DceiJDz%p+ zG(M&O4 !et@@emO}J2!uNg zI?K`Z|Lr$E0Rb{4^t|VLu7^zAT*;3p%kAZr<>lNjYHa5hUui&L$o;3*Ui=5ouhz=A zfIlsD#Bcms@PdV6Nj )NnmKc@G`tvYsvzIA6gmPMou6gS~CX9^c~PinC^J)qLy+As1}elZje9 zX4unV3)bTFvWMryXe6Y%&2S_DkYvGV2 7B`u>Py)OnsT`vLI z+txsgKL(`r!{x9as2%GaLR!8zLZ#W%9C)K#vjQx1_;*;86HDPk!0?hly9u32`ZoTQ zG?p+T`}(&99%0C_3TES)w#fF%)Tb=?H51{^x;sZcCM>~mCmrw?F!}jfp~3Avb_&fJ zEe#IE;nx24YbPBtPflZ5cPuNaEm6Db;r9Nzqf2 `QRg~@s^ss&|Y0Wp4OP&I4=GRiK&qSYjfv`M*fKt!PDu(1Fjp6 zMGRW-xq0+cjd`2TG3UgN9|YMl<^5MO_S%y!mNBEUD{x&`A{k0( zf||778m9^{k(i|ke_FpX5du?+uHVv@@Xf|VXa~mUNKVrj{38oVBjm-m--3;@6JuN> zfWF4>^A2Cn2HrdN=-(M|pfT`Zk3trhIIjcfeHr5wI;#QRde(&Q2ID6<^*e&xVI|lU z%-^Z#Mz1s#26~^zdfmNqP~lSd=vMZF_Sr9rL#KlmO)MJraTRxVo>FDZG?Rd8Jk45X zTy9u%@)auZ&)v(ZciY*1AiHzV%~%gkzj#J%C!}Y175hLJt6~|66Tz@Z2uMiIm8=}# zUO#L0c_1TwKs#CgyR@z6?E|{2#;%TCVH>*cjt4)E3D{7&@+XD&3k5U?#{dsRuH^l! z@Ofc2jfLX?%s^>0cq%Aol)v~bj8Qr!+qD^wTB#W|SjSIk+km6K0s>2S=Rm5C*Bejz zpzh?rZ30F{_cy^qqR4y6U;0>sDv0fF1Z*J#>XA#vddqf*?vh4oepv&iV9_9|88wqT zcN!;GfvefDBqV-wc1H>`=JDct&I6|1gPHFgGG7kPh*4LAMlqau39xY?f|v3G!42>- z#K eN7bcrj;NDc~fS`1nv^Hd4^6%6a%Jhsj7ygDU4H|0$~c1AiJ z22A4S4J9sAsFxDCn>?>%=b<(H`OZ1phN{8rW)2Arb4*`9d=HLe or!(aWzx z20En!H0~oE9Mx88oI58ydp0rb*az=T33G5P0$9J<)WEWQOW%AJdYK6abE6Gri@7Q! z-`bm}NDzCe{*jX9Tt^0*vd>LrjWVe!fj)oYN8}w)@0MwXGy%uk(&meavfv=n1%2zV z$)_r>s$Y-vd1&Q100ZAKSEADfwZ^OX9TE MRC7KMit%+a3z*w>x)L;4L9_LwHE zgG$AR0AUsoepEE%4aYm!`laO^W2@P~nKN`rf9@{*gX~}M-i& 0q7%vAte0Q^;q(rifeteuw6!C=ilDqX41~$n&Q)mCToJrN2Ux#Z9KH~SMmaC! z$Xum(GkUHVW}5-)H=Bs19J~C`JA2kW3+JRawmG{9%9|ws@ahih?IqsyY+25(m{?2H zc1NU%i-hOG?Nn$UjjEYwvv&A@5tKKF!c%VM+R`DQ_U{I_N^b()Zd8oT6x-euJx9U= zdwkP56=%&z)dK7l;##xeURt%$&D2pPQ{LPg;Ag 96HUO!^DmmT6#D` zFlZFp_~#RygWgPW6iPwjK6r1h%ff~fN;>hyGxllx&ZFpb{N=F`P`2S$9T=Q?nItLh z1@_0cLjglFm{G@OXeJ)f<-vP<%}C>bs45#y$CtgDb~-AY?b&hs)?vMYcX3UYmwE`O zf5qDCH-p6fHJ?U^n$K3q{zJ?U)?!H`rJ25dMdMYmrFWe}#Nu!4<3*O0v0R~MqT99v z?6xOO`n0o!X!h=XR>**x#-9sC$(562U2Lq`aWFSeGlAUy&VxDT)3R0@awI<#L$iuj zRjH$%hMzWs2)N3ppot;9-x24M0$dR0TFiC)Zv bvfv#7tqC0ddP>|v9?fiI9j;WjztEd zwmmJS;&oR@_MfiOE!Xd{@U^DHm~<)TQIwfQ1-I!68MEowY)rJJ*tC#yXkl7>op_XS zqxzT@X%X&ilc-ij9d`cZS!Ioe7uxm0oeg(anCg~<)Ru?A0xrEM+n^~Y9VpR%HQzRv zj@L0U#%sq@VbeWtnlJVnqXk&U!B>#<_P`kl(HS=4+? #5|BA^X~VO_{2<7#C} zNK-OTqak2cG`U=gOnLJR3a?0mg@`->S*AAzQN$S1%iRM+o=(Kd7;qo5ixo62&)V%o zy^@vR+#;t~3Q3D%J+cxuw>lj1undGC%@F*7Q8TRaC|V&ztE}dI7g+5kMl_@M`Puxw z#P}NDZ_>7kM`{oyq@2*HPA{tTcOf-B2sD<-_SVg8a}GRbvz9c$P0w=}An#T( *0@4hgJ@xzkZz_ z@QYjJawoxEEzq^<}LcDSahZr@$%;Q6E1>}Z+|&3wjcO=W?uPSuv5W;){6OEZ4H zJm8@%H_MH^SO1B-`u{IQD@I*|AvP4f6`p~oBd$%{9}K(vZ|K2#Gn4RX80;cTD097* zpVXR9Pw$n-79#y6y{H__V}s9=!RP1mq5j>c`__;DI-{T54T)^FCJ18cXF^fA-6Od+ zD3uOglek=Kg1qV4Az|_QDuwO3^_2>tRuL6S@m8g(_)iI7_)2<3IrY1_Ap*f!);YR_ zDo&YYlujfP-P)I09od2i6{zdk5*AeuV&0-ksGzXXxfK!}e!D+oOY5!shYC!MrN8^I z)#k$lmSDA?WpkNP_uBi`UNy0O `Mx~vqP}>w>x^+*>5<7mx@wm%TjOAD zi|Y6)T1WpkJ9~j0gY#6jgw@qj@HryfsRX&|w#>p6BV!{|UDVfsktiC7Fer^u`!_JG zN#6MTPcyJ7rCB<+^jD`xuziZzQ*3Ri>>b0FQ|#X{Gim~;nQ+`%eCRmK+Rr;eThm~O z%=u){T7z$n=sXzq+@}5+{`ul?BWI6|M&% ~Agk#)~4E?-7BAIF8++APT?qr=~% zGlmCRXP*xDR!P=;?_~D*lS5Ds-@Wg`o_G+w1wH{!ZZ{_{vj2?%k@^Q-gH2Ab`!9(3 zqeXiO^|`qnQ_gaIdIuo;Y2GLDyH5sl_rd3}JKKKa9d&G;$JlQgU?5Il5*4&l0FD?+ zBBA5ZR35UuPFIS^RF@RIQOm6JiIRC%3YgGo2%9wv&tfO}ieOOv%AxPQ!1R2q O) `H>&GHNsxi%07n4!cr37EL{Gmu<21)?RzwL%mZ`^4^AM(+qvm1r$)|A9Tj>y|(_2DTW+GX?s9&8&t1W6QM*(&6)DJhB=&JmuKqm^4nw<2!L(~ zrTPzmPpcSB{{)bt{rdogx@e)kzLX;x82H~X1P=jq6DV6p)2r8fqdjvpUF`?+N!y7P zf<6!F!+<+b1}I)g`^G8tJqAvyFV)v~vWJF305wpw)|AoKRpW=#7Xd{{8?c+fT+`hP z4l5-4PIh*6bYzvTFzl@RL@zu`Ib|R{aCiIfA!$|RcP1sFuTQ#R!*_g^OM%_Q -NoIceoiZKBZ}2ih~?whZ;6JDskyyVktH67v te8c*URmv+DWM!;A&AbTmb`% zT_E(v$v6XR_27$&Re^gz$P?(FV;;Pt2F zsTOph)#|MCNiR2uMGcpwl7CUw^H&4QZlkT^!RsB{;rYjDR=JJ`Iq=u>@OHD(98Uq+ zQ%QeK)eP_Dp_A)e$h%I50Pt#xvY9QLHn|1LY+JT1M0b`Zzj1Od@YEZV$>98lQ1CR| zxhn%_fX?j0N8e1py>j3{`d$PZPd(M4I){D>0SB|MzRcvmg|tV#+J4$9eW)m5KeIne z`wq#>)^zaCDc-(%`iq +w w&7~jD*><(Nw z?rkE`JZJ9zy1M@_`aDq(pLC*pFnHyOY2Ev}{=JgflAUb7)SH}T)+B=uW&dY2?7V-- z<90t!OnV=4nXMn#hHWwZW7_`z?*El*dZA`?mZ6FImlS=T7_Cb>aYa!u`$>lLDknRc z=k%r|(EUs~&!C32_YZm8?&n9Qy$`v({EomjY*6s4;H^|E`GdRQrEX6QL?rE5zb>fa z&C8JN =uJy?;rBG-Ou}{y$|^c!wA3~W~Ld?N+v>2O*7fd8m6}*Ox(YQ zfk{RRQ H92W(0GTm*h^Pu=w)YvCHfq~W9c`$}p= z-36BWe#(mr9Lw6a 3!9&Ta%yshkKir#nIiBo3v$N@_~o%-zw^Nnmt+Is@m%IT>SdS zBdXJN8n>RvhFR)TjWs`-x-6SQJ(q88KMHhuLtkqA1ED5W8Mi9_^fW-n{&(S5;9vW@ ztOD&R=HhRzWk!`s@?n<$p5 |~S3Mt>FN-%_gtm3}l(k~6Un2Cg~5Cr{HeLc%-W zaU1U*D;eH7) Lh7#~DrlL9$r-pdl?fZco?NI8ZX|Y}^6kDvXV6 zH@~wyyxaGpSP}TbdFlGL)3~TKUgtZp;8ZGeV{Rw#7qJW?rg$f-X?cgENY!L3P_SeL zODhTs(&D+2N+ZN_gt;y@h}agy00pM2MP&$0v7% xigRLeWc!(SE!K)xQEW(YPhD|B4#WysR*cQqFc}p8tTWnsWq29%oQi6nnsk|qW zoSZB{daK$!e@b$?5h^_}4t2RKf^3+$F>`uEj~rg}jZ@`ABtuc`hy&0 z*xC?GP7sG$FpNVe^l~gQ(4bUln(aaI?*%xD?}xo`hFhnis5OITBwszpVNBV8ic&kB z*?wvwXPUW*ln;G#C&@w~c`~<;n{y|8!8dYF?w86 *YOzK2iVBy)e1b3Dncq&G{Y0#;0Lb)ZWzPq99jTNl$xdCVsYRyiEE}6DL{>w z2d)m70LSG$OmcE^HPANN9rKc$PKQblj5C|cWegg_TmqaP>}iz4luw^3ACL?X4J >waaU+`3>UL#^k|$899A)yBOXtk%ma_k!f?*OnmmM9 z%)wUC6aAcdLIyT(6vydGFos4u5C#Pfq0L@w8SG5Zi$GiW+9VbkY!7Q&qcmdM6nD`8 zk{u#N56P`XO)6+Y2QZEdWm#V1J2)r+P}Xq#j=47A)I?l_8Vq7laKu=s!N7*VpY)I| z0;DKL4EdF|ZmL5TI0JZtPbd`#xk6uq9|!v-;$$|?HuwXiz(1~jbp~Ax?#6{0R6p=x z`hUs2wm9Lsl{;ocw-(W;`_5UGyfr2z{2n=kKKy1M)>GuP2as1t3F+6nwQ$Bc? i!G1p!8{CwPR1MH4!#j!b{3JO;dzzEOim{8_IQ;uUG2AAjIlUEVw z-SNtfqrIZdJGHQPk}O`TEqqvr%tn4Xl#E*z?=CVphd10iv}EX2WA_$8^+zD}C+Ek{ zzg!I#6N^nttP<|ufA>LH{B^;S5?<4xIlTf_{qoF?$zY=NP2HU4w>slr4JumIV`(g8 z+-cKFdsZ5*Tda3svEdEN7Did|!+F35@mJKK6)0IuPVSQfFT)j?-jgd9m(54tM#`@M z8<)UH2sD~T8Se^!vf(Gl{_l(ca>|l}T+>5KOb(Tr9R%d&vWarDXUfc<;aWU(HI1%6 zQXXxiHo)UYdgR77pwhf^;WYW3^aaR!zq)-(0J>-Z07VP1U?kT@c0&npZAtd!gLQ`` zg4tz2<(h@r)!J;t4MFzhDK)U|Q%&%|I_Tkn4bb5mHUVc+ @o3n!6L_LNw&10wFXUssuK^@`gW l_&BEd3*a++YvMS~(VlQ-5j=`25ym0dhq%j)mVkQEu~b(zmWOdUf|CwZe%otVj# zZKW<<(Dm8_FlS&P1S~s~`G@5YV47WJO08t(ePz248YXoUN4AszGF<>OTdi~J+&XOx zt~Mw%Egn!~6#$l2cEIl2%zfAG*TK$ZI%|d<4gl1m78wR)004%XceS})P8SoLal7`r z0N8T-1xp0LPD&O&U1S}C)vJe2%WCz|LSn~A&c_DXjLB+1S72@~2mXY6CkDRk?R8%| zm}Ml+#dT5 ;*wUZQff5QYY?u0Dv&_{Wn#_y4i`DtRl4nG zI t)kqt#mTxD>Wh3Xmhf zs13?FYYbWqZw_T{er%RzseUQ#mc2=v6vPw@ 3G))o+d*|Ub zoAh5 !3utBg_RWg-&p4}-bs_- z55dS%5r{bEW|%oCpsA1F(i{+0fCMrU0Q51T#gMV{u@{AcFa$XWFkorfMgV@_+hK|Y z(GSsW;B{c{Hd@k#x<@aTD_p1=;iXvQ>myf Bf@1&s@BDug8f;Dq9TMMscZ zDflyhrM$*|yQ;!sxn{4OaCqsa3)Sv}u}(o!u|#-@KE DQ_)Q(nyx;P0-Qq1u#+x)z}MKcn2F zi2N20tU3&8cE$J2x-Gi)ZA=zbJDqUt2CgJs!ewW+0PxfEE8d+iSfZDKty2N#`K<(L z^#`T>+`>W*RLXKaIlYs%+ElSw!QY1O#8(@(&Ic$=&N )NnLJ<8T#h)=w ^)0=48cg&9Ce(C5nqAYM zWd+lPIvn rq?ePzUSOnUs2I|~2+D2ZzUQ}2&`fFnIOB2`RGJ}c&l zbq%0R)nr-|!%y#LKjtgh(EHJ^`8Jv;j470!JCIb*nD3dJAe|_ryzy77b-!N*fV()& zV#rJPLV_f_k~=QV!>eKXE%0(MP3(Y1+oB6^X0+XZa0e;6MiWgbEehlkOLC+#ge$`> zm!dX^4GR~gZaP~gnlt=1JiPbdb34EVfAkL?d$x?eFnrnTPQA#(#Cw!)nvIv{515pw zPuJVT2^B*9@tFh2(F MwnFU&d#<`tx1s#ER_tkxP$%jK2Z(Rlt`g!+)sDul%7i`kMc2sduG5*%$> &R|Qr!q-zsoEAsoBK8)JD{)_2VL(GqUUPFyiVwWp^%kMgU8# zb ^!xIEb#P=Va7tyZI8<;^U8yGTtQ|&nc;`eXiT#AX%G{v=j3{ zoUdahB~Zs0OH-*59|S~M=0#k?6*8aZ=7L(X8&t6o$bOgII@GLlVN=0*kVunJ$3wRh z*;Sn}NXO`?d)&yK+y}YMvm}6DavZd{sR>6PFH cx;!3cK<0W-!eny0^S`!IK+zaB8#zL(?R>rC&5bWTn zva>r^0eCM=*)N+U-g$)@%+kU7_JTvoQD#^n{t2&ht1~5*nw0BY{~C-JkJIA!3k-_G zn&iV;P0T(;)+F1FJ?)accXl83i^HBg7Xn&Y;L9N^Ikb@j1<+ExiW0lON)FTYQahzi z0~epeXeo6e^TIHCb{=u@DkR=d?Fz15^O5J-VcX4R0r}O7&v`k@OKe^GXO2y8{a^7E zY98^v;9YBjuD;iWBVgWB%{|)MNe=3!7b{nPUvx5(v|U=l&VBkhx%GpZV7?)SfX|xw zB7?x*w}PYnzDXs{Wo>{K;RSm6 l zRX6MV)a)2t36fo?VZ-O`TE@OSk06OYm+Jw{yD!0x*Q2`T&uP6ubay*l{%A?m5%hwt zmRNO?y!#vu5SvK!`_G;WG?FkOCK3l(;~RCXc+@Xs&!o9ffiH{v*Ti;^U#&Nnmg?1d zwx8^iEwfAm4JN?g EEE9t?ZWK+pP1M`UI18@-}G#tjh{VdwI`XphrUVyvy?ymm2ejVeKib?X@$H(^!B zh7W_X5Nz{2!2u{Q*y1bLtUgh^_Qz|iT3ri`i4lxke^m$)%U >Mgvx{xtLvrJ0$HHq{O(`^9UfO1(0Y-$a0TSfr9Yxkli>NDd_`eY^p zo2;5QS6AZCp@d~I&rupad? 4&v`MRc!!*5~xN3Wq$xk=XLwi6W2w zkFBFiKRW^lw|%V7q&r^gqX0}mv%kODt$+U61AxNL|Fqa>_oV(!3^pYLH_{ACMB>?C z7qL=JjymnM>$<)7(?|k3IO7>Fde29`m8t*RqmzClibzO4Swm`Va-Rbpcg9D)@tXs6 z1!gI0B#O59X7i$akVD>8=T)_>omQBi&vbihd+XI^^rQVmi~EOd?w|E)Kj`=SlP-3- zF9wa~jBK8niJ2VpJeV&4FrCo3Ngq!!!ZSR>1SWpMJij8yd+d?tb3Ui+yEglQP$wEY zH1AFAG|s=y(yYuT+S{(;S(xx5?3lxAh~v-5;%_LSgc@7ghj@?A(a4wR<`RF)cNpi# zEC`Du>JhQjtMAI7`*P@2Ey}02wW)o5s-pg7bO+>XmRacu|Hv`_$$6jnKTQ?5-JWs# z*w^mzn3uifBOm!5&5+B@N@x;Of7P3Pzh6hvjmi3UIaP~p?LgoJpMVsQ3GzTuO7rPF z @SB_EJ_ =*PeuWej^M_haeNFwAU3tw_ zD5Avv-SoPV7TfJz7n*3XokrhlOgxAbB9q7?idxfCZRzEHvwz=(HoAAo)qVB3yL5kZ z19$VjXDsQhhdpMUO}5!>@5fX5wcql)PP$^+(7kiKT)Vv3HnT6DyUHI_1XOIOI9)MU zal7IPkHt&yGQ1w%7;hzyk^ICcuPE9vj&(v4oe!rt^=XefEtSrkF8j)eQ&yOyweOHo68c8QvF0|ZQo9(oPC01N# zJqECV=wgW <};)W%XROkz`^1v#GTyRG(ldSSCQLYmG%8_qHds$ EsWk;hjsXWiQ*Go~alSuV{^%p5#=Ab$G z|8@2viS9PD#37kpPqXBTPJ+^R993FR12%96V(r>PpD_r|Ea%dmWcHtnt*0N^Sb7> z=BpO1t _&CM+8)+bnICe#=R#wKZYg zZ2e-3wDsGbu@mi1`!4%ehyd+@zQbug0pA6Gb(lC(jz=BWox#o t!_aLAh<8Z)5Il?%nPl_mKOf`@H+M`>Fc_0z&j>VEoj2k%J-XP=nA6 zbY1A*G$KY|hr`gbPYzRDkB9LAe0$jOush+4!iB{1;j`h-!vA(1+-g^jZ2xvYPBCpJ7Zf{%2Zw)!wML)jRCn!)#?9V1Du`eOcejk#>}df+!yq zr`o9hM4pd)M| reWJ{X4`b#~#*c)+N>p*2e&dA_mL> zI?xfA3has69d#wzIY jOjdK&NY-4|Q>m8Jk^CxmFV)-huP2uEuFc+&-J3m? zeLovF92D-s3Lc;c2QXlU=WqjvhDRLW8Y9R!M-**r@DbM-D2OzsJq4&t9oiB>8kO`! zTTB+!oFgYa)+{4Ij%gbe7btk?Duaqsh)Iz4`MC7pXWzHz$tJyRSy`TfC3^w z0|
3n%^jGk<^Ykw-nE$`Z3z(Db0T0{2 zA*)eMfqnr2URWLgA6Q@{+haH2HHq{O9iQuB%Z#e;C+j4SNINuov-0iO*f`g&x>8Jy zOm6B7*|0{48(fY8i?vqhp{lA_muTrWs}~y@csdkkJe5 zigt%YUWx2`l#FxTfp8QOME}vV!fWy-e{A|R_qv&D-7!>|peRuZB>kRYH*)D2uTL#q zQ$o8K+pWD#3mn?Y9PsR9Fieq0f=H;l>57(gg^I$3Argv}Q`=Q{$pj*`wM0ZTc>69d z;X~6ej9};lk~=V+)P%pj6vo^oR*|vl^y=GlgGfkq$hiZU&+emz^S2_d(GX=~c`2w= z;8#ki)r0I5WMM|S{IZE8vV*d<3V=;#2b7c&5JgCLI|d7B=)0J;9EUJ_7^pbsAYjg$ z71j{7twVW<^dUjX0MveT^zL=x-pN?y76>7m0*e!O-`tH#+FK|LOnEynh;cInqG*s% zhUt3ed3JO25rVPA4+^?4B+bkY>9k^4{t+^Q2IY1*>ny{0X9b?MzW@Re67T@Ej_QC{ zlQ;_(W+Y$RZeRolojG`W{1d;G;zODt?73Hqqq7YC<8;w)OHPANxQp((Ab1zORzfpl zF68dbd>mI4!Rcs;s+*ReS8AVDSx1c_Bs8=s54&61(dS5_Mn(wbR|;&*w&8jKj9Z-p zlui4)6XqWuHqYMvS%V$h1%wb7=#_UTp7{0mVHLKDp(I4v7 z+JT%f>?~K(JmtDXi=wWoyF+Eo 2d;j~Csk>0tN3ul_o1&<(j3r@M zG%OUjY7N6t&^i^Z$@T+K6a|#XW%ftTBSG?`)>)uhn4ZE@*{PYL4;E*D@96kP3jxmj zRdV6txVP5m95*3|VQ^C`V1W(IP`ZGHjHxB7WV5F-7=HJ=e@VdW;&6&K-dgU&jcviP zAUbBu#h311dkrCh4CcUvqQ<74VA#4Yz8YG-9;B=B9 %snE zbTt8=J1fNzblv(lz$5BPP(WT8y3%L>P=^&%FiRw*&vqWrjXzStFi_$`9bme&VptIW z*Ecgh-TjGabhTH4za#5lCFe~ZdEF{>lIoFTwBm(P8>y;gtRPmJ;E<{)oE~W>i=2x& z``qV_xRy? x30lIuipg_;eL z{+I|^aB^PJ+K%eD2d+)N*0Lb*J oF0Q2bfF=SpaX&UlSM0 zh_Ud4W8DTSiG%gwk<=0wpCPpjIQ{soUz<0(z#m>-t2+K+$$VLda`4XfSf`uwi00j!0pRz4xwAZ&L~vy{p?B0f{E+gaK$f_poeY;- z_56qTAur9>TcijHk!%s=tW_rFZVIPo((u)eIf%+P1QCOQ_P|e{_8=lvS`|`}fL_a= zsBC*v*whYrr_24w5CRS(X(EyY!(gp)NmQI*VVOOOl%BdMxv!8$Rvj}URKDSa7Em$) z%cPQkX8kQsdPf%$hn8p5^h{^qIr*zoa0YY~k6KV5B!UPcA_$e_Fz^?tm=MQ8I;W#H zkSz^++ih^G2cro>g$YDc>YwG;(wqBJYLy1Ljmm%mDFw;n>`wJfT1sG883sZlfo1k4 zI#@ E@o+Ck}YwCv$-Mal6>ozhO9@xlQ&MAGsQLg`ZVS6~g zL<^p111z8E{%vOPW_a^5JCU+(g9=#0tre5oEK-}-1nu=x>tZ)qX6I>)`~*=3i!@%m zODM|M%M~gCCHu#iWuov)CYSICJR*#79Ny4`VYd`orU4Ja$Puacq|V6Yh;rsVP)X{P zV6B~iFpFi=(WL+$cXrNqNHkWb!`Ou-rncEYk^XGmSH4+j{ vbtD8nrF@c*O@^t|{w|6;J|2}r brZqLa#m zhG(>&ZDLf8wZ9Ra(*XDGRBiX^+XHBX-1ThAQJ+5lyTbU3-zVZbIyr;n4I~z2FEG%e zDO4a@DB_DXN#Km;xoJV#LT9sYdDgt|`Yh8d({P0h b?5&Qil6zNp&|f_oyJ2oatJ-qqMOFE(&}1gXRP#I zXf1E0wV@l{@%=xjudw>AKyCzAo9l1u9<9{t&yE_mBOr_O@I?LmH5~>P)ii!oT1&xS zr sp7Nu8+*Fwy38r*N`T z!XR>$L~ukSdlBt}pa=W!c@DhD=N04{z$PXJ{l>l$Xf#rh9_ck3;fqa8XgiTa&F*3x z^{&^9FsYn@w~`_YdXBBATtuh8TDVvgbR%{si8F-*hw!buqAP$oFnMS&f!;LKLeH{L zO9o%)H*p=``aa5jHSRCY|I`=1rjkIfzIO&3YIY*UprmLdY@Ha%#?{NFB6)Jf@Z0Lm z$1qUa avc_1T)+xpQhbXS7DJ#G4+PVrdNX9V4_1w@Un20 z5ROw2rNYABdH2GrmE6XZrSYzpKhW};De&pr%M>H^QzpoQJg^|-;Myr1UNIYQANyH& zw!K{OcOO>O0?fffEAa9HSVaa5uXVyA((DTYs9^Rp?`p|@GYBV{xC2r4<=2mVS`gz^ zM#heHwW_2RWZ)wR5FJB#^ik|3`giE}(HXdSm#T$~T1)`m`)&>r2ntbcN0|~cAOo=1 zDwX57j_|6I!mSb(+vA#x6)Lce_BMdiup}j%&=KoR=^nYLM(D#&!oo#R2}r1nf;j^U zwgj>xHdtW8tPGKCGXM76@2l6d|4(*Z@NTsaX}Bk9UF|m;0b53SEr_T2m?FQv7n~#Y z-%SFilv8-EYd`QQs@D7)55+C%!nBul^t5B*fpXkj^eU}TyR3Knb76CYQ1A{xW_od? z{{Ou9M&6^>Hnk*!$l;`^cL@pyg?o^&)+bo(IclEA9l%k3gIl2Vq({s_&?@zy+Bk zFNz+&@Z)<`<@|Ucbi7iL`uLN`DB#`O9dja*Jnv& Z z&sSY%P5s;Si CPf9Xyo?rRAVfUKI^i=5OG63!zlm9gHWA9@L(@@6IPc%6@Ut(Z0COBm^ zo1>^5uXJwx4Ez2`B-FrxA&TZ3hHkS~|L))nmAWy0S6W5okT@4RyVI1bOh9JjaI7Aq zc5ANKPrSDr7H>-@Q_Z0r*-4DRKL}N=WtmJdXBI4p4g!j$AMFN+n^U;~_lr|O57}U$ zJ+C@wK3 BtOzf7iGh`ZKfE_l-}Tm}U` zhCIP}xWId9)s04Lf$b)px3rj2@1%IkxrvDyeM?FluFyhcBxo)O6VYzNTT;(g#mFT2 z^^T7p!UN#Q29^ih$lLM`sxZ!1NgkpWD_*jqO|8>ThG#|A1{mhSnj)sk8%&n_8DT_v zwye>*T7Z>ZipX+_pyPOlMhMLNInC$aURfRAjaHLN-@2hYV;Dd# zlLSp-9I+i^X@RhkDbo28&&4tK*~MFFwzH8974oMd633%O2UX@b;ty-P$W0K~+2Bp% zIu~>+OC;4&?GqH!7o4`%D7ObCjk{tisu{UM;Z#TAp1g% Mh~LFZ6;u} z@g_nE(Q`6V1KFUaQW(}tm_}H~n6{XNNWu3M@|uW9qGp!cokgTDF@ae-u_Jn|#b_p9 zJ|mxBUQg5?s}=ZDGQ}zf@{Z7 Tz3UapznPo8 L;NCSQtep09m7t)OKJ}N0c zWV|gDr5B_XDTCsbrfAStqbVj9o64tx3c>*}`NE|fOk?0v6BodraoS;kPfQVoh$4TN zq@!T@Vw)iUY0b~g?lCQelx;hkU>yqIx5mJK{cZeU{H5<~B8R+1aVZmO0?nt$Rem^Y za*b^XHE7FNHw)wQ>hX(ja^PNYcV7H30grg2Bj0lntO+tO_jwskoJ~AtpFe5t-Lyt; z5MRN>urFVIP id4CU*g=HJ6fSP8neN{G4@2m}2 zXHjs$J;wZ2R^ONpc3}4Tm~?<2FIyb>Hj&Kpn$JqP;0ao?5H`Uoa;smj$%#F@wnX#m zpQCI ^cJN!wCbY|$UYerRjLzwhN?<_3Lh@Gh~Ajo>)3z#X}6hv znFf$bDkRSfIo3n9mqFjQypf&Dr%T;-4Ev_ziV0Xg9(x1aLz!XkSP|U( zR$PX3d}e=bVv#=4cT2Kfc`((Nd?cwLPZID}NyA6cN93^KwToQ;1!fIKYY-aK`kvKE zq-3D$Z&uQMovquJn69=}x6E|~M(y3f3-1=>8$UH|fQSV0xQ3;Y1Vg}o x{rOyGjHl+paxSJpL zM;;-mtVp=YhK&rU*I8sqIFH&v>@Wf@5IPpyV|FLu<0fPeCh*Jf%YAa+$!ZM)k*{Y( zhj$gmV9j^(18!&%DiXP?MyzIoo+uEuz3g1~dI%`FrzOQ3x+#Q|>N3sHKQgYKlkZJj zc+(A9!*w+@mwB^xp^!pnu=wS|{I&8RS=Z~IfT+I0ou27DBv6G~UTNf%D9-GdZS!n@ zhKx~3_0N#5aauQz-bfXJG@s)Jx>^X1&!Y6(XGz`Wt+c3FlXuI#inQs=`>Eb9yG> z%k-j*KdX|johmR0!x390#H)gZb^=ip{Xy(0BqSn4)iXhI3yOErx7K4&IZ>6GQ+y&- zzKV4YD~ZlSV-BP#(yoqFPd~e9&R9TxW&*Qa b>JTlEW58WZYL}rKdW5Ja z4G)9hthL*O=@YBwC9r=S#}C1K7Hv6by$KE${8QrkIk3^FvxFS>oG}6aOi+Xvyjzqt zv_h-QjI?#`M^9f5f8u703QD+=0&ju?!ip)PhtZ?$obfNV=pP#USRrK#UyWfmyL2-Q zW8rok`k>E>S3|12B#|dK^zQ3HAS#FD7}-M+&G(QemDBijkr$fndHOHhoY{8dUex=Oxn3pGCrT3?wJ7!GtF#U>>ioXqji zZEF~GaH~9Q=5 Q zb8g@tCbF0MPhd139WQzBSe@}*J23=a)#^8ggy(crA|HhGQLdt>L7GAict3DQOT4oO zy))mZYSp^;AqX123*Y10B}JMX?odyWzp9B*zSI~v)vBSiMZ2YH1f@G>=n1`Smw4qb z7MJSBH7mP^0Y^1ZdEgs!Ti$JXkun=(K8!gq32PyQiSUJHvsn^>*+4&GLC6-{)oQsk z%PBjNeBDg$v~w4c^!^_B(!fVOmypOT^_n8|DZy(mg|$8JpDqX|T|;GuXsZXNEJs`1 z@!e_D{Pd&<9=e4H6ZE23f;xqXb4z3o!Ws_F!rJ!Vs}qFeE;%_;UiP V(crD>nVO*ZH$-WxZj?( z-XG9lg%GMXpcG@m_gLcg^O+Zc0h!=p4TQf)X~Orw_c(cseEJ# S(c6VKnGQ8dJgZXrXijbvGK13TSkji-?e;0EOO3(;gCbu!t06 zN+&Ucf@ye$n?0h65?U}3P2=^UZSU*D%)XXkAWQ-MF6UvRNjR`#z5>_dxXS_(b1wt8 z3BA4Loer#U=AD@*X^a%qjMp8*3W_z6oO;L(MmuIhg}<^@2Kpt(1$bw*)=HI&ZO#X) z4}ep5&47==$E6XHF!on@HDXk=U0LmpNWNSJ#oG4k7ua%NvyD)O5@kUauIma$uTgDC z2<)h@sUoE{&kJnhxR-AujEsY}Rdv&o%FQ-1b3vA#kMmbI7Z3$`EOIVH@}hCM5PeOE zVLF)>(I^&u( 8590YNb$>t4r#t%EN4^D}pEqv=GT$29CdL zcRq^X+P%r74Z?eb_W`gBixvc3@kG6VHfWZ#Ca?908#}~FGmG262XtN}HJGO__a6vS za@H}c)BLi=+Il=d8#owDnppf`Sy8L$QNc50JgXHgfwxLOztmyjEuM!vY25CP&W9jN z&()l%?>CIq){h{hnHFzCt8joTp^xy}v%+`J@Qojwf>G{lPs^Z}uB1Q+n+?YbbkTR4 z*wRM1W6rBV(EsD1YAi{_@4{F_hsLHmR1h$`s~%v~iU4CM7i5rH& L3?PFh76D4p)CR8Iow> zUZMmn*b|sffjfcz6|>kNk4K*zl!DJD8DJ%*bR1GK2bVd30HTd?X}mX9L^V>siRN}$ zN|J%)-5AaKD$Jx%;1`k-X+g_U%FOdbaj#ayEnvgZJR2rD#Ui9XEll)M+|MPN{8L6r z<|CBc+y{jdtclv>YE-K`{6v#Sa1-s4N5|mB69g;&pJ$RkT#8K}KJn#CP^AOp2Vgax z=7TE4JbbegegJ-8K1J*QW7>8UfwB1yLm;0Z7hvoE9WGf>EW^V8fv9>X=`!*O#sccr zuMUMek>^vZp0Rpu(e!#LT2338E~U2Gv1VNPEp}tBK8{-4PQ=(oCw;N%`x1^>ok+*C zQh=EJkrMsZ`yG0Svn`qs`s1=uD G47=QAHfvZwH!Y8vDn zMFkWJb%^j$MbeT2q)GvFZmOoDD5hE`YA9Mcj2_)oOU=l3AuXaHMYQonnNdS7*fXac z3#y3B;BJ)f?sybr1mR1Uemr_i;QpnxRR)r3IaG5*ED~45OEnFXjKq3V+9KDPu^UC( zt1=u7#1Zkx9+8RgeH2|4hA=XA9r%tyUwV`a7aCt0bIrKUbPR4tN~dnTMLggZ*1`K^ z fN=EBQGw6aFG?j+#*`ilfKdP+Xx_ }}n3 zAyyjNnU(g=tR-~KYs)Op+Xy8hE0E-;P3Q6I!{8k5cEsVXK?5u%)O_u4d2w+_m!qem z$71h^08$PrLQgY7!eEB(jx^QJRvxf`$cZEm)~LK@^Y2LEa B>#CmWlvitfxu?~y z@rtS-^5^Bx*_tnzf8A<|(4s*mRf-9s6D@8iH;z{XL9~UzQ#{-9WQ2Mk6r}=iF>EDm zx}$>XXjwt|FltKvi4#q7A_^&ugu89m9y766Y};VtO&XU)D_ivx*CgTr!MSOS@Fa0g zFPWfQ9je-}Y%7J+=ZJxbtbrgJJ3?y&kDI%a%yXQ?JmHaO4Rm-cbW+DM>L5pLZtHXe zhG4952+0()P`@g=q-@V{5C#i3achzltrtfX4(veBu@CW}oBF5b+d>OR5cn*F(5e$) ztbA)1^q3hOg=6Dgorfo6kj+MJ@Fmgo;G>8Xn@J-r&(F5a4Ih-Oz~+HPI3Exl5y_i) z0=E9y-{ph&hI3x_yl4tHbh17C@!4B<;^`7k5!j<(HGhVgEP;yCJr1$pG#ZqcZLd(5 z>uaTwxW5Lc)pz?4NJJJf4Bqtg&Qq+~&!$)#c#*CYUi(witccJ6Do15hAwn3_I- sVO83r*ygM&5_UbqoyW+0Yx;P`sa?a1TKgztF9RCu{eOXyPoBe<*DfINF?ebo< zx2u<+#)8{5h9M6lNdNWpue{s%AL)ZeqgAa<(I`VJQ#9rE +L5t3bw9svD;qT}EBhJ|mVElj+uy?ws^ikCb;4LuiQ8(T?}7qd(OhXwFR#|s$wGh5Tu z=pU8qSjT}Xo| tM910o>f5_~sa8_=p#R @a$S{Y+ZTQRLdt@26 `j+N0qFxrosaQ*`-yT$yK`UJu3-$?Tvlha&;c&p34}aFaC)v%V>IS`U zV){bV^! HWO=>Fai #`MhkH5XT!tO6xKpf$pP__F$nWV?5_PU>OtiU3nzxq}AF zBEIp5L2D2M6s2qD&erDoD>jQfN{Pzx?nh6O4?|O6aGHRW_k0vH;ki}{96Wn?a(KAs zj_>7q1^{Ofz`DcH&Q-rJ*b?`=znHn!yHMg(O>^UV^uq>bCdqhYa_yjZ`^_tJVcbKo z%CAlr#pe%TO6Fk<;(O7}>;Kv6Q>%ce;#2%27r(}_)X^NQ29|{X;3g|w#w0y4o17|g z=W*UIB47RT@xqTW_h=u-&(W~Nsvigg??Cu)K&DMO zfCX6g`_G!oEDlF0 #Dupwg!V}#5EgsH0kH8hT+y*S6 z@_%)SKIPns>f0k)m0J1XIVK!bX?@4u3gp(i;2+&Mf8q=cqIB@}x;{j9IJuE@#cE}N za) gr@<2S$ie_Yq@T-g9TY@hA=BY%f2nYxPYoB0FSh~wt{Jx$w6z4#NV|oUr6P3 zwn{$eE?fSh)=QW6nSqF?o1SCR_uahLTo>|&1YUHnHu7)R5fiPV#=%bZ*X3Q+)DopN z>Uaf;Mf7p0pc2-#I6_yu%`+j_7LmVn*WHzbD^ng1-?~-fdP8G5O`gga=7(!um4+Dz zezrkhec=h0)4(wiT)7C?g}m>)?{S_Af$nX&zK?^8i##Y22>~K&5DP*82{1v$so3e` z)&J>n&^s@c+DnU}5VFw>e)F !ALRCY`&0G$IT`feC})(( N5oVTyVe+}o?$Hw7XcI(*k~t0Cld(JqIb0us$`BRv4vUlEuuMwk zLP`x%^j+=Kd3#x8LmetF2(05Td>h}LF7}GWFR> Iw+U$a^nTR>d<0wwHyj+E*F->?;?#970fTcX_sa@uH0u z*)q=&M~ ^#+3psVZIyL{j^$E%`S%F(<`oo(OPB`mw r@L>whgOZoXugJ+f&w70m?UiIPcxxiDP;2NjkSdXs zQfSb=)bmyivd7soHy4Ag*r0JL+io_yadzXy;QzmOR|`)g-v^SnQHitJe@8D|oS*-> z>a*i7B0uyuP4C!q;D5h&{F!*b6nz792jlE)I2`3xacFH&So>e-e?5J6)~C;W xYedq=>_<;y`3MLihg&7d(01bXvo(=!*JyGppXEWWFRd;<;aM^I7j(DYI- zQSV!?cc?lG9_Z$z;p(@Ge|y{dw;}75f`5FzT5YxZfuFp=9ewZm{8ZBEnfdu5**nvI zSxOU)G%-#xBc(_Zt?ftgj!YPDSM2idllFZh-wIke{W+JeT^R{jIp)d4FSv97%C zof2#{SxyzYW`MGx;tz+8n!u^1$NP PCem!-{gAqM|mNJ74|Vv+qSe- zIUifQ%UQ)M;$x+yJ?~YetIqq>y{D(^Jq(|Te}>$~+-=yf!$tp4m0wG$ERwY Bt3TMO>p3v4R z#b@K%dG_i 9m z0 Phkxvy@b{gO3d+xq&>tKA 1YyHq1uOCO`0lm5>7()Bb2x3VE{-c1@D%l9wh>l*s8V;KshU zD-^Tcz4NG#)6{Lc7S5UR7cCx;-m2Q-Y?)sx+K+d9(EJkemNxe5%6YxU@MLm!Ptgao z!$D1GxHAYTdQ5c_VvCmR;JlR4P!cCirJ~7x9oVZ942J?#ktGGWrzn-7rfs-;ar&fn zQl6SqPWqy(a4*`?_OA0NOKu@6DE-#*#&h`l`!E&P<-qMb+rWW3ib$`2<=}tm#)hB* z|9AAQ-Hjjr9m7Bf8`-n_1icheT5wkA4bcLxI|!p%A`^-t&kyY?noat7G+Ac=W#S$E zZ{ih>VaO)7>wJ`1G7N^QR-TFNY?UTmJ28p*h(L%~_i d~i?mb@0wO6pQ#>TV*v?*~YC4TFO# z7M gC=i1iC4H>u9^j&0h3Ye; zlxMb6NvXY-P#X* yF7@d60K$HuT4iGX#t8V!%_JRG`ESOB**?YCQy7H>N znZ8ymYcujgFKgb}dIj?-WC2-!`O)rIpB!!gNo0o@)omb)fSX>e64GhxQszR$sIdr2 z<*7Wv(U_a_2G09LDGSxQhJJQ(*6J|)VLmzecggy18cwQKQ`%oTTjFUk=S^Y}KV;LT z1x?gB0Q4XLxK0LhlU#(05qFZg<2{2ZcE!OGc^4QyjMjKEDUv*Oxcd6w>^uFg!y0zV zY%_-RY^{j&VaB_k`yta^o|g9$@v?k?1*4tISrk zW^UPg2LoCIBW^4s(R-0Kf?$K*rH(prV)2)wwJ{D;=u$o{Depu@z>ZI`HS;V)Y#E`x zD~bF**6Dk?ysPf}vPD32$Ud=EJVKfCk@agSdT}=iRUY3d3QwJrjIM>5a?>z2g)Vos z&dnRae2!>0msTpyValZdN^ultxe)BX>hC`iFIlAayph48pN4RJxSaEPxYubP$*y?F zDtg#+%g2fWddG2(IV{5+zwf;3bzS!{V+-4(zqV~XbXW)0`L+%Rk*IuXdA3R|+Mf0# z2B)>TKiK_BSU))f`-&3 i`wx