From cb6a0f8d2764dfefd14e3e25cdc8129897e0a68c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Du=C5=BCy=C5=84ski?= Date: Fri, 4 Nov 2022 21:20:16 +0100 Subject: [PATCH] initial commit --- .gitignore | 1 + LICENSE.txt | 21 +++ README.md | 129 ++++++++++++++++++ example/0_0-initial.rsc | 42 ++++++ example/0_1-security.rsc | 1 + example/0_2-firewall.rsc | 1 + example/1-logging.rsc | 11 ++ example/2-ntp.rsc | 13 ++ example/3-port-forwarding.rsc | 7 + example/README.md | 6 + example/common/firewall_router.rsc | 83 +++++++++++ example/common/firewall_switch.rsc | 59 ++++++++ example/common/security.rsc | 24 ++++ example/config.yml | 9 ++ example/host-keys/ssh_host_private_key_dsa | 9 ++ .../host-keys/ssh_host_private_key_dsa.pub | 1 + example/host-keys/ssh_host_private_key_rsa | 40 ++++++ .../host-keys/ssh_host_private_key_rsa.pub | 11 ++ intellij/README.md | 14 ++ intellij/config.jpg | Bin 0 -> 44890 bytes intellij/highlight.jpg | Bin 0 -> 87206 bytes intellij/keywords-1.txt | 4 + intellij/keywords-2.txt | 5 + intellij/keywords-3.txt | 54 ++++++++ intellij/keywords-4.txt | 99 ++++++++++++++ mikrotik_configurator/__init__.py | 0 mikrotik_configurator/__main__.py | 106 ++++++++++++++ mikrotik_configurator/generator.py | 89 ++++++++++++ mikrotik_configurator/utils.py | 35 +++++ requirements.txt | 2 + tools/gen_ssh_host_keys.sh | 4 + 31 files changed, 880 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 example/0_0-initial.rsc create mode 100644 example/0_1-security.rsc create mode 100644 example/0_2-firewall.rsc create mode 100644 example/1-logging.rsc create mode 100644 example/2-ntp.rsc create mode 100644 example/3-port-forwarding.rsc create mode 100644 example/README.md create mode 100644 example/common/firewall_router.rsc create mode 100644 example/common/firewall_switch.rsc create mode 100644 example/common/security.rsc create mode 100644 example/config.yml create mode 100644 example/host-keys/ssh_host_private_key_dsa create mode 100644 example/host-keys/ssh_host_private_key_dsa.pub create mode 100644 example/host-keys/ssh_host_private_key_rsa create mode 100644 example/host-keys/ssh_host_private_key_rsa.pub create mode 100644 intellij/README.md create mode 100644 intellij/config.jpg create mode 100644 intellij/highlight.jpg create mode 100644 intellij/keywords-1.txt create mode 100644 intellij/keywords-2.txt create mode 100644 intellij/keywords-3.txt create mode 100644 intellij/keywords-4.txt create mode 100644 mikrotik_configurator/__init__.py create mode 100644 mikrotik_configurator/__main__.py create mode 100644 mikrotik_configurator/generator.py create mode 100644 mikrotik_configurator/utils.py create mode 100644 requirements.txt create mode 100755 tools/gen_ssh_host_keys.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85e7c1d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.idea/ diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..02530c2 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Krystian Dużyński + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..781a8d2 --- /dev/null +++ b/README.md @@ -0,0 +1,129 @@ +Mikrotik configurator +====== + +A utility for generating and applying RouterOS / Mikrotik configuration files (.rsc). + +It uses Jinja2 as a template engine with few additional helpers. + +Features: + +* Applying configuration over SSH, +* Support for applying only part of the whole configuration (e.g. if only firewall settings have changed). + +Helpers: + +* Escaping string and blocks, +* Embedding files (e.g. SSH keys), +* Cleanup functions (executed in reverse order on configuration re-apply), +* Rolling back firewall chains. + +Additional: + +* [IntelliJ color schema configuration](intellij) for .rsc files, +* [A script](tools/gen_ssh_host_keys.sh) for generating RouterOS-compatible SSH host key files. + +# Usage + +Prepare template files, like from [the embedded example](example): + +* 0_0-initial.rsc +* 0_1-security.rsc +* 0_2-firewall.rsc +* 1-logging.rsc +* 2-ntp.rsc +* 3-port-forwarding.rsc + +Naming is important: + +* filenames starting with `0_` are considered reset configuration that is being applied after + `/system reset-configuration` command is executed, +* filenames starting with other numbers can be applied to actively running Mikrotik router, +* adding numbers help with applying the configuration in proper order. + +### Configuration + +```yaml +has_flash: false # some RouterOS devices Flash directory is +# accessible via explicit /flash/ prefix, for some just / + +host: 192.168.1.1 # IP of the Mikrotik device, can be overriden with --override-id CLI argument + +include_dirs: # search paths for templates including + - common/ + +variables: # additonal Jinja2 variables + admin_pass: "pass" +``` + +### Reset configuration and apply + +```shell +cd example/ +python ../mikrotik_configurator [--dry-run] --reset *.rsc +``` + +### Part of the configuration re-applying + +```shell +cd example/ +python ../mikrotik_configurator [--dry-run] 3-port-forwarding.rsc +``` + +# Examples + +## Setting admin password from config file + +File `config.yaml` + +```yaml +variables: + admin_pass: "pass" +``` + +File `1-example.rsc` + +```text +/user set admin password="{{ admin_pass }}" +``` + +## SSH public key loading + +File `1-example.rsc` + +```text +{{ load_file("~/.ssh/id_rsa.pub", "pcl_id_rsa.pub.txt") }} +/user ssh-keys import user=admin public-key-file=pcl_id_rsa.pub.txt +``` + +## Creating a firewall target with rollback + +```text +/ip firewall filter +add chain="user-input" action=jump jump-target="user-input-ntp" comment="NTP rules" +add chain="user-input-ntp" action=accept in-interface-list=LAN protocol=udp dst-port=123 comment="accept NTP (LAN)" +{{ rollback_delete_chain("user-input-ntp") }} +``` + +## Custom cleanup + +```text +/interface ovpn-client add name=my-ovpn \ + connect-to=myhost.com port=1190 \ + user=$vpnusername \ + password=$vpnpassword \ + verify-server-certificate=yes \ + cipher=aes256 + +{% call register_cleanup() %} + /interface ovpn-client remove my-ovpn +{% endcall %} +``` + +## Script escape + +```text +/system script +add dont-require-permissions=yes name="ddns-update" owner=admin policy=read,test source={% call escape_string() %} +/tool fetch output=none mode=https url="https://my.own.dynamic.dns.site\?domain={{ public_domain }}" http-method=post http-data="token={{ ddns_token }}" +{% endcall %} +``` \ No newline at end of file diff --git a/example/0_0-initial.rsc b/example/0_0-initial.rsc new file mode 100644 index 0000000..9ae1f51 --- /dev/null +++ b/example/0_0-initial.rsc @@ -0,0 +1,42 @@ +/system identity set name="MT" + +/interface bridge +add name="bridge" + +/interface ethernet +set [ find default-name=sfp1 ] disabled=yes + +/interface list +add name=LAN +add name=WAN + +/ip address +add address=192.168.1.1/24 interface="bridge" + +/interface list member +add interface="bridge" list=LAN + +/interface bridge port +add bridge="bridge" interface=ether2 +add bridge="bridge" interface=ether3 +add bridge="bridge" interface=ether4 +add bridge="bridge" interface=ether5 +add bridge="bridge" interface=ether6 +add bridge="bridge" interface=ether7 +add bridge="bridge" interface=ether8 +add bridge="bridge" interface=ether9 +add bridge="bridge" interface=ether10 + +/user set admin password="{{ admin_pass }}" + +####################### +# SSH +####################### +{{ load_file("host-keys/ssh_host_private_key_dsa", "ssh_host_private_key_dsa.txt") }} +{{ load_file("host-keys/ssh_host_private_key_rsa", "ssh_host_private_key_rsa.txt") }} +/ip ssh import-host-key private-key-file=ssh_host_private_key_dsa.txt +/ip ssh import-host-key private-key-file=ssh_host_private_key_rsa.txt + +{{ load_file("~/.ssh/id_rsa.pub", "pcl_id_rsa.pub.txt") }} +/user ssh-keys import user=admin public-key-file=pcl_id_rsa.pub.txt + diff --git a/example/0_1-security.rsc b/example/0_1-security.rsc new file mode 100644 index 0000000..9d35965 --- /dev/null +++ b/example/0_1-security.rsc @@ -0,0 +1 @@ +{% include 'security.rsc' %} diff --git a/example/0_2-firewall.rsc b/example/0_2-firewall.rsc new file mode 100644 index 0000000..f964ee4 --- /dev/null +++ b/example/0_2-firewall.rsc @@ -0,0 +1 @@ +{% include 'firewall_router.rsc' %} diff --git a/example/1-logging.rsc b/example/1-logging.rsc new file mode 100644 index 0000000..a02bd19 --- /dev/null +++ b/example/1-logging.rsc @@ -0,0 +1,11 @@ +/system logging action remove [find default=no] +/system logging remove [find default=no] + +/system logging action +add name=pc2 remote=192.168.1.2 remote-port=1514 target=remote + +/system logging +add action=pc2 prefix=MT topics=critical +add action=pc2 prefix=MT topics=error +add action=pc2 prefix=MT topics=warning +add action=pc2 prefix=MT topics=info diff --git a/example/2-ntp.rsc b/example/2-ntp.rsc new file mode 100644 index 0000000..05c6fd8 --- /dev/null +++ b/example/2-ntp.rsc @@ -0,0 +1,13 @@ +/system ntp client +set enabled=yes primary-ntp=162.159.200.123 secondary-ntp=162.159.200.1 + +/system ntp server +set enabled=yes + +/ip firewall filter +add chain="user-input" action=jump jump-target="user-input-ntp" comment="NTP rules" +add chain="user-input-ntp" \ + action=accept \ + in-interface-list=LAN protocol=udp dst-port=123 \ + comment="accept NTP (LAN)" +{{ rollback_delete_chain("user-input-ntp") }} diff --git a/example/3-port-forwarding.rsc b/example/3-port-forwarding.rsc new file mode 100644 index 0000000..92821a4 --- /dev/null +++ b/example/3-port-forwarding.rsc @@ -0,0 +1,7 @@ +/ip firewall nat +add chain="user-dstnat" action=jump jump-target="user-dstnat-port-forwarding" comment="port forwarding" + +add chain="user-dstnat-port-forwarding" action=dst-nat comment="port forwarding -> HTTP" dst-port=80,443 in-interface=ether1-WAN protocol=tcp to-addresses=192.168.1.2 +add chain="user-dstnat-port-forwarding" action=dst-nat comment="port forwarding -> SSH" dst-port=1234 in-interface-list=WAN protocol=tcp to-addresses=192.168.1.2 to-ports=22322 + +{{ rollback_delete_chain("user-dstnat-port-forwarding") }} \ No newline at end of file diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..992b5a7 --- /dev/null +++ b/example/README.md @@ -0,0 +1,6 @@ +# Important notes + +* These example files are provided **ONLY** as an example of project structure. + Although it contains a lot of solutions from my configuration files, + it is not meant to be used as an example Mikrotik configuration, +* Example generated SSH keys **SHOULD NOT** be used in your project. diff --git a/example/common/firewall_router.rsc b/example/common/firewall_router.rsc new file mode 100644 index 0000000..85389bd --- /dev/null +++ b/example/common/firewall_router.rsc @@ -0,0 +1,83 @@ +:do { + /ip firewall filter + remove [find chain=input] + remove [find chain=forward action!=passthrough] + remove [find chain=output] + + remove [find chain=icmp] + remove [find jump-target="user-input"] + remove [find jump-target="user-forward"] + remove [find jump-target="user-output"] + + remove [find chain="core-icmp"] + + /ip firewall nat + remove [find chain=srcnat] + remove [find chain=dstnat] +} on-error={} + +/ip firewall filter +# INPUT +add chain=input action=accept comment="accept established,related,untracked" connection-state=established,related,untracked +add chain=input action=drop comment="drop connection-state=invalid" connection-state=invalid +add chain=input action=drop comment="drop banned" src-address-list=bans +add chain=input action=jump comment="check ICMP" jump-target="core-icmp" protocol=icmp +add chain=input action=accept comment="accept SSH and HTTP (LAN only)" in-interface-list=LAN protocol=tcp dst-port=22,80 +add chain=input action=accept comment="accept WinBox and API (LAN only)" in-interface-list=LAN protocol=tcp dst-port=8291,8728 +add chain=input action=accept comment="accept DNS and DHCP (LAN only)" in-interface-list=LAN protocol=udp dst-port=53,67,68 +# add chain=input action=accept comment="accept to local loopback (for CAPsMAN)" dst-address=127.0.0.1 + +add chain=input action=jump jump-target="user-input" comment="forward to user-input" +add chain=input action=drop comment="drop all not coming from LAN" in-interface-list=!LAN +add chain=input action=drop comment="drop all other" + +# FORWARD +add chain=forward action=fasttrack-connection comment="fasttrack" connection-state=established,related +add chain=forward action=accept comment="accept established,related,untracked" connection-state=established,related,untracked +add chain=forward action=drop comment="drop connection-state=invalid" connection-state=invalid +add chain=forward action=drop comment="drop banned" src-address-list=bans +add chain=forward action=jump comment="check ICMP" jump-target="core-icmp" src-address-list=lan in-interface-list=LAN protocol=icmp +add chain=forward action=accept comment="accept DSTNATed from WAN to LAN" connection-state=new in-interface-list=WAN out-interface-list=LAN dst-address-list=lan connection-nat-state=dstnat +add chain=forward action=accept comment="accept all from LAN to WAN" connection-state=new in-interface-list=LAN src-address-list=lan out-interface-list=WAN +add chain=forward action=accept comment="accept all between LAN interfaces" connection-state=new in-interface-list=LAN src-address-list=lan out-interface-list=LAN dst-address-list=lan +# add chain=forward action=accept comment="accept in ipsec policy" ipsec-policy=in,ipsec +# add chain=forward action=accept comment="accept out ipsec policy" ipsec-policy=out,ipsec + +add chain=forward action=jump jump-target="user-forward" comment="forward to user-forward" +add chain=forward action=drop comment="drop all other" + +# OUTPUT +add chain=output action=jump jump-target="user-output" comment="forward to user-output" + +add chain="core-icmp" protocol=icmp icmp-options=0:0 action=accept comment="echo reply" +add chain="core-icmp" protocol=icmp icmp-options=3:0 action=accept comment="net unreachable" +add chain="core-icmp" protocol=icmp icmp-options=3:1 action=accept comment="host unreachable" +add chain="core-icmp" protocol=icmp icmp-options=3:4 action=accept comment="host unreachable fragmentation required" +add chain="core-icmp" protocol=icmp icmp-options=8:0 action=accept comment="allow echo request" +add chain="core-icmp" protocol=icmp icmp-options=11:0 action=accept comment="allow time exceed" +add chain="core-icmp" protocol=icmp icmp-options=12:0 action=accept comment="allow parameter bad" +add chain="core-icmp" action=drop comment="deny all other types" + +/ip firewall nat +add chain=srcnat action=masquerade comment="masquerade to WAN" ipsec-policy=out,none out-interface-list=WAN + +add chain=srcnat action=jump jump-target="user-srcnat" comment="forward to user-srcnat" +add chain=dstnat action=jump jump-target="user-dstnat" comment="forward to user-dstnat" + +# Address lists +/ip firewall address-list +add list=bogons address=0.0.0.0/8 comment="Self-Identification [RFC 3330]" +add list=bogons address=127.0.0.0/8 comment="Loopback [RFC 3330]" +add list=bogons address=10.0.0.0/8 comment="Private[RFC 1918] - CLASS A" disabled=no +add list=bogons address=172.16.0.0/12 comment="Private[RFC 1918] - CLASS B" disabled=no +add list=bogons address=192.168.0.0/16 comment="Private[RFC 1918] - CLASS C" disabled=yes +add list=bogons address=169.254.0.0/16 comment="Link Local [RFC 3330]" +add list=bogons address=192.88.99.0/24 comment="6to4 Relay Anycast [RFC 3068]" +add list=bogons address=198.18.0.0/15 comment="NIDB Testing" +add list=bogons address=192.0.2.0/24 comment="Reserved - IANA - TestNet1" +add list=bogons address=198.51.100.0/24 comment="Reserved - IANA - TestNet2" +add list=bogons address=203.0.113.0/24 comment="Reserved - IANA - TestNet3" +add list=bogons address=224.0.0.0/4 comment="MC, Class D, IANA" disabled=no +{% call register_cleanup() %} +/ip firewall address-list remove [find list=bogons] +{% endcall %} diff --git a/example/common/firewall_switch.rsc b/example/common/firewall_switch.rsc new file mode 100644 index 0000000..f3fe9f7 --- /dev/null +++ b/example/common/firewall_switch.rsc @@ -0,0 +1,59 @@ +:do { + /ip firewall filter + remove [find chain=input] + remove [find chain=forward action!=passthrough] + remove [find chain=output] + + remove [find chain=icmp] + remove [find jump-target="user-input"] + remove [find jump-target="user-forward"] + remove [find jump-target="user-output"] + + remove [find chain="core-icmp"] + + /ip firewall nat + remove [find chain=srcnat] + remove [find chain=dstnat] +} on-error={} + +/ip firewall filter +# INPUT +add chain=input action=accept comment="accept established,related,untracked" connection-state=established,related,untracked +add chain=input action=drop comment="drop connection-state=invalid" connection-state=invalid +add chain=input action=drop comment="drop banned" src-address-list=bans +add chain=input action=jump comment="check ICMP" jump-target="core-icmp" protocol=icmp +add chain=input action=accept comment="accept SSH and HTTP (LAN only)" in-interface-list=LAN protocol=tcp dst-port=22,80 +add chain=input action=accept comment="accept WinBox and API (LAN only)" in-interface-list=LAN protocol=tcp dst-port=8291,8728 + +# add chain=input action=accept comment="accept to local loopback (for CAPsMAN)" dst-address=127.0.0.1 + +add chain=input action=jump jump-target="user-input" comment="forward to user-input" +add chain=input action=drop comment="drop all not coming from LAN" in-interface-list=!LAN +add chain=input action=drop comment="drop all other" + +# FORWARD + + + + + + + + + + + +add chain=forward action=jump jump-target="user-forward" comment="forward to user-forward" +add chain=forward action=drop comment="drop all other" + +# OUTPUT +add chain=output action=jump jump-target="user-output" comment="forward to user-output" + +add chain="core-icmp" protocol=icmp icmp-options=0:0 action=accept comment="echo reply" +add chain="core-icmp" protocol=icmp icmp-options=3:0 action=accept comment="net unreachable" +add chain="core-icmp" protocol=icmp icmp-options=3:1 action=accept comment="host unreachable" +add chain="core-icmp" protocol=icmp icmp-options=3:4 action=accept comment="host unreachable fragmentation required" +add chain="core-icmp" protocol=icmp icmp-options=8:0 action=accept comment="allow echo request" +add chain="core-icmp" protocol=icmp icmp-options=11:0 action=accept comment="allow time exceed" +add chain="core-icmp" protocol=icmp icmp-options=12:0 action=accept comment="allow parameter bad" +add chain="core-icmp" action=drop comment="deny all other types" diff --git a/example/common/security.rsc b/example/common/security.rsc new file mode 100644 index 0000000..ddcd2c2 --- /dev/null +++ b/example/common/security.rsc @@ -0,0 +1,24 @@ +{ :local ver [/system resource get version]; :global vermajor [:pick $ver 0 [:find $ver "."]] } + +/ip neighbor discovery-settings set discover-interface-list=none + +/ip ipsec policy set 0 disabled=yes + +:if ($vermajor = 7) do={ /ipv6 settings set disable-ipv6=yes } +:if ($vermajor = 6) do={ /system package disable ipv6 } + +/tool mac-server set allowed-interface-list=none +/tool mac-server mac-winbox set allowed-interface-list=none +/tool mac-server ping set enabled=no + +/ip service set api disabled=yes +/ip service set api-ssl disabled=yes +/ip service set ftp disabled=yes +/ip service set telnet disabled=yes +/ip service set winbox disabled=no + +/tool bandwidth-server set enabled=no + +/ip ssh set strong-crypto=yes host-key-size=4096 forwarding-enabled=both always-allow-password-login=yes + +/ip settings set rp-filter={{ rp_filter | default("strict") }} secure-redirects=no tcp-syncookies=yes diff --git a/example/config.yml b/example/config.yml new file mode 100644 index 0000000..86ff9a5 --- /dev/null +++ b/example/config.yml @@ -0,0 +1,9 @@ +has_flash: false + +host: 192.168.1.1 + +include_dirs: + - common/ + +variables: + admin_pass: "pass" diff --git a/example/host-keys/ssh_host_private_key_dsa b/example/host-keys/ssh_host_private_key_dsa new file mode 100644 index 0000000..eb094bf --- /dev/null +++ b/example/host-keys/ssh_host_private_key_dsa @@ -0,0 +1,9 @@ +-----BEGIN PRIVATE KEY----- +MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBAI3m06Sl+2TgMzx9an3BRwuMD56J +VrrWrTlVdcNYaxgquiv3osjFHs+kEAn8jY+pPFKCM9lpfoTj8FT0qPkKtsZ+LcB9 +YrxS4bsW8LGvnQScpZcrqFze4Ec0AF+7vYhP9pBHESlxlgEsOIDZvBsVErS/U7WM +wgnIgrY0e/i2GaJZAhUAi0LIo6w4dKsjKCMN/j6X5/1YKAkCgYA8Hr5VfkCNYbMf +J7amr+SilmkBLuQUn0+pV4FvGdPCa9EY0gxCP+0N82aintU7HfqOqE9pdtwFrbXU ++/GyXJIuNME3y4JAvdFkJ18vAUVM0+7rGQ22BxdwrkBT3DUXV+9xjkYAh+6mpWOf +S6Iyga1TE3nNlHtaP6KgBS7tdlcBxwQWAhRurYPs9TMeP1mlge45J3hbBO4Jbg== +-----END PRIVATE KEY----- diff --git a/example/host-keys/ssh_host_private_key_dsa.pub b/example/host-keys/ssh_host_private_key_dsa.pub new file mode 100644 index 0000000..f43b501 --- /dev/null +++ b/example/host-keys/ssh_host_private_key_dsa.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAI3m06Sl+2TgMzx9an3BRwuMD56JVrrWrTlVdcNYaxgquiv3osjFHs+kEAn8jY+pPFKCM9lpfoTj8FT0qPkKtsZ+LcB9YrxS4bsW8LGvnQScpZcrqFze4Ec0AF+7vYhP9pBHESlxlgEsOIDZvBsVErS/U7WMwgnIgrY0e/i2GaJZAAAAFQCLQsijrDh0qyMoIw3+Ppfn/VgoCQAAAIA8Hr5VfkCNYbMfJ7amr+SilmkBLuQUn0+pV4FvGdPCa9EY0gxCP+0N82aintU7HfqOqE9pdtwFrbXU+/GyXJIuNME3y4JAvdFkJ18vAUVM0+7rGQ22BxdwrkBT3DUXV+9xjkYAh+6mpWOfS6Iyga1TE3nNlHtaP6KgBS7tdlcBxwAAAIBFHqQTevlpTRONMZ40oxL4/DOz8If1ja7WTx4hH3HXWtvDEZii57FDv/xpUkCpP0dqp4NcaPWxZ5XH8+mdKR3zPxD8L+1S4NnleoPFtSMQU5v/Zcq7R79FGC0kaocjQN/a2XQOzifaeXx0nSD49l36bpkkMXYCBH0/l9HOD3xRkg== krystiand@PCL diff --git a/example/host-keys/ssh_host_private_key_rsa b/example/host-keys/ssh_host_private_key_rsa new file mode 100644 index 0000000..7d3c25e --- /dev/null +++ b/example/host-keys/ssh_host_private_key_rsa @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/wIBADANBgkqhkiG9w0BAQEFAASCBukwggblAgEAAoIBgQDzut9yM/svAKF9 +3i6/E7HxknDdKdRZDS4vYjaBkiEg+bKI4abH/PeDN039ojunHS71rhoOzaU0CU3c +H5r/yf0G7t3yTjZ+HAtwdX+jZUGITFErETteAcYrwb/aF5oxP6K92vh5EfyjywAd +9l4n/ZYjox3b/2Uvn7C42+altSfEOkXRtsTfo9GnkkRYGFPyC+U3RN3GXP24Gm7W +2ZDRmg1hrUkVaNGqxz+oyCyUFevspjRyXDMmnhwG8Jl687/Jld4OOmhD++Mv8qUX +xaVOrF5aey9HPZvJCIktepFNPVXdx1f0zpmq7UU8dkghK90/4kxoGFe5Tt9Kxh4s +9jAKdRRhCinTXZJ6u+vrDB30Fv5tRvbwa1eF5R12jTavLSDvKjT4aMBXDvXLO6B+ +dkvEgdrFMraP/iuWN9Efcv4zH/z8UYE510ou2H+FwjRBSrqROzn2waNsY1nLHoDh +cP3crx6yHAAsa7xxUSt5qht2aJqFy0PnCI41j+qpCE+VaT6XpO0CAwEAAQKCAYEA +hkMdMAYeiqfoTjQEwFGTJqYq8kpGpb+y/3s012+uPEIQ7YKQo35gwrHGjr+96LMU +2VXNGPaD2QR/FZF7iwi0EAupy/712caNLqgrZdEzpmeUFwtpDsIfbp9Olk+GKzcI +6Vkko10bNQdwyxCakaEKAhurKTOpg/COI2dPyVzfySLorzvle+T8azkR2Q2dwKp4 +3FddbBZx1ecJw+UZ97zLPlF8/wQ867zS/qE2nWTuD/EG1zCfJNjYS6Jiie6Yae3Z +z/vNaL42NGTmgs8CpNZvgDtDWY4PhXE3b5BcciKiGsVeW5t6i7iD65jTq9kL3jMJ +r9nXC/ocqStW+8XesgQijdvOdaU3UVe1TfaMmT3TgBf3VISeZ0kCvycolpQljQkP +UIgPtt2sbuRwvRQDwxkNCmtHEgHqyM5N4baIRZnoItZ9hHsVIq8n72PYpqk7MIke +QWCauclHbIqi7lgXDLipshjNrcHsIOZqr3x1aLHKlZ7EVU3XDrHxdiXoLIpIYgTp +AoHBAPq6krKd5jAe5B1eM3pBmygg6NZoFFCj0L7CFf0Glzp22H+G+Pt8+UW5L+AW +sBJKY38M2/1h7uc1uM6Rpr3hE0Ic9eEbrpI/YQsTpQ+mdWLg/ZYUWTXnPrYfUAaG +VU5QdqeqQS84kI7KaSP0Hs02OyQM7BVFEUmlmyj26iqc6gr20bf1V8HPOR4C5ZlK +kKBVZN8dqBjbYkD7Gz3lkmM4as/SNP1BsOSYFdooKPTJapEv4Fk3EoHEBjlTS0UY +DgLPRwKBwQD42qHJDGuvk8zzKRNvZ6d68fDcS6wQP96Iu1/wQCGpQq0z1LIB224v +LYj/JTRGQ4NnNi3Y/ZHtbXqMfhMp3mna73EA/qy8bgeYFTcadLpaJdGN/b1CmAO1 +ez+Ge1c6WkXT487S4JGmdgMqxDOGPp4doqOY6Ny60Ik2FpPXQasVGkvtqW8sPIZG +/QNU85I8xP7P+Pz3+Mpp40xGP3cR0sigeuS8fbhPOc24h+IajWwesJAgrA3jEoDr +mxqecVkcjCsCgcEAlNF2zyPfhAJh3XiTT2ZvZIMcEF7YaADDnuXuTS/DRUVTPWZs +lEDaZ+MCIpz0xvZ2VevZC208cum1Fo7nDF7yolQ0MPfQRyftPrjbSQ3BMP5gJdtQ +FCl8VHcDdcv4CDLEKsJoTFHjo41KmLeGLMGamsw8uGc1WqQ8EzVzSfW3COj1E55B +B10rBsArbTAP5cqpw7CDnLVifTVONw/zModDBrU7FHMQPq5ykfkyThDa+vAS1oFU +r8cc9puU2p7reglzAoHBAJ2uOtEfc6Re7IAuyMfQUAjRAKM1t6LcNW9B+vpKSInt +W735yYjvtxNhsOqqckMLSFm/tLFHio18zyfyQsZGzaASE/JjbKRAu8MbvjyfNe0l +BXEJFED7/W2i2I+n249338LxF/36mY92O29/vn4TczCn+y1Kb4JX3HlPOQIt8+99 +KBtBPtYyy4pziwbrBwBGeobg57lgBTGu+oeQcyvx+XnmJMVii8R3heilARl9/sI7 +cjehjXMSKGohb25xt9sk3QKBwHHpzCekB+00eeuo3vniIkcshqP3LZiBeQganuF0 +W/1ML+Ew/sZCsWL9GErbP1D0o+oZbNv61dIEMbVLSZFBulghz047THFeYfSD2BW4 +qUB1zOlIwMbFirrf5SuIcwE2W+0SboWD48xRxtE1cwSgDU/PY5DPuzZSHDopATa5 +aNtzlI80LV5+t9IYkVBdzsYHk7RNKN8JBDqIrsb+byiGKG2ATjiFHlxq2lCNrqc1 +k438geLC6lhQaxj0UMS1/PvURQ== +-----END PRIVATE KEY----- diff --git a/example/host-keys/ssh_host_private_key_rsa.pub b/example/host-keys/ssh_host_private_key_rsa.pub new file mode 100644 index 0000000..0d19421 --- /dev/null +++ b/example/host-keys/ssh_host_private_key_rsa.pub @@ -0,0 +1,11 @@ +-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA87rfcjP7LwChfd4uvxOx +8ZJw3SnUWQ0uL2I2gZIhIPmyiOGmx/z3gzdN/aI7px0u9a4aDs2lNAlN3B+a/8n9 +Bu7d8k42fhwLcHV/o2VBiExRKxE7XgHGK8G/2heaMT+ivdr4eRH8o8sAHfZeJ/2W +I6Md2/9lL5+wuNvmpbUnxDpF0bbE36PRp5JEWBhT8gvlN0Tdxlz9uBpu1tmQ0ZoN +Ya1JFWjRqsc/qMgslBXr7KY0clwzJp4cBvCZevO/yZXeDjpoQ/vjL/KlF8WlTqxe +WnsvRz2byQiJLXqRTT1V3cdX9M6Zqu1FPHZIISvdP+JMaBhXuU7fSsYeLPYwCnUU +YQop012Servr6wwd9Bb+bUb28GtXheUddo02ry0g7yo0+GjAVw71yzugfnZLxIHa +xTK2j/4rljfRH3L+Mx/8/FGBOddKLth/hcI0QUq6kTs59sGjbGNZyx6A4XD93K8e +shwALGu8cVEreaobdmiahctD5wiONY/qqQhPlWk+l6TtAgMBAAE= +-----END PUBLIC KEY----- diff --git a/intellij/README.md b/intellij/README.md new file mode 100644 index 0000000..12dd4aa --- /dev/null +++ b/intellij/README.md @@ -0,0 +1,14 @@ +## Configuration dialog + +config + +## Keywords + +* Tab 1 - [keywords-1.txt](keywords-1.txt) +* Tab 2 - [keywords-2.txt](keywords-2.txt) +* Tab 3 - [keywords-3.txt](keywords-3.txt) +* Tab 4 - [keywords-4.txt](keywords-4.txt) + +## Highlighting example + +highlight diff --git a/intellij/config.jpg b/intellij/config.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f19b5f9bdd03add852161002a2d25d0e2b880c80 GIT binary patch literal 44890 zcmeFY2UOF+x-S|;L8Oa-bft# zcijPC{L4`B@oot4SGsdE!drNRcW-L7C;)i3@$m2oh=^`_Cb)Ie5O53s_8m%s`;Q5! z9#9L$(6DN0ztfE!85L1@<@PD6qHTdqNN4P>u&B9aK zUUNUY>-I}~EG&D1p=RWtR=F1VOV_LF`FvQS&!w?LS6X}IOc!QTy+l0ihD-hr z;2`v3#RO_QfQ3dQd$-eq{^7BrjAOhwqo4Y$WfCLO&M<$R!s}EY34(RxUygGzD!K&X zs=)0dY4z^Ruw`CDz>8bOGYIrEVD=Td(y!yEf`6d*onenLT(N?5el+)n=cgZrAS zSp@E3z-|0Ig^dfRvi99aOj6|fOa8$u9|7ybJ}nGe&o1r~{&Qd%l~pz<|6g4Wvtq&Q zM!nO)aRII=e72H2?F@}jvLJm@jj&Pzl4dqa^Ov4(U7e8xjOEr9>Srvau6dWVo-NTN zayne_Wc?mXtObch7iXGkRUMNl=EEH~3U4VHiEF^hIE<$&v~XeuR3Zz->P{aj-%}qO zQ$uRd?zAWNyQ=-^LhQFh|FLwga;}~I_!*u`wd}GeQLJDF^)Ht!m-e20Hip^%QNI)z zwL95D#aD)acfrxat07kqIhxzhj`(*crVVHG9;d=hKc-UShZY64a$jI3tkT0vLO$Ic z*w`oBChQ-h02?fIP%O278*w+#PUtYdkP&s$_oFG$Sw1>TndLPP`W7MkfXTzhq!b+D z3Vm`;2xp9Sw8n;`O;WmbdMuYIRT(r0JB$sGUf)S(poCxvE;1hE;PSa zGk#lD2y2&k3P)s4J;V&oU__i=A!)sp(iaLlc_$}-a)XJi{nuq>Re@XS6F>5uS<~u4YMh6!z0$wv;>0PaFEy6fXrs}J~F5zadP0-a=*HD zj0z%t2l@T+0~ZIAO8AxX!QJ?^#Tbw3Z}ug?TIiuf>V@uz;Y0Qp%12@q0eLxYe`N zS%z@oW=9X*p{QP|T*cC;$f^97nP8Jg68T5(q2_X2fB(R0^@)}^ka1H1^mA8MdxhRKy8Pw9ZHg&>s1>P%bJxQ;;q6xg}H^7c` zqn3*=HWN%uPc;XDgNt>VU9N#u5319~>ws}ChCVp31#bdMW|@%MNl8L#YkQ{5O2Dlq zjT!pw?BQD%eZHaTh1ML0oxp5SnczW(A=b)w1yq8ka%#>rnK6lr>!%+$L4n|}k4wi) z7zRlJ2tQcaHQ-dBVwcccy2Ar?Oqbr8E0ZJNGB)-L z{Hz{$O63);hw4Z6k2>Z+(1o+ruPJ*ABRj$U$#Urqmre$UXLZ|dkr8%)XidPaWB=qQ?TfoB;;KU|D9YF?Dw=0{ z(`Lh0(^pB-`d?7rJo7-iMw*uog{4ItM=GZF#OKo;upQlP%)d{1=3E~C{t#HiGTm&} zy7IfbHN68CXJMoTl&HQ2++WJ73vAF?U&3^?r#$00kPu0!6=fLf%|Bx)oLnignd{|8 zI`Ybo3dgkem|Dj4*l(2%d8~Nl6*=ffG|nk|2Gee^Gh~NIdzS#Ve@vdgkVwCx?KWTX zJE^Flfme;88%k()FkJH-A;;GMd|r-dN|3rNH+rrDmTV2b=)DH~EN`qaua-X(4^(cD zh-m0S3^{D0&1&L`v^SYN0# zppzy^7TGrKbLk~>>Vvw@?qo3Om`M)sfGzO!Hu_?Fe814mtJ$F1)=^C80+w!DVBzL6 z>&Y)?L&;f@j{GocaMY7+D*T7lP5Ms_fR(vf74P!;-|d9%$3Zt#Kj)(AfbPI))(Xn9GwqTQtnG&jcduZv6Tcn;w<_ET-}VA zDo?9z%&nzPH5>?)AXTq>hxlflB!EzfPh|CshS|--kt~bxtS(4?yA{J&YXm~?s3~hG zM62ywa`Eb6TXx}opK$Kdh-s?MMgZxhxa3=#(XHy%Mc#=i?*p%pnQzDI*b5`wD1QqB zOvUtwez=H}#J2sh^z&`}s#DI&3$s~e&G=M423_DaKxksq7m>Cm(?a@0%`8#W$wa5# zI4z}GgduH3^!juJFBAL$}Kxf7v|=wA0-4<8eF+Qb*biCSy>qmbm*C%L8c1 zoxW*EIVbsuB5vdr-Hshef|Yc;Q`0|zs*&1z3_34uuqIh*1ww{|2hNs@4l&B_n$9Sh zHyK#I=SFb(1}DL8JC~PTb%r_dvzJ@U!i$p}%~FcG@?iH3G_iIIou-V>%J1j+DDr{h zE(XAzI%4}W@O{P4E66iB`8aIzR74SqFQpX?gZru|^+Q3Ou1bNebPmsG8oMqRO}gD{ zW!6zmKeazMOD|gQZt^WC2|BH4QU-9=0pT9NoVJAT^b%q7&$1#8M89#1z`YqpFIGIR zkWHKI*MK(xdKUfrqVt1F>QQ~OHlty+{o%%WFK=GgE1Z0aU?;UfzitZs9Q6=n-R(JO zEMy?XD2*WQNp4y~jw82==a{B`#$nczYe2fj(o^uK#y*2?;OLkUpU3KjI5OcP>T<3S z$E@&gIlTYP-}pGQHDoX0Vc^tE>8BxqbE>3%OEj5gdVKW@Vcp>d79NYB40ku4RrkEt z7{~lqPJWskpI8@f%db;arzG2+0(-5!$vegA%7sQd#c5TJQXj+}3nHdOTtBI}mn2q% zw0NKIkOiC{*G%8ueqD~nt2R=xrR%NX(b|W83k_Qh;hw(?Z;`c9VK6dF{Mb5xh>SX4 zUXyH+Hl`rccR}NoH>eoV^=RHS|Mo3Dj4Sys&6S0%de}_N5>q<|M3#hxB4r(lBh4HsPXnnq(6CU%wTM&w57_LpX{(Kh)@Z z0tlC;ldvAs;!n^#2?68Xm84n8Syq@cyat4MO!*8?*52xAiTG&~+12*W;D@Wqs}%Xs zkRQzkb&>^Nmw5yb{6*C@LUiG5IBU4nnf`C!^nBUKHNZ&RiZ4kc&__u;3GyqDN^I+x z(>op70d^k_^nPyK)>qvi9~WXLrZ-;YKp^aDw@S(n2?|Q?kj&GZkqSEaQfDM1Z|9%B z8)*MtKKNu>R6>r_x0L$`nBK5;4LF>*iffSPRfp(P`h>r&rWvl(<_8Bsp*2g>$!6)F zlfaXJ`4(DS`ZZv+#oRwHbZ_-byd&DhNq=hEW9iok%V#s&3;GjYUKMM-7$=O{Cv}|> zyV5zap+3oXD-7|GKmqNBUQT1H`toRHB?^nsrvu)17D_CY>bGmOvBprPyboq>Ti>tb zcUjDpv`!dh>WYMC>QR@bDCU$W-2}vBe4`ljS&Dd&dHr^@JbK4?>5Rc0O5K3NinmQ79u#9Z0{wSuQ5$4wzwPDot%lU!*J~nnEpIDHv@S zp1fGAmTVgMj0bp5ar^&y@*D-rylm;sReS~eetO5Lz;@wYe8=Cz;%VNdYjRaqd=M;k zKCsFL{w=daP%l9_sX1Hz*~vX?t*R+f;LH2+(eIg~IEm&5G*ViJK+|s8wol!va$#zd zizjal)|E#4s^K@`>Ta2G9`T|(W~T?y(a-jWw|#2u`&~TG0T@MO9N^2*n-pzdE_e8 z4XWX**wRvX=ccjMsH>{C3&n3}nQ}1BcpfjqUWBHpUhyI?B^zA##=DayOQIYkr6wU& z!HB0`7h#+=HsW2DRpysbU`r4p<=oGITRN|kes}$$qy?|^H2`OI4Zy-Q+pC-Y^v4Rr z8yTDEbtjHiT0La2xm{awg9BnxX~6!P@+nU3a(u2;>q?r^`>!Y5cqt`lBIu2Gq20{% zX$D?llwB%*rC1kZ_>rc1U#yUlN|ScgiTD{9G&?giv{lV%823X=sS8>AOcme-X%w$I zy(oH*4t1T&h*43=DUZFfOl0nxt^tRcH>IQ2t`8l; zKokAlFG}TNx4w;3XtAO87pL$bn*?i&WV?G+j9wQq##tdm0o-B@x^|~c;NbqvP(-h4 zfs#N|36dk{u4q zi+7GEiX3Q#x>X|i9s1Xv^YM9kW+X+pFXb^h@f!JTK4{Dfh+AFf=9b9G!L-~%mUg)a zJICU*n}@cr#6N5wt~(IF%Y<_zs)uyFUu7J?Y?l`^bFL%MGua>{8H@KG@vXq%tm*`i zIM1A~(RxDDK}yAYHF_!O1Yk*=BU~0<5%EwA(hR)nn0FY<^PlPyEkHGW4ZWacU zX9DPpLaTSGC)a=8Ykw+!RM0<6~cfa5n`RVr77`ZGZJ_VB;0P-h7d*r%4%)bUTFpK7~$9?S4Odvy2Ktu*qA8$*)T)fV`n(k34&vMP3|k_X(6 zX?`8_$8vfGs^VnM=8dA7D%dafLF^K%YqhA^S0^)>Ppmo8s5b6=`yutZM7C704A6C- ztX>4~*J%|!8x*vMIP&W+EKOz+L~B*m2CFgi*a^K$mic6;=&SkNf2q9NJwo#sSDd{R z6T$|C7#m`mN3f)?9~bG!Mg`v+bN^}?IfnYPa>e#siqJ(ynVHAw-KkxJE4fj#^wG9o zQIkmmM;g$wSG=8rm(o zozm-K*n6mb1tKEZ?Nmsmzvfq!`X)#UHKtLE5t_*)HKp2wGop?;t_oI^6D^~FS5S>47C$*4e-&X={B+PcZ9YCHgOYMmR8DDH_Wxn z#(pVB8m1eW?9A<`zL?xB9x5q4-Z{>B{9nlbtGQ809Ul1tecKaekoaMTpob>~Z+}ho zZKVkwzI}5T?i%nkk@|kK{4#ZOPWtDkM)!}!{#F7dz;Wh)HOm}{)E-`|0@3f9#0;^w7R>$ zdlVLzbywIZy^4m<;vDiPRMS!HkfK_|j(S8DzKAZGEPa&jT!fRKjB!H9da+ zH9aGymQ)RZbjOuADwDYdwiS1z8rNaSs*v4WsKg}V>rG#*4>bOLEC8s)I7de6ftXU0>#+d>r>Z*2j=XHOV8}RWTI`2 zJa*+SZ6>VADrkIUvzo}I2bfqX-F}DcN|gZ!>en+Q6WOP$auW(2y+(Gr)dzZK^lAbS zfx0z>eoV^Wt>^_^ZTPXA{Hgi|NpR&}^zCWC=d=$|lVM47bd9DAoxlCM-?;WY*wibn zotS}xa$p4ZH{#BSR5R_-i2dR6+pza0dMozv`#;g1juy*3q0R%sEDw~Div@?gzt+43 z?BPkJ(SLx(FUq8QwIo0%Mh{xBYgRN4-%pd&O5sborz4mE^=sZAus$t-EgT^C@dL^En0PI$F<{amYzx(#6RZ;A_ga;_&{h3P!j8 zBB!)4WR$u#Wj(K_B=NI#E)L`)B_u|_HnzXhgMtFe|o|MUr%F%28=|Qew0{<|LM|b zWy|8Vi;D0(aWfWw&6I>=b6-wE=r`$@*6-)uuS)VoZH?C7hzS%lKXqDhW;c6|{7i)9 z-5pOtOAuB}nA_7q$%xw`HS~v~5sSS9bq$H#vSa0s6h zHqM-@H%o+p&3VN65<^L|Gt8*NT87!0oKj|zlxZO%cYhv~hP!a74--03!gy)+%xSyy zZX`n=KD`U1PAO{-XC3>T+5%#xL{ivzKQQ(CV>MdojdqJ|Q)3?BYWjVze)G-_{KWu7 zJ!QeXm#2MrY&1CBxRGb9IXv+qRPz%|tVDGF*P!}LK=Ym2aD-v$3TVLIi?Ij(C93C{ z?}=gt*oc;b$i=ha*C%TEj!mnWBeetfqMlNIv9!|^Uqm1jT^h`ND%`6F=iyt)*DIir zFCM6yl5u!;&_2ssnMZ@kjXhXDD z+L5U)PvsAMl;xg!;PFeSUQ9x8FX8o4tw{#&!Y}M1|1+g)oQW;kNDm?kT1XYj`MTs+^d+z4O8580`fqq=Hig32OB8jUUC&c@ zKj8a+#)9G3a2X+fnjd&OzlQN{;m3cl@9;Ye4o^<`b$Ex4Zvx%el4xIA$tU}=M~u`m zb&Jl`A56~c?a(P~A?P|)AV~o_6*CYWq1siw5YpgIOP5_KeYr25Z_LZA!@I6rhN4Cr z^zM%=Ma=k_kW)w4i~K_UT5TI=QFA|qv z#fNoXZV)mqKN-!Irf$vIG0mUMJnv^29G%WDH#oGjahF$D)mAONq>cShwxRiQZ~hop z-#sZU5u2(p&>+OkRs1a!=pJxP6LgU3T`ck|vqlw`Q-fAQ13^x~Uu?aTeWk`KO3&HT z>XEYQg4Ny%KW&_T77bO>Aru-)r!n)qk@-?Jp`^er>?t%aL(tn* zf49N3uDKXqC6mz(X?fMQu-?u-=_AoVJKb|9q~eJMxlJ-gmUwB*7wT1o2eY3N+v5<; zbRC#YEyB6iW)B4Q+%4r+@vPy2k-;%%dPH?v0}YS)^>T&jG-i^ID%|>rIb^Uuy=RzT zE;}*-~h?5DIS^J;Wd z-J1d1|K@bJ#$^bqJr;->bNz2Xc@7-1pEfBypXqT7`G-RSws$>^8Jf2++QX7ZBNQQJvaQl*jF z^~p_`6X=TN^_V|W7icz%cw(^Gx{+k&*Fyic92tZVX+8}Q`7gNtG4DE^c+Yhsv@{xd zg~VQ1&W-=L%hI^C`atzd63;&pN&iks`DaWpe>(|o6r6ub`T1XnD`gUDGbnHO9)ge) z8y4*Ag19BFde^wUFa_gMX0Nt!s}Z^NPtAgLn?Sy1mnP2jO+>y$sH2k2yd6il6bYt7 z)6+Y*K$B9do!)80hS|_T|4(`JcCW!YyW3A(#3Jzd0^Ph^07w<34`q^4dxaEDN=WF9 zOp-!1JNo3fpMp-^Djy`{2X#w7yOBu3NG4_n)fioe2a!Xk1T zrK#J>8Q(EsVx#@3-!(|LXi}*|;9C92+|(mvOeK`N2Sdvc9z?&HNOuroSGsTwSl}iy zlD5DAW(f4w+@l5=B@!UffLSd%|D`V=mzvS!CLevpj)`a;KN{dwHtJ|B)ww~mLMBPO zD7qC9WEWPnYL!$h^m8F@#L(Q1#0w@8F~jfY^J5Y7$xkPbDH1fW&4iZ6*u%6`#-bIG44UlXv|E=KsjN$$H~xWOVe*^ArCtJ5PjE zSNe=>@0FPR#%Jj<7lbWA(j(R57Zny@$v!P(sPyt#TW{$pKTjjb9pgwLuRUF>=(vZu z6*h$n7M!23nBWGby5Aeeo)?#y&gfWu+Ekte4c)O1pR}Eu1#1wO=s=S|cl)89NKTXd zjpF!WM!&>2m*I*8W8H2)s=9EZL(cB#en^Fg=�Isq~Z%4rkqFeF0)|W+$G7+?2!M z4Z2wbi~fVToFYFb#ovg4P6yn}J3&@-bcGmRb0<>_S|@;ez`How>c<~qqDa1xER*vr z6H$a7dqth9GzX!{xYJW*Y*VjxhkvpEhNocz;=jY^> zbS{$0{+(=gm=u#hvmLFGM6;ezFmB7^LCvfAy67Mm4V7$LxjR~oEb>a!cN}dtCh?Um zJLj0Vt|v6uBfOC6NRo^bWq2)k+(=#fZ6pDfjN_ilQ; zN!o6HkH-+=wPUxag4al2Z{7GN#W;sKv^POy04`XhW_qm6%I%3$}yvg;NhuM&nrT5Owm->yZU?jCO)=Y%rdHB^qm_6ZL8+MUIT39Ks~0c6Vie_8u;UW>Ylo z*pWEcY-3<9&H!3)$DU!Kwo9N$oEe8MwthY>w?1B1pe+?Ct8-lF6g6-(@pi06VPbks zz#wuaxb9aX$9peu*jHr8P0V!qOBjld~H8%Iy_iPS9owY&>UQ9E3 z$wif$blQ{1qCr>}uL5!p=lI;EvFSlNOd;|plK6qP3SS(I-2F7KXU%pk;i|#gnECS6 zMTXdME=l)@av;J z#~r$wUU6vrjgGfVjsI+a+2LSc_hVd^x8=*aYG*qae0@8KTUd<`WWR4^PuuL#VCT|j zFOGc@FP_TKUMA}}+64Gc8OPQf7h`^|?Z_v+UrkztFN1O;_I{2nu1{9Tv*sUY_Ck+n z3;p8w5ee&g$5IgqE2i5t)29xVyjD*2=M^p+JYtW{QT99Zv~seq8K%b)8v%?Wh&P$d zo7+o0F!H(NBA9PS+y&aNWe<&hb*#+CjIho0H)L(92kEB8vQ(H)e}cHB*iv?z`e<-z zi`P>A8Z*{Wm*eJ|()Fi=IQEG%46LgAN0k$xuvDC1_N_1^kw9%`DAhO1?JTCpQ2qL+^M4$b z*kTD3so3mz>760C>;@C}v3NBIE{A?C&53^3xW2N~2k2yPsyB1qbk0gmT7lvPKMIBa zF`@SPp7|%YfMnz+6L)NRzpt99WShy-Erl_S-=%7zbM!cLrSU|zKzvbYIk&QR0`uc zdLx>@wh*c2g)B8`8eO{ifgB8Gx_#1W&M+sVla(|t?kPV!rx*z(qLXnzM0$@)!q}Ns zSw#5WP)-ENO6fWES``0Y6>Zq&_XSRT=jMMzHgfz+?1H(+8+7i@LT@0-uU+{tj3Mb4=0k?l3Ek)e&(} z*LWA*6)-ENFN2RPUWdJy*9PXa9TL^C{u{qXy-}hU?lNF3ZVyWal@#q4>Y*;Apa^cq z5z+1l#`vMF72}`1=-y>B?O=L5(QiC$Tv02dVq)+JemkkU_HWLBTVA^al>!Y0-@{a( zpq9+Q=Zh0;?Z$k~y$Pv6wK`kkG6UWQJLxvHA0FE;-grKeW*lqAZIiAaCg9Zhqe}Lm zL!g`3^6X~alZra`?B)2zS^c*7q?jab$(FVx6G)7Yt6syt(2}H7J22<@94d_3$*kL` z=dR)R`^pbIvJ)#rT2gM;Rujgr&4>=)Cw!0+`z{-7Isz!gap-#+Sk-#OBgDOxMHWul6re=*0zX-q<@{=Z~!!)D5-$;KG z%@w$mBc0z=veCNXs6;w#|0305quu*wL{_=y$`kGxOit$Gh@-8a9RczZi|mYtz5_Ee zi|#IC5lTYwtnEgtJ*yam`>BtRo8n7pG`|y3_Sh!Oq<(a+<UwQ>XuV;HsHraPSFG;yv@TnY)m^L9zNINvi?z_%D-P~^m*T^Z! z5VSf(G>De=CI2z%(j)+KrG1#pwho1R4`Zs-vl5p?+x2g$L0g0WB+RT!+Uw>GV2;pE`KgyfV;aXMs96ZEv=$|j}Dp?g%xTp z(UFWu{!J@!OWdeC48Cx=u{*9i2v#iG>}t$jTm3p?9l7H)=i0)3&hc%^(53(8o)5ym zHeGtDPJK6m@mTT$tt=|Oe5C68lkrrIumM^Q-iR3v|8=7y_-IkVTC8P)(Bh0|Jq)~& z*j}3V?8YBTo)B1`dkqjJpO2$i`bhou>3mC3Phc#|PDi-2YzATY&XL#Le#qsi7VYn? z`M47jNEf1YYg?SP|B%xtcupTjl^iYNV4%55j<^(Q3S5vaLda%0vq>?;F5#{Z~B&?De zhY%qOn?+Ijk0{!hd)jFvqNgd0u)_MW60b98cQLnxN(ozn1`gF6_j**CO-KIQ??vv8 ztJ;7Y|9s+IJDS|c%Lt4Fs3^q(T;qi+BjbU~sML_(#8$42YK~ORz3PZ=t5sji5%t#& zGi5HUgRiF5REo^hgikTjC7s{NFSu`ONirJ2z-@U91&&@`jw%d;N{gQ5F}~ZQT|mGt zbgSmRIB9&gP%;21Uhz>~1A2CMXPin`!QUqbz7|AvuDlO5P7~*d><@X4R$QpmD_$iO zQsGgC*^S|>2*uxOBp2FpJsgl<2~QwhHA_&xXb5*~Ye`kyyV5`1Y$`o-ITs+48{jL8 zrvFl|{LLW_EuGA>cnydsCXA@Z^ZXp~oPNX0#Uz7f>Gtsu_0jeV@Q$vd_BCK_uz9=P zAqE#a+Q(Rh6GH2|5kB~#ew+78@w4Dw1J;pl!&-R5uaE5>&Os0&Whk9muWJsbZv9a5 zN$aATRYsl{8rhY$oKc2mQno2T4cIb~y<~gQIcc?iTlBl-vL!3USCf{;wL|_@h771} z*b;=ja9mtfpeg%IFS2%{Ns3o0Rn1{gwg9oWV_cNTW$x)~>lw@=>ZHOx<;@vN|3DEl zMioNn1nE6VYrDk$reBavWw!)HS5;DVZ`rBvBur1DR%M#;1J#sH5{yiqEY3KhElck|j%bg3?4mHVPMD5hH zs10Z4MYn{BUIR2B(=A(J)uK2X(w|eHJp&_A$LTEI(KnlKd`<7vO=Tsqg50XWO1NVH zU~E+d*yXaEwL@LQ=bL!X%kdgem$S}-M4E;$=Kubi@PmJJ>J!(d!iUVu{nd1etaFCy z|AbXDX_t!)l(h){na0OW=R8z zSzGd6=E>d-v}td+-Sv`9B2wz0!bL{u_?8I0Lv-96y=JHW$ZZs8|3>I9-^I!~k4YT( zUNMe5932Fub5XgqCauGcf_zQql1(Joh zV^3Q({Mp{m1~UzU8VN}yb6x1E8ah%n8X!B74s(do<}JSa#&KRY*obD7k^a-=<)j}? z+Wk;Em!BKh)PrXm$mZt*>tu}@ds1m!+PTq=CE`Fk_?&u+27#!{pCco$ow}k()XcAr z(EbeXVn>zLaw?PCPLPX!2iF}!kq|<`jGR(LJ-Gdwks2g!DX>60CN?Dvo3~=5IX(Ud z!@t77z!%zDR=o@^ThjYC&8r{E_fw9?kc}hvHI5@{NWx)Z7YZ zuC~ZNbSmJrcRq=r0T%)OiR(;e!Fb|7+b74pqK3N ztA{RHxltlsB*BR)pWY6DA9xe|RsQ|m*iv12<+(}pZ>#rx&lo)OJ8*A3zFDzmO{>hk zCu4k>vI_8Wy8rqKqDu=1ELwkeW8aftfO2qyHO`xuS`__yD1eoE{ZJl*cm_%t6~^*L z_?DMc2qD>{pl;oA2up~9K-vM=nn&6kUIRh?L8JVtCJH5*8;9y1`|&@zWq|bnNs+pb zmGOpZdDfu2`BCMZ%LQ8?d7c}0swaC7(7mRWCT%^%M1r48W&x@1H2|*N?7&Ce=T_uk z;?Xg3#Q0tz$6m4>O!aVC7YK`|is+fRL^F`{JBC1ZRLSZ?QYSXH$Lb|^??xNB!WbLu zdwdFgLD-r+d{M^&l)b^a%L7~p#~r%kI@Act*CJqd1XaaEmQ~YtP#mqTDqy7@qwT7x z=iPx78=1FABH{FX{6d#?oe zXEgQrMEh@>_Ul#DKwgeu+>K{<1H!+AkAHa1{g>7GKS=&_{{XVE@W~e& z+3`Z@?uxfL`z<4e6zRLNzx>v4cQYCyk7S*W2KEa6f!8v}uX~nkiroe?2D~5bNStQazmKf?8>as|`)TJ0qzGON z7JXc9rJ7!qGf{DObdg~u1j!2}+oVDNO;Hu8w*Jp3s)k9ae%4{m`T?x94i%!Gzi}X6 zxF3v8<*!mdr1(dUExfZ3F0^EYc(pA9R92H<-O1J}i?@zJob^W=+vn}}{@Q2q`VHYh z>aUTX>XcUQ@^fPwpsFyV&xn!cgB-9oM= zRT^g{{9CKkX%$D!iQtI?rH0LS1NmZXuUMMt_pjKU;Ir)zvH%ku^et);F5l zaZBW`9Wtx|uU~I>zh@7~?<7)G9cGF$nsXja$)RrN*@8EpA>7tVN_`0{CyNY>k`+^X zr}C8GKMTrq^QTs#4e5``sYjm?1eZla8{7e&QQGHb2=H8ST5?z^K#GJ2t+B3>eUC{&z}(Ee0iwUXex-4#Bs*)bQqu}-5DoA991}XBXeZw+@j_ z)S?MOKzMvTrm7L^f9%e&+(JF^;8&1+3TlG2iG47-kw1+Rh%a_5{$S@04F9>>$8lyx z35<_+%oNYDYQyGWq9I>?$-$GeJ!5cMN?lrkgWMlsrXRiN{^i^(&O3FgLe)X9Mr2GK zp&`mckm$S4%#ydIO>f&lDQlI~LR}7HjrRIlpBb*uPhm70Edx~pW?rM2%HzaxbJho6 zOqCmMS&4x3B7JoT3Gd^&P7RDl>hVZsrD~m-3iF)Xhvq7>YnC)qouNI8c`}W1O|`yz zx;}7~bLz?(Zino54lBul+)7|^Bc>G#O`xW~-T0uxb|<340Z}*=c9h#Qn&dqv zN?`!CP5n5_n;mp6Chjh-c>%LjdXN&ut&-8Cb(Pi@n>bCnUF;1_W>{{9YInQ z?2c5DriR(^vUFoJNF@y&6vMiQ=ap{vezvz)`-A7MvwpFf3 zxWVHXH)jb#8T(y=U-sL>5-=HCFXzsfF;+-z4R0Z=$Ruhlg@=~v9?wa%e(O6lF5;+! zRNOW2n*)=N=cl2!9`AdI&WL@q2wGtSZZeqdV+nGmOK~sUNl|wC3@YvTK~bdDa)Vv! z5zu66kVn>f(_aW#f{B1m6ePcOP-0;#3!p;O@JgJ~Nk>h!a5y^1J!XPfr}UXB9|Ub z2(X~e`y#E%KK2UHZDyYA_oSre>^q)o04!^cmR8e>$0F<+P;r^5-@jt?v_;%Z85Iim z#AmXJupzm?_Re)p_34y?$gGDI2boy7B#TTjZTkT5hdl)ujTo`{oWZC3W(Z9U_v~~s zIeQ}YQf)^8ATkba?7ijC5;Kqt)AlaGI!+8I)2azTB=#JgDGeNeLgIA62kp7<7wJbu zr8Y!#zm7B3aa$jhHdP@}C;e1O#wbTGN9jZO+GfZ%Ntw2{G2C)SAgrQNM7ZBuITGh+ zLo|f8x0{9z_z*Y|p|ppUqROKWH_k4bTXc=}F*Y%?MO_1U9rdiMb@>}bc3|ac-5k&Q zVjxtcRh)=PxA0bDVO@-cRp}h->zU?7T)@ED#zY!^2s7jE>T#$r>c$v#df#bk9p>{C z%x?t;^LY$_yiw=dYid0KJjL7!1PDoZv7(PkDu;#k`E`UC+k5!`px3Lj3gpZ(WGdp3>%zQO5pT1JfyRZk=*!tpR1KY`N$O;Ejd~<`(*wXJDwHRKttyZP0i745v>653B zJoW0w(XTslSbxsc%#?&{LA;BJydp>=30`Rvz5(l!ZzCNo3W)Als=(Xg9isB?Wt zg$E7o1BUa^2&N6{uC32`CYfbPNdFlB(Du}1{qb)3KC?q*@{jLyDZcLeIBHGL+Cb~m z_4!DmtK-1nYBQ%JSl$EnZB!xT;%7`@6^xs^a|ooCj5EeD1SNsqwHi6{T$$2RuszqHeg|(S`WML!6HFeFFZpkyVdo9r8M#wCW_Uuu81JaQ; zbHo++a2AncqHl8P^)mwT&E(qRFR!8(9k5@Tq|tZVnHaA}&w1q>7dq#|ZXd zbdglQoo6h+UR`=fr9F*JN=lj$7vMt&m<92?Y2*=z5Wy)aJI0Sm4TNPq#cA3;>MxEK z47ZG^-huqNi|-zB>`YH4n{w+bM{s6V6{HbyTyK;tkSKC88XzV+i8jWDsn-v}N~A5) z?w|ccA&$|)B(6?w4h$%Ghs)OZdWK<~&Ub>Mk-72W?eVnrxmfRvY9qx6D@wgO;!K#< zq2U9><0N7H9HDs0?;vougj(bK*HWNKY89J?B~!E~IB7g?AK~nHYM)*>7PWK-Zs?fe zo7-6(WGy6Sqb4RtlpU%txi*cv-zL8w)%_B6E0E0W99g=sf%fy46%(_=ZjUYfDghFE zq%$e-Sgx+M3fFMVuCnp_5~niM%&HObAv)G!4|3qnFk;0Y?__(aWJ)w4cv!MW~?o|>!RJ39$b`8j@ zpSLnqubYcA%WU?0{pa380W8bqx0|Ky(_N;7`u(q}5z9?fv!(i#Jxl9TzV2I3{~LSn z9S&E&whc=ax8ROMbdo5O=tQrPq6RmDC_~gRWAt8ANz_D*UPl{dv@ymgN%S&;!7zit z=)HIH&b`~SpXc58-urpq&qM^Rg7bgy-P^yz@Y`C(#VE9Bcz*;7sMFd`l{HTz`=0>=#`-OKKh ztrL_Me#`3|A7VN({M4$R{vgoo92j|#g1Zbqdu9+}#+Ov*Y6;cSHSlmX#x<5K9#^S^ z6LoOCkDx|mlk6Rr_tZ}oj)`L=aWr;q-H(Jho{({6Ds~MR2QJq{_B*15ueyQ;;4t`E z{nOu8+XjX`b+pUzwho!rSB-Al@%FSy7=LN@rR5kIp}itJHA<*xmC^$WwvvVjvrr=* zmkfC3aB`Jz?{3v)c96uu-4%T95(43j#F-#<1%E|j@!rHZDJ(r(#uc^&jTK&j2?52X z(EXkt(>>0us6ZWh;gJukUq`MQe8oq&ZTC0d=GRCOSvzK#o(BzoQhZ4#2{27~mZ%)r z00~+~@O84Y%GP(M1*i4nMK9+Q_0ltH%!OB{JQ7$Ao9wFHMFsD)eZApF%*#t0`e}GUyt* zRkLZ?J&;#lX;*RkTcd^bC1YQZp4WPpVjodBx2^ID%;J5&Nzsu|1n3i%_4PoCHb;9k zlAO*rA;!xox$;YX6>t*)!AN02T8E%o=@X>hkW)u%I3cQ$UO~*j+XP=@wg?+7X8K?` zw_LZ{$u<{Gr~8iX0k03^^@Bf$zN~8}rnOC^_0LPfWj|D0KYY!WLR_hrH+(h zJWayF77JG>hER1fe&<>lOBP_wO+&j9R`O0OODDi!Q>0!3T}fW-5&@rm?E|1>lv|6s zr-Pq{2!j$knrlI2y9LTHki@{C#eV*B}l}{)4 zG@dVy#U`ODA8kNy+x``6`A?hLAQLejT(S3a=l0+3*aWy}rn?x`c-yxlN2{K?*%6=5 zGbHaDe5&;5`$Nd#?_1k{MR(3&!oz6RYZR{0u<#_#zWYSu?Bcd^Ywz`T-pHM>zrrj9 zBmWYI`2)DbrbAVO%x%LauF3<5PObPMA1*cXww^rqzW9xN-(Sz+@6XFBh-HD5Rvu0r ze^Jjf{m`4QAK9|u$C-c91xfY)8y{da>0c2B{_cbwK;D~4!ry=g5mS{N!;HMiKpNZ+ zZHK({XD=T7VTT_~X}L-3y;yQ^=q9`Sawk`qZd=3!^L?y%IET!YR&*0}$3F;i!EFQi zBExDWS3M7lIzWX%68Lodj%Bz`@=PG($(~+nH;PI1Fpy;>P+j_fd~I#%&`Pq$%>m&! zl(R-*Z&NW`;?HsQO*t@#)5dfSPiR3kH?$}KO@vF$e25cAg2E*Z45uvwm^xmlvtF!l z$!4CmF2;rbfFKv+G%+v5<~XT_!3@dSN7*$+z_uHoH9$oCeZCHU}n)ejS;j zIRAVQc_-~LFD3`guN8YWm!WK3dp(Aq*UW@DgaBJOUeHyv4}UMc6K8U?4^A|kbDG(E zNt1!nsU6L3AMTi2vlW#4GB33nc;{^z_-o49?Vwj6DYv2CP2@O7`HjsRf~H#1bxWtB z{g9f%pr9`XE#_*%fVO0;Ynh2J?qx58t7~X93X9F^bnwDFY+5A<#(i@QE0_AZc>yTb zOZCZX&{4My1TqLKmIrzl5|D5wHfJMR)$5Q3rB)fNCG*yT00e({1 zFLQlk2mfVB2mNQM%+bx>l^9y3&TeQ-URXc&6SA*>5u=&+h9&dpICX8woM#MIkY6q{ zZ^D~Uz6_Zia-ej-3)O#8#k~A>RW#L*(n@1AVAGjk`0w@VPp0Hm^@fLc+7Gts>N^5#@ECyWE}k zUJr1bZsHY>>I4s^$*x9@`rYm#pcAT;rGe=VX3#=|^DQEa6_3>=dB-OPHTubmd9SCo z`M26M*PxdQneNV=4DAhczQNv=s>1%HViFy|=j7V0TV3T^yX90QAK}zGo3w}5xdGfJ=ufq7;hB4?)Im+YY`anQBGno_&c=WX zVaU%-)nWdl@u(;mr#v?4-Z-tTue`kk9gBbe2uEo9+aOilOrh_$rXyf{Q~1WTq)`CHM- z29eW~Fcr~ZJg7;A~#ByBEZrOjMDquHZWyqo)lu<)v)X)Ojjs9vT~o&_7ZaVT(L zyR)g*FEU_f9Y5MARg8Kw+VC-%H717ir-!mg83yzJ&^|(eVv1p*yrZGl^Sp zmsJN=RqLw<2q59wS9AGW%%!KsY~K~AE0ukQ-)g)3n!t4-Fh4FvbbMlcEnGYjtlC)xM?V@g6;uf{t-q6^$^x_$p4;O_<(^C+2Nx z8l<3jD1V<^DC~m)_tlrgV}=CHL+U)7WctX7alc;tzbdiEe9Uj1Jd;&_KAdoqB6>uz zPj~Gh;XZXB@2id!4p?Xe(LYaF(AE6teXf%`Y}0$!{%sf6VArvMMU~bf%6fQ)S$t?k zs!En>z5-!=mG>Ncfoef&)4=^9B0hL`@vE@(OmZ%CAzEXv$uT#7%-Nrg5Dnu~ zj=3G1Cay$W8^Y8vGgJBgh@v&m*;M<;r+~$sDVT^Tc=}=*bXo~>BzP=QPgjFDI*vqE zJ-?cCC(&$6^Apnen|JEw^AFNDyJVhvNMU(X*i;Wup$*T{K=(pvU59ICjnh<_-l#8Ku7B)2H6l4l%_OcxFQUjKYJP-i=<@KO zREGpn?U8XbDo{ND3*O^{;sl@D*AN}#F@T_+X-W_J>tB1&hOMAO`&4-!qGcN6KmrF} zNy#S3^O90IL7vXmX~w@11g6l+!zAXk71%m02h3p>l

