From 038d7e0fa670405eb2c6b4c135a1453e7c994445 Mon Sep 17 00:00:00 2001 From: Dave Date: Fri, 19 Nov 2021 15:20:00 -0500 Subject: [PATCH 01/45] Add missing HTTP_X_FORWARDED_FOR See discussion [here](https://github.com/netbox-community/netbox/discussions/7876) for background. From the [doc](https://netbox.readthedocs.io/en/stable/customization/custom-scripts/) i should be able to access `META.HTTP_X_FORWARDED_FOR` but i was not able to since they were not being sent downstream --- netbox/utilities/constants.py | 1 + 1 file changed, 1 insertion(+) diff --git a/netbox/utilities/constants.py b/netbox/utilities/constants.py index c3fbd0687..08e9dd9cf 100644 --- a/netbox/utilities/constants.py +++ b/netbox/utilities/constants.py @@ -57,6 +57,7 @@ HTTP_REQUEST_META_SAFE_COPY = [ 'HTTP_HOST', 'HTTP_REFERER', 'HTTP_USER_AGENT', + 'HTTP_X_FORWARDED_FOR', 'QUERY_STRING', 'REMOTE_ADDR', 'REMOTE_HOST', From 2ec64a2ea25848e1c4770a65c99920da599553d3 Mon Sep 17 00:00:00 2001 From: rizlas Date: Tue, 14 Dec 2021 10:17:00 +0100 Subject: [PATCH 02/45] Get_Environment from napalm should not need any decoding --- netbox/dcim/api/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index f359f0f24..74f06c64f 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -501,7 +501,7 @@ class DeviceViewSet(ConfigContextQuerySetMixin, CustomFieldModelViewSet): response[method] = {'error': 'Only get_* NAPALM methods are supported'} continue try: - response[method] = decode_dict(getattr(d, method)()) + response[method] = decode_dict(getattr(d, method)(), decode_keys=False) except NotImplementedError: response[method] = {'error': 'Method {} not implemented for NAPALM driver {}'.format(method, driver)} except Exception as e: From 42b590af77e1eed0f439b5186753084d6e6f7c52 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 20 Dec 2021 16:06:42 -0500 Subject: [PATCH 03/45] PRVB --- docs/release-notes/version-3.1.md | 4 ++++ netbox/netbox/settings.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index ce6a67327..b117c4b1e 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -1,5 +1,9 @@ # NetBox v3.1 +## v3.1.3 (FUTURE) + +--- + ## v3.1.2 (2021-12-20) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index af4ce0a4d..675d8f78d 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -19,7 +19,7 @@ from netbox.config import PARAMS # Environment setup # -VERSION = '3.1.2' +VERSION = '3.1.3-dev' # Hostname HOSTNAME = platform.node() From 3a54ecb5224253ef2be808276fa58484d1773292 Mon Sep 17 00:00:00 2001 From: kkthxbye-code Date: Mon, 20 Dec 2021 23:31:24 +0100 Subject: [PATCH 04/45] Fix #8097: Re-fix markdown table rendering --- netbox/project-static/dist/netbox-dark.css | Bin 788892 -> 789153 bytes netbox/project-static/dist/netbox-light.css | Bin 493648 -> 493807 bytes netbox/project-static/dist/netbox-print.css | Bin 1623714 -> 1624275 bytes netbox/project-static/styles/netbox.scss | 13 +++++++++++++ netbox/templates/circuits/provider.html | 4 ++-- netbox/templates/extras/report_result.html | 2 +- netbox/templates/extras/script_result.html | 2 +- netbox/templates/inc/panels/comments.html | 2 +- netbox/utilities/templatetags/helpers.py | 4 ++++ 9 files changed, 22 insertions(+), 5 deletions(-) diff --git a/netbox/project-static/dist/netbox-dark.css b/netbox/project-static/dist/netbox-dark.css index 25017505e04a3c541e8e65211b4287e20f1af581..e711685bf40042d2b0918218882f0acba69a0d49 100644 GIT binary patch delta 179 zcmbO;*F7M2#)7Pc1l7LFFq7OocVEj%e~5_(0cc`2zysVTa-iAC8d z`Q>>EC5cHnsnZjaSoN*3NM=+gF7M2#)7Pc1l7LFFq7OocVEj%e~+cVjDESLca(hJN0 diff --git a/netbox/project-static/dist/netbox-light.css b/netbox/project-static/dist/netbox-light.css index 07ad0dba297c4e12560fd426b5479997128fef43..10c15397d1e4569f878cdc5a43c32ba37163dc76 100644 GIT binary patch delta 177 zcmcaGLGJxTxrP?T7N!>F7M2#)7Pc+yY;E;=MX7lysYR(Ny19u(*(v$uc?uL%rvl;r1H85LA06zAt;rYI<F7M2#)7Pc+yY;D_@wy}FL0RXDv3Pu0` diff --git a/netbox/project-static/dist/netbox-print.css b/netbox/project-static/dist/netbox-print.css index a09f4922203efc024056c4451260fe9ca2fd7bd7..4562597d87cbb286d15773b5aaa93fe207d7989f 100644 GIT binary patch delta 356 zcmZ3~n|yg>E(=Yz!SDM_=%pr(XN=pJ$OG#o NOC Contact - {{ object.noc_contact|render_markdown|placeholder }} + {{ object.noc_contact|render_markdown|placeholder }} Admin Contact - {{ object.admin_contact|render_markdown|placeholder }} + {{ object.admin_contact|render_markdown|placeholder }} Circuits diff --git a/netbox/templates/extras/report_result.html b/netbox/templates/extras/report_result.html index 90726d287..e2f89a180 100644 --- a/netbox/templates/extras/report_result.html +++ b/netbox/templates/extras/report_result.html @@ -78,7 +78,7 @@ {% endif %} - {{ message|render_markdown }} + {{ message|render_markdown }} {% endfor %} {% endfor %} diff --git a/netbox/templates/extras/script_result.html b/netbox/templates/extras/script_result.html index 3cbd0c611..15c446492 100644 --- a/netbox/templates/extras/script_result.html +++ b/netbox/templates/extras/script_result.html @@ -74,7 +74,7 @@ {{ forloop.counter }} {% log_level log.status %} - {{ log.message|render_markdown }} + {{ log.message|render_markdown }} {% empty %} diff --git a/netbox/templates/inc/panels/comments.html b/netbox/templates/inc/panels/comments.html index bfacb25bf..3219a25a5 100644 --- a/netbox/templates/inc/panels/comments.html +++ b/netbox/templates/inc/panels/comments.html @@ -4,7 +4,7 @@
Comments
-
+
{% if object.comments %} {{ object.comments|render_markdown }} {% else %} diff --git a/netbox/utilities/templatetags/helpers.py b/netbox/utilities/templatetags/helpers.py index db9c40fc5..47e341400 100644 --- a/netbox/utilities/templatetags/helpers.py +++ b/netbox/utilities/templatetags/helpers.py @@ -59,6 +59,10 @@ def render_markdown(value): # Render Markdown html = markdown(value, extensions=['fenced_code', 'tables', StrikethroughExtension()]) + # If the string is not empty wrap it in rendered-markdown to style tables + if html: + html = f'
{html}
' + return mark_safe(html) From 872691a138486c80fe5589c68314dacc4ec46c25 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 20 Dec 2021 20:45:32 -0500 Subject: [PATCH 05/45] Convert scripts to use HTMX --- netbox/extras/views.py | 11 +++ .../templates/extras/htmx/script_result.html | 52 +++++++++++ netbox/templates/extras/script_result.html | 86 +++---------------- 3 files changed, 73 insertions(+), 76 deletions(-) create mode 100644 netbox/templates/extras/htmx/script_result.html diff --git a/netbox/extras/views.py b/netbox/extras/views.py index ab9e3ba52..f2cf1b38a 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -10,6 +10,7 @@ from rq import Worker from netbox.views import generic from utilities.forms import ConfirmationForm +from utilities.htmx import is_htmx from utilities.tables import paginate_table from utilities.utils import copy_safe_request, count_related, normalize_querydict, shallow_compare_dict from utilities.views import ContentTypePermissionRequiredMixin @@ -820,6 +821,16 @@ class ScriptResultView(ContentTypePermissionRequiredMixin, GetScriptMixin, View) script = self._get_script(result.name) + # If this is an HTMX request, return only the rendered table HTML + if is_htmx(request): + response = render(request, 'extras/htmx/script_result.html', { + 'script': script, + 'result': result, + }) + if result.completed: + response.status_code = 286 + return response + return render(request, 'extras/script_result.html', { 'script': script, 'result': result, diff --git a/netbox/templates/extras/htmx/script_result.html b/netbox/templates/extras/htmx/script_result.html new file mode 100644 index 000000000..013b4c81d --- /dev/null +++ b/netbox/templates/extras/htmx/script_result.html @@ -0,0 +1,52 @@ +{% load helpers %} +{% load log_levels %} + +{% if result.completed %} +

+ Run: {{ result.created|annotated_date }} + {% if result.completed %} + Duration: {{ result.duration }} + {% endif %} +

+
+
Script Log
+
+ + + + + + + {% for log in result.data.log %} + + + + + + {% empty %} + + + + {% endfor %} +
LineLevelMessage
{{ forloop.counter }}{% log_level log.status %}{{ log.message|render_markdown }}
+ No log output +
+
+ {% if execution_time %} + + {% endif %} +
+

Output

+ {% if result.data.output %} +
{{ result.data.output }}
+ {% else %} +

None

+ {% endif %} +{% else %} +
+ Loading... +
+

Results pending...

+{% endif %} diff --git a/netbox/templates/extras/script_result.html b/netbox/templates/extras/script_result.html index 3cbd0c611..f00b3bf91 100644 --- a/netbox/templates/extras/script_result.html +++ b/netbox/templates/extras/script_result.html @@ -4,16 +4,10 @@ {% load log_levels %} {% load static %} -{% block head %} - -{% endblock %} - {% block title %}{{ script }}{% endblock %} {% block subtitle %} {{ script.Meta.description|render_markdown }} - {% include 'extras/inc/job_label.html' with result=result %} {% endblock %} {% block header %} @@ -37,81 +31,21 @@ -
-

- Run: {{ result.created|annotated_date }} - {% if result.completed %} - Duration: {{ result.duration }} - {% else %} -

- Loading... -
- {% endif %} -

-
- {% if result.completed %} -
-
-
-
- Script Log -
-
- - - - - - - {% for log in result.data.log %} - - - - - - {% empty %} - - - - {% endfor %} -
LineLevelMessage
{{ forloop.counter }}{% log_level log.status %}{{ log.message|render_markdown }}
- No log output -
-
- {% if execution_time %} - - {% endif %} -
-
-
- {% else %} -
-
-
Pending Results
-
-
- {% endif %} -
-
-
{{ result.data.output }}
-
-
-

{{ script.filename }}

-
{{ script.source }}
+
+
+
+ {% include 'extras/htmx/script_result.html' %} +
+
+
+

{{ script.filename }}

+
{{ script.source }}
+
{% endblock content-wrapper %} - -{% block data %} - - -{% endblock %} From 4ae2b4e0b90446857b8d2c13cfa6eeed8e175a24 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 20 Dec 2021 20:52:29 -0500 Subject: [PATCH 06/45] Convert reports to use HTMX --- netbox/extras/views.py | 20 +++- .../templates/extras/htmx/report_result.html | 81 ++++++++++++++++ netbox/templates/extras/report_result.html | 96 +------------------ 3 files changed, 100 insertions(+), 97 deletions(-) create mode 100644 netbox/templates/extras/htmx/report_result.html diff --git a/netbox/extras/views.py b/netbox/extras/views.py index f2cf1b38a..d5d36d364 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -694,16 +694,26 @@ class ReportResultView(ContentTypePermissionRequiredMixin, View): def get(self, request, job_result_pk): report_content_type = ContentType.objects.get(app_label='extras', model='report') - jobresult = get_object_or_404(JobResult.objects.all(), pk=job_result_pk, obj_type=report_content_type) + result = get_object_or_404(JobResult.objects.all(), pk=job_result_pk, obj_type=report_content_type) # Retrieve the Report and attach the JobResult to it - module, report_name = jobresult.name.split('.') + module, report_name = result.name.split('.') report = get_report(module, report_name) - report.result = jobresult + report.result = result + + # If this is an HTMX request, return only the result HTML + if is_htmx(request): + response = render(request, 'extras/htmx/report_result.html', { + 'report': report, + 'result': result, + }) + if result.completed: + response.status_code = 286 + return response return render(request, 'extras/report_result.html', { 'report': report, - 'result': jobresult, + 'result': result, }) @@ -821,7 +831,7 @@ class ScriptResultView(ContentTypePermissionRequiredMixin, GetScriptMixin, View) script = self._get_script(result.name) - # If this is an HTMX request, return only the rendered table HTML + # If this is an HTMX request, return only the result HTML if is_htmx(request): response = render(request, 'extras/htmx/script_result.html', { 'script': script, diff --git a/netbox/templates/extras/htmx/report_result.html b/netbox/templates/extras/htmx/report_result.html new file mode 100644 index 000000000..3bc5ad27d --- /dev/null +++ b/netbox/templates/extras/htmx/report_result.html @@ -0,0 +1,81 @@ +{% load helpers %} + +

+ Run: {{ result.created|annotated_date }} + {% if result.completed %} + Duration: {{ result.duration }} + {% else %} +

+ Loading... +
+ {% endif %} + {% include 'extras/inc/job_label.html' with result=result %} +

+{% if result.completed %} +
+
+ Report Methods +
+
+ + {% for method, data in result.data.items %} + + + + + {% endfor %} +
{{ method }} + {{ data.success }} + {{ data.info }} + {{ data.warning }} + {{ data.failure }} +
+
+
+
+
+ Report Results +
+
+ + + + + + + + + + + {% for method, data in result.data.items %} + + + + {% for time, level, obj, url, message in data.log %} + + + + + + + {% endfor %} + {% endfor %} + +
TimeLevelObjectMessage
+ {{ method }} +
{{ time }} + + + {% if obj and url %} + {{ obj }} + {% elif obj %} + {{ obj }} + {% else %} + + {% endif %} + {{ message|render_markdown }}
+
+
+{% else %} +
Pending results
+{% endif %} diff --git a/netbox/templates/extras/report_result.html b/netbox/templates/extras/report_result.html index 90726d287..9dd733bef 100644 --- a/netbox/templates/extras/report_result.html +++ b/netbox/templates/extras/report_result.html @@ -2,98 +2,10 @@ {% load helpers %} {% load static %} -{% block head %} - -{% endblock %} - {% block content-wrapper %} -
-
-

- Run: {{ result.created|annotated_date }} - {% if result.completed %} - Duration: {{ result.duration }} - {% else %} -

- Loading... -
- {% endif %} - {% include 'extras/inc/job_label.html' with result=result %} -

- {% if result.completed %} -
-
- Report Methods -
-
- - {% for method, data in result.data.items %} - - - - - {% endfor %} -
{{ method }} - {{ data.success }} - {{ data.info }} - {{ data.warning }} - {{ data.failure }} -
-
-
-
-
- Report Results -
-
- - - - - - - - - - - {% for method, data in result.data.items %} - - - - {% for time, level, obj, url, message in data.log %} - - - - - - - {% endfor %} - {% endfor %} - -
TimeLevelObjectMessage
- {{ method }} -
{{ time }} - - - {% if obj and url %} - {{ obj }} - {% elif obj %} - {{ obj }} - {% else %} - - {% endif %} - {{ message|render_markdown }}
-
-
- {% else %} -
Pending results
- {% endif %} +
+
+ {% include 'extras/htmx/report_result.html' %}
-
-{% endblock %} - -{% block data %} - - +
{% endblock %} From 17ba0a97d5a898b409968f66e20bc62b318c42ff Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 20 Dec 2021 20:59:14 -0500 Subject: [PATCH 07/45] Remove jobs Javascript --- netbox/project-static/bundle.js | 1 - netbox/project-static/dist/jobs.js | Bin 108677 -> 0 bytes netbox/project-static/dist/jobs.js.map | Bin 105846 -> 0 bytes netbox/project-static/src/global.d.ts | 32 -------- netbox/project-static/src/jobs.ts | 104 ------------------------- 5 files changed, 137 deletions(-) delete mode 100644 netbox/project-static/dist/jobs.js delete mode 100644 netbox/project-static/dist/jobs.js.map delete mode 100644 netbox/project-static/src/jobs.ts diff --git a/netbox/project-static/bundle.js b/netbox/project-static/bundle.js index 100b70ac8..76a1581ad 100644 --- a/netbox/project-static/bundle.js +++ b/netbox/project-static/bundle.js @@ -40,7 +40,6 @@ async function bundleGraphIQL() { async function bundleNetBox() { const entryPoints = { netbox: 'src/index.ts', - jobs: 'src/jobs.ts', lldp: 'src/device/lldp.ts', config: 'src/device/config.ts', status: 'src/device/status.ts', diff --git a/netbox/project-static/dist/jobs.js b/netbox/project-static/dist/jobs.js deleted file mode 100644 index 2aedf1219487eaf56a9ed4964b409d5cacc6cdd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108677 zcmd44i&q=Rvhe$_2pu1`6b2b*f9F1gCoF<->>a#nRAO;1lhs;jE&)zz(5JOAe9syA(1PV?7iAB%p~=}(JZRqRUPu<(V0 z;=CLcZ>Hl(F|8KahfurrqAX_FX?XRas9s->{5MaES$|qis_`^C{KG1ks zG8y@S)jK&_T%L`Gvuu%m%?PS-wU`vI&$Em0;l!7AE_$f zTb{QjqjvmmeBPLhT2;G!HofJZO{nF-kT4r=H{jjXJo^XxmL%c`jA>heo8xh z+rGUmI&rjsDuVk|0lPnKF=uIVBOlF&!@bLCYXSJ%Z6KC~UbAv@v+P9pZ*GQHig*ee z8BE!616=}A*R2=GlHw-#lmT!-v%W3A!f;evHz1wMa#pljqijsWd_QeW^Etn&>EdSC zDmtU$bJd!++jsq5)xT(6v~R}zb9a}`YSpTX>G*nWy`j{bcLw88u{UbXJBm{6uIsro zEoS54RS{lvs*7UOnr5^1?yv=ri%xGc87_q6+HD&RgR$8Zqx`aJwSF0A!%{}y@(ZrD zZyY8V2V-^pTb9?#I=#!mp8bRjx~~4PjOYX+lpcro;?KNlLCc-PtHaB(s*0&R-?dw= zf$MTK7+-JX&H2b0A2j!@tjkdSC|d2C=6qH(X4SOpSIu2t-Y9u zJj#9DRssGAEo`(lird=_kWrU#oL3j+taDmi6{Biad$_#?<)--<64QTfZ;wxW+tUss zFFwCMZ;je{zWr!(bK05AXBRwX(jcoY-GfA58h~~^9_iQ=>HKKq%foa;v0!ynH+NxF zkX{ZKjUzZeUmAcw%lBe)hBqV-V6wtDfzlW#jXT3)^r5$+#-tjl<`m7NGf zazq*V;0(Zc3K--!*V09IC%Y(QLi{L4qhhKJ_=jiy)p!n5_OJB8zq-p75Xs{4ba&yY z;}Ggtoa_#c4^Q$PkL!cDK*PA);LE}Iazg8aqiVs1J_w7txV;^W_7hA;zV&*mQU9dy&8FRTrJ<7_w?rtwWn@8!~0K*=eVoeLI#R6t4w+@{4SNbaFYqDtu#i z5h+duDS$Dc&b*uf!OCVn`hbAZO5pw5yqGSIV6c6ZBfe{AY(#?~sSc17g7msE=!`&& zcL=s_ds^7w>1)v$lm1s#nLr8B6<^iHzNd~w`A$<9)qc-h`Pq%b!Qc-G$A z>7FUZUeR5`t+v9GvX1O1zJ_tcx5hNGeO^b7#p{G)We4Gv+s_!UV$(yPT+QoO^I~7C2jgwww}DR&$nChAul5<^xtjm`{JcsytZSX#~nNVbUXH?Xd%VSQ`4W@xlNe% zV}UtJL6O^j-*K!X5w)SU0-VyG9F4I<>SI&n$neq+W2uraMyPk{{fOQ9x;Xn(%1(Sa z{$2i^@z1z9lPW$aH}N+}*(g96JaT6{YUR z6^^hxw8kiIUiN~+iSqRABpa+-*1xop$0(|^-e@o#Z#y_`&m6ydxLm-D!vKpgyhqVMpc^b6=0gT`CS5}ue>>ROm! z#t0M4?g+K7Vk3zH{tP)e2qbf{*9_aUY*!>wWa zKZke9vB&xTblO`)+%qMB-Y2kt+FejhCT82=Q;Y`5s01w1%{-q4>37)PotpwR z^9s})1xngLfO*rKB6%z|A*8Z9V^@%Ouh;`OH)k95eSf#DQ%oymMN8Ht0KxU}PuX%E zVJH1WbTh+|0K{$CdtQ?0)VFIUuWNb%dJj!~tu<%>ZenEGnstO|c15~FjWQLDAFPp# z>bx8xRXjz*cH^2Q?FbBKd9vz!q-!_Nqk2B;0HebmR+vCQ7m5-WAmgm+pbvZxDk%@fe0LS*th0}Q#8H$`! zXBV`7$EZV-xvx_1HaX{}Gl!~B; z+2UcV({3H_Z~t=Ae)u6W-eES+z#X?Y%(t4`&8-V;x7GN?__~-L^souGjYVO6=s0!L zbB0mpqPiSDAC=2A9HA6Z)H8<>joXL?oh~r8_NpG;&RO*^{Tl5F<~5HQ*jDodUFY;m z)jA(%(iTfsqoVV+j2+WuE2XVdB&tPDv)ki|*oWDP51Hjh@fZ*CrT1fV<)vrG0m{>w&TvoCG4 z|8bH{{s%Vu;%ZwAU|{pZ_!DUc*lde(DoU#UV6TsM)k$qjpTsRa{$%II_zNe&2HNhn z$_|lYV2=Vs$&do0al6UJBaiSs z-BmOEAOiVuL`09cj^UaPjWxqbPvcHC?Tu!oAX&22G-GMA+x$u8!grw}1ith=qq|)B zTng)7Ye_cDZJa<6@}F%hpAdupdJi$y+BQ*ejsY!i9U zo+e`l=9|x$gBIN#Y}NA7skuABCtW+)-omcpeT=S372n{VQl?i;=c2S@3pn>JMgHHu zu^tpk2#wIMn<0Ku@$AUPG?E|V5datOn2o7Fo3(EIfV<7!8TJy`NmFR{9Czg!Nh5F| zl{6-aq|x(|M(+enmIfRltPE60GcRhe)cOo3)(st{AUC`Y+DzZ5M5VsVe2#{Hd)wdb z9bca06CRkR4&sep5>IPR^P1$0ux>|7J8NTN&}UoV&MCEDE1zyP$J5f=DdDq!Pz~Lk zZR3(L_4b-WF^YDZe2+C$%@oJ|y=Fy~F6JgRgPvqpb>jtg2<6>o;5}<&ct{5(@Z7x& zGOt*CP3CP~cbWmnsIZ*M=f zn{>mIvzu(^{aAzf#|qALqT~0d*ZG`Z)v2em$d6?84D|Oe;4&CkGQsy6c(z-31MK?wM{#qv z_QAa4qm#U8M#qEvG7Lb56#6$%HZdkqp@u;ijwo{I1XC4T`wQzP3}C?k4rBn=aRBda z054|)CnG^R?`62%#H<&C!XYO6891E8em^QOur*p_J){$og|npjFXKz zug(&5hpPaXU_(I)mZISym_8eF&kqeF^Sk$k;a-L}ds+DQ$F!n$m*FI0TEZXx&uf?mnAV z>|3`lt)bF@wo@Mk^4aV__B)2D0V8hhLs!Z2%eF3p)c+*E@EAOS1x&izfDuycb+>z& z$u=_EzYki7)qoccp`EJqQbbHO)&2J)$zV#Gv=tr##IX&yotfM`eW;0 zKzp)Wg5BT69KnfnNQxsS?}l9;kpfKLNVd`hh8@pl;+I~G!~voe>(fNYaciyk?qmgn z`6$f5M3m+6wtJK?6Y)u`PNsjNpSw>1TaR5k5$WVB;t=YvZ1qsnKzn;>;aQz?EM&Dc z&;m8+ICkM=S?8lML;Nl(9nnE|I_Y90(PI(*ZXxwuTvvTuViJrok)lsUy>Z-ql9&Zn zZ2}Ob)e~btZ^;y3((?fO;iT6ui4bgVor;a>oXDs8KqDI3vacJWk^jV)q}!VA$Aeue zn!OIb>aCP}&@m?Tu2Tk7q>d=$HI43IovOk&fvcMSp@YPP_TfV@)sov=V%}^Q_Di*5 zni=Z*Yy-QdP~&)H7XG+qU|NI*%b>lm?jjULZT0v!Sih zP&R^QYJ`O$QhUI?S;r+z0ZNUI#(dO@UlH|KFONl}r_i@2&CrgLzfJ2hkK6z;-r_BV zkHybDvv4HogMM0xy386!NlegSWfE~I9R?WVeHXC6vEU_ivs!gyV8l2>%@xXjq}xKu z*<vW`UWmQA3PMWkFN$1;&IX_yJrI@1r(yJ-TX*ZFs@6Br=N<1k zcg}<5X~*#;4D(R;5=W1*1~ZsAm1rU=k)!>TZgXP`0tN>_j0Uj<*M~}($WfA)DYs{g{`flu58lkpIz9M?(T()-*xI>8A$++ zr=euY847_py5ji6tLZp#7$qDoG5<9)F=7b&RLh0(Q7kt+n;}690=o@Qs)z|Ey36p~ zxPZ!$+4+B;WEbn~{QrKe#&I)R`v1u2pEcDRzdbLv=i-llsQ=<0=sYYj+}8pCGGY|6 zsh2z(8V2CXVlco(&2w-OJqPip`uv0MAj5G+%)5&X2u=ix3kXr$(PzM~G=N~))o_nT z!H>NLRncp)-+PxC=6LT|!l0h;V^%HS!SyAZu{);FIBoTC=G>TfXDoKy)Q`=kEOONb zn#By?xc47@+Z#08Uey36P;8ZHh|A7duR9}Tv>DvO`H@H?UuHv( z?+;w7#Ge^ovnu$`^wG)d1a4ZOL<U+12;IpkpJba8RQc1mnxej0lqC(P-H#+ghWY)mPFJ<4gjAQ^K7IS4+sk$k0kha5MS0*BRgg>()zoDEO1M2i8wim(O5Y1JI&48Ify>Toe#@+~g z4vmqCmgB9rDKbhGY`8$}ikO$H$9*63a^)lQa5LaOz`QCR_{-Lj!l=D_W>Gf#;lRY1 zuGjj`YvXk~(s)gf5L-fu*&Uf~3~2+DfIXd5Y&UMIB9+Q_Gos2SF)||TFPTNPV!Jm$5N0CJ%y0Y3kV(wlIh&t!%8J#;5p|kRl;{W zp?1XwFN@x6j%J1~8NW-m@^k?uRQhc9a?c+YOC9@XhOVCeYQZqA%Xatjo;WXd?6dsR zAVT~383*mo+QJn1NII871xy0XrI99!Cg?PKI-b7Jom8kqCvcj4tb&Rw#zGyC!b7Cq zMAB72%AUjZh>l1;Mh6>xtkusyjKyZv1y2_XX zG50+*@1CP(7hQiT@pX)4Ik1i(9oefA8ADn$hy-8F84OSf3sHq1Y$@ymb9E8-@Iw;5lftpyX`H?XR|t5}k5=1@UqJ8*tNDabA)#3@ zcS6Z)=HDlX$WgubKnMU@EDe9Me&;j)FZe&qTB43@W-^Xi7jXnNgJQA?$v{N7#YrY6 zaMv}^loxPeC#pI=sgv+8CjmiSiGjhz9>}0$_t0bpZ_lpUH)ngj&If!xEtzQ-i=_Ly zb@f%+ya2}>J6cg$#A(F%*t8q6?R;U!_Pd>Mk5HI?BuJK!UVQ@%U$B#kuw5i3M-Q;-@X|3TR!>h35Xj`wZ+$KEn2KdPqGD)Fddla*RM&hQ=cfEmmNYPW zuh|%UX+?r3ICJC9oG|j<7T!AuC7xs33Qun(a)Za^;~Tz2-|HEpZurJL^|1{Eu+Rd( zwRR}5%38*%+gYK@-e*{yhn8o|Di}%lh(eRV0E1WaBv+pzqP0M04MSRjj;y8mgQ5<2 z#%_D52Yn>uU(LUOrRh0aGZXsA;O*v-Aqc{YCxRhxo()0nXdIM2j-VjFnK$<7;Am?L z7jce;M9sVYD*HQV-yGmGz@*sAkY^O_#Ud2ORGW$L3h75eHW-;mi4t-tJC@+Bu6Hz% z^fDr8h7!uHFM^s`dm>`iedqRCuNYtDL!$oJX;q8VI4BaH zJG}2H&*IFc?lsAjYGekLDeFW17V1hiC!`I9%zX4$T5v|yq#Z#Q*w5vpHU!TWNX#)1 z9tZh*;?~MeMz-G`=G2SaTxV@VGtTTr`zQN~4SD1N=4gFpgO*bOwnR39Ad-1#P&wHU zPGuUk`3b(l(L7H#4<8$VkH{B(@CAWLqJyzwK&j(+SVG{`Q|e3Q(%3EGgbEZJGQ^TR zIXd#uhQeJ{H$ww^%h5eA@j7^Wi9s7krQih8%T1)?5PDgfUee*gumr_jw=PUV_7Iba zPbI`&PWnoP{6@`(BG;T(Tm2gI>@Ram4B?Zm_;x3;rZ7cc(KAJ7itKfuq>E}Bq<1{o zxUjDtc`h+48bn9q_9OYmabf>a%4dyJCTnFI3y^S18t2T}Wg_6h4#@5u*QW+9=V7k_ z34IQ)qXgI)w1jD%SKF8N=L`h$=bsfqeSr{fW##i9JeO*O&!WOhB?R{z0vzSfIh;$fl75 z)&|Tqjv-<+pMjL2amRo>lb0Hf$Lmke;`=Z?ygBrtC!Nz1AoV`{7^Dw$Doc9d*_**f z$B1Mb1VZyz!Mb&;m~f1Q7=`=0I8COZ{M>g_ll5%)KD~wUFfBuP39^Fn&6=X_Ic~~b zgKg`N#&6A~wVYaIGmIDj%)BVFPGoCARpP5`N?hK09n$gVn#zL!wr2Z8_YmohEkxy$ zv#&5?z)iFRP}PKO@gV($;i<#v|GmLU^I>Q%;ElS-&^q99-%LhSVc;`^fs_O4?@YM?oWO$wXT-M z4s}WNlhbO%IU7=43Q2@UTyO(A8{`2Iw|~|)%Wo}+UL5;;u9M>h&+))R%uP^ z9X7V=ZUZ#4XpH=HIY~#s}Gj z{PN{}NKY1n*r&@`_ff|G#ov?hh`~v>jHt1=lha<8={aVA=|~i24q^WHzXo6ZtFyU&v zx*<3;*-@-IN0{WW|IVDfXkTC~J z1J-zGk86TTBt>Th1f|U$XUswLz{E$;;$ZM_emPPZQj$POx*2=$X1V1LKFsB`<=VQJ z=6pENCWClH5AVhE7b5-CifUUT?`FGGwnAlNTGKY49k*9w^?FZmg1(NfQF?feEcjVG z38>t)Zc_+&X^J@R=mo-Y0LZAWwo&TKp0(VQ20Le^|QCO{+~<-|X5?!TQR zH*r!wbZq`f?NG^>01VMWlFzrS#9&HPhI^lWX)zS8#zj7VIFz&L+w=b%at!$#R{Z!8 z2aVKo+iji?$79kaSb8B2!*eXyZwe%%Aa%zDeBd)D?j-?&^8PwpQs4>3`gCsq(A$GO zdg3}GABg$B{Z18w7|jRn%85J?7hpGq97&9@Sn@DW)u>vl7g#Wlt|Na1&pLeSZT!079|TtG6@I9k_?g&wlRt5g)O4@ zC`6=vEym@&rpzw7^$*5FKS7MQ@($%bEo8A}BF7gebjRLxn&V_yp4wM(M0Che)AP;( zp_YRmi>-7n7Szu{^ZAz5JfsR=>>fT|>>k$0Pg0K!Ja0Mm%TXUxZ7BpzypKE#|2q(J zB3tb+K+A2Ef`gJ#)3y|XTZY{p^cg}n@S&DurAP3&s$$JH{pFFuXY#8BnG6<$18}Dr0FgUTSNErw4 zp41~Qb>nm^OupgiF$K*~3G-egSsH=>-*poajqxgX3=}Y9?$d9`1U1~6e&fM4BQM09 z$mOAqRq|gf5s(CS#Ueu?4;yV{wa5Hok1h;7SKns3+JdHQAU_1TZQ)ZBoR_sgr5i&u z(q9Tzg%%EtF`IEt-Z>^J5cDi7hC{)$V4-_M1RLTU5v0YY2#H;gF(vMO5ScEGa?{qu z8YbW>2rngFn+Z09^rQ1N9}Twi^ROm<*I@-7L9vDk@RYDT+Z0ExVu?eNSSEh}85&_y zhk0wktSU^Zh_7noYx^lV;-BQFyOYPz_M}ellM~lDb2$tQ?fs14-hhf>lMt30QP7DP zx<{|WWj~kqpuFuSH>PhH0?2p4_81n_FIwDZutH7ETNsx;jL1t!oT|^Jkz(B*}gJMwIIdz2}e+NcH4+24(*f0nYPV03;*&fxvk&YMlA#RLsOsI zTJsOdQxE2pOLVA?^ANlM4F285RwCoLKL9hF| zJn#DXppaaUKfHY|PCmklM^(1p&x_GY=}|v_xZC*ZVfLZSAO838zveqTJO8)*`}NMY z{P{l%`S<^_hx7B3tp^XI-|uzbvLcIkW||AxsJ*WRQIP!24T)!Z$4kvg(rS9uN^%r8 zF6XnVaaJ^Xnz5K9hmlSSIsA>Btyz4>WG$AQxmD{3RgxrTsG%~G+uL`2mi`Yi)DE$u zS_1w7WCmBRE^Tk`_lMzOv8kBp#dw#qFTK%p0 zH;|gt!ERf4lx^eR&I)#Ui#p(~J{-KiPFV-Xn;xQoh-!|6+*<_Z6ecm83XgMN9Ht93X=l`MXRK$@>vhXjjk!a!d&yD)W zq_&n3k#lClH^$_?+!!NRZEKd7Tdc~KMruetozMFp3d?A2;23J|9Vy-3kuEKJ!4Q)? zIdI8*g?vx$pY>fkFj%AYzGqu`bC-Sl^ENHhf3i)manp~a9l9i1SEYk6$x!;m4(-cz z9X`=E>CZQ0UEu@2Snf#6zSxb_Sl7uL%C!rrU>%S@zr+cW+887moffj${P6DJNVAOo zdDOCR*L8nruXF@!y1=@o;FTP-uSdfL6k?0<%oVT;3Qy}3{TALG>7%^?Cy!WlLl1-m zV?2D~UPN#2UMysiNfxSZe6c&bF2$Zg9fngB*}sh?pX`?M={NS5%q zxm@i9WoaGwiF~$PZB1)>>SMXyD>(|{+H)p1_S!Z4)Zw_Fd~HDjvzbL^10yO)prpC@ z9V-$>;8O9&DP2O`A%5z?z?I0JFZgbonte230-vM(t!O@rUjD3ObZsS;3saX zD75675=pkNG4C@i`mV})B&fR9ho6e9H|M~OG&e7@GvND1vW!XKqgC%!*%_&er$y-Y zY~)HpzlXjgc6>yUxsRpk2PDoZClfg$s^{~p>9dkMHZ=EgGQ6Lw%)+7HjB$odb!5L4 zwX$y+rIx=P)yiM^Sw9$I0Iu+)zrHG_NS`*>A2S?Z`rUbv;h>2gQ5()bkzg66)_7V- zsJ`{`o^< zEBExBWQOaJm&khY#U_qh%N1XW%Vkub)%OMQ=WhM4M*Kc62&C@Y(BGBL!7W33p5djM z+C0iiz2Z{*nafO&U?k(y($aq_IDSxE%S9kMtU;l7pjgwdNkygz`Z>3(C=Vp5uq7XV zp1YJS*_+%YZJER71=Da4RQd7e>_PTCdvlTz(~H2usG8Y1HCQ0dNR{N-tD}pY|IIl? zXoDe73!fPno7p?6hgmnXPetCVu zdl+jaf3=(nzrAfXmof@=C3r3Jw_z59# zd`(h7mBQqnjPW%j@x)~~58^zkg?EDd2s+%}TGL*xE8|dx!dP8vGAy4J*f&+Cq1STn zP5SKA;n>>SrN)w+oPVmpq<(Dl8TZGeLc!5R4FR81`L!Sh$m)JNP^0 zoDhF45J`UCxs5k|pCpP)I5%14{F>I`5 zdf$0OEt1J9@~CU#JA(H_Z6gI>6uX)T9+CxPAZG(7A}f%-(RlRvsCzWcit}@XmG0{) zNbuWSRE6%brkcf#bfm=9JW1S@pM-2Ze|DNV8D84x#5#x%m6@W{n-SUicTV&K?d`xF z@_hxl*fw6kav%T-PE6_-E-E0rGYc9o z+nKxj;{(}2T?5d%Giqs}{eDQIBcUTL;)gt|t}9qNY}}-%?YhHZ7B1Qtz{U z=N}ho!^u?;2g%j})UYVXeiY}2WyC+*oIJUz9!v5^Sm(7|Zn9mpALnv)02k6&NjppG z*d(_{u9EmQtq1^pCIz~6`GUb??DdcDh+5RfyU3_^J<2E<`-R?RXLKmNvZk`3So-bS zBOw*CQ;V1*9ySK;lWudt2yf8;*r5ES6%1~7FqXZ2BzKyXGf~l`RVdVNP&>Qab0o$w zgj9LO1uC5j&Jx{SbG}b1x@~&nQDn8>CdjNCn;PrV8(C0~JTGb-m9hG9Q?KL0g<2s& zHMyiQrTb+h^8_I5cbJm;SwfS#FFr9MKmCgIMSnZ41qNz zGNQRx(x&ZcTrV>miWQHq{rq;cE_ae z4;pi|9TLf)4If9j3|)%B5}!&mjNf5V!z43t8Bb5UZ-`@I11^WF>u~By+c||nl z7*X#gZBh?8;8pUy&z(p$=e zqYwuvX_&Y@LwUeyelTqb_2~U+Sod)bvaRFT#CtEey=d-z?!Lj}=bs*QpJx-ss<7i< zXGh_}fUVWS`N_8UzPJ4wlfS9U;g#Bp*v|Y!LeO;x1d8qXZi$!HlOZNZkfg5bOElm` z3c$^L^6=~J-ovjs?r_T0W*qgp+#b-~_9=k|99zHSwLCxkdh3k)k|2hwY+n+AUgz`O zCHM=*>7}$>KTF2i12hH623t&RMe>8~eN2=I{=bUr&r;j!t3>1$U8F#_=;Aj4x-OwZ z^H@R$w+%SkiVi2u?r0YuiZC&eKh1nRWVrd;`UMtn_iRHYdZeAGYPh;w zks~4Ten<`vb9M-&ub)uloQN)F&~?JOnOcy|Uj*6wRZTXx8959l`;8adpPwIo=9&i) z-!gri8%$SdRa8j&$Qt8!xC$#vawich29v9G}i7Ntr%p+G^Z}|q9 zVE9(ddNHIBq4JW$$iVEYaT^I4E2v2k`CYkt8^2xWYtGFl2_V4y&=z`X` zdwV<_Caqb4wT73IjO0K*&q+kwy38MBhuirTxvsYnxm7F34!_EWdyl%fM77=<>h<&I z8Q~LG$NN%GnP)Z#)olCmTDh~uL}LYkJlrz+d8(3?yCLX$_r7iMAZuNV6Zu+l$dj#o zhm9SZBmvL)Bs@j&EN`8yL)`Y`uSv))0+?j`CD-r3=lVUAA8i^9Z#5Ti{e9LT7jVWk zZC-X-*}WO2+|Law)M09?I?~EUs_j`pGFS;`r%}HPH=ft1ay^G!M*SM6#PNmg9zGg~ zfl$1Nv%H={KkPOVpyS- z9VxpjvI~-gXRJ$8=#KApt1s>Cki<3HJt234e;Rqv)gfM2~k*m!l>`rWjwU-jb_aqe$Z1xh- z7JWY8qq1M;u8iWKU~27+``YtCVlpmPjpgSYcUW_}(^>+AF1bebtz4KV=P2fDYTJD3 zwNoqY7rI`13iM08ul-=%0PYky{uz*??pIxh9ntdX*(VwqN{iV*-z?$ETjV8^gj7@t z85N~0rc+d%QpGCgf=nc)e_|Dp9rRbRk0-`Z9<6znK?1$;eWSUdmDYCFK|HW zjg;k}-D!U{>z(7b#<;A(RBOyqq6G*auuVfILVx}dXu$5B8G7susZ%V(vn_>;MNo%@ zxQ;Vt4cw#^P|Oq&V#$_>`9w6FJ>yBRQ?Z=@gP&1#Z8;1obr_AgpD}rh;wL2rHLc&} zJoPMT#H2&`M-8&E8GB!A#}|nc1sO0RiktR4mI5Qs)-b5u-eN%-U=GA=CU;-qx~_(D zFY<6pN0bb6&9Jx8ydAWs9@;aYEn&>_MB{j#AiNk072!Fys9_w6Xa3=50M7>RUcGlC zeJDW&w>GO=dC7Uq`uzqGC9%cQ$QCMXd=LPR8g2wM|?BrxK{oH3(ZN5u>U&@J2tU&gOOJD1qZ zCs^4*k?|hU^FDxKDtVF<+Qg`Nk}*VFYojh*B6<=D?rX=m`tjb7FlZMn!MK?U=9OeF zzoaZ=MP4g2%5RZ;f)f%5TV4UEPdr@2vJwYw)~}$sdL`23MrO*Z%rr;O?`IFFdQPz zWsq6IMPH#+3krAxAxk_c_5h}`*ETp*wfC4f7wu69=TY9A!2M$a6k8W~H;Nl)px2u_`V-!uidzczxkH`En&PM$B$fIbmY9c1h z@9{|_umf19S!M<2*|3Cn0LL^QthuLi;yaITm1wQ;ag-4?AP7Fj%P9!XMqc;-asj4M z)kUrVo(EjffPQ$?g)W3X!TsENVN@Bs1>s3RM>T)WQf#awG*_g)C!1+3NazlmMJV z-qf;PT4WDr$pk?-rD?`lI4PDHZxR+hv-gQLR~HmO9_`VSe3zVbh_xex6GX(Vj3@wv4pk}>I4oi_6( zRPlpNtN4IU9S+UdfJ~6RfOBGf9vdV?pT0=Lq0JyAw&N8Ov+AXPhIrC>M2H`alPql`67!(@OJ1?iiE-U+C{9yK zFu++KGz(F0x`4nE>%&jR;ZLlmfB2R^{3OcH6a)`uN#@4D(?0zVb0bSiZf*gC+h6-h9&nG~D>Euz z3BTCBmVdcxR(OYTm+rM^Ggs~huRU9XA9b&kE%BvrC*CQOvc3A+ajq--%S$c4;}$$F zWUu*kOwbmhG5Bw8zA!fQGJnCn_qEuvS8Kv+ezV$7^W*2)gSc`1rk+7DWM=yoJG%T1 zg6v|y-F&A3ju*JOwz;H8wD2Ige^N0Bbd!K6rZO*_>zqUKw)?5>@Al$j)yWY=_*=D;?ebY7 zO|5rt5dn*%Q?08@210ykB+dL(0wV8%7sXc`Nc(t#L|%#OjEPn(Q_BDJ?K;yGs}9PX z_4=P`=o0bloCZ9^m7At82NUY-b;0uzR@QhbV-k1BeRxVfyI@0&;zA#nE%`ohV=_6C zKjz#3FINz39PS+h@?QI-%i2gPzpI=?#a^U4Yp)>J>nbavB>XxkA-IGqThcv9wo37> z;6Q>$I1Y8C2zMF~j@x}}q}XL^SVxH62?Rt}7WRF_Y;8*j92*Yq%goXTQZ#BGcE%qtI!SJ$_Z1xXagJ32n`KgXR7ojgK0Yn&Jufj0P8X59 zU#IJi_5J2m{!&2t$i$<&1Busdy`*0~vUJ_{1oo!L5BL7gao@u-_q;&RMdAIR$gg09 zqpqGS-w|wF9_S*9+=~+aqaQ!;yr%Ige^3z5 zA|f3TzTa2*n_~C->YE+@+1|E6y=BB@>w7!3$Ac(JTEDG-?h&YKd;3{*YA2p++s5%~o6%m`TbGc%#Ju@gHCQ<_ z=@_}p$)rjK&j9?5-57lkLs0ldF!724LV2_Vm|oQV(1 zUZ}B<=04xWUExU*Fvmd?Lu(jak4k!^(uf(#edtz+hr+fAT4R#TG>oSWFJ5)`Q zlz8X5XtWd!z%HP~?1VulEpwN(7Zl|lqM_AENts;u5+4KjXQRTPX_{d9w;)1l zxDYWzj1q6M&rt#$sdT#i2!6z}TR02UkVGgHt0H`jkHb^ggGA+$jbzB5N8!4ZSw52> zjbYvz^0)ofIIG7*S?`dW*imP9U8i7^`@`dUkVOH%q5S{5@8SxHB-jsxcxJ4q=dW$yf{#-pn9Ub5&Fq z#gvGlLD}oPXN(?R06Rqr4ccQD~wImXN28>qw~{Ln7{6hcbsXuROz&TX_AFHuolL z7?y2tsT`h+Q5e_+5jbr7sw!>l>)AG~Ry*EnMXof2yd~&kd6!_q|B(1_0stij{)BT&HHNjW zj>o{RMiC<#eqYJ#URUyinIYJ{s>qC?qdhDcb2~%CJ=2+Ca6PKFi)#CAvHhxhTKb>a zRY?tM*eo2C3g^bu2PbFB1hJfh!N-_B(^$tC;@Xe{ z9gjG8B!6Pp&(-cH3d@qF;*YQfPtc3N66W zg(;{zLE>q-tKIg))(CJA*RUZ6Fj}0dsG^VT_7(>$jv`(Rb3lo{ok`bwtvS6_n!bB3 zLXD?4U6Z-UFusI-iF~C2>gB{N&>HF%9v0P(wn(587IT{_A|R?|*uUU=$`|f1ne$Y6 zF6TW|$%6loET1=la2^O_$PqS~ky-~j;pI@Fu`kYsy69Xx2I6O1t=Ms+ z)0N{4a(EO{Blm)ttYXh^W6!=%59M&;r2&T~%0QOv4dFE9EK!Le4OhlMXX7D)C`bJ- zxPUcjrgBPthKG?%VPXtHpiXe)K^%p;SJuo}fP;iwPYe9( zuDn)}Lz% zsX;gjfV+Ct)01%HHzO9v8@I~br|1$g7F%Lw3${O<_7>YE08zviaIJ|bjoHaZ7^HF!~*TZ*?nL`hFM|UEO?;3uEOeEu(N8Q!1;%R&-xxC4CmPVi^W}Pmc%3*ttkdR^9B6kvR zr4}!FFeOmKPlm7Hg$mBg96kmqM9?KCSH;>HHVDpx*8Jg=JkQs^UOTxQ77 zXUS?3*KS^32JS*~Lg+mThFlIHEvW_f5kG^Ig(0oXUKU{q)T`Un%K+)~xKx79$1jcJ zt|Hh=&kjT8SMEtg)!f-Vdc3Af=i}hYF@>TZzns)DxVYIIabkE^T;}CyUZ{y>UuLy5 z0}-wd^8F6N@-=_lr17g0I`(ytGAg*id4A9el;)c0zRJYX(tW|r z&K5)7UEHyApR?;jq;|nam%THPV}Rb;U6MTU3jw)DC{V4}qA~s>MG_h=3HVt?R9Sq;&anYa}|DU4I_NuZ$3e>si3U)Tp2fXsKai<0K~1-`?!GevyA8K5!EI6`EDz4g;9vgqT?)+~?Ym1Y3v( zgdl}%5z2ga5l@f|NgnYITRKQ6c_ccAFAiTGzIu21>h+Vu^gT-6chlXrWUlm`kw@MT z3I9kv8-*7s5ctF$la7U9P*RTPGY6TY@@&XyR2x!3UICE4HYGznk+=%6Bd-10VIydn zjffhmcPJ(QUT3Rc#*Xf?pQrhw;{VA0DS!T+y(BrB9*`>~Xj{{({euIV`8P;$8le8` zgPZd1S0olx!y`R`Yl~ls?5j6j{A<=a?rr~mvekZAwsB2RG0Ekay<`!|kUJPRNQc%c6Mos zT$LQZRQ!1|w`05H4@e3NLhQT6ojV#UYb9BaNnJG1+(n|ZU?ZDfo{_H#YM&KPxhWn? zqgY#3i$f*~wVaH}>y5^WI-~iANgN?rj!-lLgk4E%wWX@PwOU9zo3H+f)}DPb3@eu| zW|dw4P%k5WscdzjAl)dzF7xe`1RahwB(J$gxT4<*%g#q#7T(6hZ3rbSC4 z0vl3|mJ=L)ACh~Leo{E2@NCZB@L6)R zBrnEy&CahPWMw}qm^Ktnl1xXCEnKY0RVfZC>>E3>I%{xIKEcqzu&Tw6y&;!#lUH(9 zo|WXc=BPJc+Vc=^a%sJ>_?83l9RrmBjpZ##-uH)`Xp}1!RmIYLN=@$9RZXYa7Eh92 zM!`5OuAu;{?#l_6z|NC0ywHxMUSa}k-!ZZ#v14S&&7L{rhL{80`yY#fTkRhRXQ$J8nyXn9VSrc#WV2R)y1wQ30$lUkBADM|%<&tQYev!VE1 z_Rk`h?4>B(BVDDsK{)$qWUqyRebkG&x}|4PewZaZ-$Mn*;b5^0c9f=V_LON|5> zRWJCGj82)(kdHmlR{1x`v!ZNJsNynAs*5S^E_<)@4XyhheziHcB}0-UTiHK#&`4w2 zyshL<7@<_MkGtoq{g;PuZY+``k#pQ%c4LF*b3&n~=i~~;qpmeN3?BY8?~_;xV~{T$ zjVUJ-iF<9OKRirYJ0EfN(^5++_h)Zy7xUzj;vMKObN!aZRsJR#C-9d|3*+2d;ht`B z?_^q|{J+>^ei2*#mK?9g7&FUTHzqf5L5h4UN9ZM$9d9MHYTd!tmnGMfFf3ZfKtim` z^2%8SRJnKMWx@Ry23Q=QpSXyE@s9cbM?Yo)ccfcoz2s3FS#Erb4U=F|@-=t@Io?2K z7{M8g*Ary2Lyk+nlpGsQ3wL$LTX~_$9x?=I4pO$pThsP`V$mv(RT3i$J8ne#$@LgS z>e3HUuvsz7A0GdA=j5x_UjDC6=d1R=I=3AzBq%AD=ZD#dU)}D%2HZW6Jrjdp_PZto zoN=2P5_6%sW4cZKEhp|sc`3!iqR07eS3IwXjhoWYf4AZ{x3M0wW%d+t-JA(6vLAvl zpV;mPXG8x}YtJQll>Q=9D*13plc*v2WLTd2H`fHE$F4vr0 zsMwTo6S*RCARpM1ip@=elwFtnLg1gxsK8Gh5m%!C22G;e*EC?ftH$&Gg>Ok8Tp#+| z8r7fu9{HMOz>_gK$BL=z#yz=@+>`d^ek+9IXQ7!77$QjD?z?u6VO;Ln25?S-U75() za4wgTg-U9YqQD>^KjvqbrNBhLkW|F>3v}nFusZ(CNA8EE00@t?#!-AKxXG+?Izr!I zoeY_@-5!7iE_E4H?~J%`{+ijdiL=KW4jS*-9HL&@fRGV9s=IFY!OicZt*yIXWow?7 z#%XVFwJd!6g9zA4iB&EQdEUXvD*p)wXr4)kV6Ojaep~$&trIh+)H*s0jZ3=28&@bf zd4>fU_lkF_vWTf1qmBgHZEk)LH#oBx>CN{{1}>z@Ln%WfgC~YI@jWTq3k`=iP_)fN zI73Z8z)k=UQbiWd;d$TeE+6m8HC_k}a^K1>foAC@%ZAeuMng23XEej@?cFwFwOIC4w?DKLb?cBc*>f zusjbDzB6xD(lG{@|K^71N9Q&yv`{amv-ynn3bZ8-ey8~Ll*8@fN5l}xzJq>rJdz;J zlep5~xwi3pv9M7hlVoj92SA1OikfWPsI(}bBe8i1#9+22pW|3oKr9Ga`o@o)qZqnr za+nA04N=?h^7eMA0PL7};5ghxW?C+a67SOIL4iJW79}u^LmhX!oG;`GQ9>gM{*d#6 zl{%hsa0<)_S2#2S_|CvcoVN$dz4wWk`f>G;S*|C_I(filpx` zk>>lNA>SU8>(jA8SW4(^=r{_qRxH6aM`hu2wbNQj=IyD;ThnL_A^)o*wXs~;7ACMl zZ5(fPtRjJD-PWsQ;@Kv;Gt;z%0&!TVY&<(I8D6R0gb(@6IM7M^CZQSpN=RL14OL{S zy(CgzE@|*^{uA^i_z8h#++`K}Q?px`mv_K>@akiT2mA6F%LrQlS=Nm<8vCXu&xk^$ikGq#}5Ipi~2UDETV z2B;~g$UMA93U3+z29d{ATY8g5VdrPKIUPN{`=-Nu6(jp68=6M91e zWF_OaCT+*K<<(Zk!Vm>1C9|x~E=YS}ikq8ZDmtTzNvmu^B1)041t!K}!Y7`^2uC1( zG(e(IA|yHnOoH z+O)`&ol^%2c;o|Hl3KC9BrzBbI#2fB?Vo;s_+H<@zyyKDVmrLydpET|*+e@tx%v;P zAO0wACAtjB{{eb({lF`n$GEVVO=OoCVQ!>E)B=Ti`|cExdtMxX8**^d1Q@YR+LM znhq;0Vyx~f`-b=cZ$C)fBlRe{pC8-|q>t0kM0Uu}bBujl z2E?z~g(RdM7e-Sq z3b;=J1s|>UAL-&l*pw?kP33x@!gdnFyWLq{!dO3pr@yv@K)HrliY z;WA_VYPfP*)omHA!`~|vM%x;_a!{hz!UrtD=$kzPpHv2?9MnTw&ggQM_fl)%?;sSdWq`vIG zN_eoiejeP=B_{k|RUk8BUughQ%khEO?rIAr(A7Q`arH)IQE$jW?G_GzWb4lmG*b61 zA~oXzK@mnQHHb#qK=(oEJVSSgq6)8dSCAw?UbB1n-)FOjqD<>$Ef`y;`hL_CKsoLvodLQbg2lKWv`Di9Tbzy*-0HZzkz-9qUn)c7KFOea^l-F7lTQ$A8D z8ZTOO^9Dbo9xb;NaGpn*8_x{IoNutZ99%NEb#>%a1(JbJx*M_C9b3mtz>q>q-pOd6 z-DSUU#a_QhN?y$5s7v|o$MrD!PrqsV6 z%3$^ccTH%e*&1m)2ANOQT11lU&?w>4TGq_0?Pkjr+?wH$x~{L56(o&lx3K~1Jv`rK zFS)l-!k3!aN4dcft&xuTHB=~^!Q#=u1pv<(?eW3vq94phm=%0Brr(Wb2EnJ+>jvyz`E zNjx@I_-!nlPps%iiU!l(hot@ADH2bKRDfNLnaxv*)YFxey$3BKHa!DSetZ0ZHwubo z_I*-mn~NVWx7D-r+e)$a-^{*Sd0{K^^Gdm`&p#=5)7&n^I)MsEQO6JEAFP^tz{+d1 zpyOy}zev5MvZ}XShRX1vnH4ML+cK`KQEx!@Vvwe+*B%YZzT9VoCu_u;Ah6pucY;Wr zmMY**vPP(;1>4n_iql>qcgSr<$qFEMj38r07MkSeq(H#owno*66LDRv2thYy>$sWC zF%7VhILT9%iPW_0aZaT0l$n+pfSnYYzQ8ag#IA=6Od{bnF8BakQVd>Nq=R(s=;T{1 zK9c?7XPhRn=96Mr^+M4p<3BGyI0XSFe4x*AXMyW40NfAnT?|6%xk^q<^50n3^NC~! zX6#Mm@#r8eM;KW8b2Xg!AFgRskZ@fUUhH@B(Hn7;&c1OoICbc$+DnefMh)QZ0xzvv zO!b`~%CZrjz#%WTG1*2iV|mG@7^ko63fM2BJHgW+Mk+3~ULrF{@lPC}`ccA*xc*F{ zx&0h1zs2U}&sYIenexEGASTb&_IjR6zmGUUGM=~?#qwfcoB4!I zqSmLaSAWrGkYZ-!vgV>UeJ*U1Eyq>%80ul@pB1_8?Bjbz#03-{ZLCQK@t3>sZ5V1g zFgZlURO%bva6LH^38pBE^bd3Lt@#ggcKPr!XgrcP*F}awGgV=l_0qbUS}ld`&Y2`0 zk`eg!ZM0#0s0Y4PV7Wh?y`Ql@9Qi%Kmon>j!qt^W z`*1kn$pVkHZ`=}%oh7zY+X0voCuJ>^<{f5FCOam3`EuE4OyG1_TDK?qZ0kQeV_CYh z;C5Y8U#Gsx(o{`uN?5_1x0-})!Er0%-*KYqFWPx_j?-0Qo47Q2VO zB9{;|#KUq#*#51Y8Rbw;&tI*8hHciOs`o+sAwH_ZvAyS#*olTX2_tB=0y+nE$Lv@T zF%u^nSmf^tUlWb-A<_Tva zm({M@R(|wMO`DKtfjVl7PRpR3b@xd0ZDmxo7Io-L^8yWQY_;+)?DBrIY$Ud1ZP>Hr zH{9u13)msFDBQ@v!D{g=lBla1bI}JwhG6#9oQkMm`q5!<2FQ9l$oZH4?2~sSBqIgv zwm2(wITjNm-<>i1nfem#A=-S%kb^0;KcC7;Fsx4|5jf%;dE#URohs+XS_|{q9Y6Nw zC=Kyq66p~SB)FCYdx>O_bSy?QG3F@>qUPaUe?;7{MZR^G(XoA_O~hFVHOiET6`(db8ZV=s{ZeE0V)gGtx{Y-{&!*U%)=Bx!m5{2aM@#vu`SWPVxm8M5O%sGFWZOc9YV5%HnD)D-A@zs<-0a ziQO@34=NI~DZ85ryCalePgvXZ9lKly!5`RFZ&KI_aTA$>(!)qa1oEeNnvz?xf&y32Ax)F=x3UBRKB#@hDR z4`oe%`1K_pj=piK8xBto>_}cL2(jg(W9+h@D#?QBj!<$6@jc!g*;+qUdmpPVYMy&g zg|Ca2wSw(Iw>ySTKHk&Z$7=6Wg&kO%<3V*Ln!}ta0Ttf7s4Ps5qoiD7tZZ@Bkt#7? zH%?Y0(|$hkIR%pV2vH+c<3!(t1BioDwyau`PcwjXo)ghsS(H$35^7;q_9h3EQJis{ z=|aUSL>c>NUiAaHFGqw?@+O`mTz|su)wto}D&(9!(G?GFrgu$3iR622lI%wNlM)|J|I;%Iy>7Ai0#EWa z6CA(?7L{cub0ZlB-uE8Lb!^Eb2WJXcX9i%c?llka%E@JaBqZ#P6;vL6P$i$Po32JH zQ`xXBMCcG&$Et%mt1|J5)AlK1c~4qj1F5#T;oS|tzt8Mcm;j-4TU~3~i(*oRk%1F& zJ{rDy%q>$y!>=8=9Bq(ZWy|wXNm7QCuI_vc*5WvwV(RX58EtPOhYM#s;n0r-?>O{~ zOMfPAjF}kbRrt{Gncq1tWbR|}Mw#T!J+S1>>4g`;KNQ}3$C6{@ZR!tuID3eWd2sWt zpqsvX#Mh(GbDkvwuzNhWM=t$x1p^A4cZK?lwMQdA;ZU)Nn|(3!hY9`?pXB&nR&j{l zzaFXKfYmbc3WT6aRLmBoOnH>#1g+%aqWu2$6xTu2Z5s5|?k!GS}o!GVYt zZeR|&ZsSi!<%I#)s^N>%MC)5m**O8PPQo#e%MyA7xbV86y-Lx++jn)fYYP!~*1d~+ z)In=bk9@CL$?ioW`O&mV;QO+*NIZd@y$2WN_7p;rK|d!RjNGVS2Q#`yLNgoNrgtHy zYEgB`S@ex$syx@11^U4+HC}w-Fipd?kojw5@8Bn5|9uklu(vAYd$6mC#h)R7v~FY| z#BKlLxfijfC^ITjU1UwouZ|dWd+TC(Ie$Z1KAE{YXppE@PdEol&IlA5@9|tk1t$Xo zQAY-=RYV5=W#zplSrZY-yZ=)92`s>twDu~UY`VH`BvpylR*wTR1)qEb$Se~7CBn8F zu2>^eCM=#aWqh14mIJ=l|LUAvXRFhSL?YAPC(RH_L%o$SbGd(9aDH_V$SC(AL!UfR zu+?8JItF1;tjx6(4O>$m^+UwdT8+aSg510`P3b*jl!KT`m#*&d{N!%(`PVyRCtu(l z&V{!MxFR?RyEW$Ppy%bQMb-sc=j^kjiSM;5J^xgg;G0_fx|;)ZkFu zw;vYWlh;yMKbF-Lp_Ln~4BIS6^e%>HQLq3G57*? zT22`QvNP4RwFH5kVy^N2!3DZ*L3{YUdgJb-r!9DiMszVQWf$8lx^+zoBH~z&b|?-a z>eq!q`zA;EtdJCcb+)L66aFw|#%RQtat55k(q+)RS5)Gz3pxI*bG^5coRkq>vOy>W z37m`?{1#_&sD!zCt4@m6n6CYfAReHRUbXBi#ytVmK7Q|UA9a7#5FBxz`-Ow<>oteC zo9dWtZ1wG4tVGetEeNqryH%I&%5e??x-mmYHdcWKXWYb@D2Rmc7%Mx2#pdQi5#i)w zvjzO}-!fYi&TLVL*}{vjf6)-JPHYhb zGdsj`ko2IJ9pNwW`3DKZC91XV=0dt_?n^i_X43S0yPj;TmGGfD#_S6Yl-(P6y>>Yn zByyFgJu=?5_g5w-^8`JOtJm>G?AE)}JrYu%Ix_UCkQa=dvn)!(@N#NH2E=#ym)@n8 z#di1wv+~S=ZY1nYu&K%EXwGx3gEr?d1?|Of@Qc|Eo}xGpI74X(EiO@zu^YsKca_== zE=3oAPu0Y3Q1EE?3pKML`u5QT%U(0<^YdNrteO45dySv{fqWpPe|VxPK|b{Iud~yh z9+h;-s^D2aly|q}q|$#2j_S0t!)P<87{OI)GmwG>1wtj55ajX9J&H*|p5O88O$zcn zCmc0CKe%}>=Yh^CbWT?N%oXqREyWTcN?X2eFh?8#DFKrt`*`hsYf$I4dq4q{Q%nau z5*&BdBTL5Xb!LVDYs?JaD}>!@Y$KnOFXaUdko{9y*yay`$5P5kx83(| z>Q#Ib$rssMS4AR<-Dg~@Wp^(d&>pxNX<=6*kbO5Vu}xXvcbB`5zCMZf?5$i|&4Ejw z71|RBE((&>krJ;tSYVhf`s9`{C^^RapAu2vp{!4dNgm?dy>1?s@c2F*ZP7z)TX8>{Fi~64 z_A?Q*o{0M(c-?IrG8@U5Bnbw|4KyNd5!bu;JXEzbk>@+{=lp>mrHP&$Yei zA&u3tDu)Pc&G(mNE*?)0!WJdMCQH2&Mbzzdm`A} z3W$iymQ|ZF(Syz=Q)lLgn4iZ( zdUi_hqW!7`=4puq=DvnRKA@s)K5{tR35O|DmgKd`D;U&j{qo$zWHHoju=hx`@-H)IGM1fU%XVXO<#Ka{HGf2Hmr86%ly|d#i zhFXrbp^j+k6IC;ZD0iTo9HJ35mweAD=#zj?v2Cn1=e*{!aVM3%?cH1JI@Ws7bLK4O zS5H@MeG3J&RSrU9N^%8nOCX^?F51MyuX(&>PZWj4NoI|;V?64$_lmtIz3%5;x7d5r z>psT>SC>^i#Om`;lO`OXEXyroBCV?d@3o##HOP6bW!Zq|Amj0j!8#p)8~I{lZN2P> z6T{1)g@r^*;{S74&DUNlA@D^aotNVkCDunI$VBT2D|-_zIC1i#RE+B%FW~7O-$+@x=7VR(0U63$)M+H|^; zEVGkH#P1hHq}&fS6^t@>&yC!jeL{X2JGvr!yn|#a-Wgjq##MuGZ5(MWw%U4xW%^R1 zecvH&XNN%GN9IWHrQh$IE}lcTb`uv#Q?S5-QDoS?rQr zu32Wh2;pDIM;KE{B`VHg)2h5Ez1HrjD#qHlEG1q8kO=P%QUCvAXZ$_bLz0QHl4fUg zbJxQS0(u<&Hgv@o%U=QXKJ-w^G$p2>lv;w2qcw~k+U{d(O%$@iJHlTlkrX4mpC}1# zX?91C$GhY^wMCtp1{WfFxLWPR%)+D&jMl%P*)xU>j)raUYE|%rs?7B*TBtn8Wj@L~ zIig)x0OR)-jA^4GbQX^?d44#t`iA=<5c%Zp=YTqVr8p-GUoUop!PmEb(9IGbGpTbB z`N^brPaXEN|6SdcH#d=F`Tyrr2sOb~<;!jzgV9sp_3i_~$Rp$uN z=3fX7a;_2=P$Zlz_LuPM=KEk#A%@PXHJHV*a00G$GoD94UP7p9M~ZMIt7sy&+{q(c zlpSF*DNMb6Nv1n6z}hU@zWe4B~N| z5nTGs&W-(^s2sRz3DgSPHdzZe(*BF-(6C4X=em584TTwK86-C1-^a2o5d`Smz?>L14 zp8OWUFdnm_#U=PzK;rk|jHwWj3QV(9fB>#b zyLEE2vh5i}Q3DDYpdm*nlFV%%?{S(rLmt2ty3V9 z++)PP%zC*Se2K5F6I;vFpiNje2fK+3jBR@j>&$EbE6_SSLshJZ1c#*+_C~?Fop2Q? zAPxZ1u^`#*dc1XOZolr4g@oJR+atTcFPTySaSdOj`NGsWMH6-Uo{*?nil{b7bHHbuyy>l6mTu=6)-F3Mr+R$y^L`Do~eLq%RBhD}gG)+}-6^DB(?#c8D4t@FgAQ;&tL}<$-`L(D5U%MQu%U_(C}gpG z9+m;unV}3>#2k^6gW!u3!Z@ikN%o&?;DyvFK=^v0efz){^sFMst2*a_Iq@>3apAF$ zgu=~{uzYNGC>SG1*{G44Rr83{PM@IrQ8^EJMR$KU4!UAtLwOJ_*aNcQ3K1-h) zCy?bRYYR=rK2S4WETdvPq*)N(9eX*ZfoGy^oGs19sfvH?`Vh@_sp1^xhr(5I(t z`SO-5U%ui+VEOV1pP1##86v+K1|mEP{=o%)V`&Rp4{QQax?1x}djFM2m-4ZDM)oKe zq!77z^ZY4>^hTdvN)&_?amuLp0O(HWDS6((vlz(G+o$-5o?stCkE5*nj=RaU;67^O zT1A9usqhdLc)v;aLt%BLcpKF)Pcj*bUwlOSjBKaKKM{Vhg)cl7j$S>)H{1ucjg&C7 z-k)txS`h3aeAgciv9CGA{s(Mj=!q|qTkNkec9^J(Z2Mt< zGsy!#ART4!`oXtH5tBpXO(PUhID>f^XyB0W%21S^0y`82J=zonp2r-qQx9+@uH#A! z&dD}yvA>wIqai|}Q$4ym*XSM(Ud9d!{)L#JKjm4v4&QNgFxHHZO0E`*t<87le3U1%N{yejtLtaJ3m#uISO!(q zJ0U&Agl^%~DDBPmogYt;;UAit1H=2*B6<4TA zA7%h&#G#QWEX=1O3rG^w6xd6)6w%WgBQ6y9l8-%V;T*oPEF^+3L)J*&lUzwwqYA{x z5yRaNw3P;eOmWDERJ`FLUVug7feQTr@0VSecP91wuQ%@3Lq}#E4*rv9CnVCElQFrA z=lh`M&r5t1N`SJ=ETRSL4#9<37+a$9LGu7}{Y{3}*q{m6+rUA0BcS+{?pgzMRo%4@ z@o8A@Ai-LUeb{~2ZQ7mZM0Gm|HAn$71B9tY1-t49E9)e!?>S3uXz;c3m}-0z&{>s{E1}Jl8892eVLF8RqMvSx{*LiY=$T`LfBcOKHM!6o*wVF07ycsC zn5VsRa1UIZCfSHlgxQZNCZS9N@sKHcR~dVuCdp^KcHQA+ zgU_pvqaNG}N5$%cF2~nSi}gKMmyfU2s(^ag0K@D;tg$G>Ah1lY>80vPHkLr%=kXRS9f{-3JTeF5xDDoy-d1 z8Bc;%n)o2MR;V_)b_66ip>hNyq{Sg)X#A7tId)2thrQ&lUZivu{i=&Xw16$7OVG1~ z^B#W0K@f|ZKq4S)?Y!BqRXI?uSfhUfb{OtF_0UWftsun|B0oGv)If7^wtIjTr6@hm zAie?_gd~8UdI*G{<}7dwN(SO@m*$Xyy+Gwa>X_x0kYGUmXfH^MF+>9!;iPYmX>4xXjJXk*A0woj3@Nn8+pf?@2p9Re zhi9T4^zkKRf^zk1!8jC0@)tS2P}!iLbKeTRh>UQV!Y@hz<2BXo7gtFC2T>3v@r5a$s0KoxKKsF30oh6PDjLr{L9u*uWlv2 zbO26zVFQ{YLOI}q61djARgSq$uK7baQ%9^YMX)}y$P`QiETVvls(q>E^(^?V&Vyqt z$jSveI^DCyfY3wGs51JsZ5O7--3Mbw)Y#G;96UD&2#%ChM~P(lc|-UYx*pzI*|D!$_-_>L86BBuXJhT^=rUa(g>Rqn-A zvO4VGm6EY9KR`0}j3i?tWCwp83Gw954%L&ya%{F9+%*dLsWiV;rmwkuYWr$+~BwWhzq|aL=+RcFy~G za+v!(6EY(mV_b8JU~X57Nrnh$!{52JSwzuZP0yy?x8F<8rU<48rt8xv8`SQQ)h0&a za<%Q(!9tKRJ)#Q^%_ph;jifI1pu}JWwTlEp1FUQi=b}XI;&T07g4fy93O~SfHW9!t zub^%fABxQpiHslP7NH1dBzwDcOV-*M!@^HkwlG<=33DVdgO>`GG65|vA&XzXJ5Uq9Vi>a6bljEcKIEv@cd+-x@S{Skdn7QfU2 zjIWN;znAdq;NJh&U`M> z*CR{ij+MS)@oNnTG6Ih{mXTq#y46A6b0J4Zd{PAiwAZ(u!)c;G3Wz3MrA1246Wb6T z!i+J)RFUms>3DLILkTnPZXLXb(-ax)ljjcn;3Mzbkw|Sp)Qr!zadY*Na_)YfH?Ze8 z08pYd2*h(JZKmDATyyf@rYpI*<{Wp6U2Oef_xO@i07o3>9dn3y<;NykYp&46OAa_Q z>S#Y6-Eq5TF%l3^Xb`-d>|%s_7Z+Ii$?hTlXs+x#On8Q~xt}-A5EB04!aDPMtur@N z5-01S)TLm9^+!9;pK*fKn_%20;P59Ij3_^e{J}ksMf&iGqz}(g5q^~J-I?H4i`LWl z*Tvs|7tNdJ&quSr|K7g+E~y`3dk#VjT=a;6{Yq#SP=`dCSwWC%#hb%A5bF*OBi>1;O>pKKmAz%vnviP6A zaTS74B2Dvr^e+vn@fIQi97?=e6cR?suypJ{S9&VQ$%!1ioR!{rSr#4WG!bLw@{ls{ z6(l?>4Dp@hPqsfM%B5$0pu?v$KU^BWg}P+1Yx@ zVT0<)>&Fit?Q|eFU6l-?8tJE=JlNXV*?LYxqwqn9bF{Ik^~Tu|@{3Bm9|)hfBLD#z z?jYm8egkf;F&_6ojY!xzfl-h)hy!_Z z;r64g-#aP@bOoqH1RG?5T=e+G_Qva-jrGnu-16|G}kPPU4^cv%RtLVrS!ZM~n`kYoYA2{1v}^wsHS0Cc+kpa0;XR zvGj756fi0j3-b3se=3dn3~-{cBbb-_^$HcyBN7S&g@Q<8gxV6YNuHsaCi#6r4U*Cx zAEPDr@w#OJqlm402`br{Vzp4WXrQPldICZ0QzB;e!?UF+&Ap;h((1a62~* z3B8UbqBkRns9MpP(qt?8P{pM?U>AJbJNZmJ$5AA#Zx$>QSwhj0RlQu+m{Yo_RaHt2 zT97I+io4;=+O&lx0f(5vn{LcYKDLI)9G4zpX9l9;MODPq+>dq#axyjvtuBXR5&GEQ z5q9D}C#upd1wzLQK3RN^KJ{0Q%%RB1{eZSoaS z1R(W^#eGh;Z|a(>qC^0wiZSrZQGpS->-($Y>Ih5gR?G__BfAO+BiOPckU~gok@`!l z8q&-lZ%B=rs*Q#<6^PfA=s@auqS9~38pyt`;r_vbl5wld)WNdxcg&tmx0 znkw>jq=&s}K5>@vaHAh8Kf)99ZiOLyg41}e0}rQ0c%->fjx9^vBcf(Sy;p^wB}v0L zJ4goyAnoh};54@d+5~!};Gd2zCJTXBtY0V}g-D;OrezZ#{m{`HfE6R~>blnDDo73k z{)mQ-R7KGY%E2p)5=KO7sfQyC9t1JD$oz#uR7)|GQ@)tV(?-r*ANlN(u?9$;sToYj za8@*8y^a8d4w%;O@7&*iy74EEt-QwH0x&qAV4fP&$R!3s=WhgSBVC;GNA5ITU3q9* zWGj^u>$QhKYtaI`1;;|Z3`4QNSu{#UMW!7$fZ zFi-}!cDs$Z`=@y}Y1C`rq?7+tbgTgwU6Fd1qhmplP8{{2XldxDrD*f?hXSB45Zd7z zcbE{@3u4c^-B+0*#qxzTL#{a9OhWtqY$}8o4LYE**|CDLKZUfA19P7l?75l z^rS{JrRx)TmGyb@RpkW@SeLhcIUv4WBMD9Uo}xQ*2<#_^wS35`wVEL=`{qL=jDvL~ zlXm83@(8>Q9KiAC!lmIIg`)uB_HW!*VqX?39YY5|)feK({l@?uIcx#vphm`JK(|$i zh_v0ce9s#S#IK%Y3tv4$yl-S5q|>6;+&6-&>H`T}o$}Pf6X^YNFhJQn02*EIc6fA0 z4J*P^nFz`?BRq`qHsLYvHv>F)YsmO1f&-w_(T1m8!T5m!75@9uM2n>CVs%7PrHySo8DPpJ86V0wcS$o)h4+z zg~Oy&rr|KU=}drz0Vv!VM{8o4y#TdNY8Z+eHv-3+4dGTU@^#}oYRFxHFojh&FIQZA z=kjY$W4QnoCE|*!VNQCSJpDw>oq;RqAw@d2%CYP?-=c_tR>|}h0mmt@+ok*;SqBoJ zs=E@_dydl5J%l1iQVC(Dn2ZiX>?cEz_E?jY<@mhYK~wY91s>3nF{Eo6$hMg%=|_Zm z+yjP+PS|i@>;FdxJ;#WLG4v_|<{joFes@vwDujN~`I&$JU6J!F*q*w|S+Iy;AQqS} zj#_7>zEcsP`Uzm;hy~~n4_$_ZHnB`Ik-5I}O(5b4ytj^^91uwg;!Ys@;4%1D2$2sV zu={L4 zZirmH5n6$$gU?n}Xt?Hnz6*pJhAG`+hnYb7CWA24tkUs-NpQ+5^;_V$Z6X0}R+yK} z!Hq}}SRh=w1pscO*CQid{z~m_aVfa;tz@b23|F9_I_mmaDlA%nrc_W72#gmDLPgLN z&hP4$M7n%gOORTN$un278>yVt-V_LsM94H%+%^VQtXMx|-Z4Lt9n60%91OmO&9yFQ zS*8{86nduhe5j31MaKZUe@lR70AvG>#1!54smA0C#2ZKqtkBkRVs!hOGMCzcLOih@ z($2t9YTy691~I^wF|?TwsD@`;SA=5eT!(UKfMy^tGzBK)Yccy@k`OH*K@v1mC-*~g zWZ+e(9tRtz`q#9+pGa()m=$;M7q|CZ?%hMHz74M@^L4^r`zW< z62j}b<_@L#nTp$u@c*H!PTDP7cJyx0;#Qbs2tjHI;3Qg=NCsMBpJR2x>t-!)IL1Cq05+_9Kh_3kfWBJ)1d)B z$2Ah#411vA+xLuqO5aNv@CTuNkT2V~CnywJ@EHvpq-yCyE0v+*ee^MW?r)N1@!Xvr zCcgh?oa1 ze`to_3WeXEwG$l(LKPB^A2fmz8ZG`S7kkzh$rNJwV0eX=kTKnvr3;cJ7>L6T6CY&n zID;yHZbcCfS#;!k$kLl~baTKi!i{jqc5etugkFH=RT2Vv58lX}tG=2i5O(YwoH6W( zQfM4jC@!m9!Vncfa-nFgXbaVCbY?tVEv-;%$Vv)5U}_KuR7_C<>r~T0&w1&2uAX+I z%11Blo_?=QvmO#LZ4N>k1}eiHoFh$1@M5I70%{b_9SH@%Gq8^yeGlS^jh0_EPSwix z1*{jaT;#EeWMX)Lrqn$bVnX(XOvpZn37LDhzQBa+Lu5ks80p28=)?T=gn{I9tLjXM zycNy=KqP0@Icj5}CmQtN0)rtN)@24mTBl?%bo`4M9ohTiv^T(Nz@q5*m&l;VDsc2E zGdL1^BH*%@Ra2#n!F1jD%h|$ApNE);&E$2-DyOKj%HhJ$D#sOgs~j#e)mCVg!!Kg1 z94?x-%JIb|s~mn2Fj(_8>=dDH_N5&tq)yRwJUCCJ$28Uag=IcixE49+hqoM7T8Lup z{tjPiW?n!z-8}D6n$!m`j^{5}YFbdkzb~7P;;~Mm`xzaf`fh>dBv4%Ni$y@2hL+8(uQRI+Ucg zPs2wTv~!N!4S82+fiw~nD0eHtWQd%%L2}#xiEaWL(LhugEfXNhI}`4ojz|5pfK8`P6^>f) zVWmtYG935b2x?4s{`P(l*>%RZ_g@(tBecBNM=2_^Lwq?&&KjxiH1pAIy zrM4VG+Fv$)2a6mnzPwhOx6P4?H!=Keix&o4oI5MmU3D3)uC9FK+LBVNncP__Z8V@E z4(zl6VKUFYplsGKLCd?vs=wk2qzlGQl5vF!&nXcMI(R^ibU+(x9J=N;Q+nlFB%CAAzMr8{nf)ZzD?1o_VEE^9aAGj$Rne7_NMy@uUGmh@y!{=+|2X z{&?<>h8!(V8}4k!4XSD2p}=V`miNdH#mV}cqER|4qOnt&J(Ayz|rCWq!sQfUczkPDE)Iw{9mfxOH=5Br5f7- zQn<8J4WlQZd~xx-H#r8}esOUx#lK4$mr6dss!5*g)P}V{n_=QIUOOi-1tql&iMzS0 zkD8c7NYtmQ=`J`UdMaif!9}q-c$IN5Ew=E)Zj64HDE& zcjWf9tPnPDkt0h*L;t3kO;{9nN@;YVA|B0ljYp7ac18NLm+(9Cd9@N)#)nZv)AsvO zHf+E#32N72z!4Eo0VCg{@pjZ)ZTP$8DZ&w>nkWn3z{EB9h7{Ic!QF-JXc@9@RFvY1 z6T77X`R+Dx&tQ)&JMg(?h8iW9pwdGieBSv=bnVRdPWL9+Mj$uHpFxXs{p>jNFI-cT zp>GNKXDF?VxiZ+8ar=OhDcdJT7zRXkMJOEM#NY^vE)O&0f`~T}9mB(%G;Og&)U7!d z(GRXvNyVmA#i*$7;;LT!AL6Q*x)cvU)4XE#fy~2trx`-ZgY6-e#Le?BxMGvPf=!BXLx1_B|qOhe??sk`vKboLz-zlS%)u`U^g&5U{6H;^#;F0{x!lUF3ll)3FvX2 zdwNRzku~!X51pcqkovWIwLHTg_p0azf$uH+6|KZxQuFwMIVW&RSx%ns^Dl@IBUY{# zj?FP#IZ9pkZs;wVZZME}-b?v^TxTUGu7{AgK^BOkLL?gBCB}1klSV_X^KV=LV~{zN zhp)ZyY~wlH2KQfVt#6b+^C#S$v~^gg$^EiI=oV~YR|C{}p_03zt$Ra%<33Z*ddWgA z?i{#@k9hN}j=+Uc(blv2>c>&%>1btQxh8>5K>~Is(3j`w@Mv<3dzhWham^uktqR1U zlYcUgXu{Qky@b*H!B=68WYVudRnX6s9cxBTu``-`Yl{_JUwolO9SudESBN1>FdQ7T zxgmsKLKYs>4&Nkc)!=6({(I^<&L-(!cd;!M7cyAOcAV3FLBU!o0xQCpYoH9&P zoMVe&3k7QD)~#Z-5jLV2|BW-hd`DeB==2hvIj*-L9lxQ8@?6~-w-&!q6UqBJm}D3&f?YPPI^EH?{9 zZPYE>yadg{$b`Z~QbT^m;eG%+1aGKYtS~PGj$QymL~(-#9z|gC>@n%ON8M3S5#Bzr z&yDMC*cU#q#)@_&o<_hP*leW`dVRQ(Ir^u9AR$bJxl~L#{emzc$YO=HM79P1A@W-O zTckm;m^5I7XWDygv5FxDdkaVWBgL&u7#KsCWPQZ#je;y;YkpKzrOPI*20$DIv@ntb z7x84&qhJ_)T#7_=$kVYXPy2n)1XCjve3;8)Qtln1oE_Im|9bPB%LcBDoZz|W6h+Qo zo=c9cggxcC=mbSV%kbloJTfiA1^XzVD^}aw&_~cR{Q46HFLcQtm=QHpPab<0d6dz| zENedNS4a6Ei5VMs_^_jF_0ch@^(=V;iMMlvBqL$>4Sq}If2P08l7o3T6Ayj_b+jl;u|)y=>m$8LSD7dcQvNXJW3_R`3a~@xYfX& z%~MOpSLuE8%3WmhRj9Sc!2XM-v(dK^p7hQR((V3nI+*6^BY-WCo(eGLo7JBGK+kk3 zgp`G~H~$fh#g8?6!yvEYgTxj--*7c}=_3F{S z$kKh^T6jsW!Way6#%4ZgO<%q~iz#~DVH%?-%w2CRGF)SLj@)p_2Y|D=Ji)qLZLNm^ zs>B!9-kdERq_YpNVO%!buK?R~HS-lr)i%s%_5&5zD0o$Yi_AF6Y+vWBRC)OcVdKce zkjt2u46;VU0J(`paPc`K(=Ujt$+qRZ4<`=Yvzo30!n+}ei~ z{=jU5<#T=_n^pgL#r&)Vl0IS}RlsC2Lpm80kuI`wjj;p>)uFAY13nXe4RIo+{fd2? zbEOEBWQG@}eOzf?Lnez(#}G+Vq+zRh*r#xtQdVAlBJZod8C>?wa`iW-mwmIKpX1BE zK|d<*a%UN-7J{QKbJBa(&Utw4+70+!a;(k&3+8n+MQ38SsU~*o{qFv-fnaqIt&+t+ zF{bA+Kb!qmtv9B8>>`4wrwC~^uEQWXo4E?l`c#316Wv|d!GWfNob!ACwG+ ze%>#}hm+BVblAye-C}HF1!A6x)N6(MqtS;9^feB4FcvR+4=f)wSjuC>;Lj2Bbu_LK zsR%N)wzmCxv&NkvOo}XQxSn6Ip5T~)IP_g#2!e#x)iD=8%fNv=Xbx~0BEjP$HV`Zt z=k-5Y)XNUdsNNYuY%z9*N>Bv)0fR>zcb{x;y=V)glpUUt120D&X;3s;vSM!0T(P4_ zuZ0*s971pDeK8u6NS^k+=$>V1KByh0gnzT-Tn$DhNEA9a>x>hzoGUt`1j%zj_)}6z z1d}UZ2db{HWMv2)G4xnu;>e~~jXLf`?tX{54;MWTfh6}Z!Z92%Dp|O5hSrXZ4crgh zhlvEE5l?l*MVsc~R5&+^_UOZ{TQQhUo2%N=RCE#V{sEV^j@GRYQm7$vIulc0PYP#< zKhpHTmIo)Pws2E*(`D2Q3-yN^J9W}D+mZXZKW-pY22P!+oZxqVSj(FBn9`$hrEL&H zag<6(=DlrnLwbU*w>6J|K6IipfP@cG%<3C5>}tSjh#zjA!(hh;yW}BYU|_KZXOQ|L z=-p4lbaF8I(xU1pq1c#=C+3W|Gu~Vv5-04erKVP9O}=VJ*G75XJ1x@gUn^R|p^}hg z#GYS@#c+3=TFDMEz1>Y$V@IN>!RpyZ97ULSK5`~_15bG}$XdM|G2`khN>^Y>m?HSx z8xM)w?8LPKnxUBX$;!ml01wdr(CTMn+&cA;xX6ZwBUg(a#uA`1sx%<~)v>FlgW~R3 z4m<9;ovutxJuZo4m@~p@W@$i+jyT84shMd~3r=h>&z6XZtvfa3b;jS5)-O1Ma@sHN zkF6U6ahvw{j{B<}9KraI04FKelX$p@;Yo`=|5{wevQLbN3X0}OzZcZ&A=qO^;gu)j zDWMJ;cYeh><<;vX<5uHe8-9(DNsAyICqNL&qD9Hj{d7Uo05TX+kUE7rI7N%_6? zeJ~leSmS_>%XJu2AmD*YN(}5OYKAU>^)(Vf>b~tS963-7>fkQkFOA$rCLqox+PGe# z029-4!Lj3?hS3cvDC=zDAPS0gjA5KD8UsPf$rQ2iFzI*U8mO(RegzY z$r-32Z~*{9qopSa={nur@lq+OTE=l?y0}Xu>c#ufL2Ek3Nu8oc>Bg?(jB2cQX-cM?smK^-hONxQ)@0TtIA1Y_LXy8(qX3{${wZy6yRZ+mBM70w;B1?` z#0Yw6v_wX%QYRf(334!Y`7jY}qmHoUN(ev0C!|FgjGHU7Ci?%!($6>kQLFu2Lr9|u zj!N&e_UWJPJMFu*2B!+>EG>#e8aUs1t%lhfC05L%f$GGOcLpI)nCFD35E+IDpYFDo+sjmcf`vn0Fh;7OdhKXBDTn~?Rg8ps0uM#25;iJ)CAH-?rqOTG-rU9B zEdN@2Jwhbk+V(L*bmB)<#ede;N7Eyi2-Vh($1sr?ogQP5zh^mCi|Pk+9E4p1K(-M* eou+fA{R`DRL3q#U7{NWM81qm8P+_fvxZP$nthDWo*YbB+y^JpWpMo zbIrB4B(R;T|BbW`^YETebFR7nzyIUk{_Wp?+P!@BiLf^uXeAv z|G)qJKmOyrXU`w){@)*-Kl<_M?$vv{pMJml;mPaQyO*oW|M>pZzu)<{Yi<9wd;R-Y zPk!0GH!f~z_h|R(^4X)8&wu~JeD(bK ze?8f~_vG25-9K+>@_)T}{^G^%<@c}NyL$d|_ukVd58t-=?%9t&yn6G|A3gt}Nd|{L zhs~c~{;+$;?)Sm$`9I#J^OI+o@PeN4O84|M=|DlV^Y1K7GOZ{9#Pj^R8{}oz(^!)0_u;O1E<%`Rgj1hr;7eo+? z^T&^0?OxX~Z$88#RcG*F^Uo)*K7RT9hj);!8VB3=-P_Lnk0-Ccd-CjUdx7xBFL$rL zyLj?wcmDAEw-Vrnb@%dbyDu&uMGf9kO5@6Ik?yg3RhOYrjL+ZdqP z@v21sZH>qrVD}T^_SutHuXoQdNpBAOA~5GKUOaz=M|x*riOlvGUthj_a`_s6{tkof z*|oCh7gsNzKYjYiNIys2JeI3sn8>h`C7nBB5_C4%N36wXE}7BmZdk8uZVJb{{`| z8$+=-_vXjf&)-3@rmc7k?cN;k+3!1y^SktWt}A<&o)wM0Be5|^o2Rei1m9`umzvbK z=hdFNee%`WXB|lVOI9p_#J@B^Vk_czX2~qEr2T zh)4hM=eJ7;u3qjgabjjMZw_e5+3%m?|K7IKE$tsZfByQ_>z9`=-XoWK_44XH#Nxe? zRQ`VV>~Bw=-8R*=t|7;-reW85WHQC~_umoHJl(x~8z>)LzP^0Z_76#3ejl6o{2B4b zoA$Z{qBm~*@WHC{Pbanai`H!&YjoTBDT)ueq#w?_? z@Pgd*jnRT;5qY!~1uc^Yk zF(R*@KY#lARws3B64duOKJ`s8F1o&Y@$;K@czyZsjhjBde6X z>_7SbdA0d}tbP4JJ%Pw3#jk(=!|Uy4v$^y9!_D2z9j=b<+}mvK-8tH9?&i7BF9=KRh@9zNJ?uI`-Y_GEMP%QlyH?;LNopR5|5rXhnp-~|ouZjS!C9hba0 z*&KiWVWv2*MrWJj7a!g*#YOs@rOka{Ir`wEJC~cIO(6Jtx*xs#Fbz)fry;(#IePtJ z;5^I2(}I|Z?q{|PvISz_@W-o59(r{G2q!(-#T_s>1#W=#iV^SA@93Y~4D=v>f;5!y zihjGi{_{t{;xupWrT0ZfyyDOHg&iF&pdEh$-HyLX@3YL%wB>d}`lnxmbWC%SAp%+` z$g~pUvVfLTf`8fYz4$22|0eC_jqpDRl*0eZQ7D$n%_VmU5fK%M|3WRdmv!sW1Wi+VH|%EQTHK>1i&K;%h!uV9Bn{Z1wvrQ>n_$il`+8ZT1n zKq7H3lfey|s}xVX45PMx-j?D)iBC%U800i9l~_6fYzPHkQM`ZlAU*^xrICl;!;6+l zwEAKw-gdmEO_TyI*xK96&G8p^&bEK%FNWmeHbZjsKW#|VRSXG+MT>+W{P1B|j|g3E zPB(Y%Z#F-Q``tYK^VF8Jyoxp)J@vg7@GRQW=kA*AUMb*e!F8nKIt#<8W@5H(+wL*>3La^5-&t{`TQ=>6-`3>;Ll2 z5B`1P-@kvjIabCrl}O$>rg0lEp~7}^p=y7rgsCB46|6w`MG=szFN-oj z_zb#z7MKqN`nftCx^2slIhFP%S`fC-Ni$t^8$x!xx%et`z&#oW8?T0GyL$)pHvg3e zTQm}eoI$nir)hid4rJIcF<>HY|M~IeI0|<9)zUj^bo4dP&OZ%8Xc2DZabCwZ9eH!NWA&d#VY;(c#Dj z5W0tpOnNsK_(Dl|DJZAKnF!@<-&Pc48HD*jR1?Gi=ed^+Vs;to{Z)%}7fDM?9P2Ok z>Y))zP=O;*oxb77#ZQ^*%MG26J2pTS?qV<+iUt^}#ps;C4N%brt5a%Dnxl8RU&cM< z_T;@S&5Q604#!0ZO`0&@M?gbeu{n*&nskB=-vmmba)@Bj96F6;U({=C!n2r)Po`Xo zZ<7XeFYjR6@LY`cma_dP3FYiDyjyj8nwjFs5Pia{ZJ`1d&i*-59usK{tab&lA|z@U zgP(+}Jo#yu6XgVJ>_WYAr1cx9P!iL_N&GQfz3D!fndbFrv~7!rr(Jj3wTv(ql6zF| zFew0=7RT5a8VilXorPHpZxjh{BM&Vk3y+TEAcN3TZ>XojPYwz=QV)j`F$cUqjZ8xU z#)FeIUD%6?bGsVPR>$8f=4+ZTO4J>o;8OYJDFhA|ADT%}rDr#F50l%L9rTQx9lf8P z2&kfZzWv}#FL`UY9WQB!`#&0UH-B-KfVb}~$NV6zUZC=NFRVBQdpv!RUJ2_}`J;NH zekPp5MTqXb*35np=hbfz9E|daloFPsVR}V78kL-qGbj*8k%}28T@=JflD=i7CMve! zX4&Juk9}QPkT7)ns2Q?3U0~h(!P(9-n~4JAAT%JYs$v=MZomKN={9lB`E7AdOx>F> z4}yMv=P&%-E+I9v=AOW0Oe+F+k@Cdhb5O|hYsnSz7<)swaJD)5IOv?;xh&-@m&6+% z5-ps3UDSm3W!$w{0&?_IXIq2m$#+hTzoXKa(GkWpZ-5-NEGo z<3tAal%pq`GaNIQ*9gEfg_=+dfEK@qzhSVBDbBR! z$D5B@KIju$Nj%7vae<1k#b`7g?mn!^+Mo;;8nfYrq=c3Nl4TO8N*jYI(@m}8SxbTL zZ46y+67t?`5)%*6pP{PC&_gk3-kfOshOX^oS4Fr`f#wtY{sSQtoLm@sfq zMEzClHJ}yY=#ek+5OD!ax4g%p4!5x?4=mM>*da_(gzxClGDUiqu&IIH4$_6l1UL_t zArWFHQwqI;d#gM*(Iu|tbc46$b;pbYXPL7SEp_lBfWCa$2!Qw7 z65(b^B#eaPWOH88!NFWw9%v(^l2Tp1ia8$eD3uzE2+;OV)9qOHFulQM?m9iu5}BgL z0iS_31077O*vL^5)jFCrKR5_T{)d0q>}QqM2kUj#f;JS zfCCjl>C+N8dg>gF|J0aHWH3_|pnn-lp`VXEr@qNxoxOznm7l76f|>j!+(Y5x6o_f5 zN_||D0ib?N=EwnlAllra zK5!K1j*bfkMHJY7Gqix`9a?~ud7c)bVy@2nq`@LSQ?buct7|bw7r1~8dBK`ms=;ha z2A(3W2+Uqo(fS095rt3KzY zJzJStArpi{c1Y5r<7F&>!{4?kctv-Jpq=0mzK*Cub*efPnyR!zmT#&RSKnsVOvtnh zh~QJ7zTr_kY`I`sU2IN4hlxzd6ut}1cY8(M5Fy9sL8GhK2l9PKEevuu*%3e$r%R+}|p0$O?c$Ct$;Y4QK&b`_gLz z_crHcUt*xk0Qb@f5b$P5V%NkOGPdIgyS5f)0Y1X|jpj%zAYcd?R0~{Lsn(;+W5hlD z7gFgwAYIiomoi!NIN2K=c13s~IFJ0?Pr0BH_N&7;)EKHL&^FlKbWGg8t?B2Rt8mNm zPmOkx(Gy2(D+O5YQypcbUZ4;Tlo!B9T+~^m!(qbTmokR`Cn1T_7n_^Rnt|S|Ic4p_ z-(s90dk?wTs2kq&@{*Ccns&crjcM=Sfjs}TKH=-Dz!JYzg^$qn2vum}mm7{b5>aDnXTwK-Y?xJ`|+zvu3P=93lcB7ST%rBytOt7~yGZX5U~Eu`k74Q52pl$O<;86qJMsPYV}fSJ6qq zW5kgH`+pxiktqp{py~3zu3O>P>R?%qphFg{K=&Za(mYjeAWAo}1==Cn=lP>0Zu#wa zLc@)e-~$-GDcoGAJ)M%?z{O=m4aNO?a|8R-6VFm+j#J1G}8}lT!h#pc3G1E zW$~DAfMqwr5z7xv66*JrnjI`@PZ7W`irktl;kgfqtXM>3x~?yIg|HO+4;=j*lVXtF zL8IXqz6V{r>CMUJKDO1-3ynce>lTp8PTBw(CGyy2$%rdT=wH@bWL$FP?Gec^DzOBp zG>io+u)Pj@kvzpZ$UUeM{Xq#R(;s2t6lu92B0{4PFovM`n94TNQn|)yc!A&{gv_`n zxK{-$yDx}RZ-wwdStMqad@F#D*)E`^(dGyivzSF8InD03Jjn}plf3N}c($K6{_|MD?@O0P&W@IxB1JPPTE}5^s z4t?AI9q>8X2%^n&y^2grOPYGh`$0D0=+Te@2LholX8Mpa%aTjvrY(&#!9JuW8v#>s2NlZcGjU-97bBsO?vQ8DC{z^-g798xf8&&U^)xUkn=9lBm z!{oM5mZ29BPtZ<>u9E>vG+wNM6i2~iDj+Qgk5C0hFzxDUfs;XRtw2`8=L}v!G!R{l z!c)nGnHa>W*nd&04iT8PnG_FnFf0MqPzocMCOVcSi!B`oo{cqgn;<{Koc^pM6wAf# zz!Y#9l938ayS3&IWw44(&pNQ&V;GioVB-z|49VIkb*fSd!KhN%z?snCNiVR3I=sQ9X?ODL|R{J;o5Z1u7)jzaG8uYc&**r_AZW}8ZE#QITg zdl?BgzQkWJja2U2q7b6O4(_z0<$43bI&C|ckBVbl;r(-wIE&!*Qubv-7I8nSuWz<{lSJ|RTzYuwo*n3 z?y`@Cq2P=uvK;QUifoqZF}pP;sf7{)vo{$W_P$>qKV0Z$^(snCO?u26i)f(K3nJ?%)Gx*LoHMCd850eHCNx9l3Uft9K2;HgCQky+49=W5yS~T*GnZ`l)$^iGkWE8*-rC#^;-JF_ohE|#3VKY zFj5J>B!oiRW_MWuuoNT>q!Xy>(Ux0d#Dt zaH4h4@jy6PM_BJa7yypYj^SJ1_R!;d}dzP>|)I=!6yh} zIG{(vEEiF%TK?3ZxG1Sx?GgvAZ{HlQrFZ4F(sC0QCpOke`nDxmkplo9e|FrPpH4P+ z8}k51>@+0K)MJPglq8g)0a5>iTUzfn=ajV^I{e0BH}$efR=)5@R=PwoKgLiE$Odeq z6@{8*1G@Ax27)e<9P#V5s4#fio<07ibXUQ;A2a|@L|<|%)~ljlidzn>J@Bf5Nom*n zMu`Axq%^cp^8;gc#EQA5a)3Mfx?tw(wbW-J)1mnz-|pH1_K0hM1pF~&HXe`&aV8) zbXr)izN(VuXmm^rPAx?&7}4r{J7u2L?h;wi>a=8TM+l2l(e^qQ0V_lKaJRYW?4q6M zAdN!0N~PN{jMqi97BL9o)Y%DeQF?MvNR=G{@))^4-hABEW7fzMdOB#LXbp>hVwG#q zY!Esn-Zr#u0@VWX?OTV|6`!P~H!4!O#iJva_L_{WG*oSI)DLOu{*dfeJNl$Z zmU!7{DEt849V=0>+3Nj)C;2r+|#1vi`kTD4ej8BLZ|-NQ0anOYG)kvUG{+T<}5pG*0^`@j$jt<3UaI= zXn_a3I`B=~~S zs*wdcUQxUE)0zW4Uj?#LH^^N4(8i0ncYaN}7*z2Re!R~rs%tV&2( zR7*3?2XAgyRWOmUmK+*dt6d_uu9k)pN7OGX2&5wtW!U7V{NZiD z%T@yV^qS>(6El2S_4l9C+1JIYTYwl`WiA_eHzMr+I% z^1dmqwBw=sebpc-Le#S9O}|aCK@zvHMx4f0BBOMv&DHtfRTixrTVjmYccI!jV~;oc zWz{&-H<)#F-p`?W8*G13Gbe``8rkmT8tU1wF3FiDD6G&lc#7}sZ%djo zV7P3psqze6TMLy>Kp=ZHgcA1B17F1@HM7-H;bg$n8kl~dkt)Us6b0JTm?To|^(zF? z+sl|fT2?->EVuMby^g4ebb>DE+51;vK?@G%2Q_!Z0u?Ap*?6EEGo4g%*I&29{iB-0 zJZ7(OHD7;Qv(p1BN>IXm`tG%KKjtoC;TJ^NSf|e0h%3tt`H(3_$yONB^ZG=s!#2L( z8_GdCn$%=ZJy>NL%GUD)?J})xBCbT6(Zx+ggbdu9Zd(gEz<;S$s7?tkuA^@`$9@)u zaf<`}{&r6s6+;orhiMagziiRW%6XE9+d9A+jibI!rE}B73nRAUqsQ z?gc&RLoPU0cZ#~J?*$O2xo5ky_IxbFjm~3fd~{xx=V)+$nHg{tCyLe`N$v(KQyI~= zb*#Ie?IjD=6mA!Fpr<<{hI$|gQH>s-O|jCTWniEVj)VQpUE62LOBS~XG#f&xrfzwS zmQVZm=fURQjhnl5tYj}^vc=t?(Re8Q3FGQb<2@-fdF!-}%T;GBwTIw%VXyR*>frb5 z)5L8}qDc;nf*)wBv7JI<2}h8tvYl?uHSPynn4Aj&-;B}{XERM(d?Gi4G7Sy-IuR2) ztl?NO5^v!XfFh91F%&boAJ&eTq_Ud|AP8W$4))6x`0#S6wE&5Gq^J8OuAD(k!`LKh|0F;5 zGtU137>N%eD@=fTVm$X@YfUC4 z|EiI=bGpmA(#Hv~MGu(oL2ZEVU}2AP@CXd`NXxQ1V^#>Ni0UhptoWd1N5=@Rvgfk% zs}2>$_?;4y-K=WgoohoZstvU4Pc;UWQ*6e@ach*z)};AHI2{}S2i)cLXQSC2;u6N# z2}URNiY9pvZ5AKg;evAS!)S3f06FHsC2-}-e1`A(;i`Zsy=fjk)v*ASDiOf3au=01 zpM7pNJ=XeUC!i!@NH^x{vKr#nX^h~qHdR%9U-wx@pks)&`n<&D!QPKTs%VOw8qVow zf#wg5JkXS4E~;Vbl>|YEV9oquMP$1ndfGcmEw6Tt3@=JcEb`BXBZ(OroGqEPES`o; zA$?U-hA=xR=hmD-zA||vvB82+)NmdbotlM=bGH5Gf7YV*tsk(z)rUy6k`1zch_rq8 z50T^@vLPB;jtKi$U8Wj;_?ffB4ik?!6X0@lI(KFGM)iuGccOVW*+_3V#}@3xe9WB> zA5yDAtU5s%p(rHPI*>-r5GNrm<7M;x5*?+c$77X%$5>|j;Y7zrIIza`p@+BoKP8+< zkBHXZba9u8t3Ifd5BU?mcWhUeR!gd3e}vd?bU3UY5@T z_7jt%RbtZ1v?yh^g7w#q7Onb?&WYE{?J-qDU~ZiS1_W+}G|;!_!08cl({$PLHcV?( zqI{S9bmbA9x!vNN6u{~W0Er{}Y}mx1nqKFL86-DxnD^Q^__9jhua#9r;B0eAym7wy zMklzgRwV33h5i@H@s|%%Pwli;NpQj{5kzwGjV_a${65T8>@lz?qugdqusB^Z z?qm)Ij$1lUCGFFOjw#)C*3zjO&@EI+w9%KVRUWBdk%VgAMAi(_+Jhm`Ws#Uv;x!B& zKuYNqrTQLQmI!%5$`!07*GDIWx1pp>*28(tjCPiG>|ma~4@k@EZvlOF=MPZqe@$SN z3KfbKt1(gU32d9H_)%XgZCt{!F*QK6KCseJN7I;1w*9FfYK*K~S|qc~*K(Wv9f-Nr z!X$2v%pZsAIZ{Z(l&uA%R`6O)1}8G;3GT=4n%Y5rYXjgiK++UgIjgct*Ck`~2*(zg zJ=h*JWPtIl&CO^ql9t2lc%vn2f+ZvqrCGLV8z_CTEvOuQrf$gENK{t&2eeIw!TwG^ zapp)JZ91CTvlx-)-mbAWT+P-JqfB##U7zPj`C7XkvnS+n8O1WI%Cg11YUNuJX4bdp zT9q!6f|4g5vSq~~m0reat`8-jREhANltErr;zk?-gcEG94g}q2gpEZFwMOC2N9?ep zAvktFszIuiUO$7ZSlx%+kgelxF&oBifB)b7xTshWTaa?FOtla zYK?WlK71UNwWcaL42WCMwD44s1s{IIE3xqohRGPT{4^VO>H}hWn<$igXkvBYb%FVxB5`J zctj;sk!-h)<{CmPjJ-PVI7$LDX47Mgnqcuqb#y{Gsor+t%+@ASCmTu#^1X)zG|!y0 zw|g@|R0-@5Lh1)j$e;PzYEOqa21i7HSPN>OC;1}~ej=RWJ?bdv9>w%Q^Fr()4mFKD${Jx8PxTH6)_IUeL&e^ktR2>Z`Zj=#8c@l$Qf<} z6f-NSFt$o=Yxb`@NJc;lKI_vcyMnksRGF9cP=8#_O{h%x4<&g^63j4{cy7v# z4Emlw?Z~X?pyopmK;7vQsZnymz34=0d3_DY#OeHwo=EiVj(;CIETW1gQt5_^>m;)c zC3u|Af!eI+&~o%}`G!b5ytfm>cgBCn5!)a|*M}!)Xg<0Dxua*a0#%>G8>TUQ?=V$1 ze5;&;Iz}qHW;Nn#3jOD5cq!C~qDEJn`)(TLgijxmfx7wQoHwMD-Ecf3XXs~odtfPh zrb_hpXF`N|%XvBdW!gz`kJzE&@Z2XBl^rN@A|tFgJzYy8AqR}(C|p0xmc4$+px0Y6 zMnA-Y(~`xo%^?ea$C?nb)l|E`(ozEf!xq$7@Ig%1p~ILpf-hpx`opjD?N4Xl+ zgCB>Dk^tt~9W}66cGHZn!`4ADJB}F*t$H4YJ(%{N+0t_4v^j5+P~J9!jKP@QbUgd@ zw>hP$w0{zI_881y7(XvtjP&8Hi7v*D!0m&N<5=;`@J%DX+HB|&bst}<3%*hVPPZT7 zk?1v?1X5MpR*w=L@mYyvA~xy5h61AUCP<+tomT54rC6TpiOsMtGuG2SE&)eK)w!s@ z{cRY$yy?kt#P-p@TR4&OJz*~o_Pk1Ap@zYMrWZ^hg!*P@M!(kdgbf3V4#-*E<5+{H= zV|ycnEnzbqSS8gGR?Fd*Ng5#~m@dH8jvX| zR-M&-a~N!drvyzJd1hG`YLykV8|9OhByGUbG+a}{Sl63Ua2;JAP!1sghT3YKR ze5T7otzPUO-)itD;Q+fKZ27n}21bu^+>P#%^{Tm>Q{Az(p_|-FWw1jnTfEts7r1FCSN(Z1AEBA?h+?q94Ra7SAJU&VwQlD{K z^Ked@n7$>#?XzPMgg#3Dm@nRrV@lC-LFJG3bY;2?la~E$@PSx&Y+tbXuq4>nX8lng zWeA}RYm8o0fK>ny0WBMN9LNuRTOR`k*N~1L_Qdd3!Jg%FPlAQBX7JUJ6$l+*DV|(g zeKlm9QAb9iKc#w5;2*7KfHDfN>am)yKrwiG4A6Et2?5xCM1>SBr2@;-%#~^;O|3dQ zSC{avjJarZH|^a?XYO^6Z^O19Rf%O^&KN}v?YZy~6mMAnv{W9&t0+I`y>f+IG@YG8 z(Pky2d_Upa@%Br6FPQ%40%|r*ILUDOu?4-KD6|O{!itr_K#?APTw-#`{td^PXs>Hm zo`~w#x;YO|?>FoS41HH+YIGR9^=e|Ud5;y+{g>d32_9YJO=>J_ZqVN4+5e|41|4zc3Fbe&UrHN}fw z62#&fwTkUWt54T@eFWh*u|2pQ4te{L&HzB5jyY}HBBmZT100pwxn(9<+s9O&VB%kl zMMu6yuVqb)E8(4{nJbTU!Vhjg)!db?`8_vFt~Q5^9e6UYmFl>o?Z+%zLYZQ-Fq%IQ z^4N>EUA{zg3?Rc%C+APX z83zVbZ%KGfJi4HY#V|@)UXHI^L##-NL#Aq=9O+San&t zZYyx=bM=af(6BIokbcM(x6z+IoGC&(HVp!|G_W-R2YtlA7&1n!$;17? z$jK8U9{OPwc*qyjN*G0jA)F5rZ!W!@D_BZi7641 zj)g~>0D7$^zHh{`%TGb&B)dK~<^cILfi z-{4{VLFHGnblyf4KtLMs=VY8~ReA>QGSez|Cm;-|NUG(Xk5+5?|4JLo15g1boTa7X zQl1jRVGf%afTY1wtTkWd^OeDZC?O3lQ7%mHcn>$cHOuMS(ZtW*v}Tl1ZA z^V&*A0Kj>a9IuAoSi;%u`>J#U11U$xRELN%`btxu!gO;tHD!V^0m1Wwt_%}X` zaYG(NVO)i`^_xC2-I~Tc4a`8O>=}HaW1_usLpj1NOJJ%S0$6^;55vF!f=ISR?PIH7 zk!;3Vm7%Riq=XiQWu9~kc^P> z3We%pf$6ti;EbfnqM(CP9e*>;`b<%c)^2ca{l+K=;yraAfDZp4_z}Dke4$cC%1$bJ zMsjM$8@?X7flT}BXR!g5N@@ehpa%mM56zkc2py_-CBYWOI(z|2B!EmBo-IzUe_P?X z!e#-LDHzU*GtO(TZ3QG_WL8otF46@ZjGLb+ZAjSq8FGz0V0b`RGgDfl`EsM4 zGCo~RHhE%8+NQxUO)<5C6q}Wn90H>X0(=K}#ZrX1cARt|BSwm?e+1G#96s zHGG`lF#&c+NC<7et}E1Z!Zh}0K;SM+-8BDrt3Ri5*~iT|5nl+_T6w!Tc-tjc_;cOm zL$P(u)soD~_NPxZX}W?ozoLTveG@gPcu9{cd=y zQTS@R@ui^vxonTnkTGsUdb8=V+D z{D35HNSu{J$`bzK^(-geT@@Jc0??_dHEvSW0u4uZfBWU1kD{KVh`Vv;e|o%dKjNE%m+T4Ytep>Z8TOSqI@r)rg2=Qw%i{@N=ThKjD#(H z96LIUK&cG&6e0vp6!(z;)NIS{J;=YpG`9ROOc?b`F{;RH(Z9m+!Bv_GQg5-=zrY6^ z3|^I&Y8Vg5v;KPUAjKbHU=LMF_3+N9+%e$x_EW@f(VU^$^l0kgldQM7Zg*LB$r%|a zz9t{-bMH9@SB&0Ayjcr3z)NsiACs=@uDsuVLg>WIl?2Okr)R*nEClHK1<0;5vzQw1 zzS=%x+ph2bAZnZk7-FzA1=w z0IsSVV!D(_QxM4RXD?EwhVQjCWa}4WuXX;-r>9 z>B%$7!}-v&;|tgim2Vl`eEjQv;?5K#3Hld_-c~Fc3rTtlSNCHV^(MpYgXmNh8|&<1KXR(|P-&wJc*Z^2&tI6v z#y5X?qLf}!p-`;yX!m^gDN9JSi&t!8nS@3NC3KfZfXgdGySdoX{9@YZ^On>=?BBIB zQSaF}8=W;__kxsAtEZZ8!o3lyc%c2GARSY=`Zb3TrMA$NQT9B7@{#Thpu{#Lu8*r( zL=&3|u5OS<2Dm&djbRpPOm@q=g3W^j%Sj&A#sq}g*sASrI8+#gF(&p96p)ApY^!nA z0CO5)`);E=7(CiWw|e!h9D-q674!5PAU;qGlls%;5)^vqV)dnRANXWyDSvjrY+opD ziby#L&1sasmp*IWUJ1&&gH}~TwyY$!gsbY^lBupjk4VzCJ}v`R&@b2oL!q`)ZS#}n z@m2KeVMf_2?YGZ7E};x1e|b`+lNz#$j}}2%FuF6fYp_qsLV3*8m@2kgl?r1x1Pu@3 zzzERxX$(`UBam=VhX+D zXxDI2yc!`I9mZv{f}CS7a|?tK($QgDW~?JN${`Y{zOCV zMmDkv>BIc)nt)zbQzR1*#*5gl4k#;$DlP)Q;kQO)&x7S)r zL5N3d+Q4caI8aw5S(h9eHjXtWc*rUOO=Ci^`4+}R_opqX=vOh-RKR9n*yWGb0LpMF z`Bcm*G(aC4U;^Iva@Y?Ray!cA323a0f*P5?iJpt+UGM!}d1^&JQYlvk7mOU9dJe0U ziPr{HDCg!NoGL??*|Q!zzs0a821$8>1&l9$fiPm5%vW(MR}5J(6H z^M$jdd(NO@I1NXfGJs;DR7y+hY)GZLi4pV1-b2+<&gSY-U`i@l;eb{Ze+eMjj*Jr% zdfN1{3c%A}xDEno=-epAipRiJJ0y4%!PwP6?1}uWN_$i`L=EJbQ<5_0r~y!yn8!>= zi>&R^U?iBzHUl7${FON9Ts;VB-Q206)OFVvJd#HlpCxdGY?i#0?IeQh@ASIt%;>Sq z&l7Xr-F&xoxZ?b3EvPgJUTb{llOg+OcmWZ74Wj?#r4DcSn$fnbdgXJ3z_KGrltu2CDKQ1;JN4IL>3NRV8cY@-uNCdf8 z!Mf;EP8=ac!ubo@m2$|soB_>qNHFXY(+@V%f_J#>!NKiIg(o`|saTV# zYS46T#d)LtjFU5HWSG(b5Y~;krPa`}#!@QKr9bQ*YFS9POJE~Ws7)J3pbeOFNlwk_ zc9LJg!<^7c-S->}t@n^`=1_x^edWAq$Aj_~n6l|0pPdeu+VybeC@;Ei#32uFN+V_t zGuC!NFy)Q>G!b)LTc#zLytW3%v-K+Ndizyur7lindN0T6_RsuK*iv=SwvXTzcGaqu z`ymhumgrDtKtUCFS%rw0gORxttZnjU*;flqpq2y9BBPR$fKLX(HaBW44iTJrR*g`2 z%&ialXggjVjzmEQ>N|-Vpf=7gXc&oP8%)6RcPfjyIYl7nA8tTq+qKs*7}FCVn6br$3Dz>C#UBz~-h$A>s`U zw0p!AewtD>R|jAUB(d^VObRHD$BbjXSik93rp*?828umnhSFd6GiBU0W3-`HW|0(b zve=9?aYF#!AGdOYaJIPOBq|iQbnq728~Efq{++?Fa*KOBEvxb7`m@%W#63U;J+N}r z{tO^lk%TI`oR%1*gEE(`_;WoPK?sMS>Aw0L43xtNMT4ZhIkH-YvMXu4pT8d8DeQ

A-Z-1mueR=4A)d)d{JiqSwcA=YXS;De3R02~Wo*0Ht# zOy@$Lj${AD$rn+SB8_0f{XsA_JgRW>z9@;DuL7!sRwTP^L&yMImnbg87O+d3eUKZe z^!glh8*gANZFNkKSS(gW(>otH@YjsQA*+#t)Fw`!${6$kDkAO7JRc;Enx5e*c4OC} z;j-b$r~ZLD!e83nS~cGg7Vx*t9L5(TjXAcx!bR6l2XK6Wz|dAP3$TY+bfg8p@?~Bn8Gz36VbQ~<$dp9RN-m>R_NiHeW$0;TeO-#=9^s+$aJ%Z!)o3-I z4!Nuv?2Q={%pA5EtIq18t@?w)J>%Sl14GF^jVb$=WyZ=(YYDAZ?pw?8V`e}c9p{&i zkV;k0$Oyv``)i2pQw!Yl2Nx0zEd-$Fd}DpO7W!^jK1d(fZrFVlB38g>aFzSY?2@+h zVHCH&Q3iTf09eQv?SyhtX^~-+<7!a6vQ1iV*>@!@z~60}*JH48o43c*o@lMmb#)nc zQnpahQ4q{T%-P^L6y#$_nF+PVH@TZ5*9(nMhG|X6qD5anKoGE9*on|loFRlx%3|1A0T z2<$9Qs-mh_-nylgF%4b*q>~p@B}7L1hry5_BBO3vlwRI1pSd#T*w#!-Gg+YHQc8)a z`GCv*Mh0D(prcx{ehUY`bG>Z=rXv9RIJtx8!%Sym5EXf~E73S?s%!MCOZo>Yp4t19 zLd|;S>>v6z)bU{ytPfYY@nHq;2e`If074~GG$*c$)i`=NagE4yJzHEAAqFQw+KXNo zGX%RWM#(WpHwP(_i#a|WNrGa1fBVZPMk!UMbZL>gr7DefFPkQr6hA^zF|086TT0DH z;VQl%!KbI$uIO5Km=-Jq?sI#PeTZFL!%!S=sl(1#K`?mGFqbGDoCQH-$6Q*yxK!;{ zJ6h+SN$xn}Aug^_BUF*V3T5nU0wZu?#Q}+`fJN;RlAk{Q?d6f`DTZ~lZ;?eyX#yR; z8T5}b147K-#n5rB1eF4p^CffVvGacukZ?yyXO1k12*K3?cX8gxJ1bq zoOko%|TQSe1Yr}YrO*+E6U})=f2dQjX?~@SF;IMgNbuOk^s;m6mt#j?oI%q&=v${2US#MSD!&fV##}@Z0E)Em&^Y#P%GOS@m zcA>~hIDON>Y({{qHLJZP1O48hiO{iU!O@t=f@3!6q%L|wImRC*DCIOipPS^coAy!@ z;WOgHee4IdJBDf@VI~WHu46?Lc-9t+~DoZu#XY{D}yT=Ae0Ji163}+|v4(0?vF(D_k1M)rzYOhTfYK57s znAG3o&^8ARePKh2pKeF+2v}lsO2KSkUGuNY3LQ@7~ET$>Kt;D1EPXM~P z8Bzdq=@k7_k*JM+1{0ZN;BRT9Rtd}F(R@c3s&U0Gj^r z%{k{U9&bKtJVJW9f)fOWcymvJI{{Xw7~aMAws9?=wYR+JKaPqJ29m=F9ArE)K3GmxA08VCe9 z+DsngVB@A3PldnWjjO$=T7V@7C3K0k8Y%rTqky#oHbs#X4{qgjofbZPJVy@}EIk~| zQ_hwpsuCeBe$|5NcP0S`(U~4ZhqZETT^1B4^w9mi2O=2Te8RrRacGd_siVMEQ>~d- z%apy;68J-4JKsF-4Z14bo%LHY1c!E)@ zCZ=dBtD}vojTFiSZCQJPRazNM5rC&6nJPViH;xEPA9bfXtB+jur*d5NDT+wv=aA~G zt%STC{uvm@1p1@N7VSYrdinKZh6R~011slL41rbw1ny=SjciLhsg=kM$e3-)-|2fj z9k$Z(++MHH8ADEIGU6Rcpu=Gx16lWkFs0C7b28;!?$M&Z2u|t4!kIl;bJ*2qK<)9y zngNpEB9WyHE=}%`E~H0yDyz!Xw0;oqjg_B4NEc&_epcz73hVTEGh52E4jl%oc=mNs z7q{mDQHI1ofW3!!fCM$^q-)NW^iymUsB^#)oG3LrR4}7FiV4mNymQ-QJZnRJ+y)Lw zBZxTNzW)V59W*xpkJof4j>?JJG;~EF`oLj2I0LPLYr?`0s=ft z0e?&NfXmy4Pawc+iwz+#hy50X00Y#dlU(!siy=?j`Y}o* z^q4J|Hn?@vQCMIy&-m@b)#e~DmTw1yg+V&h1sp_JR)EhM9NPHV55bqNi`Q$*3`m4r z1Ee_`%_R(fV%&-_9mnv?R1|E1$Y@Z(?9W_;vi!KPY4_p6(=HD9(8+jM@kO7zg+f0L z?VTc{<>c}qT3RFx;{=e`z@}Soum}&=aOoBvSED&EW|eszxUIsmc}3657;iDL+V8Hl z=n-L=TiU~3D?nDfj`lK{OF2A#z zYPZt2i$Tril(q~^tFk3xq$Q(`K*D=SVYK5XMMt#)Fm3!SNSe%4oU!KaWwe}Afe$-g zGLefH5JRv4IHAdSh6uW6iWP6kON##0QmpxvF4P%{I6`JX;0}@|2HTdfh~T92nb2Eh z>0Kn~7T>Tq>!1zJd=RJhW@)c_j3tYY&D`qC;yLk9^og3)QF}$@HycR}^*2P)5W#Z4%fD6qPiZGQniUZG1P$eY# za%^>r3!`Gjo7h{5%E*>bX!6vASio$Ia|m$JKWKiJhP_dBR~8*QW5>Z)y@X&*;t>cj zM!Q^hK+XC>e^LxEs~!D{D(wL**;D5Y#*z`UI!431%23CccoyW+(0ww=*h})FT<4?z@-d@QYj{N<=T%$r7HFX4qg5-388OB`76Qx5dr<8fimA02gD4;y8a@nln zc+~6&=YW8w=9O?ea*ncuY4|#+fM9_0>6K)*dAAWMVi~Npx9GMJKw^k^OSd z^fDHB5(9HRU-f2E)CA*k@MZ*b#iiLN!;ynHCcHQs3m}8&?{}$OX#_VFfkC7Zjqql& zl>w}1LIEx{)(8xt#6LT89<6A=(*mQ@Ycfk4Ne;b3pKnK7rodA0SGpY4H!_jLIz_jI zN|{sY8JjRiIRV=E=aa|j-T@b|F+rba!()^M8f#UcEZU-C(_|W$YJ%(10}l2+&K$|b zsz45O$PQSYY#s~@rhcZ^JIK)`*o@)#4NY|@-4heMVnx;8t8TbW6-Bv5&Mf2-hH0m-hfVhOyKlwLq z4S-2Rw;z02F$v(P&Be61@2n#L3{z6RD#RdpH!Q3%4 z))l$wzz0DurgKx*{Y6Qjz zrDu}on&r+l>8XUU0bJ{K4Tzy9S2g>h^7&0zBEnE;xH85PcS93DO6d80fsnBBZ5L&e zhaN>@Zihpe5Aib5o75*A8n|raoUrav|A6o0BJD@v#m?1!<8Iw8Ds#OH2TbsX`qk5HZ?O0u^?}pNQ6l@!S z<$7S)6$V47?w0*Z!Veg2{*|7SO?J)eWr5czndH~fiTGD%69m=7dxy((kIuWpO6dzM5v<8zdSoF68 z4o>o!jz?5g_u`SZi?pdB;f8gv0-UG~KJ(K0unG4cr(6hqajQD#K>}Mk9Gi=mdN!C0 zR&nL=SQaZwVQUqVdkdWwh&0aPA*rHq*>gneC2itbvKbjry+&+RwldKws_)gR60W~a zwX)PKNhP*dVn8q?@0A=lY%qIwgjI9WrC>NWB{-6E9^gXdVRqGB&8|EL4O_n6rKY% z8V#<|x$LmeXL8>wXH14*BcAUm{@U{h*m2F%W*2QP_u6$T$K%g5b5(7cT+*=iYg{^2 z=Mj+kaQ&LWYaR2Adk-Z90%^$J2Wj}LHf#j%!;ZY6ej7%F+{-#9Q>ihf?{Wgx7;M+z0Uo4^xcuNv%Oi?BV2QZJ*$$PyiMUTA;h`hg%v=l3R939@l9EM@|`YAE{0+<0acx007xn$ZwLH|;o$LZSLJ zrN&Uh-cIB>7d9fVdJW-J(2OInXH4UFm1?IyEi?Tb@~-&k%?BcGII{+^IOI-R6^kfJ zuXkHw?Pv%s#bEGi!yhA|@|AE9K9Owj6zXwZ5oH2L!YQVAF)MzfQxe%@plnzZG3g`6 zH8^eoGCQq-ra(Q&W|po5G3}7E2Y3Dkl?AQ?l?VC4ECK8Ek|Hl#5Zs(G-V4Q66!luI zs6dU40vVZZ>88yvlVEB(g<;$fHm^bqUC!sw+}uk%i+TTQDWp{@EiAzEX8rwLo_Est{W||!qW*GKbJIY z1vAWX%7aV`u=K7URvh*jYU~r@2to*|5Tv+ERiDqds1A)GAEAgywy0CE)^SyGjyy@4|qoglT>61(3Xsi^^m>QjQ|=k}3P7 z{3+?am|f5i;%g>s%i)`YHmrssmk!YdA;6mIQr4Zk#=a1b2V_;G%)8bdRaQ1A$Qr|n zIx5KO_ZRHH-rl*4{5OS`C0}^kc>Bhgs41idlu~(l3TH6HGo3{QfYXHxPk%Le(TesD z*g2F<7~asQ%}PeD!z9!v*kmitBr|!{KEPL?=psI}VK>FcNrUvl5FRzBlV`nkc_;?K zG|kuwU+a6O?u6lz0~a4f74wZ~EegyZDV9BH*iw)adh0g^u;bKxdW(h2BGyPNxq%fh z)AYI)YW`vHXD}F}cvRmH=}9}l!sDT#CBa_br6&|=BIlqL6BH6sBPXf8(<^ykvqrUI8!jn+3EA(;9ENJI~*1s>=f?yan0m=?5~WoE8$+6Z9V1{#y@_fcS8Mp#GtAVf%s?tzL4wNM zTLYZ86YKa!5R^G48fPOXAp-=@LG~y`ZF1L}#EIcXcd?Jmp%=pcN-sth_K{gT1h&x> z)vZRy0)3U{Su3~?r9}cjOw(LWBURwusEbxtZHc3>7wBE0;m_!Ja~)Ded1~&}k$8 z>`TB~Io>iq(ICF@{^p)LvEq9pD1(G19$8?<(n2n1A}8rCHo6+uRn*(2Q=7~_fXz3( zy_A00P_x(<)tG4|rhKel#551_k4B=iKy0mfDM(zS@5)la+wO$|?Gc%EV!lEYw?Qc} zXd5Q}q+k6LwPHArPce4r16RF2biR&+g8{9;hxIiT6Dcp@1W$+FkyBUV&37 zY2lRL0~9}u1hFi(6kgK?@WGpF@B^^NAwfqmyrLQRSK+%~U6kFX8>Uo;ifN$%mJoSK zfER6hqX&S2kxB*-NuUe!tC~Fczz0}<#63*QjtyE|>%z2SjQ8w<&1*;jhFGntO2e~& zn@0a?AqL%D;hV*4auhc#-4V>J89l4Y5eNcSBhfztu-P@dj>HD}X~m zI$6Olp@$tzf=33c`9b@S$OR!DCQ;3)Weg?EY+6b983^Y&^r2I3_Q;KE&H^GHNf?@FJ&etDBWJPkJGC z4viYHy9Di65%B$f=fJr6htb8WrTt)#BlEh*@kStwDZi*VcHHibh_`xNb3v8PQ)G(s zNv_ckuO^OoagMw8sg1DbkIG6l^L@3xZq%R;J2BafU;}3%Is_cppl_9n{_f9dK*lDZ zFq4X?XwTZ8>31;W!$~w|PC~_?uI(fxECut!5wm71NU7}9l3SHSy3&CBo3;WMv+K#$ zH3)_^yRG*}`JwCL)AQXoQC}VKlPAa8-q|$|OLVCaRg3hL2Z}14_p~ zE#9Zp5mi;*xVVTVP_Qwtp6h6_#S}7nDFhL}PGXS3bsd0wu1E&lV5oQ{(yOv2p$z2h zQk<`)f@3mJlZOpp<&q4wv_=VQS6FHV;~3xvKf6ObZBeN2HBe;wAk;M>Ux+Wy?Cj8> zgDSFkn-~;LDkGtO+oR>THZcYcSmX=cKex%FajN54+-o+;%+4AI2w4&8O+x^~97Fkr zSQQq&S@Wp!dP>l2h~ljXVTI-o6ac;&hoOOIl{S=n*BeZ1a6l9Jon{!=%qd|f48r_C z!1*A*U*YiW6?lb6wjJ2@=JxqJLbCvtLupQ`4s9}RGI-!(7)(>*jIu)1&^3Ptp$hfu zAtkopT)O&aM~QpL*x$x2kx2jO#u~R_<(YuB8Rr7cuHy+~bNm91YviCuzrIRfco|Dz zKitqjn1}f}DHQ2I6u6Z;1hw{Y1_YkdeL-$l4{3yR^gU*@KdtBCSmdN-OA=RFt&%xy z*HL6YD}9sk!b$&|#E*%1)2S|kTAyj&)DoLJTE>p$2Ob4c(;}R$@Vy!HrZI+Y0JouR z?IpjdL3Vnr2b#>j-UCwvn&n_($rHay zN&=r=mWvwB;4I!hzZ0gLks$~tiiebS@Wyx+RXsR_;E6_))7H{F(%3TOQ5Q;uPU#@? zN9W@-hv%?AlMod#v?^~kFDZ2l6JqMx+6W~WOE1z>O~J#(b6`TkIK;qF`GZNw*dHxp zcf=unOi+*68H;fg6BaHBu#{xgkh+YqZ~(NjG?AdE2Sg(mMD1Iq)xCrZ@TzJL<>Ty8To( zz$Q;~B1Z3#c1j9n3V~ul?#mhMcB&&jt5WnKt!6ZJgvk`_Z9FeL={2hrmG=Jz@pZ}r`(5TQWVQ7Qd|zhKDyOc1-(iyDku&* zOw*~;6>wJSsF-QB`wN*eRnrahTGoJXLF{OJ`vZhpf(Ir43S)%=(fcMk&MU??S>yTU zL8RcTRyU4L{0xiuQR~9A9=69?G9#Pvlo+N0ycV9M##-7&(+N0SmRUOJpuW}hfO=iZBof0P$584DXx0)KfNB^LxQ%=t|XvBoj2%E)R zO+K9-g89B+$!Y7rS4G`^-D-McAJy?1D&17|Vm5RVVz6L%Ff%&F%slM*Y!7`HkB3Mx zpdqk(B!{OXKR_plaPdil#!ALC2uHQ4XFWJJhxRvuv7RN8!_ck&YaSD}woo#NF%5QG z+pv-u=mzl8okd_W5T><)sfHm`;243+Z`soJ;OQ5Be0}em)kMYuwH}u8xQRsNYuN^> z^-kI`rfCmV0?afF$TagQBw{Zn%S3lK4?fj}4)X$1W?i)xOXhY&9J7euph2`Xd(wd8 zD7;7p6M`9NKnmTrpJAHxF)wAr?1I2i;t#ET=-4@dZE2NEBLZZ_a+r1ev6SP3x%+Nf1 zr$&w&03YGl<*@Xa?lQTx9kzoQr9!E45Ol9xd>#1&#f63Mk|zIGV$6*tS1z~ z+)9xl0Krzz2FZ1+t?4;ae=jQZSVA{jFNrgv!nEM9JmKSsVTS~oG~hDy$@hwTF{E|& z)Lr|__XQt07uitVb-ww{C#C>wGlzWVb6knmS>*0s?*Qlh;R+WnfTtIs%n>^^8N1_W zjD%y+0LjsQx-h{d9b{Hpcg&0Nu@YNV6Qdi;0Iv8NSuXp#vp>x_r-rLDX6KCwaHQvb z{5zL1eA^G6d|1UE1uNfm?yVaz;_d4Oy$;YgvDw2bNb6ArR$6spO5%78Q^tFm8|Rm% z>G4;a2fFM|9#HSgDE;PU0z?yyWnMtXbc0X1t$(<%QMo!2$^L~}cy;Ya-;%fD+kp^l)y zY*wZ)zWKR5bU!|>-}zRQ)&;s-qG!MX3X2&P{->=duZ0x4_GRkn zfL{7g2BamIr!`&YA3BLPCD{Y2KJsw>VB=Mc5}K;fX`{7N(IHCbL3P-WBN4hb4Gm(& zZ76=gI3kN04dpOtqW2VUHh-AZ>_K*}5AJp7$_sja=68|`I})K`zP;`ZIL5hO6q*hx zd-iM`?#?%ut)-Z~SKx;69rQ(=ab33z1jmQ5jG|k}89yN0T}q!_OI;YWqyRV!f>X#B zUR9#d8#bgXfAm}x==f{Yn$>8Q!#DMFVg_;kW3!sA45&!SJK!5OWC|PeTP^~g*$44;%-DyxOy8(tQNjKD za#hBO04t(YAV7anxN)P8$sX_XrV;@pW(_li2S00gvvG9{4KE=B5(~v)@L`kNsQ9?;UU4{^X+d} zhzMBAR+6g&klU6tt5(GXF)aCuYiOO*fkgK=J4WtlPTJFm=Odu5!fj5-vrP;DR{Kk?FOCjt{ z%*Lt`6;6^5UM9R;qt@TpZyonWViS&_(5w*9`NmsjJYjjTHlwFk$|kk@x|d zjkIn`q_B4zZdr}%$bw-tC%S@)$=6%Hha9?71tt&g?R<9J-?N#3i6Pq~0ghY&W2C z%rS8i>B?$EEp@f~eh9-arAY}9VmS9{X>peXoPJIz*`pDczp2Jwa zg+dbuEj4miTWvZkXX>|0u30R4yL4GtIvoRxY-qesWX$8v289bah^FeV4|tzE`sn3S z!Lch3B_<=8`7IxY(!Re5^*zh^oUZ9Z)S7Lt46Srs<>8VsrWDczjQ24ZbxK~u>e%gV>-Z`qgZm&uQ>@zY_WS$qoa1_|=EJ}knE9-etH>#P)VRvo zCX_X~!k#XB=yYej9f{|>?d^?R`B4g15ONTaVw38~p5IJ%4;vh2%ZK;)ahSI3w9kqJ zvy=HCBd%$?L#*u6LEGMyzfPoaz^HqfRF-*1RyL=nZaW7R(I1dd?i@phsBa9r6!SGkOh}w2zfyr9oUKJ$H zBgd375P9VoC{KGNh}3hPXhl zhrKz?%3QpPPk(p&Rxqe3!bk)oo=0Q%zFG01`@qC2{GV2Ziu%{#WnsrJ56n)nIZdIoUseFK2wVYr>L#&^wpdU|B*cnN5mC~Y_^ zmO&}Nx~(POK|m!He!KZtgL^HPdGHI7G>3zM#m_8wMb6&%hXeicR2l+fZ)HKJ>W+O{M= zuhfY~yjt&1;}uq0sQA-H9dhrh?wphjytHQ!Y27r8W`GN}8_ngfM=v)3G_^+B2LP6) z(?;3I7Oformu^7f^&MbJ)-x7U=Pq)$g-sUca4Jnm?i4nA(uq|{N_Mv}N z4>cpx2g3E~pvtY&!dnV}Qjj)!@Qwn2-y@+Sl*jzSrOoY#!+Es2#l&2?My~P7=CFZK zOL514w`FC>H~KC~g=0+AYbz9PS>=*EQ^bI^Ijq`<^TDiw%GjL6xEIads2>qX`)ewQ z@o^-|HdB7N5=um|7bFFh-}I!?UikIo6(?TCCT>5Eq*>w&P{Z1Wjf(LIO!4 z#|}urGsmx0KR-_y`%YN$aOa)Mo$Yto>#T@SJ^EFR&(034>)F?)VF$t_6!Ooj-;f(k z#-7|zt!*5x)6Ex6JXHCOq+}2zA1hC(gQOKSK9G>O{4sWd(|&i8#k)c`Q~%KK0C=*P z3)sPLCMSJ@+6?_^jb_x(Ew6dA1gy@4g)wF4`yJ?ngz>jGM*7~q<;@jjUVB!h%c%Xa zJI@R#J+OOqxO}ferLg{oWWmQ&Mj3QkR3qh%X@7_467KdS{apz>MX;~}W9~L-f~J(i zxE(Mjv)#>XSS0u}EWX@lH$v3_ErBG`1Z>}+Yj{8BfU13bD5Scz4H7%1Sk4>~CPg91 zKQs3~X2@?s9C08VGw3%D#w{1&GL|kNo1~cC2WB$;tzzl_wOn7_g$|zNObCe4g9$Kh z=J}})5-Ef6;$5=+M0i?yd4q^N%)}O~d+V=?0j_->z2u@vwsxgP-87>!g7h#%QDaSG zdS4ax#moV^qO5V6uvAG!66o*`AK*YIbohoa-3J;-dVF1?lW3}c3X6wdl&O>Snl*$B z>%p6&Y7R>4*5KNuZkTgcix2(va9c&x1HEGmAcOXR&_W)d^$*!$ItHa!k%Q)OdW3%0 z95oghF__VjQ>gt6E~AD^&o6|0GIndpDhS)<1}4VI&_inV?l&VJ2^pw`#X4RLr|fs?iAtZ&LQn6+RIETLE+K0LgYB*p z?Fac;M;t%u;57Rog<^revJNqzmPFIqSusy>B>5`MyMjKm>Wo&T%mi z!>&z;r+%eyxUH7+wYqc6ak>2lt!NQtNUsd}{Ic~17NNU;hZ=wHxXwN*2`c{6r$q@h zWxUaAmTmHD#f*MZAzq*O!PaohMt(%Qbg816#d$<#keuEmf|1EFv~hsg5+(^X?^c9f zCx(m|dH~?Z&t&S}gKaOzt#7k%26q-Y?5KXZPewC`la@r%B#_DlJ==%chBw%{JuzO= z#_1g|{P69IDS6_z%oqv@5%^*m9T+>!ryV@?W7UWIQ-C!@Y7ZlX+~Nl?Wg3*}<&71f z9YzHM$#DAao|#*B#Nj*W&!B|&wVv*YFkdZ`t~=2Zp`Qe0kWvDoZDgUpa~k9I@h+{1 zz=!)v=0X<)mfS+p4H=R#YuZ5GlKBf%=DuHj98@a78VE`{F8nx;6Wf69#%5|;wPHc( zdaE%E$*Z3s9FFn^?+X~Twj(;M5@l1#wQzT-4Bp+`EA$e!Y+pQH6$No`&p&btHzN}L z@#PyyF1!W?#v~uTjK$(|E`=om!CDYm{AqFiwSQ#TD&IH#L6T}4I@0Uwu*_4%4NpV9 zEbRE2NsMkCrTu^6-VV0OkH@Bg=rsW9Ql-JJSslJZ1Y`_Je6RO-c54uXi#N60{f@{!#GL~>a*QfgfX9$-gm%0Oh%02xrBc3EogKO{S)p=3UvKn&Hn8u`6;7D-99>toQRnGY3F?5)Lt!ElNPG zU<=n(-YC@8BKkml@FKEzhPiJ(Zu*$CiD6y5=?@rswRMmuHO?eZ-d}r{5cA+=@i8w( z?$^C|0o&Npg1%1@>((UOFvzsK3Pl&BQoPYNKoON_sf$P_{v-oBVY;4)C(SuzcC|8l zjYloYwBH{xr0)WYqK{HY2V|YL4cM*(FuN51dC5F!P@GviTN-4)T1@;cTv+pkA(S_q zUgOO@FnM^Rp`ky;Gd)n3p$G$(Z-Y*d3?M9{yiRtMz!Q$CtMYhPmQ50vqJK`+$;^ES z%O94mu@GbQtGU5J*o6?FyKwbwrAw)lb)OgoJIx(@7>1a@DgY|g@iq|1>-jl+>{Bqz zQ63n){-O|=Ix2v*^pl#rZVG^0WMQcv8_#h+jFeiAWgI;Rr5^@>cFbc)7d(|r>?p4j z<-1#OC@YIStyDT+^u#5X{`L|<5Xl0&O0<^<>P$E|50o{}Oz2 zUM)uj(_(jhULV6kEqshSzxp*@%K>q;=|z9us6_2_oDz{SRYeaBOd%V=;3TVr0<#XP zn<({@6+{m5h!Qb8nr;aT_Gqt4lObv8E?jp2%-~U2wAxv6%~o+HOH~Cn0IzS(!7gDu z_XZ(gL8HBG0Rzi*`R_7SHlXSnveM`uvD*<|Ia!AtJ{*1uqdoXsi;L|-l^rx9hrHQA zI4Pi9uRw0IGubx4;X>cFPmW>o*gPS1$lO~BSHm{@hj6{Gcw-!WFoE_;@UHk2pKqEV z*0oc(=yTIf+){-kF7@jVZDyn?@^I~J4)8TF9md6mF(lVc-x#NB^vYw3PQp*{P$q*X z3u75Zp4R@_!!ErzNr$pVun2*T&}273iN^j25NVmD+&nHV0g_f&V?E+(s{^L>YTyE-xRhS%WG+skxck?Fp8jx6 zN+TuO6Y6JuiP827zrWsgq^+hz<-2Ux z*F$eV=qHJF5)->bVVllmG1b&n9)?>Ln6;_6eO*rrD4ZY&>DHD7i{Rk2>CdXYB{~{A z`nux)r{FX?H+I26FnTqpl3@6iK{!NW#NtedQ6FH|7OAy)VkGM|gUxSlX1@!YU!#FtR%nmt;L3E?X_>^xG;9S%{cGU}<{YybosO$qvZsY`JdZ*fX4 zND&)(&!i~_+>bf@x;NWsC+X5wT4K?zPwrwiG9K?^c0a9*z5yA63fayu$ZR{gnWc~g zAD2KTzm7Q~0#QO-;Sh-H7?)4MQz@QNth{ge#`X;s-^?x9E2Eee?G#qAlKaEE6I|ZJ z0xV7~jINm@2N`Vyq`Ro_9+j__X-pJgoe;pqFNY?C5 z|7FeW+&V|MZVXem*J(1}rZz2Ge{S`y;AfNJ# zxFF<`@1{nTk%c*)Ld&#n z(ngzo2-Ndqtt`crOmlFFkjqsXhD}Q{v-c31%o1DaO5An!&(`Jee$6@8mvava1V#e^Z*ZuJ$2P!|(piBTXjNByE!} zXVJYG3W_5XjkE%dgU~bk_2YzhE zUa4Bp*pG9dWd~eChT*Ra6(nB+aiYg1*Jbr+czP`X6Tnz8oF-A?vEGLB0%m=i5mXhi zZsIw5G^7z9&t-={(;7oEq1p@J_A0u)7^E=rbtgiPtoAseH5 zlhR-r8dPZ@qyyz$F|OHu=~+Ig&iv*WpC)BA=YZ+9pyhL=6HZM70JEe1iF9lu`b(e1 zB#tBxNZO5~qKJ%bhM;7VDC0=18yfcD%r&xgceC1@G_KFul7bhTb3}_VhGCN+{Fy!r z`vofwanBKOz%+6M<&+XC-iW8z&U%NJplT3JS}?#{9a78$=4`HSqFwd}-IPO4&2tG31C5APDA#&>oygUeyptz<4^K#G-u;<{Q;W=$AUi_(Hj4O?pGHb&14=lt}z? z(28o;1`sfki{y^L*o6>aFz`Z6vBGcjjq|9KFv9zeNQI$?FwX9(I~d38rHtDfr+;3` zC6qi+9)O{1e*FS##SJ}h`uVCk9eD*CtyJLc4Pd!{w@L-n+AB9;Xm2P=FgfQ*%64Fa zT56GX1sw@Hn2hZq=2TkeQ>JP2>ve^549D^2^QEr9XLz?Jp3umxG?o&M z_-F;|aa#_0U~+V_*z^(mixBk$_XM>jR?sj^MF|kL!;!K84}ZKy#P*{5_HO@8iNfO7 z`s6Uph{X`p2Nob6(EPU0ob@kka(?eYPq;I-caR5@x!iQu9qS z7eNZMz3JG5H<@@KEuFo{Ie2Tg!5{%I_QO^od*lo@~-3ye;3QTh=r4b|xtx$_e)EYP1-&<`9 z&eLnZ2DTR?K>*L(^J_4J@m@w}Hg^*J|J9vcj~vH!hVS(&1l^i|EX6kBmB4_o=tKdS-_r^${ex8T52lSDiZF=hUfc4=?A;IL6#p z;ih~KCAB;E1|V|8-%s|N9=p~sYu3Q@tNbR-f9hq)pc#oVrxQ17^NZ?h-}8&e5}Z`5 zH8%xWa8LE)m>`Y?0O1h8^<&$z+oJT+;%DSD=|omKjT;?k%WZWYoL0Au&fKG*+Xi1T z&ZuSULN~*#?3l#e^@nbHdU!gDY;@HA^JeF$Md{K4fdyIKSk*n^> zgk+UhTB>|pUKz5_hRRjza)6MKQCXx8qn}^J!iqg`M2wA6lWoNiMy1D8DM0|xTF${) z%q^eJA{bL?_}Et<*D#Nn)vyt6f@?_|_maIuIJk1nqwUr`p|{=7b0w(s_rY#<;z7v0 z5^{gAa6~NU20rOV@YlT}c5I-yH>EW>5yiWHQD%=ANTK)qtwuzHATO#bN$d;KqAMP$!ww;5n zZ}w?kau6$za|RLO!7DmFpa;e4S#98e=TS9@!Gxv`AJ;jNIk|;NBA^m^&o171pW6Zp zCEXs=02Y$GB!K0KZYU~*7rSW~TWhT_^C7w$TtvKPgX&o%Sbqp@lh6KKdKS(I=kP`7 zz^&Gw4lzgX_WK%S=HPWjhMPTKpWt;00CLoC7LNh}J4*KR)3C!$PCP&cyqhKPPiKY( z7YHU*GRKR;l^0)(yT;N&oY6iXT>!$Tuq$BGFHR8?1evfBeN}w{j#7x#@Z)qY>bs#S zUxEyEgo~bZc(o1|YUQU}A@9{;2`AfmDD)5&w;L+p*lr`e+;GCZ;)JX21O}X9WHNEL z42v4tZJ6=7tWvDQl>p8Xhfo9?{~DVSBR-MkI3f%37gzQvu5f}xl}u}*MSBvzSC?e) zPS)v~ZQMTw5)WQ5Bk^Tm$i^68qBTzK$zwovAt^C-g7eeny!ku?966WnB=J8$(j5dH zajsE#3_MdGCf)n1Bn|ts-ADb5_LzAzQa^D9XYle!vb^jXxqZq8&XM65DtT1Byd=Y+ zL`fXj?Il}kfAvs4qE&RzRTo>FIWz%KgU%6AAzer&WyCu`(g;GVfo?x@tCMQh9qSNCrZb9)&0)_rMlic;7Cjk9 zeV*!zO8lPfwDQ8qWF1#NXTB+_Zf?DS81vy9+ZR?3Dmc*Dvn{rQ8Uex@lLZqEw9;#b6O`){0gx2%w!`|jwd)$8ggYMxDKuFGq$TXgQj@m z@_jjalF=k2j^)nn6G!`F`Vh42|H+0dd$b?l_AftHUG{)`5JG&hZ#d3U*~%HfcR+8O zMB4-45twyBj>+84PLef&OzRlCjwEWBdR(vVOG2XJJgK0%yYhL#SAhai0jsZK7qX-$ zNsc3Sw>WZ6_*opg9t+?-0c4N@UAGsM567@yJt`e)jO64x>M(561mFY(sM?#Oxetq* z>pvp#_Elgo;xvD=9|An;UT=c%gk8X4YHTDVeQF+>6rJtVDqe|I2a)b_01w7K3E97^ zNleu3K{Kg%881f^rvn@faRLj$z{0z1wZ? za%FYW59NxK5lno<^NRZk;6{}DlUYGWYs=)De_8U?B`3TRwC7`Tf<7Hpj}5XRZhH&~<)H?48qRl4{;E^J7! z1gvr~ttpCAn=>p-k-~&AdVua8uAJ_Y5N`gzomW@*0Lu8e-j{AhqKvHt$YgWZ3Izo! zY)1_+-g8#1bU!vwQU<<;CR)Um^(EYo&70j9 z&s=u9xTX11$F`coCi~X3F+0|*vkbrpNd0;RcI_+ByQw46 zSL-;hLRKEjRgHC+_scZBYNU8Sg%d?Va>);w?1ZTT3CRxCret<IQ zs{mk6t9J-LgPL^{&@iDOQh&-fVX)VE6W1K2&ztvV#l5|TJ~s`_?SE*z&b?gqB|gu+ zOdLKxxfdHph@-&;>nPe~OHjO9U7&;{)kPf@1G<01DLc?u_9O6?`ceiEj&*KVlLt09V^l< z7S04MxKXgN7NG3-7&JHw&j}iD>v^HJyu)k5nytzKq+0hJa^RD6Y#eSRY;cE)=Kkqx z%f|BhnWLPq#^<?Pw4D8mC0jo4G05zU>0ZqPafRZgG0m}%?DG0OwmtI)vMY%GIgU+!sR^O z{(eu0)-7ORh;~`$k6{QWSVGm2jnDCo3^P_ZBypBI`N%GvlvS{&f7sY*%k(AwQ^Hl3 zLL}Jy-CIh?%#I7^=Z~#zNM?WN_7DY@i>Cv7q0t;%Saw0AsZL4PtfulSV#gQ)18=M^ zxwszeS}(d4>}gdjPcV9PTMa@nIaN$G`=uHpE5WYa6`07%W0!IBj>T^@sl#h&5G5A` zyFkLgJ$DJE2?L0MUACr;Lyh0OSxKNHr)+40&O6hxFV-0aFe{sx~a@?lb6;_ zOu+rMJ6IY9rs@7T5iU(7Li(9QVV2RZrc-Td}Ot5P?k0 z59{er4y9dX?;y|zF@5QH%);@|+M2-i4 z`~RPMr`#K5{tMHvzt0hR(i)C=-JK}IoVVBndCrQV{ySIoIiFyyT^(m*Ewr`{2|6;r21pH zDTw)yj{P+XEM+~ou?)}aG#YO+Mi!%oT@ zpCL_NGSwb-!yM~u^uZQkq9`lzVCtxP0%dEaprNQ5RRv6Ec=2|0bQ4(DO?v~)|5Yaq zSnM4wJz+cgKSD5G0EIRfH`sK?4N$O8S`3v9K3gqpdsf{r!(L+5d$PI z4&Y3=1q!c=GX{l~5}uGRgOxy6VG$q#2}~HHsozb#4L+R_6PSdc0D=PMU7b%Lvm0Ti zfp+L}+6f-%a;%Jsg$hq{*4Y-v(WvESy}Ee2)))-?RV1?uNoy$Gh#}cuV7NM5e>BWC zad^()9dVIbp_w2ZS-LeZXSAaQvwG5USPjqKKIt+}WoL=_~2V_iSb_EHoM>1F&44#a_8eQ^t z#bYitjnAXFWvG!OvrOa|or5j62HEun^R#Z%c58*vrGB}~#6#p7a>6*la+Z?-4fbMO zF&>SaZ|oVW4TM10y&F}jVSKWLOLm41T>shN0Ttq>AYybeoi-+&!~o1ZwZkA8-qNBL zj{6tmZ}cVLao#ecy`;Azh-55)Y0A=(dRQL`3#y`-ui~=Gs=7HZLru@DQk^PluwB86 z&Ijk*=o@V{gljc=Oj40VSe0bEMG|p;#Sf^FUdGG9f|N@De#*%U7hb9B(Mj{HK>In@ zGu%U93$k4hq`#GV8PZ?S?G-MlyXaq9D{BdIE=W^2$fVMy!{PdVX{12SAts=)#EG)? zGdZbfs@Oe#JA5j$8MXR&-UJ&`QC9ILD0d0q$pgGSYasU1@F~7Cr(YMpV8N^Qcug8u zD@RKe$23@bd(;;=w+M*TqV2>tfhDMlTAxa{hBVu^ej~)6MOVNI`Jlm7~WcYo-Mga%l6FGEa$do zi9jveVDGXrja25=zGF;CM3L{B?X7v=kHNsB0&KmW)NH)8`Hsv!D*U=%pD|3RqnBr+ zdmW>OhaB#UpzfyHLOZ~&FcQQ}xkY?cx>9#~yhy#Q{b?@GD=j($jfZd8dgb{{g+`XTUR4p%`MmU$F5qOHXGh8WH{#~3G ztRb&6UiANP?Z2ifgoDB1l`1vxl={O+o}26>1zWi%@TS`8~0K(3gm z+=NOl0a1)NmVtDSme9xd%lEk%)+hCOz)N6DMGfdw!Nw&Do@iOo=E|xGv!29l%Cw;4 z@WKw97W#f(PZij!kHD)&z}m)h7&34hx62tlvyc$?N+cFvJIfJ3vYTu|yVjY8D|G_0 z@f@MSDadPblLXFCl#?HA^JuM_1P-TK!0@)fx-T@^IAnWtc>LjJ&_u6@j#qn)3Z4Kz z4U*hO8j>)xBZ6*!FIWU-m=chNND34jal=y6S=hOZ)OQarVnbW?%u4rfW#KtUj82O) z=d;p4f*ie+Z~r-K!Gjqrhwo=-6r`Oqe-{|()6wE4rLG8l|KTpd)ShjHxXlAf_}|cm ztK;r-SRSLxkEkY|FXQ`_Oq_(rC9CWObQ}!bV|EK;KLDe9;@7%nxwykU51OJV@W6m~ ztP5CIWtl+~Zq$!J+7>CdgRy#j{25-H_8~zLLw1Du)=~>tFdXG|v(`VpII~>q5Xrt? ztLE@ii+wOt4#@^GZi>xJe-!bZA#>Cscpfo|ID{=6eQFtiJwn`KGn8;t$g;PMkd}WF zpH2t-912#iR= zv12lHo?p7!fwS*hjc$RC+t93wcKat<#eR6BWRhYX**&K#LQb7{V^qy4=} z-aDhyJYv#SS&Rc&XYy_FjqT_srP>HuK^Lk;%z=+Ca?OecJspYx;-H`_hKy)lF1GS6 z>B_f+z8G?rsuv{RNwav6lP8!#Pn1UqF4|0OyJt{^r{AMmLM)Iu5clb8dNLLfUzGRu3cYgGMf=*xRHLF$eA2<8)oryY46k< zb%Httw5jPXL69MwnYr%|s1Psa1DYA+e3>SFfM0(9)^ODB!OY7KalwSpzDco#E-cDR z>KolN%7kCr$63t z*$$ASL(>V<+g0)WjNS`#jl1}Kggv?szt6EGFzR2B&x?ly_FVJeDL3+I4p#y$%=Yw* z4v?0mp=U36diX}a`cD_(6pjU`yH_YGuz%aNt;b9<(&_7hOV1mUmbaMefZl$@~)7PcmRl}(PEUA-~(}@ ze+&qnw(bV59tW~4Z}K*n8KuMfJ)~cc;t%1mD2Y}Ho)GH!^LKWBGx8{=6IbR>T*1(j z%%&_u96-7aH#2AB43v(VY|hpXZNY?qyqPDHX_A7b9xHk| z2KF8%wVR-#TUbe>kt(I18ivf$x)L4m#p z`g{*aanK$eo_!q7{@O`@OOg>b;}b&{XgJyq5wdvF;xR}B zPW|u7kh>ncw8&D4GzFjT-Ews%BYgG#9|8p070`ZTzvM+}Yg+$NSX8HX(7*CDJp477 zy;6h(lmU#*YzxnH+fWQ#V5+1dKZ0CIhlP9f_~CaqJ-1NthnvT=TIWa~UuKrALgX)E z>3=ZRg~9#fU%!{5A%<>Qvf-5*<=55=&n~cUYYmb!$9w|453&~pv$^givDcgMPaBdl znm6%2_HR=(tWA~W%CHDsVwn_FGt9FG&to&-Holzx5DpPlwzpg|=e~^ghyv}eckT5` zux}(c))UZ>`m=;l>n1I8+(gX$x=F`LU}SZ8(#^wD){rAf|715L^N;rC+!Vs?`PLrL znA<%#PE69kJvguPoo0)i9Oz|}HGp{}Mv)Q4FtQp=ldv$p(`tK2dH)DfQIJlZ?H+tk zFmfKf*=0h|HE`J5kmME|?&00f@yX$_dg))nP)8KGwW5QYR`(_e*S#Lwe-y^!Jl0-F z79?j!^gUhx>pos?Ct9{H`%#|le~$hVuBj=*+1)wP?PWuNY$OwH|Bp74BZ_s6+K7ra z=vOUyb@^RYt2YSPQEiw8+LEWBZ!@z@ZO*rrhaOstPn&p#H^XEOB?5UI!dBWiS}6{< zF$g))i5s_RbeoSaWSNZtdORvvJ+ctIk+>fVOOnwpQQ04DiaFSLj7|n*yiNLrwIRnY zF}gOQ0^YYg8_ST+*o8$GN&spCony?ZoVIK%^(0d--9GXIM4sl$vhvPz>+yvaJ4UZ36PwG+63FRfXpQe!eoU+ zunH?>t&oWUG?~1E?)nG~aCOMrnqtlD=RvE-#rSDhlg4$c`m!K07tlx=Q0@X7spfxl z*zA-^A*1S;G&c8W%k^2HZf!LK>xRo1Q5e^(b|SSnnRGsl7Vzk&$@E!}xI`&p; - complete: boolean; -} - -/** - * Mimic the behavior of setTimeout() in an async function. - */ -function asyncTimeout(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -/** - * Job ID & Completion state are only from Django context, which can only be used from the HTML - * template. Hidden elements are present in the template to provide access to these values from - * JavaScript. - */ -function getJobInfo(): JobInfo { - let complete = false; - - // Determine the API URL for the job status - const url = getNetboxData('data-job-url'); - - // Determine the job completion status, if present. If the job is not complete, the value will be - // "None". Otherwise, it will be a stringified date. - const jobComplete = getNetboxData('data-job-complete'); - if (typeof jobComplete === 'string' && jobComplete.toLowerCase() !== 'none') { - complete = true; - } - return { url, complete }; -} - -/** - * Update the job status label element based on the API response. - */ -function updateLabel(status: JobStatus) { - const element = document.querySelector('#pending-result-label > span.badge'); - if (element !== null) { - let labelClass = 'secondary'; - switch (status.value) { - case 'failed' || 'errored': - labelClass = 'danger'; - break; - case 'running': - labelClass = 'warning'; - break; - case 'completed': - labelClass = 'success'; - break; - } - element.setAttribute('class', `badge bg-${labelClass}`); - element.innerText = status.label; - } -} - -/** - * Recursively check the job's status. - * @param url API URL for job result - */ -async function checkJobStatus(url: string) { - const res = await apiGetBase(url); - if (hasError(res)) { - // If the response is an API error, display an error message and stop checking for job status. - const toast = createToast('danger', 'Error', res.error); - toast.show(); - return; - } else { - // Update the job status label. - updateLabel(res.status); - - // If the job is complete, reload the page. - if (['completed', 'failed', 'errored'].includes(res.status.value)) { - location.reload(); - return; - } else { - // Otherwise, keep checking the job's status, backing off 1 second each time, until a 10 - // second interval is reached. - if (timeout < 10000) { - timeout += 1000; - } - await Promise.all([checkJobStatus(url), asyncTimeout(timeout)]); - } - } -} - -function initJobs() { - const { url, complete } = getJobInfo(); - - if (url !== null && !complete) { - // If there is a job ID and it is not completed, check for the job's status. - Promise.resolve(checkJobStatus(url)); - } -} - -if (document.readyState !== 'loading') { - initJobs(); -} else { - document.addEventListener('DOMContentLoaded', initJobs); -} From 8af12b22bb29c217071900e19866d85114e89b0e Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 08:43:01 -0500 Subject: [PATCH 08/45] Clean up report & script templates --- .../templates/extras/htmx/report_result.html | 136 +++++++++--------- .../templates/extras/htmx/script_result.html | 18 ++- .../templates/extras/inc/result_pending.html | 6 + netbox/templates/extras/report_result.html | 4 +- netbox/templates/extras/script_result.html | 37 +++-- 5 files changed, 96 insertions(+), 105 deletions(-) create mode 100644 netbox/templates/extras/inc/result_pending.html diff --git a/netbox/templates/extras/htmx/report_result.html b/netbox/templates/extras/htmx/report_result.html index 3bc5ad27d..b04f0c78c 100644 --- a/netbox/templates/extras/htmx/report_result.html +++ b/netbox/templates/extras/htmx/report_result.html @@ -1,81 +1,73 @@ {% load helpers %}

- Run: {{ result.created|annotated_date }} - {% if result.completed %} - Duration: {{ result.duration }} - {% else %} -

- Loading... -
- {% endif %} - {% include 'extras/inc/job_label.html' with result=result %} + Initiated: {{ result.created|annotated_date }} + {% if result.completed %} + Duration: {{ result.duration }} + {% endif %} + {% include 'extras/inc/job_label.html' %}

{% if result.completed %} -
-
- Report Methods -
-
- - {% for method, data in result.data.items %} - - - - - {% endfor %} -
{{ method }} - {{ data.success }} - {{ data.info }} - {{ data.warning }} - {{ data.failure }} -
-
+
+
Report Methods
+
+ + {% for method, data in result.data.items %} + + + + + {% endfor %} +
{{ method }} + {{ data.success }} + {{ data.info }} + {{ data.warning }} + {{ data.failure }} +
-
-
- Report Results -
-
- - - - - - - - - - - {% for method, data in result.data.items %} - - - - {% for time, level, obj, url, message in data.log %} - - - - - - - {% endfor %} - {% endfor %} - -
TimeLevelObjectMessage
- {{ method }} -
{{ time }} - - - {% if obj and url %} - {{ obj }} - {% elif obj %} - {{ obj }} - {% else %} - - {% endif %} - {{ message|render_markdown }}
-
+
+
+
Report Results
+
+ + + + + + + + + + + {% for method, data in result.data.items %} + + + + {% for time, level, obj, url, message in data.log %} + + + + + + + {% endfor %} + {% endfor %} + +
TimeLevelObjectMessage
+ {{ method }} +
{{ time }} + + + {% if obj and url %} + {{ obj }} + {% elif obj %} + {{ obj }} + {% else %} + + {% endif %} + {{ message|render_markdown }}
+
{% else %} -
Pending results
+ {% include 'extras/inc/result_pending.html' %} {% endif %} diff --git a/netbox/templates/extras/htmx/script_result.html b/netbox/templates/extras/htmx/script_result.html index 013b4c81d..0336bdfaa 100644 --- a/netbox/templates/extras/htmx/script_result.html +++ b/netbox/templates/extras/htmx/script_result.html @@ -1,13 +1,14 @@ {% load helpers %} {% load log_levels %} +

+ Initiated: {{ result.created|annotated_date }} + {% if result.completed %} + Duration: {{ result.duration }} + {% endif %} + {% include 'extras/inc/job_label.html' %} +

{% if result.completed %} -

- Run: {{ result.created|annotated_date }} - {% if result.completed %} - Duration: {{ result.duration }} - {% endif %} -

Script Log
@@ -45,8 +46,5 @@

None

{% endif %} {% else %} -
- Loading... -
-

Results pending...

+ {% include 'extras/inc/result_pending.html' %} {% endif %} diff --git a/netbox/templates/extras/inc/result_pending.html b/netbox/templates/extras/inc/result_pending.html new file mode 100644 index 000000000..7d053ec2d --- /dev/null +++ b/netbox/templates/extras/inc/result_pending.html @@ -0,0 +1,6 @@ +{# Indicates that a job result is still pending; used for HTMX requests #} +
+ Loading... +
+

Results pending...

+Last updated {% now "H:i:s" %} diff --git a/netbox/templates/extras/report_result.html b/netbox/templates/extras/report_result.html index 9dd733bef..3a23d705d 100644 --- a/netbox/templates/extras/report_result.html +++ b/netbox/templates/extras/report_result.html @@ -1,10 +1,8 @@ {% extends 'extras/report.html' %} -{% load helpers %} -{% load static %} {% block content-wrapper %}
-
+
{% include 'extras/htmx/report_result.html' %}
diff --git a/netbox/templates/extras/script_result.html b/netbox/templates/extras/script_result.html index f00b3bf91..41368ecad 100644 --- a/netbox/templates/extras/script_result.html +++ b/netbox/templates/extras/script_result.html @@ -1,8 +1,5 @@ {% extends 'base/layout.html' %} {% load helpers %} -{% load form_helpers %} -{% load log_levels %} -{% load static %} {% block title %}{{ script }}{% endblock %} @@ -12,33 +9,33 @@ {% block header %}
-
- -
+
+ +
{{ block.super }} {% endblock header %} {% block content-wrapper %}
-
+
{% include 'extras/htmx/script_result.html' %}
From b755c7dab34d17dadc09f58f823c6075045fb3b4 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 09:03:36 -0500 Subject: [PATCH 09/45] Add changelog for #7962 (via #8114) --- docs/release-notes/version-3.1.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index b117c4b1e..3b5c17e2e 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -2,6 +2,10 @@ ## v3.1.3 (FUTURE) +### Bug Fixes + +* [#7962](https://github.com/netbox-community/netbox/issues/7962) - Fix user menu under report/script result view + --- ## v3.1.2 (2021-12-20) From 57a78b3cadf6633e5aa5933f9de2e23f914044ee Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 10:28:28 -0500 Subject: [PATCH 10/45] Clean up device/devicetype tab views --- netbox/dcim/tables/devicetypes.py | 25 +++----- netbox/dcim/views.py | 19 ++++++ netbox/templates/dcim/device/base.html | 54 ++++++++-------- netbox/templates/dcim/device/devicebays.html | 8 +-- netbox/templates/dcim/devicetype/base.html | 64 +++++++++---------- .../dcim/devicetype/component_templates.html | 8 +-- netbox/utilities/tables.py | 8 +-- 7 files changed, 97 insertions(+), 89 deletions(-) diff --git a/netbox/dcim/tables/devicetypes.py b/netbox/dcim/tables/devicetypes.py index f932b7994..4df1dec71 100644 --- a/netbox/dcim/tables/devicetypes.py +++ b/netbox/dcim/tables/devicetypes.py @@ -111,8 +111,7 @@ class ComponentTemplateTable(BaseTable): class ConsolePortTemplateTable(ComponentTemplateTable): actions = ButtonsColumn( model=ConsolePortTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_consoleports' + buttons=('edit', 'delete') ) class Meta(ComponentTemplateTable.Meta): @@ -124,8 +123,7 @@ class ConsolePortTemplateTable(ComponentTemplateTable): class ConsoleServerPortTemplateTable(ComponentTemplateTable): actions = ButtonsColumn( model=ConsoleServerPortTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_consoleserverports' + buttons=('edit', 'delete') ) class Meta(ComponentTemplateTable.Meta): @@ -137,8 +135,7 @@ class ConsoleServerPortTemplateTable(ComponentTemplateTable): class PowerPortTemplateTable(ComponentTemplateTable): actions = ButtonsColumn( model=PowerPortTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_powerports' + buttons=('edit', 'delete') ) class Meta(ComponentTemplateTable.Meta): @@ -150,8 +147,7 @@ class PowerPortTemplateTable(ComponentTemplateTable): class PowerOutletTemplateTable(ComponentTemplateTable): actions = ButtonsColumn( model=PowerOutletTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_poweroutlets' + buttons=('edit', 'delete') ) class Meta(ComponentTemplateTable.Meta): @@ -166,8 +162,7 @@ class InterfaceTemplateTable(ComponentTemplateTable): ) actions = ButtonsColumn( model=InterfaceTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_interfaces' + buttons=('edit', 'delete') ) class Meta(ComponentTemplateTable.Meta): @@ -183,8 +178,7 @@ class FrontPortTemplateTable(ComponentTemplateTable): color = ColorColumn() actions = ButtonsColumn( model=FrontPortTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_frontports' + buttons=('edit', 'delete') ) class Meta(ComponentTemplateTable.Meta): @@ -196,9 +190,7 @@ class FrontPortTemplateTable(ComponentTemplateTable): class RearPortTemplateTable(ComponentTemplateTable): color = ColorColumn() actions = ButtonsColumn( - model=RearPortTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_rearports' + model=RearPortTemplate ) class Meta(ComponentTemplateTable.Meta): @@ -210,8 +202,7 @@ class RearPortTemplateTable(ComponentTemplateTable): class DeviceBayTemplateTable(ComponentTemplateTable): actions = ButtonsColumn( model=DeviceBayTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_devicebays' + buttons=('edit', 'delete') ) class Meta(ComponentTemplateTable.Meta): diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 3180d47b1..5c5b6b8d3 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -51,10 +51,21 @@ class DeviceComponentsView(generic.ObjectChildrenView): class DeviceTypeComponentsView(DeviceComponentsView): queryset = DeviceType.objects.all() template_name = 'dcim/devicetype/component_templates.html' + viewname = None # Used for return_url resolution def get_children(self, request, parent): return self.child_model.objects.restrict(request.user, 'view').filter(device_type=parent) + def get_extra_context(self, request, instance): + if self.viewname: + return_url = reverse(self.viewname, kwargs={'pk': instance.pk}) + else: + return_url = instance.get_absolute_url() + return { + 'active_tab': f"{self.child_model._meta.verbose_name_plural.replace(' ', '-')}", + 'return_url': return_url, + } + class BulkDisconnectView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): """ @@ -798,48 +809,56 @@ class DeviceTypeConsolePortsView(DeviceTypeComponentsView): child_model = ConsolePortTemplate table = tables.ConsolePortTemplateTable filterset = filtersets.ConsolePortTemplateFilterSet + viewname = 'dcim:devicetype_consoleports' class DeviceTypeConsoleServerPortsView(DeviceTypeComponentsView): child_model = ConsoleServerPortTemplate table = tables.ConsoleServerPortTemplateTable filterset = filtersets.ConsoleServerPortTemplateFilterSet + viewname = 'dcim:devicetype_consoleserverports' class DeviceTypePowerPortsView(DeviceTypeComponentsView): child_model = PowerPortTemplate table = tables.PowerPortTemplateTable filterset = filtersets.PowerPortTemplateFilterSet + viewname = 'dcim:devicetype_powerports' class DeviceTypePowerOutletsView(DeviceTypeComponentsView): child_model = PowerOutletTemplate table = tables.PowerOutletTemplateTable filterset = filtersets.PowerOutletTemplateFilterSet + viewname = 'dcim:devicetype_poweroutlets' class DeviceTypeInterfacesView(DeviceTypeComponentsView): child_model = InterfaceTemplate table = tables.InterfaceTemplateTable filterset = filtersets.InterfaceTemplateFilterSet + viewname = 'dcim:devicetype_interfaces' class DeviceTypeFrontPortsView(DeviceTypeComponentsView): child_model = FrontPortTemplate table = tables.FrontPortTemplateTable filterset = filtersets.FrontPortTemplateFilterSet + viewname = 'dcim:devicetype_frontports' class DeviceTypeRearPortsView(DeviceTypeComponentsView): child_model = RearPortTemplate table = tables.RearPortTemplateTable filterset = filtersets.RearPortTemplateFilterSet + viewname = 'dcim:devicetype_rearports' class DeviceTypeDeviceBaysView(DeviceTypeComponentsView): child_model = DeviceBayTemplate table = tables.DeviceBayTemplateTable filterset = filtersets.DeviceBayTemplateFilterSet + viewname = 'dcim:devicetype_devicebays' class DeviceTypeEditView(generic.ObjectEditView): diff --git a/netbox/templates/dcim/device/base.html b/netbox/templates/dcim/device/base.html index 13d4bbcbc..705a51eea 100644 --- a/netbox/templates/dcim/device/base.html +++ b/netbox/templates/dcim/device/base.html @@ -95,74 +95,74 @@ - {% with interface_count=object.interfaces_count %} - {% if interface_count %} + {% with tab_name='interfaces' interface_count=object.interfaces_count %} + {% if active_tab == tab_name or interface_count %} {% endif %} {% endwith %} - {% with frontport_count=object.frontports.count %} - {% if frontport_count %} + {% with tab_name='front-ports' frontport_count=object.frontports.count %} + {% if active_tab == tab_name or frontport_count %} {% endif %} {% endwith %} - {% with rearport_count=object.rearports.count %} - {% if rearport_count %} + {% with tab_name='rear-ports' rearport_count=object.rearports.count %} + {% if active_tab == tab_name or rearport_count %} {% endif %} {% endwith %} - {% with consoleport_count=object.consoleports.count %} - {% if consoleport_count %} + {% with tab_name='console-ports' consoleport_count=object.consoleports.count %} + {% if active_tab == tab_name or consoleport_count %} {% endif %} {% endwith %} - {% with consoleserverport_count=object.consoleserverports.count %} - {% if consoleserverport_count %} + {% with tab_name='console-server-ports' consoleserverport_count=object.consoleserverports.count %} + {% if active_tab == tab_name or consoleserverport_count %} {% endif %} {% endwith %} - {% with powerport_count=object.powerports.count %} - {% if powerport_count %} + {% with tab_name='power-ports' powerport_count=object.powerports.count %} + {% if active_tab == tab_name or powerport_count %} {% endif %} {% endwith %} - {% with poweroutlet_count=object.poweroutlets.count %} - {% if poweroutlet_count %} + {% with tab_name='power-outlets' poweroutlet_count=object.poweroutlets.count %} + {% if active_tab == tab_name or poweroutlet_count %} {% endif %} {% endwith %} - {% with devicebay_count=object.devicebays.count %} - {% if devicebay_count %} + {% with tab_name='device-bays' devicebay_count=object.devicebays.count %} + {% if active_tab == tab_name or devicebay_count %} {% endif %} {% endwith %} - {% with inventoryitem_count=object.inventoryitems.count %} - {% if inventoryitem_count %} + {% with tab_name='inventory-items' inventoryitem_count=object.inventoryitems.count %} + {% if active_tab == tab_name or inventoryitem_count %} {% endif %} {% endwith %} diff --git a/netbox/templates/dcim/device/devicebays.html b/netbox/templates/dcim/device/devicebays.html index 2d66e860d..6ab387513 100644 --- a/netbox/templates/dcim/device/devicebays.html +++ b/netbox/templates/dcim/device/devicebays.html @@ -17,22 +17,22 @@
{% if perms.dcim.change_devicebay %} - - {% endif %} {% if perms.dcim.delete_devicebay %} - {% endif %}
{% if perms.dcim.add_devicebay %} diff --git a/netbox/templates/dcim/devicetype/base.html b/netbox/templates/dcim/devicetype/base.html index a06886de5..b3c161002 100644 --- a/netbox/templates/dcim/devicetype/base.html +++ b/netbox/templates/dcim/devicetype/base.html @@ -18,28 +18,28 @@
@@ -53,66 +53,66 @@ - {% with interface_count=object.interfacetemplates.count %} - {% if interface_count %} + {% with tab_name='interface-templates' interface_count=object.interfacetemplates.count %} + {% if active_tab == tab_name or interface_count %} {% endif %} {% endwith %} - {% with frontport_count=object.frontporttemplates.count %} - {% if frontport_count %} + {% with tab_name='front-port-templates' frontport_count=object.frontporttemplates.count %} + {% if active_tab == tab_name or frontport_count %} {% endif %} {% endwith %} - {% with rearport_count=object.rearporttemplates.count %} - {% if rearport_count %} + {% with tab_name='rear-port-templates' rearport_count=object.rearporttemplates.count %} + {% if active_tab == tab_name or rearport_count %} {% endif %} {% endwith %} - {% with consoleport_count=object.consoleporttemplates.count %} - {% if consoleport_count %} + {% with tab_name='console-port-templates' consoleport_count=object.consoleporttemplates.count %} + {% if active_tab == tab_name or consoleport_count %} {% endif %} {% endwith %} - {% with consoleserverport_count=object.consoleserverporttemplates.count %} - {% if consoleserverport_count %} + {% with tab_name='console-server-port-templates' consoleserverport_count=object.consoleserverporttemplates.count %} + {% if active_tab == tab_name or consoleserverport_count %} {% endif %} {% endwith %} - {% with powerport_count=object.powerporttemplates.count %} - {% if powerport_count %} + {% with tab_name='power-port-templates' powerport_count=object.powerporttemplates.count %} + {% if active_tab == tab_name or powerport_count %} {% endif %} {% endwith %} - {% with poweroutlet_count=object.poweroutlettemplates.count %} - {% if poweroutlet_count %} + {% with tab_name='power-outlet-templates' poweroutlet_count=object.poweroutlettemplates.count %} + {% if active_tab == tab_name or poweroutlet_count %} {% endif %} {% endwith %} - {% with devicebay_count=object.devicebaytemplates.count %} - {% if devicebay_count %} + {% with tab_name='device-bay-templates' devicebay_count=object.devicebaytemplates.count %} + {% if active_tab == tab_name or devicebay_count %} {% endif %} {% endwith %} diff --git a/netbox/templates/dcim/devicetype/component_templates.html b/netbox/templates/dcim/devicetype/component_templates.html index b1e0daf78..002a2044b 100644 --- a/netbox/templates/dcim/devicetype/component_templates.html +++ b/netbox/templates/dcim/devicetype/component_templates.html @@ -13,18 +13,18 @@
- {{ form.initial.device }} - {{ form.initial.virtual_machine }}
{% render_field form.device %}
From 7ba45b28873a24133cbee625984f2556476ba3fd Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 10:48:10 -0500 Subject: [PATCH 12/45] Clean up imports --- netbox/dcim/models/__init__.py | 39 -------------------------------- netbox/dcim/views.py | 8 +------ netbox/extras/api/serializers.py | 6 ++--- 3 files changed, 4 insertions(+), 49 deletions(-) diff --git a/netbox/dcim/models/__init__.py b/netbox/dcim/models/__init__.py index 58a3e1de5..d74f34828 100644 --- a/netbox/dcim/models/__init__.py +++ b/netbox/dcim/models/__init__.py @@ -5,42 +5,3 @@ from .devices import * from .power import * from .racks import * from .sites import * - -__all__ = ( - 'BaseInterface', - 'Cable', - 'CablePath', - 'LinkTermination', - 'ConsolePort', - 'ConsolePortTemplate', - 'ConsoleServerPort', - 'ConsoleServerPortTemplate', - 'Device', - 'DeviceBay', - 'DeviceBayTemplate', - 'DeviceRole', - 'DeviceType', - 'FrontPort', - 'FrontPortTemplate', - 'Interface', - 'InterfaceTemplate', - 'InventoryItem', - 'Location', - 'Manufacturer', - 'Platform', - 'PowerFeed', - 'PowerOutlet', - 'PowerOutletTemplate', - 'PowerPanel', - 'PowerPort', - 'PowerPortTemplate', - 'Rack', - 'RackReservation', - 'RackRole', - 'RearPort', - 'RearPortTemplate', - 'Region', - 'Site', - 'SiteGroup', - 'VirtualChassis', -) diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 5c5b6b8d3..7048ae63e 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -27,13 +27,7 @@ from virtualization.models import VirtualMachine from . import filtersets, forms, tables from .choices import DeviceFaceChoices from .constants import NONCONNECTABLE_IFACE_TYPES -from .models import ( - Cable, CablePath, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, - DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate, - InventoryItem, Manufacturer, PathEndpoint, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, - PowerPort, PowerPortTemplate, Rack, Location, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site, - SiteGroup, VirtualChassis, -) +from .models import * class DeviceComponentsView(generic.ObjectChildrenView): diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py index 1be187596..9e4665cc2 100644 --- a/netbox/extras/api/serializers.py +++ b/netbox/extras/api/serializers.py @@ -5,10 +5,10 @@ from drf_yasg.utils import swagger_serializer_method from rest_framework import serializers from dcim.api.nested_serializers import ( - NestedDeviceSerializer, NestedDeviceRoleSerializer, NestedDeviceTypeSerializer, NestedPlatformSerializer, - NestedRackSerializer, NestedRegionSerializer, NestedSiteSerializer, NestedSiteGroupSerializer, + NestedDeviceRoleSerializer, NestedDeviceTypeSerializer, NestedPlatformSerializer, NestedRegionSerializer, + NestedSiteSerializer, NestedSiteGroupSerializer, ) -from dcim.models import Device, DeviceRole, DeviceType, Platform, Rack, Region, Site, SiteGroup +from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup from extras.choices import * from extras.models import * from extras.utils import FeatureQuery From f2f10dff929cd71a244173910c969fc953e19b09 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 10:57:46 -0500 Subject: [PATCH 13/45] Fix RearPortTemplateTable buttons --- netbox/dcim/tables/devicetypes.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/netbox/dcim/tables/devicetypes.py b/netbox/dcim/tables/devicetypes.py index 4df1dec71..0aa8ac2bf 100644 --- a/netbox/dcim/tables/devicetypes.py +++ b/netbox/dcim/tables/devicetypes.py @@ -190,7 +190,8 @@ class FrontPortTemplateTable(ComponentTemplateTable): class RearPortTemplateTable(ComponentTemplateTable): color = ColorColumn() actions = ButtonsColumn( - model=RearPortTemplate + model=RearPortTemplate, + buttons=('edit', 'delete') ) class Meta(ComponentTemplateTable.Meta): From a0db10838b8f0a2abd875600af8a336b018d2066 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 11:09:30 -0500 Subject: [PATCH 14/45] Fixes #8131: Restore annotation of available IPs under prefix IPs view --- docs/release-notes/version-3.1.md | 1 + netbox/ipam/views.py | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 3b5c17e2e..a09b43400 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -5,6 +5,7 @@ ### Bug Fixes * [#7962](https://github.com/netbox-community/netbox/issues/7962) - Fix user menu under report/script result view +* [#8131](https://github.com/netbox-community/netbox/issues/8131) - Restore annotation of available IPs under prefix IPs view --- diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index cff845a7a..4a4aef28f 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -5,18 +5,18 @@ from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from dcim.filtersets import InterfaceFilterSet -from dcim.models import Device, Interface, Site +from dcim.models import Interface, Site from dcim.tables import SiteTable from netbox.views import generic from utilities.tables import paginate_table from utilities.utils import count_related from virtualization.filtersets import VMInterfaceFilterSet -from virtualization.models import VirtualMachine, VMInterface +from virtualization.models import VMInterface from . import filtersets, forms, tables from .constants import * from .models import * from .models import ASN -from .utils import add_requested_prefixes, add_available_vlans +from .utils import add_requested_prefixes, add_available_ipaddresses, add_available_vlans # @@ -502,6 +502,13 @@ class PrefixIPAddressesView(generic.ObjectChildrenView): def get_children(self, request, parent): return parent.get_child_ips().restrict(request.user, 'view') + def prep_table_data(self, request, queryset, parent): + show_available = bool(request.GET.get('show_available', 'true') == 'true') + if show_available: + return add_available_ipaddresses(parent.prefix, queryset, parent.is_pool) + + return queryset + def get_extra_context(self, request, instance): return { 'bulk_querystring': f"vrf_id={instance.vrf.pk if instance.vrf else '0'}&parent={instance.prefix}", From 39a0b15df4b93d6c3b6b19cc02752bc19cc173fa Mon Sep 17 00:00:00 2001 From: rizlas Date: Tue, 21 Dec 2021 17:15:54 +0100 Subject: [PATCH 15/45] Update netbox/dcim/api/views.py Test without decode_dict function Co-authored-by: Jeremy Stretch --- netbox/dcim/api/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 74f06c64f..03e7e51cc 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -501,7 +501,7 @@ class DeviceViewSet(ConfigContextQuerySetMixin, CustomFieldModelViewSet): response[method] = {'error': 'Only get_* NAPALM methods are supported'} continue try: - response[method] = decode_dict(getattr(d, method)(), decode_keys=False) + response[method] = getattr(d, method)() except NotImplementedError: response[method] = {'error': 'Method {} not implemented for NAPALM driver {}'.format(method, driver)} except Exception as e: From d275538116f8d2c7994e1bdd737b2ac94c7f050c Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 11:53:31 -0500 Subject: [PATCH 16/45] Changelog & cleanup for #7246, #8097 --- docs/release-notes/version-3.1.md | 2 ++ netbox/dcim/api/views.py | 4 ++-- netbox/utilities/utils.py | 39 ------------------------------- 3 files changed, 4 insertions(+), 41 deletions(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index a09b43400..9856544ba 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -4,7 +4,9 @@ ### Bug Fixes +* [#7246](https://github.com/netbox-community/netbox/issues/7246) - Don't attempt to URL-decode NAPALM response payloads * [#7962](https://github.com/netbox-community/netbox/issues/7962) - Fix user menu under report/script result view +* [#8097](https://github.com/netbox-community/netbox/issues/8097) - Fix styling of Markdown tables * [#8131](https://github.com/netbox-community/netbox/issues/8131) - Restore annotation of available IPs under prefix IPs view --- diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 03e7e51cc..5830396ce 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -15,14 +15,14 @@ from circuits.models import Circuit from dcim import filtersets from dcim.models import * from extras.api.views import ConfigContextQuerySetMixin, CustomFieldModelViewSet -from ipam.models import Prefix, VLAN, ASN +from ipam.models import Prefix, VLAN from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired from netbox.api.exceptions import ServiceUnavailable from netbox.api.metadata import ContentTypeMetadata from netbox.api.views import ModelViewSet from netbox.config import get_config from utilities.api import get_serializer_for_model -from utilities.utils import count_related, decode_dict +from utilities.utils import count_related from virtualization.models import VirtualMachine from . import serializers from .exceptions import MissingFilterException diff --git a/netbox/utilities/utils.py b/netbox/utilities/utils.py index 3234135fb..ce1f6a111 100644 --- a/netbox/utilities/utils.py +++ b/netbox/utilities/utils.py @@ -288,45 +288,6 @@ def flatten_dict(d, prefix='', separator='.'): return ret -def decode_dict(encoded_dict: Dict, *, decode_keys: bool = True) -> Dict: - """ - Recursively URL decode string keys and values of a dict. - - For example, `{'1%2F1%2F1': {'1%2F1%2F2': ['1%2F1%2F3', '1%2F1%2F4']}}` would - become: `{'1/1/1': {'1/1/2': ['1/1/3', '1/1/4']}}` - - :param encoded_dict: Dictionary to be decoded. - :param decode_keys: (Optional) Enable/disable decoding of dict keys. - """ - - def decode_value(value: Any, _decode_keys: bool) -> Any: - """ - Handle URL decoding of any supported value type. - """ - # Decode string values. - if isinstance(value, str): - return urllib.parse.unquote(value) - # Recursively decode each list item. - elif isinstance(value, list): - return [decode_value(v, _decode_keys) for v in value] - # Recursively decode each tuple item. - elif isinstance(value, Tuple): - return tuple(decode_value(v, _decode_keys) for v in value) - # Recursively decode each dict key/value pair. - elif isinstance(value, dict): - # Don't decode keys, if `decode_keys` is false. - if not _decode_keys: - return {k: decode_value(v, _decode_keys) for k, v in value.items()} - return {urllib.parse.unquote(k): decode_value(v, _decode_keys) for k, v in value.items()} - return value - - if not decode_keys: - # Don't decode keys, if `decode_keys` is false. - return {k: decode_value(v, decode_keys) for k, v in encoded_dict.items()} - - return {urllib.parse.unquote(k): decode_value(v, decode_keys) for k, v in encoded_dict.items()} - - def array_to_string(array): """ Generate an efficient, human-friendly string from a set of integers. Intended for use with ArrayField. From ceb941df811a32bbc18b84d701f3a7fd738ff921 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 13:00:52 -0500 Subject: [PATCH 17/45] Closes #8135: Append version when fetching static assets --- netbox/templates/base/base.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/netbox/templates/base/base.html b/netbox/templates/base/base.html index 50bf7133c..6e71b3995 100644 --- a/netbox/templates/base/base.html +++ b/netbox/templates/base/base.html @@ -104,23 +104,23 @@ {# Static resources #} @@ -129,7 +129,7 @@ {# Javascript #} From 8e95ac42c2bdb27f627e92a2cef5a3eab0257c47 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 13:05:38 -0500 Subject: [PATCH 18/45] Closes #8100: Add "other" choice for FHRP group protocol --- docs/release-notes/version-3.1.md | 4 ++++ netbox/ipam/choices.py | 2 ++ 2 files changed, 6 insertions(+) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 9856544ba..ad69b73b0 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -2,6 +2,10 @@ ## v3.1.3 (FUTURE) +### Enhancements + +* [#8100](https://github.com/netbox-community/netbox/issues/8100) - Add "other" choice for FHRP group protocol + ### Bug Fixes * [#7246](https://github.com/netbox-community/netbox/issues/7246) - Don't attempt to URL-decode NAPALM response payloads diff --git a/netbox/ipam/choices.py b/netbox/ipam/choices.py index 638ef62f6..526ef07d9 100644 --- a/netbox/ipam/choices.py +++ b/netbox/ipam/choices.py @@ -135,6 +135,7 @@ class FHRPGroupProtocolChoices(ChoiceSet): PROTOCOL_HSRP = 'hsrp' PROTOCOL_GLBP = 'glbp' PROTOCOL_CARP = 'carp' + PROTOCOL_OTHER = 'other' CHOICES = ( (PROTOCOL_VRRP2, 'VRRPv2'), @@ -142,6 +143,7 @@ class FHRPGroupProtocolChoices(ChoiceSet): (PROTOCOL_HSRP, 'HSRP'), (PROTOCOL_GLBP, 'GLBP'), (PROTOCOL_CARP, 'CARP'), + (PROTOCOL_OTHER, 'Other'), ) From 373cc74a338c5c182cdeed8bdc16744f4a0e3518 Mon Sep 17 00:00:00 2001 From: thatmattlove Date: Tue, 21 Dec 2021 11:11:33 -0700 Subject: [PATCH 19/45] Fixes #8134: reinitialize event listeners when HTMX swaps elements --- docs/release-notes/version-3.1.md | 1 + netbox/project-static/dist/netbox.js | Bin 374756 -> 374954 bytes netbox/project-static/dist/netbox.js.map | Bin 344228 -> 344416 bytes netbox/project-static/src/htmx.ts | 23 +++++++++++++++++++++++ netbox/project-static/src/netbox.ts | 2 ++ 5 files changed, 26 insertions(+) create mode 100644 netbox/project-static/src/htmx.ts diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index ad69b73b0..5ff6ea1bb 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -5,6 +5,7 @@ ### Enhancements * [#8100](https://github.com/netbox-community/netbox/issues/8100) - Add "other" choice for FHRP group protocol +* [#8134](https://github.com/netbox-community/netbox/issues/8134) - Fix issue where HTMX-swapped UI elements needed to be reinitialized ### Bug Fixes diff --git a/netbox/project-static/dist/netbox.js b/netbox/project-static/dist/netbox.js index 95fd99270f6418fc224d471cf1054aa65323fd0b..c15316ce806af857ea5c84e8f2596fc225e5f072 100644 GIT binary patch delta 31115 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 delta 30966 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 diff --git a/netbox/project-static/dist/netbox.js.map b/netbox/project-static/dist/netbox.js.map index 6fbe0874b1025b63008a8cc41168eb25890d4295..ebab0d3a7ab270fc60f314a51f3a5809be939a9d 100644 GIT binary patch delta 185 zcmZ3|DEgpDbi-GBmW-0zist9`?a%EQftU%1nYTZ;XW90jKS19}C(+R{(^<#a(OKVV zdY~MuIHzNvJ4n#LX?lSwtH|`ZDy$r_K*yE?QXUBs1KI?X_SeaD0_)EOQu$6g-p+0XF4Gs-v&Kz-V9&}r J{hvMSG5}o8Iu8H< delta 49 zcmaFRB)X(gbi-HsW_E{mb_YfvW&&d7?d%RLEB-Tk>pM*kcVLa1uAsuoHvNDD>jD6% CyASIC diff --git a/netbox/project-static/src/htmx.ts b/netbox/project-static/src/htmx.ts new file mode 100644 index 000000000..70ed4f534 --- /dev/null +++ b/netbox/project-static/src/htmx.ts @@ -0,0 +1,23 @@ +import { getElements, isTruthy } from './util'; +import { initButtons } from './buttons'; + +function initDepedencies(): void { + for (const init of [initButtons]) { + init(); + } +} + +/** + * Hook into HTMX's event system to reinitialize specific native event listeners when HTMX swaps + * elements. + */ +export function initHtmx(): void { + for (const element of getElements('[hx-target]')) { + const targetSelector = element.getAttribute('hx-target'); + if (isTruthy(targetSelector)) { + for (const target of getElements(targetSelector)) { + target.addEventListener('htmx:afterSettle', initDepedencies); + } + } + } +} diff --git a/netbox/project-static/src/netbox.ts b/netbox/project-static/src/netbox.ts index 79c196b96..c178a2dbd 100644 --- a/netbox/project-static/src/netbox.ts +++ b/netbox/project-static/src/netbox.ts @@ -12,6 +12,7 @@ import { initInterfaceTable } from './tables'; import { initSideNav } from './sidenav'; import { initRackElevation } from './racks'; import { initLinks } from './links'; +import { initHtmx } from './htmx'; function initDocument(): void { for (const init of [ @@ -29,6 +30,7 @@ function initDocument(): void { initSideNav, initRackElevation, initLinks, + initHtmx, ]) { init(); } From 344fb638fd11ce97b35f4b0365bfa16a24d7711d Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 13:17:54 -0500 Subject: [PATCH 20/45] Fixes #8127: Fix disassociation of interface under IP address edit view --- docs/release-notes/version-3.1.md | 3 ++- netbox/ipam/forms/models.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 5ff6ea1bb..2128abdb6 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -5,14 +5,15 @@ ### Enhancements * [#8100](https://github.com/netbox-community/netbox/issues/8100) - Add "other" choice for FHRP group protocol -* [#8134](https://github.com/netbox-community/netbox/issues/8134) - Fix issue where HTMX-swapped UI elements needed to be reinitialized ### Bug Fixes * [#7246](https://github.com/netbox-community/netbox/issues/7246) - Don't attempt to URL-decode NAPALM response payloads * [#7962](https://github.com/netbox-community/netbox/issues/7962) - Fix user menu under report/script result view * [#8097](https://github.com/netbox-community/netbox/issues/8097) - Fix styling of Markdown tables +* [#8127](https://github.com/netbox-community/netbox/issues/8127) - Fix disassociation of interface under IP address edit view * [#8131](https://github.com/netbox-community/netbox/issues/8131) - Restore annotation of available IPs under prefix IPs view +* [#8134](https://github.com/netbox-community/netbox/issues/8134) - Fix bulk editing of objects within dynamic tables --- diff --git a/netbox/ipam/forms/models.py b/netbox/ipam/forms/models.py index 319d8671e..c5e3146e9 100644 --- a/netbox/ipam/forms/models.py +++ b/netbox/ipam/forms/models.py @@ -471,6 +471,8 @@ class IPAddressForm(TenancyForm, CustomFieldModelForm): }) elif selected_objects: self.instance.assigned_object = self.cleaned_data[selected_objects[0]] + else: + self.instance.assigned_object = None # Primary IP assignment is only available if an interface has been assigned. interface = self.cleaned_data.get('interface') or self.cleaned_data.get('vminterface') From f1350a10229ee30dd57e37651d5c633858528c1c Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 13:57:12 -0500 Subject: [PATCH 21/45] FIxes #7972: Standardize name of RemoteUserBackend logger --- docs/release-notes/version-3.1.md | 1 + netbox/netbox/authentication.py | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 2128abdb6..5d445959e 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -10,6 +10,7 @@ * [#7246](https://github.com/netbox-community/netbox/issues/7246) - Don't attempt to URL-decode NAPALM response payloads * [#7962](https://github.com/netbox-community/netbox/issues/7962) - Fix user menu under report/script result view +* [#7972](https://github.com/netbox-community/netbox/issues/7972) - Standardize name of `RemoteUserBackend` logger * [#8097](https://github.com/netbox-community/netbox/issues/8097) - Fix styling of Markdown tables * [#8127](https://github.com/netbox-community/netbox/issues/8127) - Fix disassociation of interface under IP address edit view * [#8131](https://github.com/netbox-community/netbox/issues/8131) - Restore annotation of available IPs under prefix IPs view diff --git a/netbox/netbox/authentication.py b/netbox/netbox/authentication.py index a67ec451d..acb04ce34 100644 --- a/netbox/netbox/authentication.py +++ b/netbox/netbox/authentication.py @@ -105,7 +105,7 @@ class RemoteUserBackend(_RemoteUserBackend): return settings.REMOTE_AUTH_AUTO_CREATE_USER def configure_groups(self, user, remote_groups): - logger = logging.getLogger('netbox.authentication.RemoteUserBackend') + logger = logging.getLogger('netbox.auth.RemoteUserBackend') # Assign default groups to the user group_list = [] @@ -141,7 +141,7 @@ class RemoteUserBackend(_RemoteUserBackend): Return None if ``create_unknown_user`` is ``False`` and a ``User`` object with the given username is not found in the database. """ - logger = logging.getLogger('netbox.authentication.RemoteUserBackend') + logger = logging.getLogger('netbox.auth.RemoteUserBackend') logger.debug( f"trying to authenticate {remote_user} with groups {remote_groups}") if not remote_user: @@ -173,7 +173,7 @@ class RemoteUserBackend(_RemoteUserBackend): return None def _is_superuser(self, user): - logger = logging.getLogger('netbox.authentication.RemoteUserBackend') + logger = logging.getLogger('netbox.auth.RemoteUserBackend') superuser_groups = settings.REMOTE_AUTH_SUPERUSER_GROUPS logger.debug(f"Superuser Groups: {superuser_groups}") superusers = settings.REMOTE_AUTH_SUPERUSERS @@ -189,7 +189,7 @@ class RemoteUserBackend(_RemoteUserBackend): return bool(result) def _is_staff(self, user): - logger = logging.getLogger('netbox.authentication.RemoteUserBackend') + logger = logging.getLogger('netbox.auth.RemoteUserBackend') staff_groups = settings.REMOTE_AUTH_STAFF_GROUPS logger.debug(f"Superuser Groups: {staff_groups}") staff_users = settings.REMOTE_AUTH_STAFF_USERS @@ -204,7 +204,7 @@ class RemoteUserBackend(_RemoteUserBackend): return bool(result) def configure_user(self, request, user): - logger = logging.getLogger('netbox.authentication.RemoteUserBackend') + logger = logging.getLogger('netbox.auth.RemoteUserBackend') if not settings.REMOTE_AUTH_GROUP_SYNC_ENABLED: # Assign default groups to the user group_list = [] From d4b6fe14c3212f7c9e67e313dc655bd6c1d1de51 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 14:04:15 -0500 Subject: [PATCH 22/45] Fixes #8138: Fix alignment of tags panel within IP address view --- netbox/templates/ipam/ipaddress.html | 254 +++++++++++++-------------- 1 file changed, 123 insertions(+), 131 deletions(-) diff --git a/netbox/templates/ipam/ipaddress.html b/netbox/templates/ipam/ipaddress.html index 624735a95..cb1281e53 100644 --- a/netbox/templates/ipam/ipaddress.html +++ b/netbox/templates/ipam/ipaddress.html @@ -13,143 +13,135 @@ {% block content %}
-
-
- IP Address -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FamilyIPv{{ object.family }}
VRF - {% if object.vrf %} - {{ object.vrf }} - {% else %} - Global - {% endif %} -
Tenant - {% if object.tenant %} - {% if object.tenant.group %} - {{ object.tenant.group }} / - {% endif %} - {{ object.tenant }} - {% else %} - None - {% endif %} -
Status - {{ object.get_status_display }} -
Role - {% if object.role %} - {{ object.get_role_display }} - {% else %} - None - {% endif %} -
DNS Name{{ object.dns_name|placeholder }}
Description{{ object.description|placeholder }}
Assignment - {% if object.assigned_object %} - {% if object.assigned_object.parent_object %} - {{ object.assigned_object.parent_object }} / - {% endif %} - {{ object.assigned_object }} +
+
+ IP Address +
+
+ + + + + + + + - - - - - - - - - -
FamilyIPv{{ object.family }}
VRF + {% if object.vrf %} + {{ object.vrf }} {% else %} - + Global {% endif %} -
NAT (inside) - {% if object.nat_inside %} - {{ object.nat_inside }} - {% if object.nat_inside.assigned_object %} - ({{ object.nat_inside.assigned_object.parent_object }}) - {% endif %} - {% else %} - None - {% endif %} -
NAT (outside) - {% if object.nat_outside %} - {{ object.nat_outside }} - {% else %} - None - {% endif %} -
-
-
- {% include 'inc/panels/custom_fields.html' %} - - {% plugin_left_page object %} - - -
Tenant + {% if object.tenant %} + {% if object.tenant.group %} + {{ object.tenant.group }} / + {% endif %} + {{ object.tenant }} + {% else %} + None + {% endif %} +
Status + {{ object.get_status_display }} +
Role + {% if object.role %} + {{ object.get_role_display }} + {% else %} + None + {% endif %} +
DNS Name{{ object.dns_name|placeholder }}
Description{{ object.description|placeholder }}
Assignment + {% if object.assigned_object %} + {% if object.assigned_object.parent_object %} + {{ object.assigned_object.parent_object }} / + {% endif %} + {{ object.assigned_object }} {% else %} - href="{% url 'ipam:ipaddress_list' %}?address={{ object.address.ip }}&vrf_id=null" + {% endif %} - >Show all - - {% endif %} - -
- {% render_table duplicate_ips_table 'inc/table.html' %} -
- - {% endif %} -
- {% include 'inc/panel_table.html' with table=related_ips_table heading='Related IP Addresses' %} -
- {% plugin_right_page object %} +
NAT (inside) + {% if object.nat_inside %} + {{ object.nat_inside }} + {% if object.nat_inside.assigned_object %} + ({{ object.nat_inside.assigned_object.parent_object }}) + {% endif %} + {% else %} + None + {% endif %} +
NAT (outside) + {% if object.nat_outside %} + {{ object.nat_outside }} + {% else %} + None + {% endif %} +
+
+
+ {% include 'inc/panels/tags.html' %} + {% include 'inc/panels/custom_fields.html' %} + {% plugin_left_page object %}
-
- -
-
- {% include 'inc/panels/tags.html' %} +
+ {% include 'inc/panel_table.html' with table=parent_prefixes_table heading='Parent Prefixes' %} + {% if duplicate_ips_table.rows %} + {# Custom version of panel_table.html #} +
+
+ Duplicate IP Addresses + {% if more_duplicate_ips %} +
+ Show all +
+ {% endif %} +
+
+ {% render_table duplicate_ips_table 'inc/table.html' %} +
+
+ {% endif %} +
+ {% include 'inc/panel_table.html' with table=related_ips_table heading='Related IP Addresses' %}
- + {% plugin_right_page object %} +
From 275560698fefe079421a9d549602a8e1fd4c1a07 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Dec 2021 14:10:12 -0500 Subject: [PATCH 23/45] Fixes #8139: Fix rendering of table configuration form under VM interfaces view --- docs/release-notes/version-3.1.md | 1 + netbox/templates/virtualization/virtualmachine/interfaces.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 5d445959e..40abe7e15 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -15,6 +15,7 @@ * [#8127](https://github.com/netbox-community/netbox/issues/8127) - Fix disassociation of interface under IP address edit view * [#8131](https://github.com/netbox-community/netbox/issues/8131) - Restore annotation of available IPs under prefix IPs view * [#8134](https://github.com/netbox-community/netbox/issues/8134) - Fix bulk editing of objects within dynamic tables +* [#8139](https://github.com/netbox-community/netbox/issues/8139) - Fix rendering of table configuration form under VM interfaces view --- diff --git a/netbox/templates/virtualization/virtualmachine/interfaces.html b/netbox/templates/virtualization/virtualmachine/interfaces.html index cbfec8172..6b3e70c7f 100644 --- a/netbox/templates/virtualization/virtualmachine/interfaces.html +++ b/netbox/templates/virtualization/virtualmachine/interfaces.html @@ -5,7 +5,7 @@ {% block content %}
{% csrf_token %} - {% include 'inc/table_controls_htmx.html' with table_modal="VMInterfaceTable_config" %} + {% include 'inc/table_controls_htmx.html' with table_modal="VirtualMachineVMInterfaceTable_config" %}
From fb4511d09963e7b86809d0e3511bb290d2531fa8 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 22 Dec 2021 10:55:06 -0500 Subject: [PATCH 24/45] Fixes #8140: Restore missing fields on wireless LAN & link REST API serializers --- docs/release-notes/version-3.1.md | 1 + netbox/wireless/api/serializers.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 40abe7e15..618da9411 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -16,6 +16,7 @@ * [#8131](https://github.com/netbox-community/netbox/issues/8131) - Restore annotation of available IPs under prefix IPs view * [#8134](https://github.com/netbox-community/netbox/issues/8134) - Fix bulk editing of objects within dynamic tables * [#8139](https://github.com/netbox-community/netbox/issues/8139) - Fix rendering of table configuration form under VM interfaces view +* [#8140](https://github.com/netbox-community/netbox/issues/8140) - Restore missing fields on wireless LAN & link REST API serializers --- diff --git a/netbox/wireless/api/serializers.py b/netbox/wireless/api/serializers.py index 68e8181f1..f1fa6d58d 100644 --- a/netbox/wireless/api/serializers.py +++ b/netbox/wireless/api/serializers.py @@ -40,6 +40,7 @@ class WirelessLANSerializer(PrimaryModelSerializer): model = WirelessLAN fields = [ 'id', 'url', 'display', 'ssid', 'description', 'group', 'vlan', 'auth_type', 'auth_cipher', 'auth_psk', + 'description', 'tags', 'custom_fields', 'created', 'last_updated', ] @@ -55,5 +56,5 @@ class WirelessLinkSerializer(PrimaryModelSerializer): model = WirelessLink fields = [ 'id', 'url', 'display', 'interface_a', 'interface_b', 'ssid', 'status', 'description', 'auth_type', - 'auth_cipher', 'auth_psk', + 'auth_cipher', 'auth_psk', 'description', 'tags', 'custom_fields', 'created', 'last_updated', ] From 0a7372460f6751f921804222555efb04dce7edfb Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 22 Dec 2021 12:48:24 -0500 Subject: [PATCH 25/45] Changelog for #7887 --- docs/release-notes/version-3.1.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 618da9411..c748bff14 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -9,6 +9,7 @@ ### Bug Fixes * [#7246](https://github.com/netbox-community/netbox/issues/7246) - Don't attempt to URL-decode NAPALM response payloads +* [#7887](https://github.com/netbox-community/netbox/issues/7887) - Forward `HTTP_X_FORWARDED_FOR` to custom scripts * [#7962](https://github.com/netbox-community/netbox/issues/7962) - Fix user menu under report/script result view * [#7972](https://github.com/netbox-community/netbox/issues/7972) - Standardize name of `RemoteUserBackend` logger * [#8097](https://github.com/netbox-community/netbox/issues/8097) - Fix styling of Markdown tables From 37065b7c504976ba76d887bad60797c6dcff995b Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 22 Dec 2021 14:47:42 -0500 Subject: [PATCH 26/45] Remove obsolete template --- netbox/templates/inc/plugin_menu_items.html | 30 --------------------- 1 file changed, 30 deletions(-) delete mode 100644 netbox/templates/inc/plugin_menu_items.html diff --git a/netbox/templates/inc/plugin_menu_items.html b/netbox/templates/inc/plugin_menu_items.html deleted file mode 100644 index b6e5e18a1..000000000 --- a/netbox/templates/inc/plugin_menu_items.html +++ /dev/null @@ -1,30 +0,0 @@ -{% load helpers %} - From f369b5f588ad29d9de0f36cfdce586bd3769e7eb Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 22 Dec 2021 15:05:24 -0500 Subject: [PATCH 27/45] Reorganize & clean up templatetag templates --- netbox/templates/base/layout.html | 3 +- netbox/templates/base/sidenav.html | 2 +- netbox/templates/home.html | 1 - .../form_helpers}/render_custom_fields.html | 0 .../form_helpers}/render_errors.html | 0 .../templates/form_helpers}/render_field.html | 0 .../templates/form_helpers}/render_form.html | 0 .../templates/helpers}/applied_filters.html | 0 .../templates/helpers}/badge.html | 0 .../templates/helpers}/table_config_form.html | 0 .../templates/helpers}/tag.html | 0 .../templates/helpers}/utilization_graph.html | 0 .../navigation/{nav_items.html => menu.html} | 0 netbox/utilities/templatetags/form_helpers.py | 74 ++++++++++--------- netbox/utilities/templatetags/get_status.py | 21 ------ netbox/utilities/templatetags/helpers.py | 10 +-- .../templatetags/{nav.py => navigation.py} | 2 +- .../{search_options.py => search.py} | 0 18 files changed, 49 insertions(+), 64 deletions(-) rename netbox/{templates/utilities => utilities/templates/form_helpers}/render_custom_fields.html (100%) rename netbox/{templates/utilities => utilities/templates/form_helpers}/render_errors.html (100%) rename netbox/{templates/utilities => utilities/templates/form_helpers}/render_field.html (100%) rename netbox/{templates/utilities => utilities/templates/form_helpers}/render_form.html (100%) rename netbox/{templates/utilities/templatetags => utilities/templates/helpers}/applied_filters.html (100%) rename netbox/{templates/utilities/templatetags => utilities/templates/helpers}/badge.html (100%) rename netbox/{templates/utilities/templatetags => utilities/templates/helpers}/table_config_form.html (100%) rename netbox/{templates/utilities/templatetags => utilities/templates/helpers}/tag.html (100%) rename netbox/{templates/utilities/templatetags => utilities/templates/helpers}/utilization_graph.html (100%) rename netbox/utilities/templates/navigation/{nav_items.html => menu.html} (100%) delete mode 100644 netbox/utilities/templatetags/get_status.py rename netbox/utilities/templatetags/{nav.py => navigation.py} (81%) rename netbox/utilities/templatetags/{search_options.py => search.py} (100%) diff --git a/netbox/templates/base/layout.html b/netbox/templates/base/layout.html index 38c1dc21b..d6a21c2b5 100644 --- a/netbox/templates/base/layout.html +++ b/netbox/templates/base/layout.html @@ -1,8 +1,7 @@ {# Base layout for the core NetBox UI w/navbar and page content #} {% extends 'base/base.html' %} {% load helpers %} -{% load nav %} -{% load search_options %} +{% load search %} {% load static %} {% block layout %} diff --git a/netbox/templates/base/sidenav.html b/netbox/templates/base/sidenav.html index 5790e8c44..1df20e6de 100644 --- a/netbox/templates/base/sidenav.html +++ b/netbox/templates/base/sidenav.html @@ -1,4 +1,4 @@ -{% load nav %} +{% load navigation %} {% load static %}