From f8c3659f6a329498b7aea5ff7f4b67ae1ef727df Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Wed, 26 Mar 2025 09:19:02 +0100 Subject: [PATCH 1/6] support creating the checksums file --- .gitignore | 3 +++ Makefile | 7 +++++-- contrib/checksums.sh | 9 +++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100755 contrib/checksums.sh diff --git a/.gitignore b/.gitignore index cf89f870..8abdc284 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,8 @@ # html files (as generated from markdown) *.html +# checksums file as used by $ScriptInstallUpdate +checksums.json + # Mac OS X folder settings file .DS_Store diff --git a/Makefile b/Makefile index d21713c2..89517410 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ WIFI = $(wildcard *.wifi.rsc) MARKDOWN = $(wildcard *.md doc/*.md doc/mod/*.md) HTML = $(MARKDOWN:.md=.html) -all: $(CAPSMAN) $(LOCAL) $(WIFI) $(HTML) +all: $(CAPSMAN) $(LOCAL) $(WIFI) $(HTML) checksums.json %.html: %.md Makefile markdown $< | sed 's/href="\([-_\./[:alnum:]]*\)\.md"/href="\1.html"/g' > $@ @@ -32,5 +32,8 @@ all: $(CAPSMAN) $(LOCAL) $(WIFI) $(HTML) -e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \ < $< > $@ +checksums.json: contrib/checksums.sh *.rsc */*.rsc + contrib/checksums.sh + clean: - rm -f $(HTML) + rm -f $(HTML) checksums.json diff --git a/contrib/checksums.sh b/contrib/checksums.sh new file mode 100755 index 00000000..b472b49f --- /dev/null +++ b/contrib/checksums.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# generate a checksums file as used by $ScriptInstallUpdate + +set -e + +md5sum $(find -name '*.rsc' | sort) | \ + sed -e "s| \./||" -e 's|.rsc$||' | \ + jq --raw-input --null-input '[ inputs | split (" ") | { (.[1]): (.[0]) }] | add' > 'checksums.json' From 690951469291ae96ead1f88226be78ec7735d098 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 20 Mar 2025 09:48:01 +0100 Subject: [PATCH 2/6] check-routeros-update: send certificate warning just once... ... and another one once expired. --- check-routeros-update.rsc | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/check-routeros-update.rsc b/check-routeros-update.rsc index 78161e4b..51df175d 100644 --- a/check-routeros-update.rsc +++ b/check-routeros-update.rsc @@ -22,6 +22,7 @@ :global SafeUpdateNeighborIdentity; :global SafeUpdatePatch; :global SafeUpdateUrl; + :global SentCertificateNotification; :global SentRouterosUpdateNotification; :global DeviceInfo; @@ -70,20 +71,26 @@ :if ([ :typeof ($License->"deadline-at") ] = "str") do={ :if ([ :len ($License->"next-renewal-at") ] = 0 && ($License->"limited-upgrades") = true) do={ $LogPrint warning $ScriptName ("Your license expired on " . ($License->"deadline-at") . "!"); - $SendNotification2 ({ origin=$ScriptName; \ - subject=([ $SymbolForNotification "warning-sign" ] . "License expired!"); \ - message=("Your license expired on " . ($License->"deadline-at") . \ - ", can no longer update RouterOS on " . $Identity . "...") }); + :if ($SentCertificateNotification != "expired") do={ + $SendNotification2 ({ origin=$ScriptName; \ + subject=([ $SymbolForNotification "warning-sign" ] . "License expired!"); \ + message=("Your license expired on " . ($License->"deadline-at") . \ + ", can no longer update RouterOS on " . $Identity . "...") }); + :set SentCertificateNotification "expired"; + } :set ExitOK true; :error false; } :if ([ :totime ($License->"deadline-at") ] - 3w < [ :timestamp ]) do={ $LogPrint warning $ScriptName ("Your license will expire on " . ($License->"deadline-at") . "!"); - $SendNotification2 ({ origin=$ScriptName; \ - subject=([ $SymbolForNotification "warning-sign" ] . "License about to expire!"); \ - message=("Your license failed to renew and is about to expire on " . \ - ($License->"deadline-at") . " on " . $Identity . "...") }); + :if ($SentCertificateNotification != "warning") do={ + $SendNotification2 ({ origin=$ScriptName; \ + subject=([ $SymbolForNotification "warning-sign" ] . "License about to expire!"); \ + message=("Your license failed to renew and is about to expire on " . \ + ($License->"deadline-at") . " on " . $Identity . "...") }); + :set SentCertificateNotification "warning"; + } } } From 16c9ce437ef268780303f627bba08a166e2aef05 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Mon, 24 Mar 2025 21:14:12 +0100 Subject: [PATCH 3/6] check-routeros-update: send notification on renewed license... ... when a warning has been sent before. --- check-routeros-update.rsc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/check-routeros-update.rsc b/check-routeros-update.rsc index 51df175d..1a5a930f 100644 --- a/check-routeros-update.rsc +++ b/check-routeros-update.rsc @@ -92,6 +92,16 @@ :set SentCertificateNotification "warning"; } } + + :if ([ :typeof $SentCertificateNotification ] = "str" && \ + [ :totime ($License->"deadline-at") ] - 4w > [ :timestamp ]) do={ + $LogPrint info $ScriptName ("Your license was successfully renewed."); + $SendNotification2 ({ origin=$ScriptName; \ + subject=([ $SymbolForNotification "white-heavy-check-mark" ] . "License renewed"); \ + message=("Your license was successfully renewed on " . $Identity . \ + ". It is now valid until " . ($License->"deadline-at") . ".") }); + :set SentCertificateNotification; + } } $LogPrint debug $ScriptName ("Checking for updates..."); From 3c30276e235b6c8105f44db49ba6586d296f264c Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Tue, 25 Mar 2025 17:54:09 +0100 Subject: [PATCH 4/6] check-routeros-update: split off check-perpetual-license... ... and also add documentation, screenshot, etc. --- README.md | 1 + check-perpetual-license.rsc | 78 ++++++++++++++++++ check-routeros-update.rsc | 38 --------- .../notification.avif | Bin 0 -> 4004 bytes doc/check-perpetual-license.md | 70 ++++++++++++++++ doc/check-routeros-update.md | 1 + global-functions.rsc | 2 +- news-and-changes.rsc | 1 + 8 files changed, 152 insertions(+), 39 deletions(-) create mode 100644 check-perpetual-license.rsc create mode 100644 doc/check-perpetual-license.d/notification.avif create mode 100644 doc/check-perpetual-license.md diff --git a/README.md b/README.md index fae69869..ffbc27ed 100644 --- a/README.md +++ b/README.md @@ -225,6 +225,7 @@ Available scripts * [Renew certificates and notify on expiration](doc/check-certificates.md) * [Notify about health state](doc/check-health.md) * [Notify on LTE firmware upgrade](doc/check-lte-firmware-upgrade.md) +* [Check perpetual license on CHR](doc/check-perpetual-license.md) * [Notify on RouterOS update](doc/check-routeros-update.md) * [Collect MAC addresses in wireless access list](doc/collect-wireless-mac.md) * [Use wireless network with daily psk](doc/daily-psk.md) diff --git a/check-perpetual-license.rsc b/check-perpetual-license.rsc new file mode 100644 index 00000000..9a3a3c74 --- /dev/null +++ b/check-perpetual-license.rsc @@ -0,0 +1,78 @@ +#!rsc by RouterOS +# RouterOS script: check-perpetual-license +# Copyright (c) 2025 Christian Hesse +# https://rsc.eworm.de/COPYING.md +# +# requires RouterOS, version=7.15 +# +# check perpetual license on CHR +# https://rsc.eworm.de/doc/check-perpetual-license.md + +:global GlobalFunctionsReady; +:while ($GlobalFunctionsReady != true) do={ :delay 500ms; } + +:local ExitOK false; +:do { + :local ScriptName [ :jobname ]; + + :global Identity; + :global SentCertificateNotification; + + :global LogPrint; + :global ScriptLock; + :global SendNotification2; + :global SymbolForNotification; + :global WaitFullyConnected; + + :if ([ $ScriptLock $ScriptName ] = false) do={ + :set ExitOK true; + :error false; + } + + $WaitFullyConnected; + + :local License [ /system/license/get ]; + :if ([ :typeof ($License->"deadline-at") ] != "str") do={ + $LogPrint info $ScriptName ("This device does not have a perpetual license."); + :set ExitOK true; + :error true; + } + + :if ([ :len ($License->"next-renewal-at") ] = 0 && ($License->"limited-upgrades") = true) do={ + $LogPrint warning $ScriptName ("Your license expired on " . ($License->"deadline-at") . "!"); + :if ($SentCertificateNotification != "expired") do={ + $SendNotification2 ({ origin=$ScriptName; \ + subject=([ $SymbolForNotification "warning-sign" ] . "License expired!"); \ + message=("Your license expired on " . ($License->"deadline-at") . \ + ", can no longer update RouterOS on " . $Identity . "...") }); + :set SentCertificateNotification "expired"; + } + :set ExitOK true; + :error true; + } + + :if ([ :totime ($License->"deadline-at") ] - 3w < [ :timestamp ]) do={ + $LogPrint warning $ScriptName ("Your license will expire on " . ($License->"deadline-at") . "!"); + :if ($SentCertificateNotification != "warning") do={ + $SendNotification2 ({ origin=$ScriptName; \ + subject=([ $SymbolForNotification "warning-sign" ] . "License about to expire!"); \ + message=("Your license failed to renew and is about to expire on " . \ + ($License->"deadline-at") . " on " . $Identity . "...") }); + :set SentCertificateNotification "warning"; + } + :set ExitOK true; + :error true; + } + + :if ([ :typeof $SentCertificateNotification ] = "str" && \ + [ :totime ($License->"deadline-at") ] - 4w > [ :timestamp ]) do={ + $LogPrint info $ScriptName ("Your license was successfully renewed."); + $SendNotification2 ({ origin=$ScriptName; \ + subject=([ $SymbolForNotification "white-heavy-check-mark" ] . "License renewed"); \ + message=("Your license was successfully renewed on " . $Identity . \ + ". It is now valid until " . ($License->"deadline-at") . ".") }); + :set SentCertificateNotification; + } +} on-error={ + :global ExitError; $ExitError $ExitOK [ :jobname ]; +} diff --git a/check-routeros-update.rsc b/check-routeros-update.rsc index 1a5a930f..361be34e 100644 --- a/check-routeros-update.rsc +++ b/check-routeros-update.rsc @@ -22,7 +22,6 @@ :global SafeUpdateNeighborIdentity; :global SafeUpdatePatch; :global SafeUpdateUrl; - :global SentCertificateNotification; :global SentRouterosUpdateNotification; :global DeviceInfo; @@ -67,43 +66,6 @@ :error "A reboot for update is already scheduled."; } - :local License [ /system/license/get ]; - :if ([ :typeof ($License->"deadline-at") ] = "str") do={ - :if ([ :len ($License->"next-renewal-at") ] = 0 && ($License->"limited-upgrades") = true) do={ - $LogPrint warning $ScriptName ("Your license expired on " . ($License->"deadline-at") . "!"); - :if ($SentCertificateNotification != "expired") do={ - $SendNotification2 ({ origin=$ScriptName; \ - subject=([ $SymbolForNotification "warning-sign" ] . "License expired!"); \ - message=("Your license expired on " . ($License->"deadline-at") . \ - ", can no longer update RouterOS on " . $Identity . "...") }); - :set SentCertificateNotification "expired"; - } - :set ExitOK true; - :error false; - } - - :if ([ :totime ($License->"deadline-at") ] - 3w < [ :timestamp ]) do={ - $LogPrint warning $ScriptName ("Your license will expire on " . ($License->"deadline-at") . "!"); - :if ($SentCertificateNotification != "warning") do={ - $SendNotification2 ({ origin=$ScriptName; \ - subject=([ $SymbolForNotification "warning-sign" ] . "License about to expire!"); \ - message=("Your license failed to renew and is about to expire on " . \ - ($License->"deadline-at") . " on " . $Identity . "...") }); - :set SentCertificateNotification "warning"; - } - } - - :if ([ :typeof $SentCertificateNotification ] = "str" && \ - [ :totime ($License->"deadline-at") ] - 4w > [ :timestamp ]) do={ - $LogPrint info $ScriptName ("Your license was successfully renewed."); - $SendNotification2 ({ origin=$ScriptName; \ - subject=([ $SymbolForNotification "white-heavy-check-mark" ] . "License renewed"); \ - message=("Your license was successfully renewed on " . $Identity . \ - ". It is now valid until " . ($License->"deadline-at") . ".") }); - :set SentCertificateNotification; - } - } - $LogPrint debug $ScriptName ("Checking for updates..."); /system/package/update/check-for-updates without-paging as-value; :local Update [ /system/package/update/get ]; diff --git a/doc/check-perpetual-license.d/notification.avif b/doc/check-perpetual-license.d/notification.avif new file mode 100644 index 0000000000000000000000000000000000000000..70ca603d4488773dd8a476ced8c89506407b95ef GIT binary patch literal 4004 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 literal 0 HcmV?d00001 diff --git a/doc/check-perpetual-license.md b/doc/check-perpetual-license.md new file mode 100644 index 00000000..d4440045 --- /dev/null +++ b/doc/check-perpetual-license.md @@ -0,0 +1,70 @@ +Check perpetual license on CHR +============================== + +[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers) +[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network) +[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers) +[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.15-yellow?style=flat)](https://mikrotik.com/download/changelogs/) +[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts) +[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J) + +[⬅️ Go back to main README](../README.md) + +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. + +Description +----------- + +On *Cloud Hosted Router* (*CHR*) the licensing is perpetual: Buy once, use +forever - but it needs regular renewal. This script checks licensing state +and sends a notification to warn before expiration. + +### Sample notification + +![check-perpetual-license notification](check-perpetual-license.d/notification.avif) + +Requirements and installation +----------------------------- + +Just install the script: + + $ScriptInstallUpdate check-perpetual-license; + +And add a scheduler for automatic update notification: + + /system/scheduler/add interval=1d name=check-perpetual-license on-event="/system/script/run check-perpetual-license;" start-time=startup; + +Configuration +------------- + +No extra configuration is required for this script, but notification +settings are required for +[e-mail](mod/notification-email.md), +[matrix](mod/notification-matrix.md), +[ntfy](mod/notification-ntfy.md) and/or +[telegram](mod/notification-telegram.md). + +Usage and invocation +-------------------- + +Be notified when run from scheduler or run it manually: + + /system/script/run check-perpetual-license; + +Tips & Tricks +------------- + +The script checks for full connectivity before acting, so scheduling at +startup is perfectly valid: + + /system/scheduler/add name=check-perpetual-license@startup on-event="/system/script/run check-perpetual-license;" start-time=startup; + +See also +-------- + +* [Notify on RouterOS update](check-routeros-update.md) + +--- +[⬅️ Go back to main README](../README.md) +[⬆️ Go back to top](#top) diff --git a/doc/check-routeros-update.md b/doc/check-routeros-update.md index 926b4aaa..b6c716cb 100644 --- a/doc/check-routeros-update.md +++ b/doc/check-routeros-update.md @@ -99,6 +99,7 @@ startup is perfectly valid: See also -------- +* [Check perpetual license on CHR](check-perpetual-license.md) * [Automatically upgrade firmware and reboot](firmware-upgrade-reboot.md) * [Manage system update](packages-update.md) diff --git a/global-functions.rsc b/global-functions.rsc index 8ae7bb8e..8ade79bf 100644 --- a/global-functions.rsc +++ b/global-functions.rsc @@ -15,7 +15,7 @@ # Git commit id & info, expected configuration version :global CommitId "unknown"; :global CommitInfo "unknown"; -:global ExpectedConfigVersion 135; +:global ExpectedConfigVersion 136; # global variables not to be changed by user :global GlobalFunctionsReady false; diff --git a/news-and-changes.rsc b/news-and-changes.rsc index 459326f3..55b41650 100644 --- a/news-and-changes.rsc +++ b/news-and-changes.rsc @@ -60,6 +60,7 @@ 133="Updated the default configuration for 'fw-addr-lists', deprecated lists were removed, a collective list was added."; 134="Enhanced 'mod/notification-telegram' and 'telegram-chat' to support topics in groups."; 135="Introduced helper function '\$GetTelegramChatId' for 'mod/notification-telegram' which helps retrieve information."; + 136="Introduced script 'check-perpetual-license' to check for license state on CHR."; }; # Migration steps to be applied on script updates From cdfb086b490cafd685e947433515e43dc5547a62 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Mon, 31 Mar 2025 11:19:23 +0200 Subject: [PATCH 5/6] mod/notification-telegram: fix override quirk IDs for chat and thread can be overridden. Overriding the chat probably makes the thread invalid - so ignore that then. --- mod/notification-telegram.rsc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mod/notification-telegram.rsc b/mod/notification-telegram.rsc index 68e913f6..5ef353b4 100644 --- a/mod/notification-telegram.rsc +++ b/mod/notification-telegram.rsc @@ -151,7 +151,8 @@ :local ChatId [ $EitherOr ($Notification->"chatid") \ [ $EitherOr ($TelegramChatIdOverride->($Notification->"origin")) $TelegramChatId ] ]; :local ThreadId [ $EitherOr ($Notification->"threadid") \ - [ $EitherOr ($TelegramThreadIdOverride->($Notification->"origin")) $TelegramThreadId ] ]; + [ $EitherOr ($TelegramThreadIdOverride->($Notification->"origin")) \ + [ $IfThenElse ([ :len ($TelegramChatIdOverride->($Notification->"origin")) ] = 0) $TelegramThreadId ] ] ]; :local TokenId [ $EitherOr ($TelegramTokenIdOverride->($Notification->"origin")) $TelegramTokenId ]; :if ([ :len $TokenId ] = 0 || [ :len $ChatId ] = 0) do={ From b560ea4b7d3da75b5f54633eea6a5fb7472d5bd6 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Mon, 31 Mar 2025 14:30:56 +0200 Subject: [PATCH 6/6] logo: strip some bytes... ... by just re-compressing/re-encoding. --- logo.avif | Bin 2001 -> 1744 bytes logo.png | Bin 4428 -> 4406 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/logo.avif b/logo.avif index 399a2f5ad184fabd7e8127b1e2f1bd994ac7a6b4..956fea8a115623093ec4aef204d69a1a29b53db4 100644 GIT binary patch delta 843 zcmV-R1GN0n56}&eBMpXaWprTx00000001G8FdUInClmsK000C}00IC2009610j>Z5 z0MoIKApw5{Ds5z8bP@mx1{fKy-(gTP#sNfR0frRY%c{{n{hP|N?3Uaqj0L}}@qNfO zUB2aZ8Kr1U{|(j(T$tyh0vOM1q|wTT0X(pK|2Cc9mV0U>am(|lq5{?-y_i?Zr%fu$ zhCDQU=SG}pl+0lejjhL_%w5(HDH(E*okS>|c<+C}P|5$Cf3i?w@OMvy-89`L;#}oM z#2YLk@1}eq#BCuEpbjI5&bIPhY)ZN!fIW7@!JRM9tZSY=8tl(Zn50AhCeIn}bsHqt zVjhC`$G`d1oc$}4gYH%lC=vh)2{;+A-(dj_29Pqp2t;H6VTKq`-8AXdR-Lqe?ll_b zFZZ*n0~`W>ozo$$2fsVSgxpZ#`gr)>n>xw_(#K$B*CM4aHkwEn#JzNubEuV$7=|bA z+ROhT#2ittG2`z=D|OK4zz~ip#0=ynf)@69qgTUtc0+U0uVpYVnm_j8zn0 zJjAjZ9#{~&B=BfFlV5^?`+Bg~S3lvt=dZ1bMkPXj%M`I5p6v2f7J3b@(m+zN6G0CG z{>v?H18V1~@QQG}uh>+c4cY33da3fQ@firsI+uS(o8t{=MtAATH=Lm)TuQAPYya;@v3#M7IYcTEH*jc21m6D)sW-ivCX~$+cSN*r2BpR|Tb22mj|3DNH zT_*pR4q1Qq{z@4w3$5CBwN)%tU^mL(%3q*e9|R8b<56wQ^9`(%3tH$y{UL2-whDf z+PTBdBt(eDqSo^hFgbp(q)#zr2WYWtTbv|w_sz`3(xK`HZ^Wld@#0fDAk(E3KqjJV zz@p4**S2B5Axq>5d?~(DcWcfn@0Gs-wjg(jH~rSuRt;kgdOR8IFNG#knQ0V1TZ3~i z{TlO|tkVnTj)H$$Qb#lavhGSviyk4IJ-g^UwjH~xR7&7SpHW^fe`YmIBX?2Aqr zu8_1h^hG$GGy=y`3LIlI`rBGbwh2kd13ji1;2ei$0-$M4jMe@bt5xL|t${H^4RE-Q zpG%uN7Z!`MfEbi_9^@tGJyxq8x;(wr1VJtc5nJr#OzwsX=}tN(;LpDRJjy5|ddREv zd?KC`i%f&ZEB@53j3wi zl_RoNS*Raoq@rbLZm4~lEaA3srZ@-8A(nYyxW!PEbvL)zS>NC;=@2O@pkAzFEw>>R z#!t2z-sGcGhBZRmWj9_an-~xQN%q|fOQuJ>IA2Jewfl0ctt7)TkciXY5*Z#$ zk8~jc#NV#gn;>c9ZkhO(Xx%U9!h%ElLo)Jw;CDbsZYyeFmmdxIYAGz#837LAKx{w{ z0=K5F+bLRn>s#zg)nWKKMmn}bcWI!ZYkBtH^BNq zrrSDz_1XfK{W_rx^Krge(1;-v#Q@xCU9FIF>7gC9{6qS+MHKcIz<(aA&ha=2IZ8F9 z#8QUWD}S?cFpN9SU5-vgikk;H8#n@Tx5!|`458gpN4b2BUT#>w7= z0CWfOO%ucw+c?ki!hG2fhgu3_1Qnfq#WPK_7b_d|_7AftXk0qc zYNiQDrFZq9_kZ@#=~`%9@4ls-Dt-YZ>XTWJLq|SqWe(SR-hI>BfoA9!n*Y(DvhMy1 diff --git a/logo.png b/logo.png index d97b75dc7d39e2c9e6ff6339d47711e97d6be1f0..7bec10e5242bbc518dc3d730c44425295b283433 100644 GIT binary patch delta 4394 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 delta 4397 zcmV+|5z_9qBFrL?HGdHSNklHF4jUn7GCSMOh3p^DPfbf~m2wQ8sPbB-z>7 zzTUifv%G!#R-zzc_OsQO_OC^dbv;6HygP&|SnFx#E zE?l@!mM>o}D^{!+^2(Jfhuq%YE^b}EeAy0WT3VXz)vH(AUbAM6?OnTeiCdkWom>+Z z0ROYPx>};Fzbq#WH~8OJZjdPG*|TRdfBt+~wrm*?G=C5qH*OS@PM$mo08a=94jd4Z z)~;O}76A8bYHE@ghz0%KaBBWLiIT2dxgtxJECB%4Kv0uS+PinJtXj1S8$p~sdsa+J zPfrgEfO~XwbV!U;>f00Sh8snlI(3Sg>sSM^Z{I#Ki8`N>l469w>-Fo`#UvW+x^?S( z0gyq1gMTrdG4i~EpAzM1hm}kQU?T_snY3ZU1^{3U#Nx$^<@xjHV$!y4+W_DTfh>u! zh;f=b_@BjM&S!!lU>FE03|_BZy((_CwY8BQPLtLk0Is3I*s>^T^a1P%fl)OMD$#ei zF%VyP(V|5F&_K+aH&32EeJXCfdGkgVELh-7OMe;&%20oQzZk@HM2S%$XduXvI4NBP z@I)f4!oor(9<|gkf&u`$L1@#F)0laW&#DuX3W4_>7~KEWt5@PEH#Zjmz7WWgIH^EA zSnHJttDvAjX3d(#>QzmU9GgIBJ;E?8VPi?+o-bd%RC|syu6jZsOX8#+%M$?by=aOU z0Do4trdf@gz$FBQP~^XKUez7WWgIH~~v|9?po#1Ze|!-wVg@#B~Pd4iZTXO4ZMdE&&0 z54?Z>ey#LehKv7YVOq({1)eHa)1c5Q>^y$-DZ%`rZ*|SIdbpQT+N|m}_ z&>)Z{!IVG%Zrr%RL<9h=f!MNTix|X+NOpKOXzIU@INIQP02m?gdh_N@38X{bwb+11r0E>V`8Dap8bW9K{^QECV@zbiU)=n%VQyCgc#8G`>J zVw3{l2qG^p&#`^jHEGf$Ab&VkK@c3S)68h9jH_BE@DrB1ckkNH&(D{EfdMgyV-T9L zu|FI;cFcw!OrsRQxpU`+0zGx=RLuquYFW}6v<5*hM@%#H1K*wag$oy0@%%rY1JieG zXn{4_0jNQrGGz+ZKtu?FCjk1-ty{Nb{P^(_3WYQSuei8a0x3}d5Px`=BLP9}2b3`Y zXvg7`Cr>8OVa;>l`uchqkrE96!EmgB2oC`OUJz6OjIV6qv>;C$Ge&+GH%@+;FhO$1 zj+M{<=iY2~lZc`?9x5#Zqk(>x(iYg5n7GzAaA8E2!h$s}Tp5ikAYn-~Du%?6xIyBk z_=Tm`?~hjN0#@(_4Sx^76CBS!R$x{v=s``HiOw=2w!Gr>D&A~0m854WqQsaF3rpwfso7P$kE&i0PO*s34-G= zE=1ML0<;3qixHRSa28Ym*oLBXI!*YUIJ%z2Vv$6^D3AIlQ&aTD@27VxZrd;j5I%AU z`VBN{&$HkIhntRR(#|*(sk2~jb(Q|Et1ljo2512w3<-d=0-#>6lY_Y*0P1Uq zXoVnNC=_(fJ3OZYAgu*0fX9Xb!4do6BEBSI?F>kprndm#?4<}PAjFY`8;yot632ZV z03>d_|9>?Rz|+I32cnDc82J!ilCYWsyg37KWE`T1fGP+9(C_!jYOPia`9TLjj-pHi z@a(YKf#7fv9wT4GSF0dN!rlUaKD!8qPYVdN5NzMgDwoT;%^Nt5qBsJmvET?X5L(RAozVg zx`nD|9OK1R;SqLT@cqkyfOlFEr)g-$nMx@MkML^v0muKnvEXoon=OWL-88MuIBeRS z?SE#R&br+$VV@VL+0ZeqR4OzW49LmwmSnr#Caf8-y@(UjSm0qh5!b5Ks@luP8Ud%C zkF}#O@`CIUC*DmK{&plnAqJz~Hw@!{dw1|6#Sw)8{F)p?t|9+N$T=Z+%^@IyA|AYX z^{(i}n|!MZSyhu_a5YNa*$TUc6L2|0FE#+?-i1a40a`hO`B zVueg1napX|P8LO-+L*1g3XLF1jf>?8kil&EFS(g+kS1*qAdeqEE)mOt-X~@cq-emq zeED*zL{t228K&bGEeZQ3YKy=KzMg*N|L zoB%gTHxdyy@!`XV{sssQK>s1b+JC`7n3NC{?Ez0WZv1dxHeVp&?c2A7d2#PTAm`4V zD^H$00akhoK&Nd6Y^S>WA6MBNXi)-2NsxQPCTGhK1xQVVR(*7IG;||}ppF3^?QVZ^ zjXQVllo8Qm0q&Wm5@j$uQ&e{~E}8+;C0iO^}SgFOqum z=FM{D$`ymQo)Pf9KQ)9}!hfZ7k5dTny57XoGfDHi_aGt!_??ToxEGY0^OLrELwZDu z2s_kcgNNX4B7!Zq-DouO`t<2jE}{2p*<3>sFiab9zQo*?k!nksY_p8mGFg-_O^tUzZuOHv$YsH3>BlT7TCL zlShvpvDrw7ZY0EO_LA|Kb`Xm|dQ`Xdo7Hz@6#{_Hq#%K|dV}=x-mEb7J?rseRFUDk zuV25uRl(KUw{N@ND1Z1=nqo&*At0{UMiN4V2fTlOauF7-EhN-BMvMWMH^uv~05mmI zqX~WpK(b`7j;uyNeBdS#UK7QfDmKc+Y(?9Iv6hR;7f=meD`wmE` ziP)wJl|8?Jth}h%iU{$TR=PP?bqxGC8U5(yiUefVM>qBcaetj{YLrXI3I0l?peJ5F&PQ8HI;|q&HM9?JV^R$9A{ z(bk|!y+75_Gk*v-fgkQ4mZ8^?RSBR?A`q~EFed_VAp^iYMF8J_=!TAhPkly6qa&*j zpoORYW|Ig6EG!CjSO*4VSCvkSxVN$M3o_3ULg~nA1f=F>h^R@}3jyTi%a;c07VrUB z$aa(sMTCVvWF9gtnUdi83Z#@Ga&rj`)X z)e-Kh{R)2Wl>pizVjBW1$a`oHZ_wq1Oz8paH4w*C>9aZ<-2^_G)vmjD?~0(dN^{1m zGB&M1K!XTn=x2zB1VCI_;P@VPSb9kv)B}izPfH$Eo>9FI;mw;juGIoQ;M3&(Ako@| z|fGsjY$Q(5gv*WGoJAeiBX~4I^r{1S`%qHNU zl?ZUgOZ{LWqeDoS9If9THRft;IZ=;ofZhi_;D1Mbm(M(Z{(M&9*3-2J`0(Kavof6A zwaA!73cD>d?S4C=WSKQ;pR0lIwfY+T5HP18_}?ksy#@ghnZ_1YTC?mqr1%bIU`~dD zEN3B##JOg-dYUuKWc$sKKjxILM}XC$ULpBE_ z&NI-v>9u;KJLSosuKd|n_fm0{CC4zY3HbI?Ji7c76c~TgI#Kng9As&^H+G)z=Vs^S zAWMm4*3WvUYJX*lTn=*9^4H|U{T)DW-J%@itZwAb9O^$=uvMIaevq>;J74z^Z;uH- zAH1Wjy`6ip`MXG5)ZfcNrpj@{)!dng@0D{X;ur_11tz~{hP$XZ30i$s;Z!kggN&eI n`TvM#^~|0f20sd{ZG+{%@%@>)@_Tfh00000NkvXXu0mjfd3Z1?