Z4u_B_-w}1!>zPY27yoQ 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 literal 0 HcmV?d00001 diff --git a/intellij/highlight.jpg b/intellij/highlight.jpg new file mode 100644 index 0000000000000000000000000000000000000000..59aaae6aa55615c3d43483c574e1dd6c82ab2eb7 GIT binary patch literal 87206 zcmeFZ2Ut_xwl*3BMWmzjCelRONADmgT|hxvXwpk)p+hK&3MeHI1f;7FkP?s*dJ!oh zG=)IuHMG!sFPHC}v-iL6x4-}X|9{Tj=RWs7d**r8vocpQ*IaYWImSEQF~+J}NzZ5pcESLal}H$w3HKM9F$Uj31Zl!WxE_W!V4eg{zByq0^d zmXLrNaE+RPkecAK4Zw2MNkW3(3*aw>km&lg8wA8RudY6(0uT^gBe?20F)`s)CE;}f zz_qLE)HFA4bKDWRr%cQFOyBxdf~bTF*aucl%w<4lBlgJ4JNz@ZW>@yh;|t5%r) zt^L2f1>mYpqU$%Vt|?sg9Dz88$khBn;bOZg4k%P{~M;Z=vI38?`}fD4&@Z1dtJ-~f6F7^t_?XR8}N zo4)A31e|EwBn%DdadeB8C$?jUf&W(+6pTmmY?4$7)xHAORn^MHeE2rE69`VHjg z9J{2lAzqD`3RE~HkNPvSD)qgoM;B_B04IZjO!3cu`J(g0`4PS$@+|h^SK7ycxa^PU zjyd#A+sGPkaic11&&L`am*`6Gzx>*?APG*Hx5K_8b*kcGtHoUk>mCz!^JKG)9cb2J zW9TmryIUv=Z|N2?H=zk+HPa0Bc*8%xgUuB&CfFo{>@g|XBZR$iNxN2I42 zk&3?rBs7oRHeh;s;=yqV;0&we$rI1XU)TX}Zv@Ln@@y!$hU9Dk_l0ykOP>A21X3O| zpMQ49bNJtACy2Xp2} zLCf(r@sGINisu$J{PPkJ;Xc8TBfeFeq>;599d66=_a@fqq(QtRVeUNWXFZGS9*=C% z14)C*d4maQpH92{L}k)4oAq1igCx7z@9(1{M_acZ4DNe&X$gn3|Hmtvd@_0efAZje z+vUHR5Rw1!+!7*x``+1g=9T6>4&DrQ{2va+zgqs+I6ss9qC!}&R4Wi>OnjsT{}5HC zw9aSQ%}!w#n#_KVRwlZ5_D(55(4x$bQy^>MxOv;LXY~@WBW8oACtpc9v(^c=!yOli zgZnYrfMxieVaCWJIJ2Vx8ptf@3~E9~eg{ojsqkCEM0WBfoBQ`Xnv6W`@RD=!=(F=r^fQOFRjU1V+^-iFRNQ>PG? z$}(?nR0%U>I}2@6vJ2Ln>zZ!wWAJ0`GDvTiMjMy1s-*5pY@N$NQ{Sp>-#*!g#pH}3 zW>fe+(7}})1Y~2|o|pPA|0wLDSz^9#ZVX%^2kj5yktu8C5?%4-1tRLcHd#FwKdUik z_cZzp62w%EWu^>$J4m&TX|5fUmu`rAxI_4mJ#6u#U3E-h!J!bS?Wg8Udcdx=*I@qj zN;uG0(D=??W68LAs9Fb`R?_ltGKom>+mY4S%3}+vvK1C|8aB>~ElT7i^UT`WK_f$k z?VTY*t)u$<&8?ZEse}mE(IuAm?v@pFZ$4By>A!Xxc62OgG%MWtB8R%w!$8ZAg-IDi z>e4(MHMP}Q)Vpv#swEHYi$lfIChmji?S<&yPKRZWtPWhrTKMnVbM1G#q(?`b7+(Tn z-E_~3MmL?7#Jrg-Qrx7$v3GXJ#34^R0@Z6}f}6^k%YFQaW1Rv_lRek*+K$z1VKj}b zn0-E5;j7!M z^$VzPEDE}t^Tb|gq-}xxzC!{cvtrm)IU%Y=m^pfuu(~JV09nXEX~rAplPy_PpCwxxrL$>K6Jk*ItDrJ1!wnw48w(adbD@jUDgixzmMF5so1{DQI4H{bxbZSJ`d*^ z$PH;qxwG{mLLN56l~g@-I^DKsQnNgQM?I4I^mVaaEH;v9ph+E|4Fs+~X`KO>XzWll z4iB_4=;h^WJ2u-_Z-l^Sie}M=zje^y@dKlqqi)9r>%!NqC^UB{zN22Uy+@eZihrKl zSOAL&;2Tj?p*3g0D0aa)KY4)hlcvuv*0``q)67H2OTc>XdOLm6jENkH1U#&2-!1Ia z8v<5!&ug~jjzNvaj#QW%zJuNTf?(-Qs=wXr)u!dCfE3^YQcd7A$KZv5cMmAy_@1g+D2m-{jpQz8Kbo`R2Gv|3*+>%8~+4 zc~jQ6DtIA_HxL)b-z?;(XpMK0qfZVM=D~aVZdTKat*P)2#wKcwa~FG%NRYCR-(BzB z!MYMl$DS2;OX-%|6x4v8Z@A^or2Cb)xr`+)4CRui3iw!POW8*>>!q03>3Xx{7eVZM zt|btYhve)Vz@H-kFO1r&x!?z^p&CC#y~i#A6NsP@c*sR-D8{`SQY8L(BU(7Q_dyMW zj@^Y%NX0In#r^HjXMcv%Hi?&=juh+8y|QfLG}@(bvN&h1K?^(g!CVA>^1ugMulLh4 z&?R*v?KOcQv4(9%xnH@I&$=9umv;@J^8krL)KSfPv*5Dun5{2S?%`RK^W=Gt+Wrj{ zU_TC?kok(`DLY$$sJcQ^Sb7(3=<4TA6O$=O3Q*{yn7sU^A)#T7QFk(b z{EseP3veGpko{5?%dvmSeBUGPVeq@d;h6&6XF9y-R$iTGaa^~iTzuGIYukmj$ zgv1q_mHF<$Xbeg~SO7v zEdqww{6fHfPF48K)0Z=u<>(|Ts7DujdZC-$OS1aYa6PWgKF*u*F7e{9xJ>>o5qq!Q z7hHuDos*-k$z<->VZII|&FP)>um7g$Ky4E?rr(&X$kKT(pmYigCppWZ3A+cZw^>s& zRp{OgoBNqMdYe?Hc*34T@TeN(fYa@&Stsp(8~20#nm5`@Pd7 z{;}EYXb!IJE}@1hpKQRpI@!4>DX2cv zFQC-Ez;Ii);5M+-&<%OVTFXS<06bv2zyuDSUIzw63 zw>y8j+R<#hdM`Ic(a>_U_9r_ojAT%oEI&w6$8Hebg#QWIel{MPw3&@L&Zqd=VU{IJ zI~UjHCX2Yu$P(Pb1yevx^TwYVvoJOz7-hAFz0OaM6`}A(rskuDqq5pAUD43NbocCR z%JTx}P~r)$ADH!d0T%zj%&I6>a;Mj0{^fG7U;BP;6tCG~e`oe~#ofKst&o4Ux~pd| zSt?xmBsgfV(E=_|o{!{(ulT!{Xg$b=35`UvvQ&>_E&-2gah&%r0X|3O{brA<$3@S$ zJhD2E8YFyR;a>ZO-HSCFMTf^*0cCn$Gk$B<2x@CI4@nX~cQ`>hO|9zij?OP;|0-_z zF>6`5vDUjXhQI5YIi)uTwAx;ldc`7tyKH_ACmFqKQ<4J(Iic%k z=M8Ql6rVeEb%x~(AsbB>xb3V6R5qQw^mg&PVjUe#O|BK$=g+I^n;q-Nree(d3=uuL zB12_s2w>Znnz&*;XNOKA7^O%lCxmbTzSNssu0W#iUS(AklCAC|WWmC2z*pNRGUN^O z*IY{k`i~AtO*=$v4=ik=pW8wfV<^6k66w5dFr)WwZ7NNU$)b$iT!IgO+tKVONdg-q zj{~wO&p!GD*rr%!n@Y$IF6Axd`;Hf3>Za;fdg;pH4R7mpeTnOCjU1i6`le0g`G$m{ zpYu)VI%mrWZU$uMx7Ouu=9)7z%#1it1SPw&D#~l>@M(*cuBaIz@QGmE5d22LWVKI* zZ-hkLw^Nfb@VJyYepLgccHIWcFg6wBL`3h_v%BWMRxT?wm^8I&Up4e|1fRMu`ZSIO z7O*EMYKc790H$Nyu|tew3&y-LAHH?&-qtql+$LIkwX@UYT{LoDEO8%UewZO}|DPgV zutpCb`a2$SLsw=l0VL1M6A~vsv~h^aRk4^eHouWR;DKXFH@mnFVZu&&8rYuK=QM-DToCw3j(I~(2aoIYB^H~e=E-)AVT}Sa|a+;0} zJnaj;$=jaW9X!ymwjUZqp)W3??|i5c5kFGYF>0e$7VnoSE^p=1RqFUPH=uqA;He4K z$W3?lC&F;&!)jGa;~HYgK7=1AN;c-kE^m8s+B&LFqb)dKPe<88b8=dTBm|;;eK5|O zU6q)8tzn9HwmGRi3d5WToAKO~Dm!wa1zwtUkM+3$--GLYfrb-POHVvem=@b`O(AM! z=fQuL})2quK(sY9c7gE8&Isy zgjw^(;_>+RR4wXO31U_u>JkYlu=^#TK7Gl9@aJCqr;VZ?)%+uS>KrDfoAI3M{>(qK z&cL|F&5o2s1+E<-s90;zURP0izTr|ZJHuYhvFCB8h+6m72SMfdT84WKWH)YnN3{(j z+YzBtEZ8Q4jm>v$*LNz^l{5v?e7l5x3q~Jgq$TQ@Jug7g{ut$@o48Fw>W@MtG?t8f8mp~_935qH&>P=d zGq7>LvL;8|f73X#D}e;4-eD_dtXEO1ydl*Ih5W)+&m@uSiolG2W@3k}L?N0IOFJVN zJJ0E?H%8MjzVAOe*GF(zY_;%JUdXw($<1xg#48HMW)gNy7`Wh(I1l?x&NnN^yIV)u zq~MMX7418GMwM5H&14y0E;Wp4gF5-may3XTYA^#bX&Vs_(m{}=tWA-|2Vqw8yO@2l zqn@{4xBAsBtBWN$qvSOhW`--2du2KG{E*ElNs~4P@4YAchmerURj=DFMM`_C&H$(d#pA{Vp}pR+ax@R{e9&{y1)o zhO50UenzE?!7ynF1l#G#J;~zOdWn`jcKM&1 z>6GAjv)N=&ESWME!c0aNkF|93b!|sWT)hJ+9@(0)yI|AiKX!>W3N0^KtAkYqcFJ#Z z`oJ`1Iz)2p`*bFa}-n*45u+*6ufneWB?1dy*zrqVerm5g9Y+!e21 z=Xv8#VnUuv%+>Acgy`SZ_y2t^r9JS=`#2m&oC-u~n5ad8faZGHWuKC?Xxw2FIK><~ z=^(VGb7g67ot4z%2f8hQhg7U|3JA~y>PCIACL2ZLUR5?%fok=gLv{XJ|BSi$cQApD z_Z-eYYCGEl9caA-)ZV|F-6g`i!(CJ*)MlSJ(JXZ#aGV)-q2_9FZ?;kY5)i{z8j}$w z;ppS`i03w^ezyy;`fXP8kG3=^si}=h=960~0i)YzFd99UFRR`5!6g?OE1tTnek>yy z1y%5|#8{^!a}TYlYIt+HxPVD}9jSOKokCePEzo3YWVB}#M=z)}ostqhxjJnN;V*{Y z0*{YcvaC;Uj~pL;+t>2!<&_I`NUJq2svUNGe*jFfy0elXQIxbJYVFwB%mz*?=??ii zW7ms`3cx&!CwE;A=)Z2BS1v7s%`A=H#d*h3Wbvuh+4&lfJP8oU&{x>NPch_Cw1bXnHRgZk%RpUr23bKK|C_ zpJRvB(K6e}IBce6tr@jEK37WfT#2!-#eKHCzov#M>=#Ku_0VW?PK4|PQX;`E=_mb( zxd?yZ>E^`c6SMxJOF;C`Xy%Mu9Phej75;eZ5-^sWG86LSiJ;LIFKm=T zK7_MIS_;UF(S~vyCDmBwEv_7leQBx>F8--$8^8(8N0n+1jp=tkfanKV=KHP8e9{6p<{4I15Qta+bT*wDNQ6t~hGmQ5Ue=j2^0 z>0V^9_7G~+Ko9FtWE8tmIS`Vi>wJEzhee2XRd=Ij3Q+>Pfu5Yd;D%oU*j@)vx3Hg>pLcVj&mO{xLZO*n>sN?L1HC;X!eO(^s1iDDMD8x?X?r$WYK5+cNG%~fnJFt~q zh)8t zis=Xy>g%+xS`C`5w}yPg)cqPN?HY<^q`LTgqU8*BNM9NGE!mIB+`{m?#F_Xdz>7IQ z`0TnqI?%VSFqD0L6LGX95UAg#&8^$kh!c>}sA{#9 z%0nzN9>pH4_sM*K$a)g78sGox82^M#W)N;{sSP>u43aGl@z5)!qgOI2SNB`ug|`N| zEMn^#1(9{5rbJa>-=!{7d!~C%tB*!)d-Q+n?S0h;GTpk3fc4J=jtsvQdK#UmX(3G9 zG{p>w8`;`71@9d#$l$$_^N_0e0)2Oj5@$YH4;TO1UE26B_fXv~WVY~%4+&ML@v2+H z_t&Ulju{)bbn-i znGN-;XsW&*+Wc!W?eX{*u9;$||uq zXyN`Qxp=vRAv2P#V`ng{abVj1NrB7Wp{z}YXFYRAO|s0GZ3)_J``UmcVIQiu=|s+a zK}udktEztP5@7Xetp#I?Kj%v}7#obeVTFc`gNtpaLH`9B@fohRG4W{fD9Af+;i^QH;g#@q&+{gEKVkOl@T1uzs zsb^NFwVmM(7_B}d2CJ@_oq$KAUY@Aii%t*|-q=mR%ULu6EHL898P7a+r90X%Gx=nq zqiM4Hb3U-Hzp9O0u3VeNK^sJQ4!vX!ty}VB1X}Vepv7FVr@4&9OXBo!y9y>Xb7YaN zmtbd7RC&e}_NWNIBM?pNm;G9A`I$Kd7qW1qmM@}GO+7+UrT@@mV2K_5DI5KqLm=); zX*R5S=fPiXGipAr%nt}nUDwxl!KFkA?OfSBjkE2aE&;!xF5Y?vTC+so4!N?)(1vG% z!OGW`NsrCh^ll!geki^Rdl*{WIdG7Gh^(YB35HStN|p46W>*peEa20+jXxtAhCV&D zd}&$w77gq$?J+K4*H2|Ve8*hV;teEmKL#a^NFiL`E@c}=vpLNq7HG$2ol5;=;aNF- zWq=e0HIIdPq)-Iwu>q&55Agnjr8*lFbT9v%H6CpB!Ge@nQ_FmrxeN&*J7}?cv2Vxc z1`gw=bm!KkAo9Ae`hj1jZ^&??lfMl>?vxD1F}giZqcd^zqSs_}N~j;^N!*ayC3XJn z*p)T2A=k@}*MV9S&`tN(4kC!s17Ls7oH8LyGwZr%-7CZh6F z96}iNv~BtrnK%cI$X9rnchtp%V-?EldMu@=puy-1Ab($7gD{I|fuH^JGY@Fg{nCdw zNxf}0jnU2IHWWjhi+h{zHpp?jLR>Vuk=a>$HK?yBd473|_M&DXkqpP%T2T zH4vLwr`#;$(U>w(IH~zf&Uu3y!6CX5DYuc$Xv~qs!@~M&5FfDValHGZddF#z5+ykTIAPWe5a&7q^vXGL^+x(QXJoh^Mc)rRbZZ+w#B~r<{ocRP@SvtJr$p%) zTc*CAV`!IuqxaZc;rnV)I$@tAhEIONvDN~9Og6>n^eag+`Es{x*8`?Joz%@^YKOm@ zlMm8!%I}*B-ADhmqVY?1N_L}Hpzki_#~`bH`b)qNw)x;e*oC;u()w*myMq3d^thD_ zi&VQ(7L`F2^}Y_7Vn>l`x0#65%>d4I%TjfFlb~WRU!#&$)K6&7VUW^;_95HELS%2i z@%C||&xS?$KDljTGy}hBnxyH5e#uBHLH}?|UVx&u?@?OE^UmK|qX_Bc3Dsz3eCShM;( zql=~$_W`3nkU4wr6W0l*cynIL# z4w4(;#e&={%}V)^gu$SyACDS2scc_`WCZw(7FO zyME_S68$Qq8pL)oxP;LiU)=JE65W#`E=N9RXV-HZ|E3lF{Nt~6N1Jbps#ljT0fUyG z>P|np4+SF7Ptyj+x^0{DUg81o`UJuLQafDYs|ml%!PY72%MA>Jj&7>jffEq9wGvGr zLIg4G^-VUC5i_dc^=)SQZTM&+E$9-k$zN9N0sjD`Zl1LsEV1@BQP|I04)8HODW+)` z$}x+zv+PL^saZzW9~k5dL#l3VG8CM=E-ecHNgsV`W+}5(50!qAfap}d3u2pNAa<9c zo_D2W=N^*(g|8DB9ZZkbg-CHt@u~YDPIY*0f&=9eeFTnNJX#J{EWPLLKNb+z(W|NR zG(D@1pHb(5%~q{;B<(YBuxp^?_Xl&3@=4BHgO*+OX_}jhloEmya$j$4&zg73Gm%4| z#v z^8Aw0Tu+Q4lbBfk#ELkS*(Od%&tOvPuodu?akbgt4Uiu-NO$)4eukWxy@OH#T@gS%|aH31hzx_1#h z%$9vp?%{8gIkc8lf}IlfYvR(BYAOANB20pE60QFjd_Sd;4R>pgagA4b$mAcE& zG(kzk3XO_b#sA1&54o9HIxezpVYKFWVwTp@B1ETYk(PVUu4biNM}UX))ea$-{n9&c zKv=!ZOVU86t|aBs>A(`HE5I0n%30B3i1F7QiQ5-SD^;;fZu_aB!cP{xqio zameQ{s0P$L|3XsBmAwChN3eR+f!NZZDM&1L+FvTVQBtvTf5}d!u4*wlDY8y-E6!NX zTw+aJp0LzjOi!!oImkds$viGH_Y&|->D<)uBq;kTXo9Ks^l@vrd!oJfTXfUMHaQ{Q z5>7@jVglos%z+lA?-t$2<~hQHP|#eEYWFbCV0dN4ILB~hTn9f@WSq1+@eBd$!MXY7 znOx?y#CzTQHC=+()3Is->#L|1*S{fc%%xAX;eDkRV@39KNU>PAmm-#AW;an!z zAGCbyNCRATqP)KrLa)3Y(LL$5kuMIbA*L(q2`yH`eZqc36TjF#{}QyX-wj3R#})9u z$Bb)&-6Td}n=Y0vN7oA;%zRm{e`=adEg#8v{e5D`NN&lBpyHxXxw-z^A3%UAEuwHR>aj_0-lcUt_kJQqI|Wh zD2gYGgM8s`&-GL?J$nq^MzXz$Ft_|dZD2?-mYkb72GbuqK7iCty&{1UgNn8p&5>zh zwgNT}9^zzoa~ae(8?91?$Y`ISB13ubQxM-;)EH zg)*n<@ct^d{Kh}fs+t0&3*j%;d5ld9dpcQDC59i{rt}1?6MpjTHd}0_DnmWb+pgWz z=E<#WIvjWILX=1u8=C~9eQ(?-efpC}Z9#pf19xx1fLxE83MO0Z8tVaGcYPt(k^0Sd zXO14b$HgX;TEJ894bq>=n8#cR!mN3;RLdcp18@1sUF|>(={~Gu7V5jMuS&l** z3(}a`t$V0~xx#Pq#se$y7i2-mJE9U>2bTa$MDr!!hfQ9A8gW^f9J_j$ADlf z2ZfNg1v)1>@&~DJT!s>Ko`2}{g0h#M^Xq>arZaVQ-lSN&m@hjwXP<*ITmV=q*3PXO5nFoJxKeP?M^H-CEJ~geYJt~oqc9c=Y`SH&8 z$s3(p;-tuhvEi4&l%7?S&pwoN@&A|H_tIsSw{A&~wK6((6WVDs%=wo}lY zuYvs=ni}m_O!u8!n~E6-Q>vBxye9 z17LR<%(x=*?BedrCthi?X)lZU6uyxhDVuH+b_Bj$0=MtXxnm|RE$gV5{S`Iz$dbQQ ze0b>IbzaYxcLkv;rDf_lUxcgIYn&zhWGP$c?8W#71a;P0`|D=) z8sx5IDl&!c$gGSM-}Bj~BgvsbHP2ad5uSvXKLZzS%G&&diorTIwe#oC6dlQI7d-7; zy(dCmtD#L2A@>&Ux40zcdVTx!r*rWi@W%egcK$0I;9ubY|83y_Zgv*k^l$4eft!0t zF`^0yVkC;;Qw+LKZ)}TU7zAA>XJ;m&1%6o~(Z_|-Lk`(|qa_v7 z3)&08S|KUp>6oXu5FLxHbq^hJi|}@HM}vXP7VYB6)nh9R8U%jc2rh#u^{#<3fQB@;UDsf*CF;#3xei0kP!ZB{<Qot2{>F2J$NAGSo{xI!GH9f{BE)TaaI4X z0^DQ~M(yY)5?@5+MRw?*bsZ_v7dk{2+SY&Zz9$U)mG-&mGV%?b8*%So7+TNA{=HAR zUMW3INj!#Ie9YYaA{)%0Tart90fg|<^x zR}af^En?lzfge&~A$;SyrWT|E44tt9;@1|5A@qPnn8J6?bu-;!E3ja(A~1Sg9YXJ3 zzud)9Ir_qzjD{5tB?=ajx0qQzQnC>r<^kGEM7;T{_9Xg8pZ$^Ai*RsLRi)URlk<*S zAPwlA78EcJfm{NHLu$?Fz`~z(Geiy2?{uM9Ly~iowoVeQdoqii7WUHwMF>!{a!Lv% zA6Z0Nq@}T`lURh|l@I)V;mGPM9ExZL2XyoYmgJ_$9T~cMi&qxSiV746@qNf^!`iX1 z(-*)(=P5qOU9oamDvxq-4?!KtT2CWLzDnagW5EUW(f;QX({cf~`BbDGKH=a$Bs%go z1g8(ZgV$#QFJO0AhXRZiAZ$_d{GhAwF?+mOa)~gBxJ&&94lFcncqBwp$`Z{(G)Tq=< zJ=^5}&AiDDH>`bUmRMF-R}iGzXi;L82t2B;ACHZFfKAMG{l4ni9>wU)H*`<(eM}Sq z*LsRh`pTodvD1-xWiCif2?lBw2jp5>8H6{xHQmKEKn&eOjjO#LqKmTe@*zDLda)mH zA*1YMWG(t#5;4D+Tn98LswiIjO*)198LtG9gYlm#v=+1`4KJKAdTsA`rlt+n8=hw> zUu3^fj73}5;+8t=+9XAX9`t-)QUgBL?;K`*>D$Kcc6|l(-0-$9ufwALp?deP3Lo0w z8Q&gDp*$7dM5-b|Z0$f_hZcLa(%V{FY!j!&OAloOFebOX$SBA7+;qh~ZRLrF*?hqw zpC&A&AoY2<%oxtASQNN-VB3E*J_h0Bt_P_72y-*i>#U160!0bu`_ zy1#>QG2aG&e;UwJ_*dycdsCb9Ythm?;_QuttBKvfBWef;HTeNL<9K&6ySJA;O^qha zO-L$CujVfT#fzKk-&Qu=cvQFIf~&Vk@}&E64ECi8j_Zex-;tD=zhIo~;mE*PFe4~2 z@@YfY6SU%o^#ZPvSIJ~{YIr6BZ$jjk8I}R{8lsQ_-Qw{LE@Wi)vyiWwHtWM7jE^PL z1t_e;A2o{1K;NRG8(7(i*VNMHyPy2e;Qv2q=n(x+afBS{+&r=x+;t%`UEftE5gE(URPi6g-4YT*81a{wn!+pTv2AF^>M0*E zlfeRdvaxD72wMufg@|)VP73BxP2z4B{V7)LgT_uTD0|;!~qmGdS5^f3e|_*+8i@pz^w|^wvbFZ9mIfYsaRCP~?P%B4isC zci7Bi^>Ht;vrhge`6}i?iF>AT=2o!n0B)gm>25o-@QSa0SDt8{fU(>S7JLcu0BjKi>H)u?1_fdg7Fi4gqmfvUwfACY# zC1E^H{duxv&AhaRFY{v^|NO%_d8xhw(v+TzAiPb+-6c(QJHmOm2-)ogvZ6bLfXm>( z0iW29tnLhDgo50%xoZ8-5&&G8<@kyajnH%}2ule~y+lD$T*u0N?BZC0gzNwjX- z5c!S#$nvOWz$5z?j+-A;zc1hPzbjcDT}c+?|Cc1opBv-AzvEsSDLjJP~i(Un)F6*@&WKV&VyR zL1`?Q<8aDFSae*EO)nX~o4GRGat~kXtwSv!`ws_Ne*kWO#9jZnG(@=^7slUGnUc+( z%1VD+nQvwI(9qM1KUv&-Q{V9uIv)=USfIBw<6rRKQ8x(pT>ZA#wxEL)8q5GaF2n^H z?KcXZjh4Z};laVNSuC!ea`ex(w$_7Q+xNF=ZtrLL&G~PwZgT{Qs)aVWio)cbw-%}r=_;#T1~KEfOU6ybYY);f=G>Qn!irS8a3dqT zavLkyYr4g@AIoy&AIHFVp=UxC)iea#6$f}*=Kfs*bCP2sS>%$wQp9nH|{1VQG%Jy z>?{ytwpYAC^?FUbTuYeJ z3%<}iNgEMZcA{4At)IArRaG_E2*bd}5}zNM*UJxVXT$$#VCzao{hege^E04&)44GM z_H?+Q!p&rcG!ZW+uf+7T0#`$Yn;IyJ49mO>$em)KWWjH9Hp<|AN{Px!un`qgR#ht{ zZjX7NH{1z>hPyjg;c0KH%kP;HDSBuVlEs}SNX59FMT{t^8p@{#IR{r+eUX{LCrhJk zVg={VH~lv~7LCliZjvm)U5X`&O#DsSWaPHlDG4r&mxj_)b4Jt6_E2FukBu^D9%$$5s5M zU$2btet^70LXv1iv1)1 zTIASrr{u%KkqJAY83y9^?jUT_P|}36-;*2eG9D^mql`7sBx@^+>iVl*E~+J|7f!F2 z!ni>!la)0b^KXDUyDhp8cKb$I$!Ik0IeMvJVGNV6DoU-(Z(IUs`J`HO;Ao~+ZJJ-T z*QJHKEqY6xf4YjYJ0^qT*}LPPVykeFZDoAF(z18+#MZzwJ&rkg_;#K=qlsOiwX+ zPHIwB*_=O4rsCor=%eBJ51jEhxAo0SfW^UrYe<;7I*pd8c;)2ZG7bWBRw|j&cKMQg zNpZ5Lf|~rZ`#i0wawh%VtKvW#Lg){_P>98E(zfBAV1!sb0$8Z&-Arp(HcW{6OAx+= zrjY+u;mD%1v+)l*Q+;y-KAm^PozjZJ23+TztoQvdtmWTCs&~8`jurUune6sc@W3n+ z&cL5;^R%|fZ;MC&jc4y4qVRWW0yvP#aA5CO&?CW*qg)s%aNEEPX@;U3A^Pmv*`a}q zZL3U+VRA5VeJ0}+$-e7oME?;2g(DT8}4~+%hS~RdI&W93cVF>cExqk_Ch!Ea^%d~Gv+(&UP!ri)*J392p-nZu$Bx^bZoTg4 z$#Y-zA#GCED%rKfs{Spxxa_Ui>Xwna&VKly;2l&n%`ihlD)WMZU~f@y(RfJK*=Qsy zuOk8I&gw89ju)+&04Zs`54R{mv}7@uBT*6)??=f#HvMGh zXLNB){grY{u7S5#4qKNTz?*%yZf>;3R`e@RUkJTHuCy&8S1DxP7a7TeY5C2NZ^kPESW01CCKHIDq=oexdY^LvPd1!` z(*hTH!VJDyR4oP1tUnr(K%4J>l4dHiKDhEk=g=Hw$1cfH$>S|1aqK0L$&&s-;fE9e zmoL{Mdw5`puVyJr${#It4ltNHkf+izfir=Sq21d^q{oJIy;ic#1^;zzDPvYv0kfQD zfm#hqQn}4|74C7))Dv&<{=CbC0|6VH#B8MRsLVbAIzu4fNc z{hC90Bpu*cUsk%GBu|N^$EdCa*WS#HQor*k`biIWX*}{}sF0FiiOjuS2fu;Ck_8;@ zP;L&^`c~g#;&eJPawPl9rwSn{IR^AVDS08~t1=VxBdb~|>F!Vxwt--eIc(!u;Z@33 zT4kcey5PaK-M$W=GR94Dero)PQ!C>mBt$H>Kz?ZMeJp=*^?kIYj7_-}f12q{&f4BQ zIv8Os0m^MoYn7hFCdP_HZn`;i<8;(NBR8L=9F#odhIH%RKur5LY;rg<1sS!uRT!s# z+vl$uckfv0Gvo63jcI)T$1u6~uWh=%<8|KqC;4>;`t?gbD@_-c4l1Ji-Hz*0h8?{Y z=M862Zf^pKTO-k~T{vDppqK!-1)QhVreWFdEGILY#D;Z$8KkKz5D0e9z3mm;YqN_q@Ra`g z^Yi3!|Bmj?TeWAdPiMs_OCuwO1lkfB%M2nzp)soPwYk9M-MPbS>zi|20d~tfU8di7 zr5J7X0=36$E#$_o!rCmKlhZMY`MMjqfA+hj$!h6nV`1`(s_BuOj}>YqI>tdou4&0i zL73l^qu&OqgWv~lVu3&_`Z0uIkYcj4R{Pp@xxmvhn=+LiahDS(xXpFS&9S=9gYgD3@VAGC?R^p-cF)jXtp?``JFji{uq?)Xi?)np>5$3{=wVQj_0{fVjQH)BQN#S)QpH=>^JXe`c1l3gi-Z# zI);Wlx)5B5se7mJd_OPWxSD?C`9|g1aFhd^f5G-tDQi3)-SOGFSiK0Jtl3cWtMs>Mlzi$`}21CgELItEZ(<=jR$VCYpy~F??PJi2} zvwQs<7hG~UXO1(pRO`D1Gz9NElnOnNW{qhWhbC=BE5iGGu$5jX-)~-R+p?9Joi)tz zu1iO*-muqbYLkX19Wu?o7J}55J(pzEW7jw3{!9jS3a@~_0eyh&fW-oxPd|~bu>!P2 z8`7H&aT}I5c)ceNk1qj4AqGM;4K#9;mId#UO;&EJa)-Lcc$mLdM2<5}dv|g!G_wB4 zn|3?&__@6$#gur^c$VeCpWgUUP|6(h!xYY<*2Kr&JAIzC93hQ62=nocxf38ZtP&3R zPZ8UH1Y7?Pdm$tx7o#kJ2_s40o-EdBr0p>5Ol}LYwZ&$7j61Gt6KVX3+fBGxE(une z8`Au;gM&-t^F|DSko5aJ5J32N^`TH`A<5+J&lVr(|FeC+y5XNN?*H%cVunGxz|5qg z4lAxWa*%p0Hz)noE(^8R|FM%@NF3tb=d`wG^y=n>oRJmEvdm{)Lv$EW4SER`2S)Mg z8f$kXH7C#{7GORefYMo}9>tGfQDexwS{~7uQtdh!lV=mpwB?J#Z%%T-q(x$!M!nzt z0)!OlUu_tHhDm?g(HYPh4?+9G%=2wxCZh#kgjVNu4nv1>p=j5c8GOb`Xb!s}c|b`6 z#_IXMZ^}^tVfAJ@!qrk)CuMd}&CD#W#fFoxt#j@e%X^_Jp;9_Sv#a+O-cHIwByxrJ8kC~d$;E6Vq2GdBulCvF{Qh(MEC63Tvp z56GFhZFJV6Kjd65)J^F6@%tp@t^fx4aTPg;v3zSNTT@*3l;v>!GB;s$e<@O2HU`}N zZo&?sbf+_!^-t#0f0a!5yXo?;Jga}@S^c-q~^g}YYN*80EUuKQv z(}A^)N_^E?GMtQh_5Nm0#{79HL9AcR#jpPDZ_0*+LY_%NQnUWe;3bm^TYOyxF#k^e zXh?0N1clV#&@=^h52HFFVA$cSz&GjwWtO0SiO^*bNclPuzt^iN+Byc77 zbFa02tGIsxiep0&H|->s%4I}pBYc#mVR%-8lNwa@EzUEh1N#fdUMod!-64s!A1rfV znp}hm)~&^^nst&haSjVBbz3QlVqn~4NiyBeecpTJ>DoPR9a*fhGaH}F>XqC4J?U&b z9J5efCwe7#Oo4Qbi{mzQ7`gI1u4MAdK;nxW9x|CY=IV>%-al{2Yzr%kbVtPW?8+p( zSY#QU4IR$!d66ItHeYSm`97V&$sl-2-z&Xgq%qu}_0n)}(=lp=y4I+A-4lMS5eJW* z?a?UI(3tciyYYdE`BT_a#*ho~@vuil%sQLe#d6fJ=naA{0 zzla+~6&9|vjcMK()%fdt(fv*tdp@m}#70l~5#D|OCW(MBJv7$vdlwsai~Su)$8kPC z|F?76Qwn}X%4Ak1z#^Nf!`7y+Ttc*t#O6Qx=K3#0Bjg+X9}Sge=jNOb6e4$niO?OE zal{@@&Mx_e*cbFa8859}x!!Kws@5Z-=a~4^eE{p$7277&hhOsGU$Xx1m8^{H|K8Km z6q~d&fQiFq4aIhH{7?nackb-1Zbmp_N39(juY5X;nes;9ZYS5#OmyWof!|p_Ol&vM z*gO%TUxbm+Vc@pgiD#`x@o?2Y7arNX6vs_`7RqG#Sqe=#dhZNK3K0LS#q^vxCg*2L zswJWgakP`HOAr7rC7X{v;^X6J^pIh5Py$J9_ztbRZm|Y+C6T&SE-~OXjvgxA3-R% z6z?zoc*KuB)G9rQfWJ9cT#%*+Y&=e<7nsdj@K@hYfrWcp}E-gn!MwVx*c)#|z23}~LopJEZZwQ;gztIcIuyYR zv6^-iYsF2{#mV(|XY|oo1`B3;L>xkM1WPfba;T^S;If#iOUG}f8dYtjrq;Wvns<~+ z53c%guo)yEUoix;Ee-WC`t7(`2}(37Rr<_}j=pWu+CuO+s_G-jfI+uyXpep0mMo3X z{XtdxJ8%9`jQby9f^wf?@bSn_=lHfUM>%xHyGuuL3H*RV^#P44`NBCgRo}?3ajn)6 z4yT-9P9*b4<=q}y?si3o?{-aP1>sw9P1=e^2UVBRNoMi@;AM2|A6R^pL`WRr&OcC8 zNeyaF7KHP5t9OlP*Gv2N1%%>bnvB{cI+LPM{dL7PL4?L`@UrkG~c)IohvN=mMyn@q}F~5R) z?d!Gca8V8Q9tSzln;3|-Xv{R8Hk8>k>`qp%!lDC(1r-?hB5n4V@k7mF=5TZE5TYJC1j6k9F6m@oa;R}W(RLkMb%K;3&#Shfx*Pd%M zX4>><-6xWo@$b6`K?roSsHgL*M_NpCy*8jssb5%{l$~^@X~s#prgw+O6eJjtAc+}H zs>*u0HtOd)bTf+9ihGcw564WDk3shtlsHUt(B*JuiyB&rc?CW8-d)}4^ABcJLaUb@ zl-aTmMjave-OBTaWtP2*1UU(K2Ig5|!=89SFnyb^w!O-zfBErzk zZ=27n1*(0$FP@GAc(14Cl65r>lAdqLhnh1T5=>)Yv~QVZ)T8F&{6Ohr{QP<2Vu zvS%`~ZfPym+~o&~c)ep}&M18GTx5JMFzhz!&61A@R%t)31^?_1lr1P{XvCz)xRgwQ z(U;sHk)7y46Jj4Fep*fbek5PXN!MA1n9cECqgOJYETwl@#-`PG11?9!vBO%qd1*%n z^TwQ%sS)4Qasm>rM3G8IrQo6Yciz!jar1|$jXw1!2F(%;*sdXG=lWMu@-JXx#^at} z+QB&V&VB-85{_<*xHq#%dq$z5ek%5`F@n~q zOvh!M#K{M!^}Khl=cI)AdYr9?T+^Ix?h~ntu8nW6**spH37Iy`9Rib# z|4SnG==slT`o47MhO(S>OaWOPsWCaIsIKVc%hfGC1)7grG=idJh!)(o-v53}9d)?# zJnbrzGLpS%e;nn+(P!Pa03$nWU-gmFt1qH@N?~gEnb@9z?WM%lRgl#l-O$S%+STTkcjdJex1`gi{W7+*dn zdUiW(d6g*MrGB61@0^|f^M_&RzbayYJ&t8b24D&3;aH)iyulT}qSqcLO-njO)cyn# zJ@_3+gxd4R&0ECePax4til0Ct)OO_N?f5LNh&6B0F=jA|93H8ZTAC2S?Dvdahkf2* z1DToHCL}3!L_Z=AnvwqN1>7n4cH%DVk#H!G8%b0RuKztbH6ov?^d5CrHzp=WS|Pd< z18fi0oZXXe0x#7|+jqvlMkc4qaH)y`RN(2hwo$>8TWPT((nAA}yyn8ko;|+Xeo~B% z+w|9v+sC-SKm7an-rdo1dOeO$tAVRg#+15CE;0?%Qk`|pDuXyyAYym|eqE2QFH`iN z4n}fT+3J-{4aa^HBqf!XJw|d?#lHrsh6NOoe_e--Nluu!)-E2o+*v7IgAAv3UJC4|^@r9n{1U0}fb>KZNp+QyLQY+~43khH;N0kI!wRE@#bM*2-yh&L>V*8c-W4_F z@87(4T9fA-pxXsjdXKUb%UMleD>T;UXgWo@miAZz?dcLj4& zJ$Wf=)&gqDy7w=h=-;@1lwSw^>4pA(?}fPM^Dn_-ueCGIV#~~hSry8HcD?8mRUR17uexO{El)Holoyy;F?HtoQ%We z3@t29Zk^q}8Ne-JN3sABr?4{CxTD5P+QK#g(3G=@Q{GI1jS_E`h9i{Ob0PlDcBtHx zaD!#UO#7^BPQ%*N%hZzFGF-n3xjHg5#B?k3iP$Nvh-HE~n7cdI`oT=sSK7y!+IdoU zSCeg44NKPz(wV1iG`!V{UQd*2b@v2jJiGDevT0;J%l;6#tuxdv)hNbz7eJ}2MCGypB$GPIyGFu_>((*<% z8{Xb*Pux*=oSQDit`5t_ueuBA2jjFF_ncuDi{C(a?Mw?1F*>|V4h_x=H|nl%bFcN2 zJL~o$&iM7nK=>oh}j`5Q(7 zXC8w2C(Io0>a-xjjoh9!4YFj6ZZQ|}2{)eDOES1F`|y_F`yi@_ z1Oxga72WJ?+X(A|`GPZk&zQ*uy`92zMR(;1%E3bVY?FakUbvmm3PkdjL+M89xwQVC z`D(hnEd1I}+=0wUvcNGW1~f2kcwN>~cVqdbe7!RYM+Eo`h_9xq3J{8nBVaAvpWZvG z%_icG13Ke}gKWK+HOrru(iY>-=v3UJ3+MxOFSK4-dmNjWM7>f^fh6o^SPsu)Cdgon zeYbZG2k9fyM!e`I(#}AN=hI)BT8{2vr&uqB=Fzv6L!uW>=&bfeX@Uibk%K_}S+dyj|NqQOT<*7|Kz2NW4Se_EmHo(9>*A zEyL5R$jxq^k-|8_v_x!zFV(ewQpj_JbohgIbr4@|dh)&dv(6&d6xS?~5vTNS4byhj z&SydvJ_@n4!F1`Ommqck$_qCUj)Bm0;XXHtjm__q^^Ey?SzWaXt zp~JCSf|S^cvm*H5&Hk~Fr|7Bfm%BU&-f42RCbU>_*A0|iX}FSG()Sp|0n)v=C>U$l zo3t;nr)c(^c0_A|MOT21CIj)lXQx!e$KDW8`OQ-{QAYM849CT*d05_eV`40-E0z=9 z*<`-kesRiOBF@MX(-4-t-qf{~mL}K~8M5n*jEH#XUj@z0g7(VFw@zNbDC0T(ldYL2 zOGiryTWY#qE&06ryL8llTdewTG^xHKtzqG^ruhV|hX1|={A@qCwieY-`%sZDfvhEe z?k~}y`m;1)LCnu@axrtuEu`C@+MRpNxeSRX(Kz*jiQghg^G{P8dYl0GAFNs54P!{@ zx;0>^NYNn)jM_*k6ALM2(rw)5LgKL#9#H5Oo5U3s>VATWdQdzK7u)qx`Xt^Rn0O?^ zLMSV&sC$zr1eKfMLtI=B36T-xxTtpRyNc$&rb4{x(=pBDS^45Ue9h!kRkb$x`w2YjTHp=}t2F^dr(C zF|%tl``Wj)6eaPLdQU$*sT2P=3?MUHu%+_=ejp7;_l7JX&)EpeK!AY z)OvK?<#(R&ry~U@#q|@!bvgtr81oQkjuPjSc&{AjYG8go?HwEzMjAw~qEDwOS?D{? z()Ts&Y-@^>@4=_IexWD69hQEUt-9i1Se)Xh*WrP{3M}l=yRM>H-?QBty$b))a+7h) zSUpt8q|2+ZXYTSXkzBGkR6#R-QiGIM=1yApUnj2P{LWDcxFbVcVtI~X(X<1V&`;aR=Sm7Rj?;3{W7 z%-o0)=Na+GbjCWq}Zx}2I2t1Aw!>U$l23FmsN-t))eUCBUBSfNT zcXdbg6O+B4{*H#+ZXokTG z@C6r{s9mRF$92fj9l@dbMPQitGH4=Dx7rYT8^?N4TslawfXjrdrt7OoW)Vrr!1Lg> zpVTBLAJ>w1Fvk(?ext+Wp;uWYTM#B@P+@KVcHF!NuY8Z{5k{7odzs!i<8K^nHC%Jn zVUcB1Pdya-+UKt-5t6%y=y!t=amQr+TUQPp+oRdl`5M~=6A;m|bLZ;gIb7+96+27r z=?&^GBYY4+^CBpY-mbeEX>G6j*=SGZMYhu z{II^`VM|+K8iD{dGP0LX-km&7Y)3+k$VZWyjC0Md_v9D2uFYa+n#+r_`l<=jTdgGHVreme=J49~J?D9PDt7VmB+PdQ#>p%y zMc2=SX=(BMt<23M9Z-10mF-hnKTt*Z^LPgiZ#z%#Ry)H+SB$KC9o)oQLe_Ez5f-pp z((|hJ>B#2l^#IEC+8-#jahuv%xy4PJUl`4a|IOWhVW$!sd&~T>UYVn1P3Ri>f+e=+ ziGUNuhq`OWn&)3W&R|u~;+h#lfIW{lu<_itdoY*esnnv-_1))?u(6;7J1BqTW}}^# z)^`NqS09O}0RB-D(-T%N!lFULLjvX+KJi9oQ|D>eM;QZX9r}%!vOfSme&S&{dP?kN z&uI;-W|%3ciD?8QTM%yCNS*!d*gPyPrUL~tfu63NC+-2|`RDEdcZ=!QdUvc2M!W`k zJ=zJ%W#g`;xAw&|rH!Cn4@ZQt(tz5-i0tIX(2kWP$7%OzO=j$%MU&rpHS%oO7i}?0@pgLm`$(1a`X3NU{x#EBW7FiFnZFx z=;6eY<9CQ}@Q(US;R_Fx2Mba9^N%ue%2#()Kh~;(wch1cLN<4A$L%*rD>T}qhFvo& z#h!WKaA6WKMvT)Y)hI+0$>i<1)$xw-&UHHk z0%rGsG-wGUwF(Il~jd$i(y3 zC$8iRgTap_5c2-4FT~r*G}6@yDz&$K_}{m`EqL3$yP|uO7Bn6NWPlYUyzE{wzziTA zoMNS;`t(^kOOX!D#AsJ31KBWaJNYP()DS?B3|>7$9Pup;Xw)sg?OLl5m_oK23^`we z2{#8=Df@sKm5S1(w`)>)dr<=kw3&Z5$O-LF`?Gr`CGX$w4erTPjkn$56`IqM80Y-Q zd8PkRaK-wJ%MOA~;#DkLd}k6FmP+mXzT@c2JF~!EHd*7JL?TtY7Wy7KrTaP6?XM{a ztQR&Yq@Kon@1`+E?&CO-fbf{ir{Cose%Gf4*+4=y^Kxxy$xjh3svOtVyF%1RtR10g z5BXOe>Rn#o(c3W#y@D$Xz}GxUL%DcLgQw+Ol4x*6=R|#63~y?@5!`Pg7nt2wz6oXW zqPk$cyzx?vQO(-ri-2bUx_B9R=DG8x1i=9$ux&2pn0W>qn%gR2X@5dX3_Q>c>0HiJ2X3e1A+F=2y zf38?XsBedXypjqH2na~Et6!}Wwr+#wA6Gv}$J>X8gHeN*YchtNVaX)=u@svwHyOcw zPo$n!c0coH>^}G6jiAfuW{!;|=o!JleEHI-Yw5_tRgv{k+ue#b$thR z8U^;w#`d(w@u|C~MLhDuP|d;KRdds=`SEl1mp_dl;OC4P874$Mv&PXkq{@U*ZWLbk z&NAtJg-+ZzD)vhbl{^p-^2KkPra`LYdbIL${ryL88uSRwY&oSD-Jmc< z)JrfCOFc~xE`y8;pynolE?R&PJc<3-MI+xU6ZBM7nVC8;5ZRB}g-jkRy;oy;&dBuc z!+22*lWuZcLAdi|^ssFE-elEAz|AL}C_1M$vw*7cvYr5yB>U{mB!+KE*d8ymJzP{f zda&>#cn6H%iBKH8mzNcPaJPF84rG%j zSh=q>l~Bi*nV!Nyhn^$_!w!6oiA#y&2sCK<8vj{5TCJ3Ie9t1+MP1$c|DW4QHPum@ zn&V83l3>4dynQ3(vHG^i{bDs37RTy~ z9%Ph=x5O$gr!Hm*MFiZ!x~VPCD3ShHbB+$IUz?jjd|K{JKWyU z_2EI(M#CCImp<<2HOkjM=XO_j?4UFAp*G`p<9wG;r^YgdLXQ`QFHaPr2(~?QmZa}b zbm>KKI*woe7R6Mb=+&a>{mG}9dU5)&qS@2~YNU9P=IP>EwFL!{j^|h3?YTC4eb|_p zQ!H8Y5=A5KU9r!qo!zU*fz%V$OmI$+qe?H}K5vie;1l5yUgb}rQV!0Gi3L8juZFNg ztI_t&I|}V8*Q&Zo7cwBD{e*|HIW<$I{H$oms@A^hftN$W3^{LsUgnUnW#m<&D^asU zVTQ(3ib|aoP(LO@dasmiem4CSdeFzoX6fl`m|)LGQtP4>64-LGDsV>w^V`#-iM^%@ zi=013HTNyA);ObQbUUYR2eCH#NPHp@e!|t{Ar#Yn?o9)2#zFvuP&l)Ju$V`Yg4Syp zTd&J=i43uZ!c7dEu}@~--3&Miy-dv58nM~QitUC?ah z=UrT;d$Q~Xn?3t#V`^&k8ylrRKC$sTG09|CzdhIavg8vHprYPIWoe+sIbU+0U(puo zC*qj5W*}`Hj;Ns!+7aV>942-z6Oh>F`53lv^z#E!*d z7vikx?nY)PVIgVl!9zl0vVxjX9qnD+3ibkyetQF|}Zno{>GZ~0w8yS?@ELy@uioA9Y0 zDA|T*iC&zO6HN!Eb4XzJ*%6fasd}|r8V}u0Hrikrk8>BX0a?HdWfwFjpoR4vP5S|L zz_ErvVQ1(0bu$pO$8t8T-#Xj3TxJ-IBl(q|%AT+DDMyM#e53JBI4{KG8O6OUWeN`( z?}w&aj!V5!WEoeVM|NxT4(Ivp%4{z6{U>k>I1enYOj&#b%S^^~wilk|x^}_N&28(8E zrK#qq$F4kg`;Yx*j~9V{osjLd;$jbGyv@_A((y&exR=JHJ+zEXB%EpbyD?{#vzDWF zsv4UxJK2j)+#*n zbKU#4eyRYy%nJ9jR3lG?G}S3Yw!w%HH$l2Rd7{310uP2CF7-XK;q8(Uu0tJgTN#-SY;vF+$4@WtuJtlbpkb9A~~B@UxAR`GIrv2I;sp@ zX=Y@p+v|pl?~edLFxYcuR5icFm|+Ac=Kyku#Z8hu2q<9UatxrL=6d5guQ7hBQ`kG` z96Win-0Xduwp)hj=>eh&N{MXg*oa$z2sM?JYwb)jryncV7uP)^I;_+#l%^#gO;A>C z7TZ>kN(L&r&k-+?yHe2L94Yl!p^k6(>6NOc=H|tZsIB|#`SH{k8XQe@?j?1*NNW|8 z_8Xs?#U&>2ld_s@z?b=j`xY698Zan(5<+4((y(p${W8PC%m9FAXN(2U-)v*uiQ_8Y zi}IC0-ymk?rx5jE`;_cU!t*v*Q`{lGF>;PlUi`+^o-%!~@<1fyom8&O1@Bg6ucfoLXCh8oyUC{U zOs{*5FuTo*H`=xHr+61@w~6V*6Ykc=)RC|Kd9icAQgpjDcBhkXTr`btMGB)fo1kZ% zQQx7loHb06_*nrJ{q?JrO?CBisb=s)kvi*4lo$4F!uSOA%$BRYA^&)P>c7fY{nXO7y{XPu@bxrxJ^tLNbi3G0> zqS%D1$Jirc_h){V_Eb9=TxH@4A)5W%|2Bh-rRD3@v2d(IL=>kS54oqJ8VoBheArm30B|I(`N6%trlt**nd$A=`A>+;4X)43~}JZ3C>p+B3Wn zjH4Hz&IV}TSSb=9#G?DfDeNt%VegafN9BiZhh2bs?FX~U8};yhtWr6glLlYq_O%CD zp*n~s68H!&XmS@=8A0$}?h#@WH87K!9sbTkq>&*$@a@HR(7Bm+L_|2-;$!_4^nu8r zGZ)ZK)8$o@D7QTA{6S%DtuV7oq{59B%hpu%V&Ae*Xf|P zQWzIiumf9y{V-zpLD$(R!re%3c)0T?qi9u8RKyMn{eiOGJO_y?L!wOq$O7S%zebyO zrpj-qFE{0usj^Cn?nbpDN?12~q(|BsqB+V?k+B!5696Z_zs zJW8{CUv1;Q97LY0LkE^Yua3a0O2G3*!2oNmLYW_$ZE$~kH2V=OAAeE_r>tSmod3Le zI2Mhxqk*P%u(Gn3o_JDlM|liWidXka!P0AcFSI%nRtQ;spaf3p64;D;o}a1Lu9P;4 zXt|5zh$>oNYTG3XxF-(LJh>&(@0jXEimmP4QO&z8MxA@jeGSAcY@~UM{H0nT#5g;> zd^crC^a|8LJ@r9r!&I+h9-C0hTa{IQZd|vm!D!st4zg=8KCM0n{^HFR{4%A;i8QU! zY~8A}mid9n!FQr$dLh-RgO-^AB;JZ+n%6!P>T$KtCT6;X+TUBvwyhF7UIf8{g1z&O zO*aotMw}u{A||SH&ucQ%cIx6-YrH2C$7e@R8$7ZWxMJgH3A$D@qsNw#;_JIfN$JMI zu^nuy%aN@hJWAir`%k&I8u4xTv9W<*$AbCs&e=xih1zD4Ao{+2<=&Cqu6Dk?&_j;e zyVQKD4uSpKUNf!?(?iGE=C`(G6MRL@9XWe<2x9x(T89EoR7Mj9ttduS56beRKd2@+#zk6vO^?n{a zzl?quU%8zj{7LZUtf{OeZATQ!Bh^BlCXo=E5r;j;4_l<}TNI+91C_b!VBfE`CpoH; zN>(O?bS}E*Jp7KYVdyQ}#ORHdVL_>(>R`~|25HUA!7YG^KeNci`&Amb-NDS{Y>aJ< z70k3{F7fr6km(|d)ReQA7`X&SG~0u!f*&a8P)!e|tbWrXmjzVpfG+_!^&!9t*ZbNQ z6_%%X@3A8957lv&+(xod-yp}zzicHJx1LrXCF<#v%(?5<7jiugE$LVjHDzfvjcGXl zDo-61VoQ_1w8)Rc_`24zp|yof^M)nR#jIu0eCNx{I@1GjJYSgCJl2j4eE%9(6^P4WZP2bFDOEwk;Ykk|er5~Q?knkr`ki!2eLdBcPUQ_q`a8UW<_>v;Mrt^jeahIcyV7bUSEs9CIqEk%v|9E*s%U?;@& z?wjt*J1M2QTCMuzxM3BQ+%R=E6@2b%5-`L|aCYX&3l~7TI->WQc18=UJP1H52fit()5?crE|te}aNE`96H+?{RrXxyHJ0h z?J)3<%PwH)G1v`N`+)-N9&LG6ldNf8`bhpCYNPsnlle!20?lJl%YT7h+8{^A8x2jE zJ}%{7DES~{>&CZY)1=&7qleMv07r#fK88x_r3CmDT9koiuO!AYdbN81i2+k^muYUU%Pz)ot#dP zydT)EKD&1MeXl7w7g6YeI?N@a1=))EKun}ZV$ahF)7p6?lDB5OcdK(mb9NEnXW8}r zGGgu2hkpgMIXp93bUFsqOrN~2pSj$_$Oby{RVMA6JT_$yX$W0(X!s7ULFmqE!?fRF zlevpzn0QOkT?kPI8 z+0N_lhlnj@Z;R3xU=AWWPeZu2=(i?pK^4pg#UlyY^#2jPv_$ zuV_z_?HlvBVTN2>nzXNdE8Gtt*OqlL_wd!WpENF zieCOQ=Oy=NIlq$bgap`4L zR~xC=tBuq8owJ#G_~s#d)oN{H#$v~@>iQA4>0N}^jPVZ4NcXrc${88Sp8bAOqM|y! z;4&0b5soj`G(1Rb>|&2=Y0*Iioso2SGi_ z1#w#EeClSOzWHW{uDcst!7)*d_~e2fA_77L9?(Y>!UEVt?ESVRa`P%&w3fIE zJ`-c7t_PS$zHvGD3P&K}vI!!UmA2nfhj^jFCRZX7Q=`{S5A3fzVx?jDo=!9FfuZG@O}nGB?ti!hEfo!Fel!@>>ACy?+mU#?fb!3nXs}j&PIR z=+pG5b24^Z(I29?5qXd1AX91|s63*5bXNFEuMogor#d}xa(1^>>w>NGA1k{oBX9-$K01zhVc=H=EbJ}k>nK?aOST65-BxXTcTBjEI?4koyM!i9o z$7gOeO{|-%W4@&JLO)ROv$Q;`wvL)RjVkp^z52!0N|&A+b@iL%5{El08HmbVTthes zts%Vdcc$+hr(8Y?_XyKx;%a@lwXc_Rici)9D5ss*-;7Lqxb^B0HCWONlNe?-@&=EC zHBI#Atg6GZqdv~8fji#pyn@Z38B3Z(HaU&{%E_z8$ zmie}7&gB%*@XY$cY}lXUR@l}W3*jEUbWcu$At5-LRafzLfJ0PLnL;wZTxY_i=}38k z@Gdq~*18`{gDx`6a4l%>dE(OKttrZ+?cux8XgRP_{Vl5ItRYn)J;MosQq(84?1*ME z-D@Yi_L`F*3Wyw=f!4(ZGL{02TIVIR-+BBBIK+Rh=hQ3$>+g4J*n(OQ;eRgf(L#p2Z(h_0{topcR8M&NUCji@ zg@YS5)+6qOA&1<0B`VX<3?F9l!sY3oOQQXuo%3Pr7jo`DRQGUPF?0|J4c@aEJ8Z`i zl&b*zB)yZ;TeHz!py1M#^?GXJ^$b~lB&dBzm%zGd*(GXgB+*DS3NNJHyxXp*Ad!-3 zeRd*bNqL+l;s-=7#zY+w4$8vVJ6LpnpkS6(y%;Y#-QOv6=rnM3FFo*(^-LZ;`Z~+= z?vOL{73~#UeMor%Dnc+gn#yO^wA5_y#?j|c*Zj-hfn-x-nM0l3l3VNzKn)x6cC{@1L$NO3Q`>o3Pu^O4fxIhKg33=u$PK!u+insoK@0JG6+z9 z-%dh!+VO>+?Inb>xHf;=2XAgH`J{!6gxuMPAiH^j6=R26K_&4|j*Hjv-R5Gj z6?m<8>$FjcorX^cVE(q7V_x2V@r?<(QinnrrBcq3=;8whhX6r5rT17?Glz(8*^#;) z`B%{_)>4xJJha3K`t3e^bK=~e{oZN0JQD}xZ8w;T_*`1m9Zj4c=`S?IhrtIknC~8V z7H&3+S*C{x8&5wdAx)f`K?w`a{MbeO)3}CdaA+G=>e zf=)L@LZL~hAo@iuHZ|O5@crfPwZ~*_zvHet@4V)z_in$#iu5Uk7OZa;mBN%cp|>5I z%tU`YouX^I<>39y>)dm2>*$^GlE0@NT`}0IXq? z2(9TS({KuKm6XZL$wuDo0p&>q~_KFLO~Md_sv+7+jZW#C;a>3P-P-YE03`O)%; zZ%jh-DEmOCWg^7qqAj;gWpbSatOo0f4~3t%ac}pN9|jRgFP#OKmswNq_v$}*ck_Vy zW?booqodE=e)7Cmm}r$22j8&(aPmw0=N)X=Y(%*f7Q>Kv>68~OHqcNu_@z}0%uv?o zH|?ubcP@C>`dtoBqupkco8l~Rrdf-+I$#USo1{6hm+A{}s#??Y{8OPpdHLJVgEyOUY*9bnJbcqb_v`h(RAflx2zqi=ljUs*GxwfHxOCQB<6HDI^ z3vLW#O>ISwv;#1>Y4Kj{#^+wrq@p@@AUd4Gl3rv_1eXJ}h#bm^L;HwFKh z+#!rng{_&(AFPYWNw29IE8L#~R3(q3%|Ie}%Bd&S#CB{xlXY%Y?B$|YMn7vpf_HVfSDq8alejJB zN^KtMV%Rb@A-_pIz!LL#yKCOEKN2Z^u+pBB<>XAJS$RWDzGRUIVMH!cE& z1ZJ13%W4^>ZHFUae)Sw7eJ-$Ol(4UBXWjz-xX<*TSgYJ&dzKufNhNowZ}y>+Vahxh zb-BEfKuhndIp%M=tm7`1Ja&g0Y$h&sBiSpZ0JS+&%i%rZlg8M z2_Yk1-tO(rxGi!72@RUy6qlkgka4fO?eSHRy(SOup7W>4i~x(gadE;MK&Wd|)ORiX zg8%X?!Y?$?FEr5q=V+jGPktL1R!!j`CQEH98<=aD)(ujX;n+fkY5m2lUPR0Ylbd0Jbcs*TH)!j9rK|p>UUF!1EUp<;n^!Sb{W!2P|8VZ&x|)Miv@#%iVj* z;EeBzMNxwlVA`kANXO|pN-Gg5NWL;mm3A*vgu;s%F7MzkI2Ijzm#KK)H=)ybN2ica zB4KC7y)4c`QqhHX>N3294(Fu2huY$7v9g=N@|%=oin!Q6jv4wJ{>wjSZqd_)3yz74 zRv^sA<$RLds4He^^$$>>fvxcZLAAXuzE95Xul5hW-J&m}b1PacHpEG;Zk%3ZAsGSC zRS4-ABI^U|2auIiVu*|+!`N62wtL@)e!pkK+~gkk^2wlRy)pred4Di} z?XaU8V>4XH2O%%vpk{$ZLixnHbcF^%auuCuBT>_4V2pU4J31N0v$#JaAx9>Zi9WaM zyNWYuobGUzcxC(50cR*jFRNScfVw~n6Sp=E<1c@4W8g330?C}beKshtLq~*|Ox+qO ze-BVOcgB+(mekF67AyDo%O2`56=O!LBn=VD9#R{_JCoPk&TteLj~}J3r194$gI%O& zG}BZjJ9IykF86)D=N9pyWro)Dt%Dw!qTI=On3lu|L`qY*LaK`-v=h5h&{-D3PZ|Wvj)jkVLeFLnM{J?_t{vqX(?FT5(>^>Vn z$U;}?L#~w?(Y4%|zwG>v*&?ZsA1KyxXWAFev?pJGpzO&#U_1&3+=STd zhLw|;owN7joCNLVTX#C*R2Cr-+ELQ zUV9mfgf(?$msJi1PCN++H?OvKg9%S8qOO5Rt_sY0{a<*d>)Z3>>Wb$USF6X5R{IL8 zi78VsHMj^|y(kSO?#ALpc<&+j5k5eQEC7aS+Zid~d6Ve(g!msQF8!S%7q`zw#(9~< ze9Y7}gpipLC6$>N^>h73mh}N_2urqMVTqm0rn%W?CtE{r0sd{AuG+zFT11(6(cM_l z89b`2}fP@xt-$3LZhF;(j(w*&F``y|i`$K#KvT|dpVrHSa$a0EG zUxmeDbR4pzmn_4T?~(`K$7`4w2S##L@gmy0h2Q@#_TDq9$#+}#20;<20@ABADM9Hy zfJ$$I(u+!HAwUSdBSi#(1VR%KP^w5T0YViiq4(Y)^j@Tw|H)c=pY!g$)*kP>-+jh7 zC=e4r`u`@jrhW4dC$%cfmgcJSC*|K3tr$Vn0ws#ie1%eTYL>q`fZ0xU9rN#_5w5q>0Nfi@imu`=D0NkgZ=R;JhK?o8l6W4fCoJl~S@Bi_KF z^qP)lFNLh(lcv%ri$P*Yjc&Kuh&#`Bh7f|c6Y;9`GZEx>7t;vK$h^G)oUtlcr;EUl zbnf-bjJG$6X^$YH`loye3|oipb`{-%AP%Q^0@+`}nIshQ$U!{9xbHhz?sHj79%%Fs zNl{% z)6VYm>GjE|sl&xAb27_RXIed5$2X(9<4sHR9%}2woMuno=l0L;`2b>miAK3E5_`4L zc=*WFi~{&I^jxrJ(aCm(-QSXSWos(2wh!nyI;J+h?f->G_uTZv%FPt>Iz!Xd&0c}p z!%A|qEvY^}kot<#^v`mVvB$|Y(&;a}#wR}m1}aHwMO285J4>DCZ3ZT?XcrLC$}FDWETp4wOt zVzM2Sf5N7hkQtF=5KW;vfseBZ5k&N zujTaNMB+rq2Y{`y{K~@VT_f3^fx74?OG43k3Vc3s?pJOq4t+7z+oPrT3p;d{Vi06e z$sDwu%qJBJ5v8g|Q3n?=taISc+#Ph+7RqqM_2-z`CQdJ`7`f&AM0WgAyAbbJt8nsJ@D|3}c~)6k^wiUBu$Uh149nn%5+d>OPw8b;F( zq^l|K@a~w(?y!_=gn!x*_sw{McDQa*k>c4&Jq-I({p1&>iX^Emc#nMctH4eSe%>|$ z!Tat)_E5OlOyJZIqQ*FTQEav)JD+)O^UM*zr5Jt)ah*ihsyRIA@n{?O?+F z`%-hf!&myB9l+HEWGG$<+9%%&rU3SL5<+I?=5Gy(`Mr$RJ>IhF2p9#7U7Y*-0CfF` z7m_r2$>io!t8}=OIhAasXCOdD;?$Od>tAg040`GOO>Yrb%`a$d%--(ahRY?xGBvG# zihpTVl_%x_KUx|ra|q2-Faz)TiRa+?d1-kT=>K-ZLY{Bm>kJ4gTADI?q+$&F zDu^wXox9V-1@;c3TgiIC8=9JnNt_Hb`7B`EZ%9V$_o42J4-}YN} zZrH?r22I1)sc7jcaZ7YpGVPTnvL9e$1Znd7~} zD^`0+^+G?&dHV34&xvEgZl>_Da83GheTgng5UI^g`82eBz#Q#(&V_i8U6Nb>(^4Uz z&!|~JgiiT6=^s~oc+Fhi@%GT7w?DxXsE9H+l`PUx2&+2h4{cqI(nI;6+m-z+LG>tY?T`tc4FsumwTtIowz zV_q%a#o0MD?X}Hm8T9_ClTqemi21FGW6)5kpO*ZW?QKhM;XS{gE1x&z%9=*rgYlK( z?t=g2agl#Y80Dw5o>Ozyzi)3zJAZ))@i;wa%QE{Z`qBeZeBN|5L{_+W?0r5hnyj}qOUiYx)H>!uc-7;weSW0g zn;3O&oNGER3DuY}OtBbaur>U3+%-fLi(#umSosSMmu$Q7S$s0By4?M7B~o{fRXd^~ zN$lpEAHnLsd;EV-VhR7p+x%y){sZmRu>W5l@IP_$Kc2`$vP$J{*+bOj!mr7AyG~hw zW8vXO87d5%A*y0fXEH8tCWUWDAAEhT0`}U{8(r7iw#~-RuCIf{@W<9cvZWy^W!uXD zb{{6zAj$^>+drp4shIJ^62Dq8T1w3ZZ#G2SWfxY&)3x%~1k=+fW+Gi!gt^|I^6EFHyEo!Nwd$$itP;u{6@fxx5icMY|Zj&A0)x6yig^@J3VN%PB68toS!^t`Oc0OdYWL7RBeV zTRR1a(#-(A`NkFAA`BiugqWKxde46VYTO~Ud`oAPEocz%B@H$-?Pjw19>%@@@tZ4e z^3L%E)a>dz{?V-&t;}O)e_AV#ratf47DLK?5v?MPjueW%l-4=8x=JB-nqUAbp% zq2S=e$F-unCGRqxsSzF$MCryIog-o?A6-J^KZgkB7FJ`es{ugo3;hpBCc^f79Uw6b z8jSVDyLfV6*vH?(GP>O0)XE8?3huMZ{n(b=L>t_h@wRecwGp}(M$~iRXuJ^tJ1~hH zzY@o~-8FvE&?Sm95bx8oQh_ioPyH?{5uxq>X_$U!E;$& z#ct!cEsBN^@oW9D4cNNX5+o!gQkibCsD<63_c)|J8orYf^8S9sd+*48K`NM><_E%< zE9gt_>*oajE8@aGh6D*;0fEmQ%X=i%*>F28>u8xOk<5^W9Q%g-(3wC$$YAM1 zZw)7A9%`%=i(7QO4eiF?T;Dybr}8}M$)qlZnk^h3UJnu(rAO~I5i_=yMpOl_IQm>G zKA|Wn1j8Y0riSRf#X(~wp~J;Mpz0PSfoZ27NPK1Gz_u$6CabvF zs`}C~=+B4M|H|+EuSEJkS~dTesl{Y`?p`jhtq* z^Zi=+eg5qK4H*Bs28=u7vcjP(Z&Nbbr|`Ll0k(cB84t8Wxs(@r)!o zD$8?IqQ^dg0}4qe&2^M)Pgl!9Ssa)aTVAuBiJ0C;@5zt32E5uRo-*1F+@{|SDQb_R z{pG&~O61DAG{<}in+5-x2UtHOOK0PB4hmhoelhif#Ke4$YQSJgP}!AQpXs%(=tnh1 zCiFt_#>Q?jw7ExzRpU-!rFZ;jbgfedr1g^^q>+a0yd>17L9#7FM*)7i0DVHCFgCtD zyQLL2x?&wm9QD|b6U1n|5Jt&>HD#sf^-%4Rz|C+` zu@WH&1I@eOu00r;{YTqa6GUBl#i_F*yLrOGy#| zsTx{2lp#`!_X{89D-s*-cV7eLt(D%h{T4j_?c^D4cNY_v`E0+o8!@3PXl8$J7}bu6 z$MJgc_uuhtZ)Hw}Y>he%{i)Om4UH%KzU0PKsO+z-N#_LKg=o9t3K2j$g2XKnkvDB) z`@kpB!{}iN31xbAy2gEuBIntm3dJdc*)a8<57Xvfqj~g(ta)uzfr5H>u#<~x?KR zA=%StT8rP2&Oj^I_x(QxfqbdVrsm^Uah+1o$)s8es|sx;hva+G++9rNCbZ?lGGB`! z0@XuYkS+7YL7bJV=7;NX2m%p1iqq%4PhRipdDXzu>hA;Txb3?s2>7*%55PHP7$b9W zP8lzkC(5p>ZlXB3aqeX!h7n1rlx(IG@-4++AznrNl>{QU7J$i0u`CI9yDbzK7@4;z%;L@qBhrPdouARK9Wkes7bB_y zi9N|*5fYB^n>5?XxG%X^YIv8&oWV@^o)p?jAgiC_UT|}$b6i3d=Xtn5_i%B0LH!-> zmv*QY(qb=shy{ePji_}HckO}c$A##*TtQ#X{&(aSJ{+*2T zKc;RYo1(A&B%79(YY7EBB8X1^W%Vq8<8{0@#Q)-eV;1#o31cnwCLsB0|7A}Ce=7Vh zJWY|ThSw6F>#(NWfmmt8J(9*IJUo-qqScB$Gw0fkkXy{fZT8h)c!8?%uS_nrp8dI1 zdHQGk)^(R|>51a3ro(%ig!f${QMjj2~?S>4W`8q9^XGm3lQT#QAP z&U2oe^&5Ja#?7*NyXSBxoBOq1EYb5WGp3J$ItkLzB9wuEPVYnh0-3sUsBfLv)AnK4 z8Jh-2mZxlbviTO%A%65{BPV@Lrkbsc(;;uwD;QPTpwoeo6Zv%|4Gn?J^rg*FHy0VA zH~K!^C+2Q?9-8SzD*VLha6#m~-tK1=Dq@&wya`m_h(DRVkdI{2{M+YC6$`!b-(@nK zziu{FL$Arc6hO0O z;u#V?kxsD}lGdIvif32YdUT@0HR!p$#_DuG#o^Z<;2lQJn%bhKwOP8DO`iU#q@$tZ zI}?^}NQ`m;&g%6}=7mRr+&KM0bEd+T4nj+S9!t`n_B&w`zPcyMb9Aiyvp6=>(G*wD zHbe_C&fAU40v%NiQtr4nGo|KjD_-~PJVG{9FU%%+XcyV=h?BUzSH|IA>QVc zk&c=i$3Hy;xZx&%-7G0$jRc2Y?=&%rb3fU%Aq9G@k$$aVGj3vj!9Q-@cefO4MK#nu z&#Xwe-Fe_Cj#}%A^3KIV7kd*V4X~%SQR(oMN|Sa`l0ON9Lq68a_kQC?oSj$e7DCVm zlLspOACAzciF|WVtp9GuHFez-?rM)KoArU&6yxX&JUl1aoU?|ruxkdPXs;?wE*yho z{>^f_vuXWx^tG2q$6t5`3m0EbxYDj}KGQ%4o~rjn=kq-2vYc`YJ2ZsMJ$%ocYK>RB z!^VEZM6hGQO;fSuRd;+vGd$sZYfHTgvUr7aU3a`z-1q7_K9=(+Rj}GgDA@<)%C4MT z6v$|-K^ta-)y*~y6}UNje0oSCj)@78Er%gYhiv3WVoWO?6&;Vv#uwHH&MpqaQEZ;= z=DE=TKle1(kCG}EHgK>&UFC=1U9w3>g|@jPNII_ZV&Zd1noioq@%}~HBc61H(%IF- z0xQwh`&;ggUC#@@XQ=j&5ERil_21KLSxsAH+z;e61sb9?Tqc~%jhG(cv~Aj*@9As}%g3-oVZAS+{NuaASoUW(MW;PWj~2F?u-y4I3p)WFt2{~Hz4&@zwqx@H_(Xzrtb8(D z;AH-S>)doal2IKuCw_NE62go;u+vIw$z60DM1^-M8$u4Pu$3%PalhwhVP!XJ&%8WJ zwD*Fj&zj{Tnaph%+EGl!P4yG?t+Q@OWL?w#k$bCB$^+YWEv<4Bx z#$T2U#Z_dG9nWq|p=RFJ>H0@IIx2Zw?=f$eX(fm%Nqnv` zy<=gSC~{eM<&K_PnDxli1&*D%jQ_~nU-N;)nj>fXk@T~-cFFk=Qa_v*bj<;-0&MvM zWfpkLYdywVk?8R1JNg|Pm5dC~YsoXrEIuJ^ z9hCFhsaoBR&)|>C6yHx!ZY3GIF9K9b^IUCa8UUH@KoDW^;!cZR`R3Bh=^q{oE6*rn z^japmhT4akl@HO!vmOP6uH@YLl_Y4&!QE$$QXg1&(s%OT%$nz9x|SB+oB^WIVl!e4 zK@5m3E%6_~=#R%^{zh_!ND1|R6%;1a&rxP~r;37g<$^aOMUy$c$#cDDURzoz|BT3zdxv~pyUzEj zHk?uJW>UDRFPn>zHw~J#6cok$h38Z{fXI*RsmfV^jVn#km*EW;8yfdLk*Y_VYxKxK zVQp+B3T(od9`E$v;zw~O2ww16Gb=De1_eF4ePFU7T!sbJYcyE&VrOihOfQIMJ5QgA z`3EO7P+Wo795y4ndNgn6niZxm6YuS1dhKuMZ`Pg6B)#iWrZ%-os{nw@8QPq8iITms z1BhlsO~;rmRMoBrL4K4s=jhAl`1{H`Vz)iAQckK1lo+RN5ZB64$#?hL9@U-@5xik% zTUFUbJ(s6g;P}Au7-=TcN@6Pp?7>n9eRAL!5}#G+xAG@*HgKP_Y6h!#2Xc;jM%C2 zyIU8CO?d{M>eve`P-+ral9qtxT1o^#ApHJ?;P!9S*WK8yY{FT8oK?Kolf9Vw9ZU^h z40^hwt6TlWj}(64Vtac4k8x9Rs~tuH0XVuZ5N%%71-;n+<9AK&uvt2~Wkv&YUD;8E zuyMsN<2l~rUzAXC0N{$4Aivt0ks(>X;{Sd~UXspLBY!%4<<*vREZ|`Qp02Z0fbRi!@`R@E2c+DW#>0l#h9) zF$lrnz7k@Ng);K=LvID*Ax42DV`&Y2qmD5wnmX!lGu82ihzH%T%A1vCSp`f^O5%o? z;BUT_bU`x5)?|d837($Bkb$`bO}v8<$8WLT7t$u|SbR z>_Xg0uNP8HmX)GxIA^8etQo!lGT6Qi3eCuEwBw7x=n{9xP-xOXDceorB@B0H5ACV& zj|Z9EmCVBVslam!>471{%1wbbz_=`){t5vPPCso36yhkUmn_i$2g@FQQAe!pSw*fc%k2*w>SKXCbB~zKdP~QGj;yU) zP<}YAum4eC3Zg^H8RkPKv5Z|~Lt)a4@yvP}uT*cTa-G&> zYpxEp9)se>#Y^v%kXI9@nDlO4_TL2FH97uV-kEunwnl_Lra z4(eJ1NMpO+rdf?NNEcmBI6?vj*bzy8K=^aHFEPL~ktTSpUJG#*})qno_aMf~|weDxaBxgxn&$uDxa2qBV$~KXAe|+ zi#Nh1Nn3;A3C2!27hpp&6(T%UQ12DmfQ`5 zEuSQM%&{P&l!%-E%jNJy{3D#vqNNk2_gpzse`5_|Djo2Skp36hxlaG}u8%7(pV)q) z`Iyt*p;Z6O{KZ?V^dB1o!%GW0d|hPTJuk?>Z{J^sUn5FD4M?TQgMjeF_AZVzJwIy6)M_$xX{1zALq(?g#RAuT!(LedQ6KK`ujOYn@zoIEaeN2sFhjZr`sb zvr8qxWeL-gDIKIVwQX@tHgrIX5Q0T9r~!{VWhC zGjZfV@^6^ZKQgk)qV2|yKoE$Mcb7h5gqM`VG0 zNT=t^9P?G~^j%(Om{&#*%a>UU(L*MjSbVMcr5$pYg&^zm_PgzdZhdg>*UesxcAq6_ zpAtc_($+gbB2q#PjsBXtMsgid@DTH-Fc{d3IB%oR82sZJs%KmrRmerV5xuF@k zGH>dZZF_xZEv`&VQx{F7E-#G6S<5*V?HDQ-xx@1XOuKih)EO_6rNk62s1_B(Ww6*4 z=bSfh>=iv`;%nv>_n5FfmXfE?UClkBC&W$$gPEi85pxZ%j`Q>PWaV5(uUQmK%#P9Grmk+C0=neUFFKRhkq z3L);gKRN%f8P~-tG{d~dUb_KR^ou{|9t0Tl+HAB>W+$R8<&TzV_CQ{z z8;__k#Ii`OWcnsO(ldamqgJ`>3Z+;DP}N@v24kCDXY14djJTJROemnugUtO>_`+4q ze9}(H5en=FOaOuah%qaqb2Q5RdDX}dEYc`q8I*zD8IM86OmK!K-0en3H`3SBxYh_@ zn#>=k_d4Is-N`au;&oL=V(Gd$G8*$#9~F{%F)0ni?8&a@Q|fL#$QhaPVoY6n=;vb! zcJR+r>8oBy-N|e7C5@Ghe8<{Scat9Y;LYQtglb`BZq=R?^9-e8o9o0v!26k(Bhrg( ztu~zZTc_U8=r27oV5FqovZ^qe7bH66vAGgqc9hD@?J;#*y0#skE>+L zb1gG~+BC9zDkqFZeBYj<#N{HEc>Jc?W6xm0rR1ohRnxQFgkLYkX(*MJ2=#H`Jwbdb zE7384{V%-7d7{zPS~wkAetxke#%e(kFndHJ3cJ^>dLSC>Jg~Ng=mQ}Q0@ftr0CIV{ ztjyC4OyZ$`%sEneS4*8XE=-=N1P+%iXFj=jpPV0I17NUrJgNg8&viELk_i!Ja(!64 z{ZW;ldsoxi5VvGCFedqeZXKKNVja}xi6NgR7lZ!7E0jQHOW5SESGv{$9UHqeO;07! zqM6@LlWNH_)705gKYk_&iymUT6SAQvu8{mXYFm?GH1iaz*e!bRmTI3^Og526XoqC;43B89!BlgWN*1KW_{~iHYO!A zb!(sGi<0aVOu<5&aaZ^^G~jT+uv%)g*Ati@)>qIvOUt!NDtIkFU|5|0)FLO6_cdg5R>#W2JcRWpagtUZ&Nfac5wwnk|O-ff33;J@x}rG>^mX%Ie%lk&_4@7^6$U@KSj8IYBABx>3cD3 z;n30k4E^T~xri5jM9ZI#I@(Lc$Lqg7xsHc^Vu@YSJAJ#~NG}}A;+h=2(CIlIzHL)wQV-gx4x2@C#kPKl*uS}8)mF0GeAYU0LEk)LcF|MyHtahA zY%1agL^uTHbubbiBJ%P+%>_lJ&VlF2e{WX~FR-nw){Q1BEDm}wTg-S%`G%~k>Gk=} zls?5&L?>#iD6)`nJ32qQka@NCtW)W{h6CI7GiPh7y>V+}u$fN1$0_Ns%)KGtV_-k3e|cv}Xd-{iFy6Jcv?%^Yo0n+jue?&jWwE`P>l8820Kf?k>wTSX+v{8DJ0 zdU!&yGA|d6jW-`!p;Br{g;>4+c_z1R{uULz&7bnshb34gY;xjZwXf#{$e3uR4b|&) z)8`FTGOtwDtvI(IO~}qocy=-IMZ|SB!0H@ET4)k4M%x?{p{Yve4a1`@5)ZFfS%~a+h-So8Q zCYWxFg4RHzNa+6Q6TN1+MqUY#uV1pc{cQTF+f7Q{mBU=Yv3Ia#{-K?Y6y@#-`aK2n z+XFkVH7)8dzUZQ2Jd{X;Z7L558W(s6dJo4NZlWsm>l@(-`|%TNIhz70O~;Py+|XR( z>jVT~T~LU#my1f1sN+7g&0n^25E{?eLvH{z3(8bjSnpsQ4VZc4n)D2{JM7d=Gsm== zB%M>T)qjVmO7cB!bc5QftHcW#XlKd)z)1$WKG3}8_$Jl;w%IMoFgId=l(S%{lKVkP zxDT74AbFWZjTD0_Q4;h6r13o6{=#&Xuhjwt9YAN{SUVnf6jw25 zdZYE*9Z&E|X`)WM%NhlZskvoqP)7;e1cjKxRasn_#Bwg>cMwEst?VG#rtjsy?o$Ph z|5_XV<*|4^$!*Q?1jQXVat^(!*U;FyYVH~#yJyXp_DERNQY?oyjTDta&1%g7cRs`Swyho%FD;)DU@aC( zE1bz(YxXDG9Ghsq01lyOC1n%xb=HL5n!Jq2|{PIN4)L~nUj=~Qm$I@SkZ<2esI zrIIpwg;rj?sA?%&#&b{gsz`qgb43PpH!oOzc0+%Fa900cT zO>*uG0qOjmeiZAv6?tk5D3R7m*Li+45q$0%llwk4vd2%D^?3G0wZD8HZ=}nh%#{-K zUS5UdO?5L6n87PF93Ox&A$n)^i$DWq0uuYSytfJy5Zr9UPzKgs`(xMu%bxeD3{}VF z((~u9y)W-?jWsWv^VxmtXpMpI@*jGMBAmWtL;S~M>LHUuNB8s(6n3Kn3iEh*0Z*?y zuW`OoTW^@^0v4LTzsTn(>i>qhc}jBkg{&X$eLj9{mXF7397}G^!!^=;Ei*K~IL1S5 zw35nehsPDyROy|3cWpa|SXzFoQe2&?Eu?S!=pqxIYEHX^?eXa4R$iux|9_*mKD1QM zh&c{t%3dI6z<}GJt{2>CQd;vWrMl`A-<_3?Cl-CG$mC;|y;fj8xE4qEa0L^>BR6Fg z#^tZ*tQhiCG;;I0RBr;M_2QHJ9d9;?d^a1Iy&uE1Hu)gz!qwsA$+Y9fs!ntwPnyuc zd{^IHzh&b067Lgx{c6SAqaEK#&m2fq-3dxD4|ww~4UxH}@{whzCg98Is&I|0@szas z6Ax-`74c%SyE#2{W3`UwYeTC|N_SyVNhyH8@Z@h1LBV|%;+N@~R&XKn^oU*13esPZ z>_fZxy-t8~9&MWz)Qk4$KrVQ-=>a$2kGxD^AO*(VMq2;)_~4oE$1>B#M_>J)W$bDk zX-)Uy$0T&j2a))T9nJq5hhN{FdGuqn;jKc-I1|5Z2@$7$o+yRN%o8~U(PvdXdgZIJ z(x?_L*;D+Hrl&+pGMvh;Jw$vO8t2muUXNi;)eQ>z4ns>O8nlud`Ji?P5H&2rY1hQU z3k|=moIzne{r2BKPm+}NpZmF12st`j!Th}1Uoom=VW@j27r>^k#vap0CZ6l@>4@nF zh=w2i%b?twuSu3?hci14jX?tkZlg6ttHQOLOHvr6O{7de+nt|T@VX>D}m@*@bN^Gc=d^>QVS{u1#VmZp z%)%sn1RdTtY5><^HZHccpRz-%)Po*|W|xL)9r(v(1=_gxz{?vYA$^HbqZV&_-4A{b z=w|4S2%mSw^grdun>F`uJ*_>4;IUrDtxxh;fKUBSuN!cM*ZWgjy3WVCM6`U9t~+60 zx)>Z#H4SXK%&{7bx0AqfnO8IO#D>G?*Z$W%^2W~sk@n?}_?zgA zq2G}V0>_S~UZ2D>O?P9U=#_^@^U?1nzS4Pvn5q7mJ+g$%jE*%uR*H=Q%DAEx$9w|WW;i>T5px3W-AV_wenda?at z1g$NPpReGyOTd_%%jv_~gTRd!f#kh<%{F#v4A)PK{_LZs~YChfZwDmmV-s%{ow5+}Y2qPriq{B*VwX$8VNV zVqLmz=iD@#uSQi4UB0L}E>n%XUbz1wXN!`MZ~*1n_Uv^)WX|V1OQgyxsE-)CsDSW+ zrpEETQ(@F2$H+c6X5-T&bpFeSSr7W}IA}}|#uUqLcY({}X>=j1ID1F8U;tYtU0{@Z zHOhbhLA`Z0Wm!jZYf!yQVlH)0OWV^>p8W{51rn(sTA{A zeD9B}6^>zDZQCGJ?-~~6QCkY_l2jLfc2SL2LYW+mi#a}ftKxl&sG!sb70qyqX*-5BcE)BMfzGJL3x zkGYV;yQnJ-|BD~-eIc@2U&33>v>pnREhx&!(%hH}mC|b&RqiF=+V(Q^x5@13{_c#HECXQd&Ea%PN+I)m_`(cB4j`64bPTY>!+mq+>8!PW2scLR&LxldHd2)(zzM><= z&>yh#@tJ(z69?UtA+dJZFRf4Pg&2tzbf8tk?b-_RK)GN)GegqzazE#Bxlcj)i=N6-9iwv5RB>xd@dHHwR!u?OQ<@@d`er`%&V7RNd8~feA;BJ8n2$SHGgF;q*!1YOffLDG)49RZ|+V zJPl!7r%1s|htAkpt~#ADSghKFhutllYzP-ez4a|za+=;nnb-e?C-PYH1!k$bHc-

H+6vsJTp8=d;waM@`t0w$s%(0O_dxaEaikXL46dci=Akpb}(3;C2x!BSbb z`Q>$~o19FK0+*>o+l>fugq&X}lalO|%ocGbmy$`6@@+JU;-DJbm%T$mIjkP6}?G<3w& zS-`t@2ebOFJ$B4{OJj@9xsdmZ%1h3KHJPkq7P@-f)UF?lr>?Z^hg7sazoXhB2UC?@ z@&hFY)Fj1DY%i#;=MZ(;rZyC35Wi)PmP1hm`vthM{*$#P6u>qdz^3T6%19X)V_ud&os+Yf$pk~IC(0$FC`qH}N4BXHhdn7+pi**GTV^^0OBmxzz-XkPUn59-3 za+w=u&n!#)@`1AkjS88SfT76D0260rc|E+nvEZW!0@D`0Xt%%B-TfvRhb$fUgw!!D zFsxao*N|QhsR$;_?-kG1v-1NTn7lBu(q|F&8ot~{pKdrKkx3jyf%$BO` zKKS1#nvc!GHNCrkX1cC5=vc{G~I1*-nqF8A1%F#j^IjoQrTp8~;h zs#kk%&GNze;Wxep8|doq7*&(WZbVe|;}f3Nl!v?+%(^pg5P35dt&VWCpSoe(J%k`w z&VYbh2iJ}KcFQqy-1#s4)=pQosql@$=vbCzrQy#B6u7ZuugViL`v#Q~LY_xn_?GPv zW3t8c?pRD~&48H@d-C~_gie#`L6*rIH&6ZH%n%{00 zST!J>J7~_@r>oWVSUav%V^r7e$};Zo*~6aqZEbSt0sFu=Ysn`}soFk9lbaj8MnfGe zV)?}UjSf)XIY5vTyue1lpmilvztMjF%7FA$Ka=E#F0_<5R_Ba$aXa>6(^2FJHYovZ zCV%a(zU9k|zU(Ct%oz^XOmLQKa4!*>VCl2)HYwu#UHvDNRrnsdOMUBVFFN?m0d{7^ z3xh*%f8kLq&o|$l#|_{cnAMj^VAng=J6*Re@17$}O2<@H5}%&P8vU$pwwu`*yGZz{ z3eO}H)c)g(FPq{TMbf2;AWd-N}t3`ct zu1GXaB832X&H3E*P8yl~=Z{goe(AzGQWh~-b4})5;R);F^I$L&{yJ!FA%LYIVfLV% ze|kUaCXmRSMFN;PoMIy%P%I?70`rrtbCv~e!cdQ3$-<#e;r{N*dMurm7jLE6#pIxV z2Sm%+%uCykhl?kCwzho(3;y_E`L=7-xw3UOC)i#Xgy!XRjrv1BjyicCKceWv)SU={OC;CR_L_y{8gvtRH>KRCIJs_Yl!_&mzeDul6U6|dn*lr4 zjUQ|9kF#ItziZUn*5j9O#SGSZMV(PM6)wG>B$Ju=t!_MOCk{_USEx&Hcd1uDof)RBcQrrj67V4v+mh%}gt&eeM_=8uw#z zn@+rOAYwy$ee3p_ZflnRtL&Brt9;aU2*X}6@o z2(RQi1`24i%{||tLCQ4rx7C$@$NEcmBdKZEj)h<~wfY+zu_HoQl*S0iM&Vu5!0*z6>gw$iy z@4S)crevF`Hvl4j@2l4jPSfJS<=Pd#aMydZ((CAN{XwSjMZWJ>d%#a39SZb=_cAFU(5o@Hn+T~ z`CVuM(s6<7ZY=r}?msopw=`PbXjJ`j-$^1XVfeJ6q_mdBVBk*%a7~A|qZ`(=g9yL( zuE2(|!=6k6%td5Iq*U)*r6en``-c%bqGX%comf|RJ(8ChDWcujl!wr5`Pe+@W?1=$ zM|d}6rKFJqGa$H!-){~5{2cHc+a{j(ST!kwcbRvJ5q7J9WGM*3k>PW{pv_jCCe@Pg z>o?g1lauL)O2DR1l`IxayA=D0PP$}esJ(URZXHI44RiEp>ju|kI&dN&9kyjA@5*6I zrT%V9LOn9|>#N9}muHiEwQ37+&-$%dbs@Y%Y#R%pa}*V5Mcn?h^O$Y3>TvP$zqR+4 zVQsCCwl7smaVeCdMT-`9DHR}4pg?ge1Stvb8VavdztXOb&x8l;1 zwf29XbMD&b?7Q!C&;544vK0J`Nh z(XV$ZjqwiOFHP!R-F(q-SMAyK@u89Oef}~_C+>H>RJt)yUl7;VLep=^sf+u{VRpoc zLq|(}U!~RLjE(BlM14*CyFHM*ocVw7)PxI#1V=G$zbm_6eyWkt73_S1z4WaBcQ|gc zn|tm&=)${c3zj|B`Ga>~x_r6(Q+K941hpYUq5&^cvB&Vy?rMGQvKLH@JH!~=OJ6ix zt%}FPr@rcL-+Hg(7Y*8|I+C5A9|Wdc1z!C&WPqVw)mzsm}%2E7^6!&9e5tp?r%wqK<2rbgZsY{mB6v!VH@ z{s0JTkcfHf$jAo3s`J_Rv1Yn+;;tU*y4)0*^rQmrgfzvLCk5GQ+Km{S===ze`MC54 z&k2W0Al)NTb2`1dzCEo+xNiAAn=|7WRsGI~ z-_8-8a``1r~6`RHK@Szz~*pg1Kw#`V^{NUAgP^F_Bh^trXGzL`K6Cb2jn}5lQKgO zyDi_rZ6S2eME36{Lc_!h#}HX0cs63jHrnugLE##s8XZK+St!QFo~5P`UK*>QmK4B^5ecLHB}}-R;zfuq zLKIqa)MdJgKmFI7F^y?vZeHHf*al` zJCXexqyO31qWvj7p{9iutbTE5XlL1h)3ckF>E~6I);i|C&+wI+w9EX8c@y3^tOj2$ zx}k1lQzZ$!H3*!%XxS%sC`X@3<4q${ohB#;#>}nkoiCc~T{@|QS4Pc1RqaX>lt+%^Fe~C&(+|=p^V;SaXBYyoQ(fdjVD)Jmy#)6N;a=MEBTAI1q5mv&xTK8@_o9BeA1u!;V!{|$AFttuqy%c$+V#LoWpxt5g#1s;-^NR6Ner}rEVtnJxM zpj=o6D;~jNLjsCft zGq`qt$gmGaoSpLXjyg*3*q)n}Mx#h*UmL7?&#Ua`c(D43L?~Fvrn3=L1K_R_DZd@P zjT>*2WL-lC*qk~{V!RJoqXXknxMSxd(51byt8|U6>Jl1QSs+j_zJ#Q>u zr-a6~+2azV)ngo-RyrXGZ|)u)ZNEI1wiA*M1}qNlE|q_f8@cRZt_9klrLy^?tJRSHPT;tdH2%OOLTY+ewdt7i9nlZii{6=4%N6zkWDkj5 zdwkA8aFZibPwR~OZZG`3QgZ+5QKgXGti{Po<&2J)8uP=H*a{lTuhFP30RKZCTx-++ zQhvMpk$^MEXDHRK^(@x`iL;!w0f8-7WaR&OF#JEnys0^_;XD(-h2Geqwm*32XUy3@ z1vwAdi;?{8R*BP1;y1kKumBvk%!Fm3LF*4*6jymvW`L-ToBb;eN>;5N5WW&6gK;X5 z0-BcAAa6Xg5A~WjxJsbVp#Q$rW93(NqrB;)&fq~mo>_>5PbNlxOg45@nMJ{yGQ@=5 zy)TcAufol%<6CUXF*20Dv#XN`my@gNpH{zNfUrGRRPGd*;T|fEtTX+Chd8*9L029V zEG12+7)R(8D}LcBnnNJF^*|>J!adpxoAbL$bW_ug99_G7PICzPrzgpaq17eV8k&$i zA0zdw4I?8@{?qwb4fkrJc+Aw!(%etLokHj+(D2u-yFE;!@l{Kyj7o6|rV|@uwDxl- zn@!|dcIpNk_Im8i^qQUnBZhAE9JyjWbnkGa4EM-gCSiAAjW&Y75M3X_a<;y zIVyE_M;v;{s8lCT@1Q37!|#V)$N*;ht>EewYbbq=NDee3Yio4CZEY$7m49?%RVOIC zSIpOyU&PEXSs|y12i9j7jQMNIde8TcAx|Hyqg&#PUk2>Dd%-Pf9-@CZJCtr%+8~t$ zo85Dut2fzBya%GLoRPLKobWdywM}{4a|z37i|kq^Wfr-0dINUqcBIwO-ZdTz?-}yq zn3WkfuHkC2=hB6#>U79H2P4Or;+rB6f%a0O+e#5K9Ui?Kw6tE!HWU;~%M1_x;6Z~# z)CY>`5w;QTGYe}0j$LOA9{dffJ&APP$Oe%WBVGrQlxcK8kJ}FSySZ|e1{$#uiS;dM zTFnEGcGKK(R~ELjv#XuU?l-yiez z@Q@tGZAm+c)X>E8hP9uWLpM3DfO76j23gvO3yHS8qy=`pQnfuJc=--ulot-F^-J8; zE2WzQeT$%Nv)-o_=e+;Jc6Mo+!G%edFXRoq%Mg^urYSaDR^t^^-XPE_Dg9lyOEd-= zliV@6gf1>86#eX_I~xb=WFC{`k~Q-mjN{It_w|dx`8pN@7OsrO=IgPtCK1KBAK-8xEKh1XxrvOA^@Gf|-_%}CjZj9`W4MvYK|p!)R&X9>_(GdEzq|&H@r!wG zO_nMO=gUvF#q(C%p`aK^=bMhEoggdEiFU>rnAN*CH7)-^bXE*jiv^~C#hU5UU z=sD`gD}5{9@C?B7Bx)5ggewUwui6>Z7GB550@VUr*=vXJ_)k zDJ_GHdMGB140%1yEG$RU6#CdGC(eDP= zJm-H?N)qQnzFiM-Z*m_s&ys79Kz~fK@>m|-jMhP>i~)3;v0Vy7LybvEB}>e*Z{mVH zp?D{Y3wQ*NS7Z4c-S-aWQ(g{l@5#vsZL#E4a>?t^KF5zg6}g;ELM^?|_PHNoctb}i zuVF>Y$PNW9uUKUbbEz=Ae-LSU_SH7ZTWCE?{SRL4I=E+eVPHf_j(X+$I~@qZqh2>D zZzS7&{|EY3NYso`az=qkP=bobQvYUR+Fjxg! zf1Hv6?KmmcF^z?%dv9O&XN5|BsLx-D&wHj|C(cSlao^8@AsTbQK!H8O2VyEN{2BT4 zOk}`(4(E||4Nwpq6**HL9)eLf-r$mQd2%kv65?sKU6<^g$rgey_n_THonRSAg6I43 zoYNd$wtrk(H-4e)6NLLW8gw{OgJa6Uf|j*u`Fq3#p;m z|DqKmb1FhR$+vyQ&m7AZmoL1zhLuYCUM3|5vxR#=Z9EHQearb$g?8FP7&xS0$;DzF z;|AgO5WM>avEeBmv5tZdkdUk0vC8A6lz`3~a#S8)|CPnwTb#6FZ@OMi_F=MX(Rh3& zruAW!600fWd2b)HUnISV5~}V(V&7V=1TD((gJ%^M>{%+6=WB3*EV?Ea2EWVc7+fks zf4Pa_Xehgt?n&c9Z&EQNf;SeMz22mRVN!dhp@r5+Q{OU92m9(4PL>+iSLg>n4avVL znm-)uQ+X(8)G?l=vIBe?74mXJJ#8PQzE*)BT=Ub*b>+959iO;3eK@Cm!*Wjl9_Xw4 zQ0lg+m`sgvT4y&j`uJL$M`Sg!^3~-J6D~LQsU5F5K1Varthj*;=?)pG6!D^yF4ztZ zwz_`PkgBz6e!IzE_abnf*TrAYjo@H8yY;jF=I$fgH zj~S)E(ROz8vcarr9(@D15rC=Ml)dI{1@JN`b_)t?N07^gWnD6i5zrm1JPg2Tz6(r#2jKFKLEEy)9i>qp91wv)Jmn8KE}Xs)1=0Z$uvPjEGGIyyzw;4y^Ps_4BUAx6SW~ z^aSLUgUiwU*qQdJBOlF?QT|z!LxVN`4OEGZH9A>9>iXy*RMcq>}l#>AV2B#QJ`zBu*jPdcKCleBa{=zZMO0mWF z<(d;7K3a7{-t(Gy>Q@HNT$tu3iS?8DSPk3dWOs{6W)B0+Ph*nk#(+4-p6O#6ULBrPC`EPn5;1p223Lexmk#t~+@h z9fX@sVV&b9T;!r(X7){tLvbD3a#Yc}SC^m5PL^gNI$!EG96>;6Ee zCsItJoj*vBkmOM@pXaQ@n!I!AAP_sBV+&5>xJ$z#(5Y+ zM#O?YQAFbMVbkV)O5)+(Z^PsF#g=xCdVON(GIcUVM!)>Q6L`(6JTK?!eI57RR>{(s z&bJb(Kx8T}>VVM#ZuC&;XAHHFyl{?DB@SGDx*Vh-FoWlz@u`w3Yf%^5IrhqGvDfV9 zRF8$zeeawvQK@eti+J$Vd)-S!D*zSveD|B0Wj^uGC`@^t2&p8Lqt|_yXomE!R{$bESM337fO z_KaYj7&{R@C6k)m%6n;T=e7r!D|>nfi!4%Zv`4)U=IA3Eq9^Gqd;?toYXzw7V~~Bm zgLOzbI=hR`I&tB|*O)}*vz!TMk_k@Glmp=vSu!Bo2kVdq56^MTQ@k|+!hV1IF7R+o-aRl)gNz>=cxHs$`pqOQ8ms)*~sXB`y#RQ zJ_9HHp!OWPu>V^0ZNRpg)sEjG4Z6hcLw2I!FKlcVo;-V*x=~dY@4MDa=OQ)S+i{|m zC72}ezh{T;9{+Fk8KVCe`pmy8ceg;h+E3$Re&CW%`kRU@fuU_c$8o%UdCFY~IEFu) znuZJbetGA-LdWFOzp%R$qbN{x>aJE5pD$UhoTP;}aC~9=RcKrQS@_tUgk8NtpIB*n zXX~SL-e4B?Ui)G#mB$*r_>|vkx*H9`*;~>paF8m|EnKDh(04(%i=5~8#HuUwBDPDz zMD~DT9@QRx;ML;y3B|%H`_E>(OuBz|?@jm}DiP_7uVu4HjMLHuBpPA^&+bLfJ>}-% z75RJfjg^jG8>xhK3~xsLpqd$GNO*6hX!n_f2H-73QVi-?f$8nZJ$Cv5zeZ#gb$gOhkmJp z&7`Rm#PY!U)+{Y2espYqju($)0JW{~F@50YRG@Q=OE9L={V&z@{Sz}PnDSrx*#G2} z`Ckzl|7*|vlM4lpYPWQy=q8bBa%-ba*P{`QiV%3Qd@2!AZQn=7MqEqkLe6nU4DZSh z>zXSD9UER158(~)WMKtAhf<>w!|t_Y)^KsDJ3RmIy`U<9!IwsuXPHNifGvmz$L;IY>YQNp zJanZWlD}P(hZdBc&n67~d3-O8+X8f&O{HjSyg^6D5=BNhdm4uoclbELY!|rul5M5g zo?l&&^4WSNWo1q_^|L_dZ6{ZYskZxFQp~lV9!zRehYOiVrnN5>Se1_uF=%J#D$}ct9!NWeIM~vg! z?d#KL6Fds%h#eB!t4W2cL4fL~bUz%C?eF8|Kaa4^y!GE|S%m?t$y4z69nPQC6hCIgSP>SoZ|KtgbEFhkMIycey?yzob z%|Ezs0Kgj~;@r|~Zfw?0YT;;Dx5%EIW`!@hUkWckNE2s$#WCX)748Pf#1g8>{o9G2 z-Q9?|sHZF}j4ggp6c_A034xM!Nj4Sr;p&mnKh)T&AV#rx-EWYW5D*iJ< zvUl~?Q_mE1^(Nv%Dw&6S6Ay==&)|g(QTFVX$NL7p+Q=F|zk#&l8TC7 zP%@3!IC+cl8hK05n|pas=5|Ya;PwhwZx@?i{%*A)x19j|Ds$$LczG3-QiHnH@K*gFLsQCP7*`IG9Z)(r}(+Tp1Wfa>qP3dV^~;ayH`sLHYbY$pcUPIY5jF zTe@OgUk1K^bxy1$QY6jgc5x(j%$B<=ol;FNu^sv_w(<|2|9YCs7j4bC4eR%M5!SeJ z7V#1EA->>zizliXk5KeD6KT?8KgK|2HjX1FjRXYjb>WZ)@_-P=?5>WR^tpbM?^o;( z=wf=6wjOgtdP{4e%fh7VF*Q8&#@H?OeGeLwtQ4F8!^wxuMdN05g9{dSr&`)ZXrx}o zfUz^)5ZNTlB9IW?x&aT+sl0nAR50WvX$P8=kzI#VPnT~`Pw~rHow|`7Dmoaxw8`nV zRsT){$an!kqj~^dK%;l68)C1Nmv$~S2Bm(V>Wo2S+kzjR9t1QAcLo$`NSYSMfcOht zYr;Adgb^JHFDB9ysg*lZPnw^cpz9n1OYaSE98UGD8;cp8C%AEH_YK3uvF~BO-@2+r ze{Nye_P5REZLBLBzuW8VMMUaJ%Iv&SiZUm#RfC)hsZ4U4S3TnUZKDMgid)EFdt?q} zTvDv|c-xPr5$Jw(x9kE1*gs?zhu|>^N=LrM)&p|TtdZe_xN!qHh9T{VoXf6^>B%U%X- z+6A{9K3qxX_J_79=E50xk8=1YRzlvwIgIUn`bsGYr<2O_QFmt?hg6N!8WG2^mF7Upp|07_~auhI>k4T(fo( z*yKZr+lE79AZsSP+pS7CXV{OUzbR#yv$M<;uK-GRVD6!nj4`3faSSA! zv8CyQi8IF7I2(dPq;%Dms?2#8knr2hsu%(vZIZ~=`DmwXQz z?)6lEquMQ<6E_;m4x}q6ZVb?tE}q#E=JR(Yy5iD~d8MZwC0nxu{(e&s3=0uAm8oL~2S1Qkyf^*cXks_pT)z6of7 z2DWz!&q#0P<%8&>YrR{$@AMeW67$73u|V2(A8w>Lj`o*o1*k8s@%I+jPFhNIOFwcc zZLM4`ZK9VAZDj=$yD;xchK9+`IP=SdqNN6n9aN?rkOv2|4H#*^&Mn7+uajPzd2sIo zj;(!%m>1{Y+#C^GZNbKiUXrZ>!{3#Mm1+UTGxepWezs?a4Bb<8O$ca8FTJ|D;-bkr zsgK+jP3lj~_bL#(3z&s5vFL*{&jzodEh3+#siX3)T8!3?cQQhPH&nMfwf@^%cmZV=|hR+*~mUeHDc}<>i>3r1}buVSnrcr%(Ri zogAV|G_^)&6+gqWnq>9x^>|$Jtm!SOa(df;Zs$)@iq-mlo~{odqjz7p@hp=UUGCue z$_jQwj18{d*+0WxLXU$SV=k!blQ3Uv;NMQv(Dba;!*{bAzXD ztZ`$zI^MoVh}a`Gw>tM}o8&257Ur{=V{cN{)ZaOXLte4eBGF<#94hXO;V7!qg5_B5 zv1PW}_0RFm!?fl$u3b!LSq5t#9G7d42^s)%bUH^(q4fzuQ#DO=j4zd~eY06veA59> zTXLfvcTB4XC;R;17ZnzW5$EFq2ap1GnGA85CLOzPtib#9TT@j|&KiW~@f)-XE?^rL zVUO&ygBx3QZAc76b_P2DQ1Qaj~<{!dJX< zrE;x9EqQh!`%O{$d+(sKxxe#Ie!+d$4E)wX+&`C#Mq~GWF=0X?uGL5m!m(5j!DU>~ z{iKu|jy8pd9Wz{om&@|$3F756i|8-uZFBXFK>|W&esNS*1+RM=w_T=9D9we;0~z zZI}D(GK!8b1=TYLd31JJCJ|(fIld`9|Ae1-IBq)1ksfJu6?0nmb`l+j@XamgxPveT z6IfIXKeB#17e<}3jSq{>@Jk@M0Y_QnB%^$9+%M=y{^Dl&56C~d$9-fGA~79dO}9`A zoU|f(vLmun7I}jHNDU2`Y7qpvfb>jow9B0}3+mY`Pl{uH&~M3c;SqSJ6h}j%j=RST zrbgoZ1IFy7DfN>R?NEASMoF`5dH>JMnQl#J?L5BK!v>S#9ZYxUj=|O&ot=Xz@*iZ2 z5QRnnXER>ng3rOLxAn5y$RurHsgSpB=&Ph!kC0#f-7uZ6;CIlhJ7yPdNF86Q+Ue=_ zS31=fh360QQgWOu`{;4ZBBx{bV2K~0_phuzCk!J)Z+%yIL~^;$VbXRNgu0g9v@wma zWfe#CeSXDkZnu(BE7=~5ydS#r^)|pEQ^doxr{X%-TlC)N|Juli?Cw7k2oYY9-agPA z50aH4?D7RtuDUFG4YKqh_&btYZN!^Z?5&sck2I4v4qcm;l_IQJ+>(T%6Ch!#od`Vv zmA2h6Jjm0tN8vRsZfOSQ-*BV(ClX~joAi{H)}*rW7%>Z?Ab5T&qZ0BgzQL|k3mgIj z9KP~+o4n{sOPgQ0C4??RhiPz-_Ew{OEFal0c33j^7RLg~8p^CtmPhaQQi!)K4E zU;vwPSsT%+PJPqPu3r#)r*ZjIqi3~;t{v&LiC#0q;8`Six+{f&AQuG!?T@D5q8v^9 zy$;@dvGG&2vF26FTQj_5UwPlh?BqxJ%PsYVk`{q~$hP^6pGZwytBkkw1K80$a(4c5 z;!vJ~G6NIy5#|RZISI;^b_m&C-v_S7!{3Kw!{k|_O?#QF>`LQXt!w3{4;lT=kE)Bt zQ-2EU(R^HZ$fy0&@?fFwTYQzi{F_$V%znd@+1O;E&o( zr?u#Qd0WmI5P(||7Y7sl%FJGB;p4%AGSpKNA+?KdXxwpu11_ga;&JO_g5apz+JHglZ+`H?P`&*{}&O2aIv(WU1pdLe>2GyR+|AjQPe z4Juf%ohbKp6XNvBM%o-)+v?D(^Z+u22cvea9_~i0J}_TV&}721G65y?5~IH_g6_Q&XKr2p}V!L0M!=iyb-uQmcKl&;&$0>jVagnoW+Jj>Wtg$*4cRj2zKl%g* zU(KuYSlT+Ze^=E4Uz8+d=;$MHILo$pz!l?FSHRVoi#oUaE9!(Tooe99+9@nic|pJ8 z?OSv8bL(+IQN-5-V+xk#yc! z>xYZEw7!VuTOY$y7$4s{eS)uQDj{yq!`{g^LzSFFMzj0j(Cfm*1I$?!r)W@dojZe9RZwGr?j(y}#h)4~Ti!)UBl)K>OC9 z2Mi!m?OS#w@s)4-dY8up;*>aK8*g@ajE%iLme1}k~rRhtth2d0Cta`3zXBM`P6%_&lr`@+3UWk#$BZ-8VWA1bQ$M<#9Fyf{mKz?&lxipHBK>9$W*GgCfGl=# z{!G(e&%xG|Fkcu0*mTlVcfM4w_nOH0SlhXKi_0FYa*9hHIdXA4=@cz3mCH`os2;^J0!LMz zsvy-f>J6>?^;@+sHmSHYOr1KO9? zdrdqw$2Wykgq=aYmM1Vr>dS}OPsG6O<)U`hJghG>1@w>;^jn_?SXrkv92S6?d!NaE zG2|>c;_bYO5>yui$X#DC5eD#GujMd06qjvOS!crU7cnHwfu5t-a_ZIf7*GY1InssZ zLDEi*bYwE!G@O+juV)9Bl_)1=2!7!Maiux;dI|slk(+G$*qn8{G|mXkOvC&t2Zs}* zQvclg!pTND20_qcq2q7J$&ivmL{$dazpkT~_I4i_40kKBXchTQnmKQjQ1%S=dl}bs zh%*Q!c%Hv0HA{Ru(rVbD+gepmEqWr#GXRm8y?LqsDgZpNohIW;-sJDK7xFGfcJp-g zhu*oIS#HI#cik8cGFDm756})#UFuVUXcraF9@o{@?S%J+QVCWnxOE*`2sLS|k4F-m z4OHRr9V`ues{1Jr?VJZ+@T)8PgGWMopXgdwk8M`N7#;xytJDHrN3R3WuTs%xQSfV1#>jk7Y*JFb24 zT(&_vD3|@~otB;7j!H7AS*AtW*lFxxLcyjxK%}+^S~I^HF4fqJa_~Vm25+f$3`*61 zAU$lUm>-D6AYt3ZMTwa;_NF=~bBnIHdE=YMZsY!{+SjoqZ4yk12WlChA`eQ z#w!Fc0Ez>H`c*eF*gm^u*ShBH_gS=ThX4Wu0@rf(8=fX|&@Ob-4Z$aKXZtBshLG5z z-6Q!IK0b&Ap4F1kLNj9XV7ln2al7AP5$1++N2xtbdR#*IF4#;`STyV^Ghvf+xYN~D z!&FHp(YW#GaqZ^_I%@&YJ@8U z*N$DJ_YOeYg=lX>_@zC2iIY#Jbj&QYJOf;RtLp#3`@Q?PVCf=ePGh`Wqd*W*xx>Zv z+8#JFLro7XM!z;?Vf(qJEWSP5#aP406#jGNr-X-kvT0T!sdiHiLtNg?R}`@!B*<{b zJO90|a|}cK8ZE1nBeQDlCvWzh2G6sHsG3t+fA6e~I>~g;I@5C1k5)qOv$~vruZ0eV zTL_?gUFqkTyE|V>l2TJ^TF>e}RwAeBUcR8eUk=G&1RsxG#gc2xMfGL-wKauf+%Rw#!Pme@KzjO5gfS zArZaqeWEEfvR+`CY?I$Pg3;UPWsf{|vcnj(&m>%~k`cNnb5xE;`8A?arXJhc#6IzC zm4Rr>y{+1;QliU9&!o~Ch4Trx)NNyT8ccU4-pJtiuRkS?tF&E+ zxTGB}oTWXJ!|y%o$rX~^4TDn0H(%QvkYhT>NMF9mz`GgX<{f0xBiSSMowcFXo8>(nO{*_Y6GA26zPE1$%xAilwh3=tcEj4xf zOU;Spq-1~|R~b{{{ZL+_YrTZ@iZ;*e@Ny2>$_EA-*wn8=_;(5d2eTFCNCj>&v9Ffp zF)&IDn1Bspl5cEzJ2S;Viyb}ivz6|9# z5ft4K@}ZgEQ74J^fAFSi&dr=;nf_~LpL2f)ex$5+3ftr$gPPrpif+zy?ij4>kytv# zFUPlI8y_XLF_Wo!)zcYj5%!5Au5kj00olI$9+AHCgkh}RY+St;=;Ijpv*MWOd_!9k z_{7YnhUr$1HBr6OLMR|6-wM=+@SwIZGW&EZ1-NJh%bDtZ$(P+EU9;WbwUT|%^x1wR z(zWSv{V)w~#r5iV+8>KmN%UBIVtb=rA;e8cGNTk|_E zS@h@rq#1;2eHa$Nl%w~vqx#7L2DdzEn&?G-?!s#_Gna02s|!L z#e0m#`fPHASNjh%NZ`?%4V9d}wl!3F(3%x@|K`oIfZT&qA!j);?dVfWKLO!;s?V^( zFKnv-%u?f0#8d9y2`0=Ozm74c6N;3*FC8^og^64N66|-5W%>DI7*T-VJH5&L>9ORV z_Y$C-d?C2ZcOJEa&>b@8y`y`G`>9u6!{K1{hC+6#86A0aAIhH5w_xd$TaCi7+JY4h{v1MxT&U7J^PKOFT4Id>V%2sx>-=r?=oqSv#3#-Lj72qXQ8&ziCHzwl{`JB=HBnWPBaxW-kf*wQxG-hN00orbIaM*0$KFocF|#@R({`0_^a zB35$HU(f_*`zt_svcnRz=HgCN!;)4dC2{>OdT`ukp9W8Za(9TTRkmQxTMKG6=DfvH zJUo0MMug=`eF7k08G@q3;iz+GbVTkSEtjgOIg!P|hSJaVe9tS=XN2Cq_ZR$w z_u9}}dA@1W^$`ZxC{gbp^Fno&b$;)o>NtKss@#iQ7j}MqGq%sLc}Q!wvOREN7E%hh z7Bh&oFFMU}xAPO5IF5F+3hbk#SdBkWs$68KR3AjnH#Mu|4)oKoe*M2GA^zt~d-v{7 z3$iqZDH497xmJ2V%5qfmHN}i(I%~0sW5?-OU~6j-&W7@DBRrDDR*ffH#5v_ z+g-ydVxOb_HH?-p6|vl4MZ*Adz@cmGs-A?!XLhbP+KH&ujpyH$$;$rygM@l6X+)ph z7tpqc7%f36A~`xbNHc!mS+?tuv9sG*1zPnfbF)E$L(6F-I# zTT7gUf7y+zhS1NR28cgGS?fGXd7`R2QzQmNtMt}vznni?!S%8MLlGp53Rf>VjY(9| zrtnRfZRd`Rf#ph~FsLB16!6SkUVvUbVvOV5nhlC0oU766X&#dhR0`u~buDEG-dE5X zULa+i@>8Bg>K2N&3Fe-28>3yHTC1XV)U4b4SJSz zFyf4@IOBVtme|5W0;7*|ay6DGd%>ff|54Oe2wwsRE|zB7PX2WE@4v*q{e=I0L;mC8 kKj&f}_u%3v|GPK;AAaGVVgc}9)|vmyw*UWVUH(k`HzdWX^#A|> literal 0 HcmV?d00001 diff --git a/intellij/keywords-1.txt b/intellij/keywords-1.txt new file mode 100644 index 0000000..4219d7a --- /dev/null +++ b/intellij/keywords-1.txt @@ -0,0 +1,4 @@ +:delay +:do +:local +:put \ No newline at end of file diff --git a/intellij/keywords-2.txt b/intellij/keywords-2.txt new file mode 100644 index 0000000..8e67924 --- /dev/null +++ b/intellij/keywords-2.txt @@ -0,0 +1,5 @@ +add +find +remove +set +disable \ No newline at end of file diff --git a/intellij/keywords-3.txt b/intellij/keywords-3.txt new file mode 100644 index 0000000..14e41ac --- /dev/null +++ b/intellij/keywords-3.txt @@ -0,0 +1,54 @@ +/certificate +/certificate import +/file +/file print +/interface +/interface bridge +/interface bridge filter +/interface bridge port +/interface ethernet +/interface ethernet +/interface list +/interface list member +/interface ovpn-client +/interface ovpn-client remove +/interface ovpn-server +/interface vlan +/interface wireless +/interface wireless security-profiles +/ip +/ip address +/ip dhcp-server +/ip dhcp-server lease +/ip dhcp-server network +/ip dns +/ip dns static +/ip firewall +/ip firewall address-list +/ip firewall filter +/ip firewall nat +/ip firewall nat +/ip ipsec +/ip ipsec policy +/ip neighbor +/ip neighbor discovery-settings +/ip pool +/ip route +/ip service +/ip settings +/ip ssh +/ip ssh import-host-key +/lcd pin +/ppp profile +/ppp secret +/system identity +/system logging +/system logging action +/system package +/system scheduler +/system script +/tool bandwidth-server +/tool fetch +/tool mac-server +/user +/user ssh-keys import diff --git a/intellij/keywords-4.txt b/intellij/keywords-4.txt new file mode 100644 index 0000000..3d4e4f3 --- /dev/null +++ b/intellij/keywords-4.txt @@ -0,0 +1,99 @@ +action +address +address-pool +allow-remote-requests +allowed-interface-list +auth +authentication-types +band +band +bridge +cache-size +certificate +chain +channel-width +cipher +client-id +comment +connect-to +connection-nat-state +connection-state +contents +default +default-forwarding +default-name +default-profile +disabled +discover-interface-list +dns-server +dont-require-permissions +dst-address +dst-port +enabled +file +frequency +gateway +host-key-size +http-data +http-method +in-interface +in-interface-list +interface +interval +ipsec-policy +jump-target +list +local-address +mac-address +management-protection +master-interface +mode +name +on-error +on-event +out-interface +out-interface-list +output +owner +passphrase +password +pin-number +poe-out +policy +port +prefix +private-key-file +profile +protocol +public-key-file +pvid +ranges +remote +remote-address +remote-port +rp-filter +secure-redirects +security-profile +server +servers +service +skip-dfs-channels +source +src-address +ssid +start-date +start-time +strong-crypto +supplicant-identity +target +tcp-syncookies +to-addresses +to-ports +topics +ttl +url +user +verify-server-certificate +vlan-id +wpa2-pre-shared-key +wps-mode diff --git a/mikrotik_configurator/__init__.py b/mikrotik_configurator/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mikrotik_configurator/__main__.py b/mikrotik_configurator/__main__.py new file mode 100644 index 0000000..a72ce1d --- /dev/null +++ b/mikrotik_configurator/__main__.py @@ -0,0 +1,106 @@ +import argparse +import os +import subprocess +import tempfile + +import yaml + +import generator +from utils import query_yes_no + + +def main(): + argparser = argparse.ArgumentParser() + argparser.add_argument('-c', '--config', default="config.yml", type=str, metavar="PATH") + argparser.add_argument('-n', '--dry-run', action='store_true') + argparser.add_argument('--reset', action='store_true') + argparser.add_argument('--override-ip', type=str) + argparser.add_argument('files', type=str, nargs="+", metavar="NAME") + args = argparser.parse_args() + + dry_run = args.dry_run + cfg = yaml.load(open(args.config, "rt"), Loader=yaml.FullLoader) + + host = cfg["host"] + has_flash = cfg.get("has_flash", False) + + if args.override_ip is not None: + host = args.override_ip + + files = args.files + + orders = [float(os.path.basename(x).split("-")[0].replace("_", ".")) for x in files] + if orders != list(sorted(orders)): + print("mixed up order") + exit(1) + + if args.reset and orders[0] != 0: + print("reset must start with 0_0") + exit(1) + + if not args.reset and orders[0] == 0: + print("not reset can't start with 0_0") + exit(1) + + if not dry_run and args.reset: + if not query_yes_no("Are you sure you want to reset configuration?", "no"): + exit(1) + + def gen(x): + s = f'\n/log info message="starting {x}..."\n' + s += generator.render_file(x, cfg.get("include_dirs", []), cfg.get("variables", {})) + s += f'\n/log info message="finished {x}"\n' + return s + + script = "\n".join(gen(x) for x in files) + if args.reset: + script = ":delay 7s\n" + script + + script += "\n/log info message=\"CONFIGURATION DONE\"\n" + + base_path = "flash/" if has_flash else "" + script_name = "output.rsc" + + print(script) + + with tempfile.NamedTemporaryFile(mode="wt") as f: + f.write(script) + f.flush() + + cargs = [ + "scp", + "-o", "StrictHostKeyChecking=false", + "-o", "UserKnownHostsFile=/dev/null", + "-o", "PubkeyAcceptedKeyTypes=+ssh-rsa", + f.name, + f"admin@{host}:{base_path}{script_name}" + ] + print(" ".join(cargs)) + if not dry_run: + subprocess.check_call(cargs) + + if args.reset: + cmd = f"/system reset-configuration no-defaults=yes skip-backup=yes run-after-reset={base_path}{script_name}" + else: + cmd = f"/import file={base_path}{script_name}" + cargs = [ + "ssh", + "-o", "StrictHostKeyChecking=false", + "-o", "UserKnownHostsFile=/dev/null", + "-o", "PubkeyAcceptedKeyTypes=+ssh-rsa", + f"admin@{host}", + cmd, + ] + print(" ".join(cargs)) + if not dry_run: + if args.reset: + subprocess.run(cargs) + else: + out = subprocess.check_output(cargs).decode("utf-8") + + if "Script file loaded and executed successfully" not in out: + print("Script error") + exit(1) + + +main() diff --git a/mikrotik_configurator/generator.py b/mikrotik_configurator/generator.py new file mode 100644 index 0000000..f3fdead --- /dev/null +++ b/mikrotik_configurator/generator.py @@ -0,0 +1,89 @@ +import os +from textwrap import indent +from typing import Dict, List + +from jinja2 import Environment, FileSystemLoader + +from utils import read_text_file + +script_dir = os.path.dirname(os.path.realpath(__file__)) + +cleanups = [] + + +def escape_for_mikrotik(cnt): + return cnt \ + .replace('\\', '\\\\') \ + .replace("\t", "\\t") \ + .replace("\r", "\\r") \ + .replace("\n", "\\n") \ + .replace('"', '\\"') + + +def load_file(path, name): + _, ext = os.path.splitext(name) + assert ext == ".txt" + file_cnt = escape_for_mikrotik(read_text_file(os.path.expanduser(path)).strip()) + esc = escape_for_mikrotik(file_cnt) + + cnt = f""" +:execute script=":put \\"{esc}\\"" file="{name}" +:delay 1000ms +""" + return cnt + + +def generate_catch_block(body): + return f""":do {{ +{indent(body.strip(), " ")} +}} on-error={{}} +""" + + +def register_cleanup(caller): + body = caller() + + body = generate_catch_block(body) + + cleanups.insert(0, body) + return "" + + +def escape_string(caller): + body = caller().strip() + return f'"{escape_for_mikrotik(body)}"' + + +def rollback_delete_chain(name): + body = generate_catch_block(f""" +/ip firewall filter remove [find chain="{name}"] +/ip firewall filter remove [find jump-target="{name}"] +/ip firewall nat remove [find chain="{name}"] +/ip firewall nat remove [find jump-target="{name}"] +/ip firewall mangle remove [find chain="{name}"] +/ip firewall mangle remove [find jump-target="{name}"] +""") + cleanups.insert(0, body) + return "" + + +def render_file(path: str, include_dirs: List[str], variables: Dict[str, str]): + global cleanups + cleanups = [] + + env = Environment( + loader=FileSystemLoader([ + os.path.join("."), + *include_dirs, + ]), + ) + env.globals['register_cleanup'] = register_cleanup + env.globals['escape_string'] = escape_string + env.globals['rollback_delete_chain'] = rollback_delete_chain + env.globals = {**env.globals, **variables} + + content = env.get_template(os.path.basename(path)) + content = content.render(load_file=load_file) + + content = "\n".join(cleanups) + "\n\n" + content + return content diff --git a/mikrotik_configurator/utils.py b/mikrotik_configurator/utils.py new file mode 100644 index 0000000..cccbffc --- /dev/null +++ b/mikrotik_configurator/utils.py @@ -0,0 +1,35 @@ +import sys + + +def write_text_file(path, content): + with open(path, "wt", encoding="utf-8") as f: + f.write(content) + + +def read_text_file(path): + with open(path, "rt") as f: + return f.read() + + +def query_yes_no(question, default="yes"): + valid = {"yes": True, "y": True, "ye": True, + "no": False, "n": False} + if default is None: + prompt = " [y/n] " + elif default == "yes": + prompt = " [Y/n] " + elif default == "no": + prompt = " [y/N] " + else: + raise ValueError("invalid default answer: '%s'" % default) + + while True: + sys.stdout.write(question + prompt) + choice = input().lower() + if default is not None and choice == '': + return valid[default] + elif choice in valid: + return valid[choice] + else: + sys.stdout.write("Please respond with 'yes' or 'no' " + "(or 'y' or 'n').\n") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..df67e0d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +jinja2 +pyyaml \ No newline at end of file diff --git a/tools/gen_ssh_host_keys.sh b/tools/gen_ssh_host_keys.sh new file mode 100755 index 0000000..c3e42b3 --- /dev/null +++ b/tools/gen_ssh_host_keys.sh @@ -0,0 +1,4 @@ +ssh-keygen -N "" -f ssh_host_private_key_dsa -t dsa -m pkcs8 +ssh-keygen -N "" -f ssh_host_private_key_rsa -t rsa -m pkcs8 +ssh-keygen -e -f ssh_host_private_key_rsa.pub -m pkcs8 > ssh_host_private_key_rsa.pub.tmp +mv ssh_host_private_key_rsa.pub.tmp ssh_host_private_key_rsa.pub