diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..809b1d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Tools # +######### +update.sh +xcode_install.sh + +# Non source files # +################### + +build/ +bower_components/ +.sass-cache +*.pyc +log/ +old/ +.idea/ + diff --git a/LICENSE b/LICENSE index 4456a1b..6d9c487 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,6 @@ -# docs +# OPNsense documentation +The documentation is licensed under a 2-clause BSD Licnse: + Copyright (c) Deciso B.V. Copyright (c) 2017-2018 Fabian Franz Copyright (c) 2017-2018 Michael Muenz @@ -28,3 +30,14 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Pictures +Some pictures are licensed under the Creative Commons Zero (CC0) license: + +https://creativecommons.org/publicdomain/zero/1.0/ + +# Logo's +Logo's may be subject to additional copyrights, property +rights, trademarks etc. and may require the consent of a third party or the +license of these rights. Deciso B.V. does not represent or make any warranties +that it owns or licenses any of the mentioned, nor does it grant them. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4b4b074 --- /dev/null +++ b/Makefile @@ -0,0 +1,219 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + +.PHONY: html +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +.PHONY: html-fallback +html-fallback: + python3 /usr/bin/sphinx-build -b html source build +.PHONY: dirhtml +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +.PHONY: singlehtml +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +.PHONY: pickle +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +.PHONY: json +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +.PHONY: htmlhelp +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +.PHONY: qthelp +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OPNsense.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OPNsense.qhc" + +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/OPNsense" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OPNsense" + @echo "# devhelp" + +.PHONY: epub +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +.PHONY: latex +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +.PHONY: latexpdf +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +.PHONY: man +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +.PHONY: texinfo +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +.PHONY: info +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +.PHONY: gettext +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +.PHONY: changes +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +.PHONY: linkcheck +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +.PHONY: doctest +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/README.md b/README.md index bbed289..f4e8b15 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,15 @@ -# docs -OPNsense documentation -====================== -The OPNsense project invites developers and users to start -contributing to the documentation. +![alt text](https://opnsense.org/wp-content/themes/OPNsense/assets/img/opnsense.png "Logo Title Text 1") -Contribute -========== +# OPNsense documentation +Welcome to the OPNsense documentation & wiki. +The purpose of this project is to provide OPNsense users with quality documentation. +## Contribute You can contribute to the project in many ways, e.g. testing functionality, sending in bug reports or creating pull requests directly via GitHub. Any help is always very welcome! -License -======= +## License OPNsense documentation is available under the 2-Clause BSD license: http://opensource.org/licenses/BSD-2-Clause @@ -24,3 +21,49 @@ for everybody. Some pictures are licensed under the Creative Commons Zero (CC0) license: https://creativecommons.org/publicdomain/zero/1.0/ + +Logo's may be subject to additional copyrights, property +rights, trademarks etc. and may require the consent of a third party or the +license of these rights. Deciso B.V. does not represent or make any warranties +that it owns or licenses any of the mentioned, nor does it grant them. + +#### Prepare build +Install Sphinx, our default theme and contrib packages +``` +pip install -r requirements.txt +``` + + +#### Generate HTML documents +``` +make html +``` + +(```make clean``` to flush) + + +#### Changing theme +* Install Sass (http://sass-lang.com/), on OSX via ```/Library/Ruby/Gems``` +``` +gem install --no-user-install sass +``` +* Install npm (https://www.npmjs.com/get-npm) +* Install Bower (https://bower.io/) +``` +npm install -g bower +``` + + +Install required stylesheets using bower +``` +bower install wyrm +bower install robotoslab-googlefont +bower install inconsolata-googlefont +bower install font-awesome +``` +(for font-awesome, choose newest) + + +#### Build your theme: +``` +sass -I bower_components/wyrm/sass/ -I bower_components/bourbon/dist/ -I bower_components/neat/app/assets/stylesheets/ -I bower_components/font-awesome/scss/ themes/opnsense/sass/theme.sass > source/_static/css/opnsense.css diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a80cf25 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +sphinx +sphinx_rtd_theme +sphinxcontrib-blockdiag +sphinxcontrib-nwdiag +sphinxcontrib-seqdiag +sphinxcontrib-actdiag +sphinxcontrib-inheritance +blockdiagcontrib-cisco \ No newline at end of file diff --git a/source/_static/css/opnsense.css b/source/_static/css/opnsense.css new file mode 100644 index 0000000..6e8330a --- /dev/null +++ b/source/_static/css/opnsense.css @@ -0,0 +1,4697 @@ +@charset "UTF-8"; +.wy-side-nav-search > div.version { + color: #ffffff !important; } + +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + +article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { + display: block; } + +audio, canvas, video { + display: inline-block; + *display: inline; + *zoom: 1; } + +audio:not([controls]) { + display: none; } + +[hidden] { + display: none; } + +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; } + +body { + margin: 0; } + +a:hover, a:active { + outline: 0; } + +abbr[title] { + border-bottom: 1px dotted; } + +b, strong { + font-weight: bold; } + +blockquote { + margin: 0; } + +dfn { + font-style: italic; } + +ins { + background: #ff9; + color: #000; + text-decoration: none; } + +mark { + background: #ff0; + color: #000; + font-style: italic; + font-weight: bold; } + +pre, code, .rst-content tt, .rst-content code, kbd, samp { + font-family: monospace, serif; + _font-family: "courier new", monospace; + font-size: 1em; } + +pre { + white-space: pre; } + +q { + quotes: none; } + +q:before, q:after { + content: ""; + content: none; } + +small { + font-size: 85%; } + +sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +ul, ol, dl { + margin: 0; + padding: 0; + list-style: none; + list-style-image: none; } + +li { + list-style: none; } + +dd { + margin: 0; } + +img { + border: 0; + -ms-interpolation-mode: bicubic; + vertical-align: middle; + max-width: 100%; } + +svg:not(:root) { + overflow: hidden; } + +figure { + margin: 0; } + +form { + margin: 0; } + +fieldset { + border: 0; + margin: 0; + padding: 0; } + +label { + cursor: pointer; } + +legend { + border: 0; + *margin-left: -7px; + padding: 0; + white-space: normal; } + +button, input, select, textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; } + +button, input { + line-height: normal; } + +button, input[type="button"], input[type="reset"], input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; + *overflow: visible; } + +button[disabled], input[disabled] { + cursor: default; } + +input[type="checkbox"], input[type="radio"] { + box-sizing: border-box; + padding: 0; + *width: 13px; + *height: 13px; } + +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; } + +input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; } + +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0; } + +textarea { + overflow: auto; + vertical-align: top; + resize: vertical; } + +table { + border-collapse: collapse; + border-spacing: 0; } + +td { + vertical-align: top; } + +.chromeframe { + margin: 0.2em 0; + background: #ccc; + color: black; + padding: 0.2em 0; } + +.ir { + display: block; + border: 0; + text-indent: -999em; + overflow: hidden; + background-color: transparent; + background-repeat: no-repeat; + text-align: left; + direction: ltr; + *line-height: 0; } + +.ir br { + display: none; } + +.hidden { + display: none !important; + visibility: hidden; } + +.visuallyhidden { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; } + +.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { + clip: auto; + height: auto; + margin: 0; + overflow: visible; + position: static; + width: auto; } + +.invisible { + visibility: hidden; } + +.relative { + position: relative; } + +big, small { + font-size: 100%; } + +@media print { + html, body, section { + background: none !important; } + + * { + box-shadow: none !important; + text-shadow: none !important; + filter: none !important; + -ms-filter: none !important; } + + a, a:visited { + text-decoration: underline; } + + .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { + content: ""; } + + pre, blockquote { + page-break-inside: avoid; } + + thead { + display: table-header-group; } + + tr, img { + page-break-inside: avoid; } + + img { + max-width: 100% !important; } + + @page { + margin: 0.5cm; } + p, h2, .rst-content .toctree-wrapper p.caption, h3 { + orphans: 3; + widows: 3; } + + h2, .rst-content .toctree-wrapper p.caption, h3 { + page-break-after: avoid; } } +.fa:before, .wy-menu-vertical li span.toctree-expand:before, .wy-menu-vertical li.on a span.toctree-expand:before, .wy-menu-vertical li.current > a span.toctree-expand:before, .rst-content .admonition-title:before, .rst-content h1 .headerlink:before, .rst-content h2 .headerlink:before, .rst-content h3 .headerlink:before, .rst-content h4 .headerlink:before, .rst-content h5 .headerlink:before, .rst-content h6 .headerlink:before, .rst-content dl dt .headerlink:before, .rst-content p.caption .headerlink:before, .rst-content tt.download span:first-child:before, .rst-content code.download span:first-child:before, .icon:before, .wy-dropdown .caret:before, .wy-inline-validate.wy-inline-validate-success .wy-input-context:before, .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before, .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .wy-input-context:before, .wy-alert, .rst-content .note, .rst-content .attention, .rst-content .caution, .rst-content .danger, .rst-content .error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .warning, .rst-content .seealso, .rst-content .admonition-todo, .btn, input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="date"], input[type="month"], input[type="time"], input[type="datetime"], input[type="datetime-local"], input[type="week"], input[type="number"], input[type="search"], input[type="tel"], input[type="color"], select, textarea, .wy-menu-vertical li.on a, .wy-menu-vertical li.current > a, .wy-side-nav-search > a, .wy-side-nav-search .wy-dropdown > a, .wy-nav-top a { + -webkit-font-smoothing: antialiased; } + +.clearfix { + *zoom: 1; } + .clearfix:before, .clearfix:after { + display: table; + content: ""; } + .clearfix:after { + clear: both; } + +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +/* FONT PATH + * -------------------------- */ +@font-face { + font-family: 'FontAwesome'; + src: url("../fonts/fontawesome-webfont.eot?v=4.7.0"); + src: url("../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0") format("embedded-opentype"), url("../fonts/fontawesome-webfont.woff2?v=4.7.0") format("woff2"), url("../fonts/fontawesome-webfont.woff?v=4.7.0") format("woff"), url("../fonts/fontawesome-webfont.ttf?v=4.7.0") format("truetype"), url("../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular") format("svg"); + font-weight: normal; + font-style: normal; } +.fa, .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.current > a span.toctree-expand, .rst-content .admonition-title, .rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink, .rst-content p.caption .headerlink, .rst-content tt.download span:first-child, .rst-content code.download span:first-child, .icon { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } + +/* makes the font 33% larger relative to the icon container */ +.fa-lg { + font-size: 1.33333em; + line-height: 0.75em; + vertical-align: -15%; } + +.fa-2x { + font-size: 2em; } + +.fa-3x { + font-size: 3em; } + +.fa-4x { + font-size: 4em; } + +.fa-5x { + font-size: 5em; } + +.fa-fw { + width: 1.28571em; + text-align: center; } + +.fa-ul { + padding-left: 0; + margin-left: 2.14286em; + list-style-type: none; } + .fa-ul > li { + position: relative; } + +.fa-li { + position: absolute; + left: -2.14286em; + width: 2.14286em; + top: 0.14286em; + text-align: center; } + .fa-li.fa-lg { + left: -1.85714em; } + +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eee; + border-radius: .1em; } + +.fa-pull-left { + float: left; } + +.fa-pull-right { + float: right; } + +.fa.fa-pull-left, .wy-menu-vertical li span.fa-pull-left.toctree-expand, .wy-menu-vertical li.on a span.fa-pull-left.toctree-expand, .wy-menu-vertical li.current > a span.fa-pull-left.toctree-expand, .rst-content .fa-pull-left.admonition-title, .rst-content h1 .fa-pull-left.headerlink, .rst-content h2 .fa-pull-left.headerlink, .rst-content h3 .fa-pull-left.headerlink, .rst-content h4 .fa-pull-left.headerlink, .rst-content h5 .fa-pull-left.headerlink, .rst-content h6 .fa-pull-left.headerlink, .rst-content dl dt .fa-pull-left.headerlink, .rst-content p.caption .fa-pull-left.headerlink, .rst-content tt.download span.fa-pull-left:first-child, .rst-content code.download span.fa-pull-left:first-child, .fa-pull-left.icon { + margin-right: .3em; } +.fa.fa-pull-right, .wy-menu-vertical li span.fa-pull-right.toctree-expand, .wy-menu-vertical li.on a span.fa-pull-right.toctree-expand, .wy-menu-vertical li.current > a span.fa-pull-right.toctree-expand, .rst-content .fa-pull-right.admonition-title, .rst-content h1 .fa-pull-right.headerlink, .rst-content h2 .fa-pull-right.headerlink, .rst-content h3 .fa-pull-right.headerlink, .rst-content h4 .fa-pull-right.headerlink, .rst-content h5 .fa-pull-right.headerlink, .rst-content h6 .fa-pull-right.headerlink, .rst-content dl dt .fa-pull-right.headerlink, .rst-content p.caption .fa-pull-right.headerlink, .rst-content tt.download span.fa-pull-right:first-child, .rst-content code.download span.fa-pull-right:first-child, .fa-pull-right.icon { + margin-left: .3em; } + +/* Deprecated as of 4.4.0 */ +.pull-right { + float: right; } + +.pull-left { + float: left; } + +.fa.pull-left, .wy-menu-vertical li span.pull-left.toctree-expand, .wy-menu-vertical li.on a span.pull-left.toctree-expand, .wy-menu-vertical li.current > a span.pull-left.toctree-expand, .rst-content .pull-left.admonition-title, .rst-content h1 .pull-left.headerlink, .rst-content h2 .pull-left.headerlink, .rst-content h3 .pull-left.headerlink, .rst-content h4 .pull-left.headerlink, .rst-content h5 .pull-left.headerlink, .rst-content h6 .pull-left.headerlink, .rst-content dl dt .pull-left.headerlink, .rst-content p.caption .pull-left.headerlink, .rst-content tt.download span.pull-left:first-child, .rst-content code.download span.pull-left:first-child, .pull-left.icon { + margin-right: .3em; } +.fa.pull-right, .wy-menu-vertical li span.pull-right.toctree-expand, .wy-menu-vertical li.on a span.pull-right.toctree-expand, .wy-menu-vertical li.current > a span.pull-right.toctree-expand, .rst-content .pull-right.admonition-title, .rst-content h1 .pull-right.headerlink, .rst-content h2 .pull-right.headerlink, .rst-content h3 .pull-right.headerlink, .rst-content h4 .pull-right.headerlink, .rst-content h5 .pull-right.headerlink, .rst-content h6 .pull-right.headerlink, .rst-content dl dt .pull-right.headerlink, .rst-content p.caption .pull-right.headerlink, .rst-content tt.download span.pull-right:first-child, .rst-content code.download span.pull-right:first-child, .pull-right.icon { + margin-left: .3em; } + +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; } + +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); } + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); } } +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); } } +.fa-rotate-90 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); } + +.fa-rotate-180 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); } + +.fa-rotate-270 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); } + +.fa-flip-horizontal { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); } + +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); } + +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical { + filter: none; } + +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; } + +.fa-stack-1x, .fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; } + +.fa-stack-1x { + line-height: inherit; } + +.fa-stack-2x { + font-size: 2em; } + +.fa-inverse { + color: #fff; } + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.fa-glass:before { + content: ""; } + +.fa-music:before { + content: ""; } + +.fa-search:before, .icon-search:before { + content: ""; } + +.fa-envelope-o:before { + content: ""; } + +.fa-heart:before { + content: ""; } + +.fa-star:before { + content: ""; } + +.fa-star-o:before { + content: ""; } + +.fa-user:before { + content: ""; } + +.fa-film:before { + content: ""; } + +.fa-th-large:before { + content: ""; } + +.fa-th:before { + content: ""; } + +.fa-th-list:before { + content: ""; } + +.fa-check:before { + content: ""; } + +.fa-remove:before, +.fa-close:before, +.fa-times:before { + content: ""; } + +.fa-search-plus:before { + content: ""; } + +.fa-search-minus:before { + content: ""; } + +.fa-power-off:before { + content: ""; } + +.fa-signal:before { + content: ""; } + +.fa-gear:before, +.fa-cog:before { + content: ""; } + +.fa-trash-o:before { + content: ""; } + +.fa-home:before, .icon-home:before { + content: ""; } + +.fa-file-o:before { + content: ""; } + +.fa-clock-o:before { + content: ""; } + +.fa-road:before { + content: ""; } + +.fa-download:before, .rst-content tt.download span:first-child:before, .rst-content code.download span:first-child:before { + content: ""; } + +.fa-arrow-circle-o-down:before { + content: ""; } + +.fa-arrow-circle-o-up:before { + content: ""; } + +.fa-inbox:before { + content: ""; } + +.fa-play-circle-o:before { + content: ""; } + +.fa-rotate-right:before, +.fa-repeat:before { + content: ""; } + +.fa-refresh:before { + content: ""; } + +.fa-list-alt:before { + content: ""; } + +.fa-lock:before { + content: ""; } + +.fa-flag:before { + content: ""; } + +.fa-headphones:before { + content: ""; } + +.fa-volume-off:before { + content: ""; } + +.fa-volume-down:before { + content: ""; } + +.fa-volume-up:before { + content: ""; } + +.fa-qrcode:before { + content: ""; } + +.fa-barcode:before { + content: ""; } + +.fa-tag:before { + content: ""; } + +.fa-tags:before { + content: ""; } + +.fa-book:before, .icon-book:before { + content: ""; } + +.fa-bookmark:before { + content: ""; } + +.fa-print:before { + content: ""; } + +.fa-camera:before { + content: ""; } + +.fa-font:before { + content: ""; } + +.fa-bold:before { + content: ""; } + +.fa-italic:before { + content: ""; } + +.fa-text-height:before { + content: ""; } + +.fa-text-width:before { + content: ""; } + +.fa-align-left:before { + content: ""; } + +.fa-align-center:before { + content: ""; } + +.fa-align-right:before { + content: ""; } + +.fa-align-justify:before { + content: ""; } + +.fa-list:before { + content: ""; } + +.fa-dedent:before, +.fa-outdent:before { + content: ""; } + +.fa-indent:before { + content: ""; } + +.fa-video-camera:before { + content: ""; } + +.fa-photo:before, +.fa-image:before, +.fa-picture-o:before { + content: ""; } + +.fa-pencil:before { + content: ""; } + +.fa-map-marker:before { + content: ""; } + +.fa-adjust:before { + content: ""; } + +.fa-tint:before { + content: ""; } + +.fa-edit:before, +.fa-pencil-square-o:before { + content: ""; } + +.fa-share-square-o:before { + content: ""; } + +.fa-check-square-o:before { + content: ""; } + +.fa-arrows:before { + content: ""; } + +.fa-step-backward:before { + content: ""; } + +.fa-fast-backward:before { + content: ""; } + +.fa-backward:before { + content: ""; } + +.fa-play:before { + content: ""; } + +.fa-pause:before { + content: ""; } + +.fa-stop:before { + content: ""; } + +.fa-forward:before { + content: ""; } + +.fa-fast-forward:before { + content: ""; } + +.fa-step-forward:before { + content: ""; } + +.fa-eject:before { + content: ""; } + +.fa-chevron-left:before { + content: ""; } + +.fa-chevron-right:before { + content: ""; } + +.fa-plus-circle:before { + content: ""; } + +.fa-minus-circle:before { + content: ""; } + +.fa-times-circle:before, .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before { + content: ""; } + +.fa-check-circle:before, .wy-inline-validate.wy-inline-validate-success .wy-input-context:before { + content: ""; } + +.fa-question-circle:before { + content: ""; } + +.fa-info-circle:before { + content: ""; } + +.fa-crosshairs:before { + content: ""; } + +.fa-times-circle-o:before { + content: ""; } + +.fa-check-circle-o:before { + content: ""; } + +.fa-ban:before { + content: ""; } + +.fa-arrow-left:before { + content: ""; } + +.fa-arrow-right:before { + content: ""; } + +.fa-arrow-up:before { + content: ""; } + +.fa-arrow-down:before { + content: ""; } + +.fa-mail-forward:before, +.fa-share:before { + content: ""; } + +.fa-expand:before { + content: ""; } + +.fa-compress:before { + content: ""; } + +.fa-plus:before { + content: ""; } + +.fa-minus:before { + content: ""; } + +.fa-asterisk:before { + content: ""; } + +.fa-exclamation-circle:before, .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .wy-input-context:before, .rst-content .admonition-title:before { + content: ""; } + +.fa-gift:before { + content: ""; } + +.fa-leaf:before { + content: ""; } + +.fa-fire:before, .icon-fire:before { + content: ""; } + +.fa-eye:before { + content: ""; } + +.fa-eye-slash:before { + content: ""; } + +.fa-warning:before, +.fa-exclamation-triangle:before { + content: ""; } + +.fa-plane:before { + content: ""; } + +.fa-calendar:before { + content: ""; } + +.fa-random:before { + content: ""; } + +.fa-comment:before { + content: ""; } + +.fa-magnet:before { + content: ""; } + +.fa-chevron-up:before { + content: ""; } + +.fa-chevron-down:before { + content: ""; } + +.fa-retweet:before { + content: ""; } + +.fa-shopping-cart:before { + content: ""; } + +.fa-folder:before { + content: ""; } + +.fa-folder-open:before { + content: ""; } + +.fa-arrows-v:before { + content: ""; } + +.fa-arrows-h:before { + content: ""; } + +.fa-bar-chart-o:before, +.fa-bar-chart:before { + content: ""; } + +.fa-twitter-square:before { + content: ""; } + +.fa-facebook-square:before { + content: ""; } + +.fa-camera-retro:before { + content: ""; } + +.fa-key:before { + content: ""; } + +.fa-gears:before, +.fa-cogs:before { + content: ""; } + +.fa-comments:before { + content: ""; } + +.fa-thumbs-o-up:before { + content: ""; } + +.fa-thumbs-o-down:before { + content: ""; } + +.fa-star-half:before { + content: ""; } + +.fa-heart-o:before { + content: ""; } + +.fa-sign-out:before { + content: ""; } + +.fa-linkedin-square:before { + content: ""; } + +.fa-thumb-tack:before { + content: ""; } + +.fa-external-link:before { + content: ""; } + +.fa-sign-in:before { + content: ""; } + +.fa-trophy:before { + content: ""; } + +.fa-github-square:before { + content: ""; } + +.fa-upload:before { + content: ""; } + +.fa-lemon-o:before { + content: ""; } + +.fa-phone:before { + content: ""; } + +.fa-square-o:before { + content: ""; } + +.fa-bookmark-o:before { + content: ""; } + +.fa-phone-square:before { + content: ""; } + +.fa-twitter:before { + content: ""; } + +.fa-facebook-f:before, +.fa-facebook:before { + content: ""; } + +.fa-github:before, .icon-github:before { + content: ""; } + +.fa-unlock:before { + content: ""; } + +.fa-credit-card:before { + content: ""; } + +.fa-feed:before, +.fa-rss:before { + content: ""; } + +.fa-hdd-o:before { + content: ""; } + +.fa-bullhorn:before { + content: ""; } + +.fa-bell:before { + content: ""; } + +.fa-certificate:before { + content: ""; } + +.fa-hand-o-right:before { + content: ""; } + +.fa-hand-o-left:before { + content: ""; } + +.fa-hand-o-up:before { + content: ""; } + +.fa-hand-o-down:before { + content: ""; } + +.fa-arrow-circle-left:before, .icon-circle-arrow-left:before { + content: ""; } + +.fa-arrow-circle-right:before, .icon-circle-arrow-right:before { + content: ""; } + +.fa-arrow-circle-up:before { + content: ""; } + +.fa-arrow-circle-down:before { + content: ""; } + +.fa-globe:before { + content: ""; } + +.fa-wrench:before { + content: ""; } + +.fa-tasks:before { + content: ""; } + +.fa-filter:before { + content: ""; } + +.fa-briefcase:before { + content: ""; } + +.fa-arrows-alt:before { + content: ""; } + +.fa-group:before, +.fa-users:before { + content: ""; } + +.fa-chain:before, +.fa-link:before, +.icon-link:before { + content: ""; } + +.fa-cloud:before { + content: ""; } + +.fa-flask:before { + content: ""; } + +.fa-cut:before, +.fa-scissors:before { + content: ""; } + +.fa-copy:before, +.fa-files-o:before { + content: ""; } + +.fa-paperclip:before { + content: ""; } + +.fa-save:before, +.fa-floppy-o:before { + content: ""; } + +.fa-square:before { + content: ""; } + +.fa-navicon:before, +.fa-reorder:before, +.fa-bars:before { + content: ""; } + +.fa-list-ul:before { + content: ""; } + +.fa-list-ol:before { + content: ""; } + +.fa-strikethrough:before { + content: ""; } + +.fa-underline:before { + content: ""; } + +.fa-table:before { + content: ""; } + +.fa-magic:before { + content: ""; } + +.fa-truck:before { + content: ""; } + +.fa-pinterest:before { + content: ""; } + +.fa-pinterest-square:before { + content: ""; } + +.fa-google-plus-square:before { + content: ""; } + +.fa-google-plus:before { + content: ""; } + +.fa-money:before { + content: ""; } + +.fa-caret-down:before, .wy-dropdown .caret:before, .icon-caret-down:before { + content: ""; } + +.fa-caret-up:before { + content: ""; } + +.fa-caret-left:before { + content: ""; } + +.fa-caret-right:before { + content: ""; } + +.fa-columns:before { + content: ""; } + +.fa-unsorted:before, +.fa-sort:before { + content: ""; } + +.fa-sort-down:before, +.fa-sort-desc:before { + content: ""; } + +.fa-sort-up:before, +.fa-sort-asc:before { + content: ""; } + +.fa-envelope:before { + content: ""; } + +.fa-linkedin:before { + content: ""; } + +.fa-rotate-left:before, +.fa-undo:before { + content: ""; } + +.fa-legal:before, +.fa-gavel:before { + content: ""; } + +.fa-dashboard:before, +.fa-tachometer:before { + content: ""; } + +.fa-comment-o:before { + content: ""; } + +.fa-comments-o:before { + content: ""; } + +.fa-flash:before, +.fa-bolt:before { + content: ""; } + +.fa-sitemap:before { + content: ""; } + +.fa-umbrella:before { + content: ""; } + +.fa-paste:before, +.fa-clipboard:before { + content: ""; } + +.fa-lightbulb-o:before { + content: ""; } + +.fa-exchange:before { + content: ""; } + +.fa-cloud-download:before { + content: ""; } + +.fa-cloud-upload:before { + content: ""; } + +.fa-user-md:before { + content: ""; } + +.fa-stethoscope:before { + content: ""; } + +.fa-suitcase:before { + content: ""; } + +.fa-bell-o:before { + content: ""; } + +.fa-coffee:before { + content: ""; } + +.fa-cutlery:before { + content: ""; } + +.fa-file-text-o:before { + content: ""; } + +.fa-building-o:before { + content: ""; } + +.fa-hospital-o:before { + content: ""; } + +.fa-ambulance:before { + content: ""; } + +.fa-medkit:before { + content: ""; } + +.fa-fighter-jet:before { + content: ""; } + +.fa-beer:before { + content: ""; } + +.fa-h-square:before { + content: ""; } + +.fa-plus-square:before { + content: ""; } + +.fa-angle-double-left:before { + content: ""; } + +.fa-angle-double-right:before { + content: ""; } + +.fa-angle-double-up:before { + content: ""; } + +.fa-angle-double-down:before { + content: ""; } + +.fa-angle-left:before { + content: ""; } + +.fa-angle-right:before { + content: ""; } + +.fa-angle-up:before { + content: ""; } + +.fa-angle-down:before { + content: ""; } + +.fa-desktop:before { + content: ""; } + +.fa-laptop:before { + content: ""; } + +.fa-tablet:before { + content: ""; } + +.fa-mobile-phone:before, +.fa-mobile:before { + content: ""; } + +.fa-circle-o:before { + content: ""; } + +.fa-quote-left:before { + content: ""; } + +.fa-quote-right:before { + content: ""; } + +.fa-spinner:before { + content: ""; } + +.fa-circle:before { + content: ""; } + +.fa-mail-reply:before, +.fa-reply:before { + content: ""; } + +.fa-github-alt:before { + content: ""; } + +.fa-folder-o:before { + content: ""; } + +.fa-folder-open-o:before { + content: ""; } + +.fa-smile-o:before { + content: ""; } + +.fa-frown-o:before { + content: ""; } + +.fa-meh-o:before { + content: ""; } + +.fa-gamepad:before { + content: ""; } + +.fa-keyboard-o:before { + content: ""; } + +.fa-flag-o:before { + content: ""; } + +.fa-flag-checkered:before { + content: ""; } + +.fa-terminal:before { + content: ""; } + +.fa-code:before { + content: ""; } + +.fa-mail-reply-all:before, +.fa-reply-all:before { + content: ""; } + +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: ""; } + +.fa-location-arrow:before { + content: ""; } + +.fa-crop:before { + content: ""; } + +.fa-code-fork:before { + content: ""; } + +.fa-unlink:before, +.fa-chain-broken:before { + content: ""; } + +.fa-question:before { + content: ""; } + +.fa-info:before { + content: ""; } + +.fa-exclamation:before { + content: ""; } + +.fa-superscript:before { + content: ""; } + +.fa-subscript:before { + content: ""; } + +.fa-eraser:before { + content: ""; } + +.fa-puzzle-piece:before { + content: ""; } + +.fa-microphone:before { + content: ""; } + +.fa-microphone-slash:before { + content: ""; } + +.fa-shield:before { + content: ""; } + +.fa-calendar-o:before { + content: ""; } + +.fa-fire-extinguisher:before { + content: ""; } + +.fa-rocket:before { + content: ""; } + +.fa-maxcdn:before { + content: ""; } + +.fa-chevron-circle-left:before { + content: ""; } + +.fa-chevron-circle-right:before { + content: ""; } + +.fa-chevron-circle-up:before { + content: ""; } + +.fa-chevron-circle-down:before { + content: ""; } + +.fa-html5:before { + content: ""; } + +.fa-css3:before { + content: ""; } + +.fa-anchor:before { + content: ""; } + +.fa-unlock-alt:before { + content: ""; } + +.fa-bullseye:before { + content: ""; } + +.fa-ellipsis-h:before { + content: ""; } + +.fa-ellipsis-v:before { + content: ""; } + +.fa-rss-square:before { + content: ""; } + +.fa-play-circle:before { + content: ""; } + +.fa-ticket:before { + content: ""; } + +.fa-minus-square:before { + content: ""; } + +.fa-minus-square-o:before, .wy-menu-vertical li.on a span.toctree-expand:before, .wy-menu-vertical li.current > a span.toctree-expand:before { + content: ""; } + +.fa-level-up:before { + content: ""; } + +.fa-level-down:before { + content: ""; } + +.fa-check-square:before { + content: ""; } + +.fa-pencil-square:before { + content: ""; } + +.fa-external-link-square:before { + content: ""; } + +.fa-share-square:before { + content: ""; } + +.fa-compass:before { + content: ""; } + +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: ""; } + +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: ""; } + +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: ""; } + +.fa-euro:before, +.fa-eur:before { + content: ""; } + +.fa-gbp:before { + content: ""; } + +.fa-dollar:before, +.fa-usd:before { + content: ""; } + +.fa-rupee:before, +.fa-inr:before { + content: ""; } + +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: ""; } + +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: ""; } + +.fa-won:before, +.fa-krw:before { + content: ""; } + +.fa-bitcoin:before, +.fa-btc:before { + content: ""; } + +.fa-file:before { + content: ""; } + +.fa-file-text:before { + content: ""; } + +.fa-sort-alpha-asc:before { + content: ""; } + +.fa-sort-alpha-desc:before { + content: ""; } + +.fa-sort-amount-asc:before { + content: ""; } + +.fa-sort-amount-desc:before { + content: ""; } + +.fa-sort-numeric-asc:before { + content: ""; } + +.fa-sort-numeric-desc:before { + content: ""; } + +.fa-thumbs-up:before { + content: ""; } + +.fa-thumbs-down:before { + content: ""; } + +.fa-youtube-square:before { + content: ""; } + +.fa-youtube:before { + content: ""; } + +.fa-xing:before { + content: ""; } + +.fa-xing-square:before { + content: ""; } + +.fa-youtube-play:before { + content: ""; } + +.fa-dropbox:before { + content: ""; } + +.fa-stack-overflow:before { + content: ""; } + +.fa-instagram:before { + content: ""; } + +.fa-flickr:before { + content: ""; } + +.fa-adn:before { + content: ""; } + +.fa-bitbucket:before, .icon-bitbucket:before { + content: ""; } + +.fa-bitbucket-square:before { + content: ""; } + +.fa-tumblr:before { + content: ""; } + +.fa-tumblr-square:before { + content: ""; } + +.fa-long-arrow-down:before { + content: ""; } + +.fa-long-arrow-up:before { + content: ""; } + +.fa-long-arrow-left:before { + content: ""; } + +.fa-long-arrow-right:before { + content: ""; } + +.fa-apple:before { + content: ""; } + +.fa-windows:before { + content: ""; } + +.fa-android:before { + content: ""; } + +.fa-linux:before { + content: ""; } + +.fa-dribbble:before { + content: ""; } + +.fa-skype:before { + content: ""; } + +.fa-foursquare:before { + content: ""; } + +.fa-trello:before { + content: ""; } + +.fa-female:before { + content: ""; } + +.fa-male:before { + content: ""; } + +.fa-gittip:before, +.fa-gratipay:before { + content: ""; } + +.fa-sun-o:before { + content: ""; } + +.fa-moon-o:before { + content: ""; } + +.fa-archive:before { + content: ""; } + +.fa-bug:before { + content: ""; } + +.fa-vk:before { + content: ""; } + +.fa-weibo:before { + content: ""; } + +.fa-renren:before { + content: ""; } + +.fa-pagelines:before { + content: ""; } + +.fa-stack-exchange:before { + content: ""; } + +.fa-arrow-circle-o-right:before { + content: ""; } + +.fa-arrow-circle-o-left:before { + content: ""; } + +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: ""; } + +.fa-dot-circle-o:before { + content: ""; } + +.fa-wheelchair:before { + content: ""; } + +.fa-vimeo-square:before { + content: ""; } + +.fa-turkish-lira:before, +.fa-try:before { + content: ""; } + +.fa-plus-square-o:before, .wy-menu-vertical li span.toctree-expand:before { + content: ""; } + +.fa-space-shuttle:before { + content: ""; } + +.fa-slack:before { + content: ""; } + +.fa-envelope-square:before { + content: ""; } + +.fa-wordpress:before { + content: ""; } + +.fa-openid:before { + content: ""; } + +.fa-institution:before, +.fa-bank:before, +.fa-university:before { + content: ""; } + +.fa-mortar-board:before, +.fa-graduation-cap:before { + content: ""; } + +.fa-yahoo:before { + content: ""; } + +.fa-google:before { + content: ""; } + +.fa-reddit:before { + content: ""; } + +.fa-reddit-square:before { + content: ""; } + +.fa-stumbleupon-circle:before { + content: ""; } + +.fa-stumbleupon:before { + content: ""; } + +.fa-delicious:before { + content: ""; } + +.fa-digg:before { + content: ""; } + +.fa-pied-piper-pp:before { + content: ""; } + +.fa-pied-piper-alt:before { + content: ""; } + +.fa-drupal:before { + content: ""; } + +.fa-joomla:before { + content: ""; } + +.fa-language:before { + content: ""; } + +.fa-fax:before { + content: ""; } + +.fa-building:before { + content: ""; } + +.fa-child:before { + content: ""; } + +.fa-paw:before { + content: ""; } + +.fa-spoon:before { + content: ""; } + +.fa-cube:before { + content: ""; } + +.fa-cubes:before { + content: ""; } + +.fa-behance:before { + content: ""; } + +.fa-behance-square:before { + content: ""; } + +.fa-steam:before { + content: ""; } + +.fa-steam-square:before { + content: ""; } + +.fa-recycle:before { + content: ""; } + +.fa-automobile:before, +.fa-car:before { + content: ""; } + +.fa-cab:before, +.fa-taxi:before { + content: ""; } + +.fa-tree:before { + content: ""; } + +.fa-spotify:before { + content: ""; } + +.fa-deviantart:before { + content: ""; } + +.fa-soundcloud:before { + content: ""; } + +.fa-database:before { + content: ""; } + +.fa-file-pdf-o:before { + content: ""; } + +.fa-file-word-o:before { + content: ""; } + +.fa-file-excel-o:before { + content: ""; } + +.fa-file-powerpoint-o:before { + content: ""; } + +.fa-file-photo-o:before, +.fa-file-picture-o:before, +.fa-file-image-o:before { + content: ""; } + +.fa-file-zip-o:before, +.fa-file-archive-o:before { + content: ""; } + +.fa-file-sound-o:before, +.fa-file-audio-o:before { + content: ""; } + +.fa-file-movie-o:before, +.fa-file-video-o:before { + content: ""; } + +.fa-file-code-o:before { + content: ""; } + +.fa-vine:before { + content: ""; } + +.fa-codepen:before { + content: ""; } + +.fa-jsfiddle:before { + content: ""; } + +.fa-life-bouy:before, +.fa-life-buoy:before, +.fa-life-saver:before, +.fa-support:before, +.fa-life-ring:before { + content: ""; } + +.fa-circle-o-notch:before { + content: ""; } + +.fa-ra:before, +.fa-resistance:before, +.fa-rebel:before { + content: ""; } + +.fa-ge:before, +.fa-empire:before { + content: ""; } + +.fa-git-square:before { + content: ""; } + +.fa-git:before { + content: ""; } + +.fa-y-combinator-square:before, +.fa-yc-square:before, +.fa-hacker-news:before { + content: ""; } + +.fa-tencent-weibo:before { + content: ""; } + +.fa-qq:before { + content: ""; } + +.fa-wechat:before, +.fa-weixin:before { + content: ""; } + +.fa-send:before, +.fa-paper-plane:before { + content: ""; } + +.fa-send-o:before, +.fa-paper-plane-o:before { + content: ""; } + +.fa-history:before { + content: ""; } + +.fa-circle-thin:before { + content: ""; } + +.fa-header:before { + content: ""; } + +.fa-paragraph:before { + content: ""; } + +.fa-sliders:before { + content: ""; } + +.fa-share-alt:before { + content: ""; } + +.fa-share-alt-square:before { + content: ""; } + +.fa-bomb:before { + content: ""; } + +.fa-soccer-ball-o:before, +.fa-futbol-o:before { + content: ""; } + +.fa-tty:before { + content: ""; } + +.fa-binoculars:before { + content: ""; } + +.fa-plug:before { + content: ""; } + +.fa-slideshare:before { + content: ""; } + +.fa-twitch:before { + content: ""; } + +.fa-yelp:before { + content: ""; } + +.fa-newspaper-o:before { + content: ""; } + +.fa-wifi:before { + content: ""; } + +.fa-calculator:before { + content: ""; } + +.fa-paypal:before { + content: ""; } + +.fa-google-wallet:before { + content: ""; } + +.fa-cc-visa:before { + content: ""; } + +.fa-cc-mastercard:before { + content: ""; } + +.fa-cc-discover:before { + content: ""; } + +.fa-cc-amex:before { + content: ""; } + +.fa-cc-paypal:before { + content: ""; } + +.fa-cc-stripe:before { + content: ""; } + +.fa-bell-slash:before { + content: ""; } + +.fa-bell-slash-o:before { + content: ""; } + +.fa-trash:before { + content: ""; } + +.fa-copyright:before { + content: ""; } + +.fa-at:before { + content: ""; } + +.fa-eyedropper:before { + content: ""; } + +.fa-paint-brush:before { + content: ""; } + +.fa-birthday-cake:before { + content: ""; } + +.fa-area-chart:before { + content: ""; } + +.fa-pie-chart:before { + content: ""; } + +.fa-line-chart:before { + content: ""; } + +.fa-lastfm:before { + content: ""; } + +.fa-lastfm-square:before { + content: ""; } + +.fa-toggle-off:before { + content: ""; } + +.fa-toggle-on:before { + content: ""; } + +.fa-bicycle:before { + content: ""; } + +.fa-bus:before { + content: ""; } + +.fa-ioxhost:before { + content: ""; } + +.fa-angellist:before { + content: ""; } + +.fa-cc:before { + content: ""; } + +.fa-shekel:before, +.fa-sheqel:before, +.fa-ils:before { + content: ""; } + +.fa-meanpath:before { + content: ""; } + +.fa-buysellads:before { + content: ""; } + +.fa-connectdevelop:before { + content: ""; } + +.fa-dashcube:before { + content: ""; } + +.fa-forumbee:before { + content: ""; } + +.fa-leanpub:before { + content: ""; } + +.fa-sellsy:before { + content: ""; } + +.fa-shirtsinbulk:before { + content: ""; } + +.fa-simplybuilt:before { + content: ""; } + +.fa-skyatlas:before { + content: ""; } + +.fa-cart-plus:before { + content: ""; } + +.fa-cart-arrow-down:before { + content: ""; } + +.fa-diamond:before { + content: ""; } + +.fa-ship:before { + content: ""; } + +.fa-user-secret:before { + content: ""; } + +.fa-motorcycle:before { + content: ""; } + +.fa-street-view:before { + content: ""; } + +.fa-heartbeat:before { + content: ""; } + +.fa-venus:before { + content: ""; } + +.fa-mars:before { + content: ""; } + +.fa-mercury:before { + content: ""; } + +.fa-intersex:before, +.fa-transgender:before { + content: ""; } + +.fa-transgender-alt:before { + content: ""; } + +.fa-venus-double:before { + content: ""; } + +.fa-mars-double:before { + content: ""; } + +.fa-venus-mars:before { + content: ""; } + +.fa-mars-stroke:before { + content: ""; } + +.fa-mars-stroke-v:before { + content: ""; } + +.fa-mars-stroke-h:before { + content: ""; } + +.fa-neuter:before { + content: ""; } + +.fa-genderless:before { + content: ""; } + +.fa-facebook-official:before { + content: ""; } + +.fa-pinterest-p:before { + content: ""; } + +.fa-whatsapp:before { + content: ""; } + +.fa-server:before { + content: ""; } + +.fa-user-plus:before { + content: ""; } + +.fa-user-times:before { + content: ""; } + +.fa-hotel:before, +.fa-bed:before { + content: ""; } + +.fa-viacoin:before { + content: ""; } + +.fa-train:before { + content: ""; } + +.fa-subway:before { + content: ""; } + +.fa-medium:before { + content: ""; } + +.fa-yc:before, +.fa-y-combinator:before { + content: ""; } + +.fa-optin-monster:before { + content: ""; } + +.fa-opencart:before { + content: ""; } + +.fa-expeditedssl:before { + content: ""; } + +.fa-battery-4:before, +.fa-battery:before, +.fa-battery-full:before { + content: ""; } + +.fa-battery-3:before, +.fa-battery-three-quarters:before { + content: ""; } + +.fa-battery-2:before, +.fa-battery-half:before { + content: ""; } + +.fa-battery-1:before, +.fa-battery-quarter:before { + content: ""; } + +.fa-battery-0:before, +.fa-battery-empty:before { + content: ""; } + +.fa-mouse-pointer:before { + content: ""; } + +.fa-i-cursor:before { + content: ""; } + +.fa-object-group:before { + content: ""; } + +.fa-object-ungroup:before { + content: ""; } + +.fa-sticky-note:before { + content: ""; } + +.fa-sticky-note-o:before { + content: ""; } + +.fa-cc-jcb:before { + content: ""; } + +.fa-cc-diners-club:before { + content: ""; } + +.fa-clone:before { + content: ""; } + +.fa-balance-scale:before { + content: ""; } + +.fa-hourglass-o:before { + content: ""; } + +.fa-hourglass-1:before, +.fa-hourglass-start:before { + content: ""; } + +.fa-hourglass-2:before, +.fa-hourglass-half:before { + content: ""; } + +.fa-hourglass-3:before, +.fa-hourglass-end:before { + content: ""; } + +.fa-hourglass:before { + content: ""; } + +.fa-hand-grab-o:before, +.fa-hand-rock-o:before { + content: ""; } + +.fa-hand-stop-o:before, +.fa-hand-paper-o:before { + content: ""; } + +.fa-hand-scissors-o:before { + content: ""; } + +.fa-hand-lizard-o:before { + content: ""; } + +.fa-hand-spock-o:before { + content: ""; } + +.fa-hand-pointer-o:before { + content: ""; } + +.fa-hand-peace-o:before { + content: ""; } + +.fa-trademark:before { + content: ""; } + +.fa-registered:before { + content: ""; } + +.fa-creative-commons:before { + content: ""; } + +.fa-gg:before { + content: ""; } + +.fa-gg-circle:before { + content: ""; } + +.fa-tripadvisor:before { + content: ""; } + +.fa-odnoklassniki:before { + content: ""; } + +.fa-odnoklassniki-square:before { + content: ""; } + +.fa-get-pocket:before { + content: ""; } + +.fa-wikipedia-w:before { + content: ""; } + +.fa-safari:before { + content: ""; } + +.fa-chrome:before { + content: ""; } + +.fa-firefox:before { + content: ""; } + +.fa-opera:before { + content: ""; } + +.fa-internet-explorer:before { + content: ""; } + +.fa-tv:before, +.fa-television:before { + content: ""; } + +.fa-contao:before { + content: ""; } + +.fa-500px:before { + content: ""; } + +.fa-amazon:before { + content: ""; } + +.fa-calendar-plus-o:before { + content: ""; } + +.fa-calendar-minus-o:before { + content: ""; } + +.fa-calendar-times-o:before { + content: ""; } + +.fa-calendar-check-o:before { + content: ""; } + +.fa-industry:before { + content: ""; } + +.fa-map-pin:before { + content: ""; } + +.fa-map-signs:before { + content: ""; } + +.fa-map-o:before { + content: ""; } + +.fa-map:before { + content: ""; } + +.fa-commenting:before { + content: ""; } + +.fa-commenting-o:before { + content: ""; } + +.fa-houzz:before { + content: ""; } + +.fa-vimeo:before { + content: ""; } + +.fa-black-tie:before { + content: ""; } + +.fa-fonticons:before { + content: ""; } + +.fa-reddit-alien:before { + content: ""; } + +.fa-edge:before { + content: ""; } + +.fa-credit-card-alt:before { + content: ""; } + +.fa-codiepie:before { + content: ""; } + +.fa-modx:before { + content: ""; } + +.fa-fort-awesome:before { + content: ""; } + +.fa-usb:before { + content: ""; } + +.fa-product-hunt:before { + content: ""; } + +.fa-mixcloud:before { + content: ""; } + +.fa-scribd:before { + content: ""; } + +.fa-pause-circle:before { + content: ""; } + +.fa-pause-circle-o:before { + content: ""; } + +.fa-stop-circle:before { + content: ""; } + +.fa-stop-circle-o:before { + content: ""; } + +.fa-shopping-bag:before { + content: ""; } + +.fa-shopping-basket:before { + content: ""; } + +.fa-hashtag:before { + content: ""; } + +.fa-bluetooth:before { + content: ""; } + +.fa-bluetooth-b:before { + content: ""; } + +.fa-percent:before { + content: ""; } + +.fa-gitlab:before, .icon-gitlab:before { + content: ""; } + +.fa-wpbeginner:before { + content: ""; } + +.fa-wpforms:before { + content: ""; } + +.fa-envira:before { + content: ""; } + +.fa-universal-access:before { + content: ""; } + +.fa-wheelchair-alt:before { + content: ""; } + +.fa-question-circle-o:before { + content: ""; } + +.fa-blind:before { + content: ""; } + +.fa-audio-description:before { + content: ""; } + +.fa-volume-control-phone:before { + content: ""; } + +.fa-braille:before { + content: ""; } + +.fa-assistive-listening-systems:before { + content: ""; } + +.fa-asl-interpreting:before, +.fa-american-sign-language-interpreting:before { + content: ""; } + +.fa-deafness:before, +.fa-hard-of-hearing:before, +.fa-deaf:before { + content: ""; } + +.fa-glide:before { + content: ""; } + +.fa-glide-g:before { + content: ""; } + +.fa-signing:before, +.fa-sign-language:before { + content: ""; } + +.fa-low-vision:before { + content: ""; } + +.fa-viadeo:before { + content: ""; } + +.fa-viadeo-square:before { + content: ""; } + +.fa-snapchat:before { + content: ""; } + +.fa-snapchat-ghost:before { + content: ""; } + +.fa-snapchat-square:before { + content: ""; } + +.fa-pied-piper:before { + content: ""; } + +.fa-first-order:before { + content: ""; } + +.fa-yoast:before { + content: ""; } + +.fa-themeisle:before { + content: ""; } + +.fa-google-plus-circle:before, +.fa-google-plus-official:before { + content: ""; } + +.fa-fa:before, +.fa-font-awesome:before { + content: ""; } + +.fa-handshake-o:before { + content: ""; } + +.fa-envelope-open:before { + content: ""; } + +.fa-envelope-open-o:before { + content: ""; } + +.fa-linode:before { + content: ""; } + +.fa-address-book:before { + content: ""; } + +.fa-address-book-o:before { + content: ""; } + +.fa-vcard:before, +.fa-address-card:before { + content: ""; } + +.fa-vcard-o:before, +.fa-address-card-o:before { + content: ""; } + +.fa-user-circle:before { + content: ""; } + +.fa-user-circle-o:before { + content: ""; } + +.fa-user-o:before { + content: ""; } + +.fa-id-badge:before { + content: ""; } + +.fa-drivers-license:before, +.fa-id-card:before { + content: ""; } + +.fa-drivers-license-o:before, +.fa-id-card-o:before { + content: ""; } + +.fa-quora:before { + content: ""; } + +.fa-free-code-camp:before { + content: ""; } + +.fa-telegram:before { + content: ""; } + +.fa-thermometer-4:before, +.fa-thermometer:before, +.fa-thermometer-full:before { + content: ""; } + +.fa-thermometer-3:before, +.fa-thermometer-three-quarters:before { + content: ""; } + +.fa-thermometer-2:before, +.fa-thermometer-half:before { + content: ""; } + +.fa-thermometer-1:before, +.fa-thermometer-quarter:before { + content: ""; } + +.fa-thermometer-0:before, +.fa-thermometer-empty:before { + content: ""; } + +.fa-shower:before { + content: ""; } + +.fa-bathtub:before, +.fa-s15:before, +.fa-bath:before { + content: ""; } + +.fa-podcast:before { + content: ""; } + +.fa-window-maximize:before { + content: ""; } + +.fa-window-minimize:before { + content: ""; } + +.fa-window-restore:before { + content: ""; } + +.fa-times-rectangle:before, +.fa-window-close:before { + content: ""; } + +.fa-times-rectangle-o:before, +.fa-window-close-o:before { + content: ""; } + +.fa-bandcamp:before { + content: ""; } + +.fa-grav:before { + content: ""; } + +.fa-etsy:before { + content: ""; } + +.fa-imdb:before { + content: ""; } + +.fa-ravelry:before { + content: ""; } + +.fa-eercast:before { + content: ""; } + +.fa-microchip:before { + content: ""; } + +.fa-snowflake-o:before { + content: ""; } + +.fa-superpowers:before { + content: ""; } + +.fa-wpexplorer:before { + content: ""; } + +.fa-meetup:before { + content: ""; } + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; } + +.sr-only-focusable:active, .sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; } + +.fa, .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.current > a span.toctree-expand, .rst-content .admonition-title, .rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink, .rst-content p.caption .headerlink, .rst-content tt.download span:first-child, .rst-content code.download span:first-child, .icon, .wy-dropdown .caret, .wy-inline-validate.wy-inline-validate-success .wy-input-context, .wy-inline-validate.wy-inline-validate-danger .wy-input-context, .wy-inline-validate.wy-inline-validate-warning .wy-input-context, .wy-inline-validate.wy-inline-validate-info .wy-input-context { + font-family: inherit; } + .fa:before, .wy-menu-vertical li span.toctree-expand:before, .wy-menu-vertical li.on a span.toctree-expand:before, .wy-menu-vertical li.current > a span.toctree-expand:before, .rst-content .admonition-title:before, .rst-content h1 .headerlink:before, .rst-content h2 .headerlink:before, .rst-content h3 .headerlink:before, .rst-content h4 .headerlink:before, .rst-content h5 .headerlink:before, .rst-content h6 .headerlink:before, .rst-content dl dt .headerlink:before, .rst-content p.caption .headerlink:before, .rst-content tt.download span:first-child:before, .rst-content code.download span:first-child:before, .icon:before, .wy-dropdown .caret:before, .wy-inline-validate.wy-inline-validate-success .wy-input-context:before, .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before, .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .wy-input-context:before { + font-family: "FontAwesome"; + display: inline-block; + font-style: normal; + font-weight: normal; + line-height: 1; + text-decoration: inherit; } + +a .fa, a .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li a span.toctree-expand, .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.current > a span.toctree-expand, a .rst-content .admonition-title, .rst-content a .admonition-title, a .rst-content h1 .headerlink, .rst-content h1 a .headerlink, a .rst-content h2 .headerlink, .rst-content h2 a .headerlink, a .rst-content h3 .headerlink, .rst-content h3 a .headerlink, a .rst-content h4 .headerlink, .rst-content h4 a .headerlink, a .rst-content h5 .headerlink, .rst-content h5 a .headerlink, a .rst-content h6 .headerlink, .rst-content h6 a .headerlink, a .rst-content dl dt .headerlink, .rst-content dl dt a .headerlink, a .rst-content p.caption .headerlink, .rst-content p.caption a .headerlink, a .rst-content tt.download span:first-child, .rst-content tt.download a span:first-child, a .rst-content code.download span:first-child, .rst-content code.download a span:first-child, a .icon { + display: inline-block; + text-decoration: inherit; } + +.btn .fa, .btn .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li .btn span.toctree-expand, .btn .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.on a .btn span.toctree-expand, .btn .wy-menu-vertical li.current > a span.toctree-expand, .wy-menu-vertical li.current > a .btn span.toctree-expand, .btn .rst-content .admonition-title, .rst-content .btn .admonition-title, .btn .rst-content h1 .headerlink, .rst-content h1 .btn .headerlink, .btn .rst-content h2 .headerlink, .rst-content h2 .btn .headerlink, .btn .rst-content h3 .headerlink, .rst-content h3 .btn .headerlink, .btn .rst-content h4 .headerlink, .rst-content h4 .btn .headerlink, .btn .rst-content h5 .headerlink, .rst-content h5 .btn .headerlink, .btn .rst-content h6 .headerlink, .rst-content h6 .btn .headerlink, .btn .rst-content dl dt .headerlink, .rst-content dl dt .btn .headerlink, .btn .rst-content p.caption .headerlink, .rst-content p.caption .btn .headerlink, .btn .rst-content tt.download span:first-child, .rst-content tt.download .btn span:first-child, .btn .rst-content code.download span:first-child, .rst-content code.download .btn span:first-child, .btn .icon, .nav .fa, .nav .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li .nav span.toctree-expand, .nav .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.on a .nav span.toctree-expand, .nav .wy-menu-vertical li.current > a span.toctree-expand, .wy-menu-vertical li.current > a .nav span.toctree-expand, .nav .rst-content .admonition-title, .rst-content .nav .admonition-title, .nav .rst-content h1 .headerlink, .rst-content h1 .nav .headerlink, .nav .rst-content h2 .headerlink, .rst-content h2 .nav .headerlink, .nav .rst-content h3 .headerlink, .rst-content h3 .nav .headerlink, .nav .rst-content h4 .headerlink, .rst-content h4 .nav .headerlink, .nav .rst-content h5 .headerlink, .rst-content h5 .nav .headerlink, .nav .rst-content h6 .headerlink, .rst-content h6 .nav .headerlink, .nav .rst-content dl dt .headerlink, .rst-content dl dt .nav .headerlink, .nav .rst-content p.caption .headerlink, .rst-content p.caption .nav .headerlink, .nav .rst-content tt.download span:first-child, .rst-content tt.download .nav span:first-child, .nav .rst-content code.download span:first-child, .rst-content code.download .nav span:first-child, .nav .icon { + display: inline; } + .btn .fa.fa-large, .btn .wy-menu-vertical li span.fa-large.toctree-expand, .wy-menu-vertical li .btn span.fa-large.toctree-expand, .btn .rst-content .fa-large.admonition-title, .rst-content .btn .fa-large.admonition-title, .btn .rst-content h1 .fa-large.headerlink, .rst-content h1 .btn .fa-large.headerlink, .btn .rst-content h2 .fa-large.headerlink, .rst-content h2 .btn .fa-large.headerlink, .btn .rst-content h3 .fa-large.headerlink, .rst-content h3 .btn .fa-large.headerlink, .btn .rst-content h4 .fa-large.headerlink, .rst-content h4 .btn .fa-large.headerlink, .btn .rst-content h5 .fa-large.headerlink, .rst-content h5 .btn .fa-large.headerlink, .btn .rst-content h6 .fa-large.headerlink, .rst-content h6 .btn .fa-large.headerlink, .btn .rst-content dl dt .fa-large.headerlink, .rst-content dl dt .btn .fa-large.headerlink, .btn .rst-content p.caption .fa-large.headerlink, .rst-content p.caption .btn .fa-large.headerlink, .btn .rst-content tt.download span.fa-large:first-child, .rst-content tt.download .btn span.fa-large:first-child, .btn .rst-content code.download span.fa-large:first-child, .rst-content code.download .btn span.fa-large:first-child, .btn .fa-large.icon, .nav .fa.fa-large, .nav .wy-menu-vertical li span.fa-large.toctree-expand, .wy-menu-vertical li .nav span.fa-large.toctree-expand, .nav .rst-content .fa-large.admonition-title, .rst-content .nav .fa-large.admonition-title, .nav .rst-content h1 .fa-large.headerlink, .rst-content h1 .nav .fa-large.headerlink, .nav .rst-content h2 .fa-large.headerlink, .rst-content h2 .nav .fa-large.headerlink, .nav .rst-content h3 .fa-large.headerlink, .rst-content h3 .nav .fa-large.headerlink, .nav .rst-content h4 .fa-large.headerlink, .rst-content h4 .nav .fa-large.headerlink, .nav .rst-content h5 .fa-large.headerlink, .rst-content h5 .nav .fa-large.headerlink, .nav .rst-content h6 .fa-large.headerlink, .rst-content h6 .nav .fa-large.headerlink, .nav .rst-content dl dt .fa-large.headerlink, .rst-content dl dt .nav .fa-large.headerlink, .nav .rst-content p.caption .fa-large.headerlink, .rst-content p.caption .nav .fa-large.headerlink, .nav .rst-content tt.download span.fa-large:first-child, .rst-content tt.download .nav span.fa-large:first-child, .nav .rst-content code.download span.fa-large:first-child, .rst-content code.download .nav span.fa-large:first-child, .nav .fa-large.icon { + line-height: 0.9em; } + .btn .fa.fa-spin, .btn .wy-menu-vertical li span.fa-spin.toctree-expand, .wy-menu-vertical li .btn span.fa-spin.toctree-expand, .btn .rst-content .fa-spin.admonition-title, .rst-content .btn .fa-spin.admonition-title, .btn .rst-content h1 .fa-spin.headerlink, .rst-content h1 .btn .fa-spin.headerlink, .btn .rst-content h2 .fa-spin.headerlink, .rst-content h2 .btn .fa-spin.headerlink, .btn .rst-content h3 .fa-spin.headerlink, .rst-content h3 .btn .fa-spin.headerlink, .btn .rst-content h4 .fa-spin.headerlink, .rst-content h4 .btn .fa-spin.headerlink, .btn .rst-content h5 .fa-spin.headerlink, .rst-content h5 .btn .fa-spin.headerlink, .btn .rst-content h6 .fa-spin.headerlink, .rst-content h6 .btn .fa-spin.headerlink, .btn .rst-content dl dt .fa-spin.headerlink, .rst-content dl dt .btn .fa-spin.headerlink, .btn .rst-content p.caption .fa-spin.headerlink, .rst-content p.caption .btn .fa-spin.headerlink, .btn .rst-content tt.download span.fa-spin:first-child, .rst-content tt.download .btn span.fa-spin:first-child, .btn .rst-content code.download span.fa-spin:first-child, .rst-content code.download .btn span.fa-spin:first-child, .btn .fa-spin.icon, .nav .fa.fa-spin, .nav .wy-menu-vertical li span.fa-spin.toctree-expand, .wy-menu-vertical li .nav span.fa-spin.toctree-expand, .nav .rst-content .fa-spin.admonition-title, .rst-content .nav .fa-spin.admonition-title, .nav .rst-content h1 .fa-spin.headerlink, .rst-content h1 .nav .fa-spin.headerlink, .nav .rst-content h2 .fa-spin.headerlink, .rst-content h2 .nav .fa-spin.headerlink, .nav .rst-content h3 .fa-spin.headerlink, .rst-content h3 .nav .fa-spin.headerlink, .nav .rst-content h4 .fa-spin.headerlink, .rst-content h4 .nav .fa-spin.headerlink, .nav .rst-content h5 .fa-spin.headerlink, .rst-content h5 .nav .fa-spin.headerlink, .nav .rst-content h6 .fa-spin.headerlink, .rst-content h6 .nav .fa-spin.headerlink, .nav .rst-content dl dt .fa-spin.headerlink, .rst-content dl dt .nav .fa-spin.headerlink, .nav .rst-content p.caption .fa-spin.headerlink, .rst-content p.caption .nav .fa-spin.headerlink, .nav .rst-content tt.download span.fa-spin:first-child, .rst-content tt.download .nav span.fa-spin:first-child, .nav .rst-content code.download span.fa-spin:first-child, .rst-content code.download .nav span.fa-spin:first-child, .nav .fa-spin.icon { + display: inline-block; } + +.btn.fa:before, .wy-menu-vertical li span.btn.toctree-expand:before, .rst-content .btn.admonition-title:before, .rst-content h1 .btn.headerlink:before, .rst-content h2 .btn.headerlink:before, .rst-content h3 .btn.headerlink:before, .rst-content h4 .btn.headerlink:before, .rst-content h5 .btn.headerlink:before, .rst-content h6 .btn.headerlink:before, .rst-content dl dt .btn.headerlink:before, .rst-content p.caption .btn.headerlink:before, .rst-content tt.download span.btn:first-child:before, .rst-content code.download span.btn:first-child:before, .btn.icon:before { + opacity: 0.5; + -webkit-transition: opacity 0.05s ease-in; + -moz-transition: opacity 0.05s ease-in; + transition: opacity 0.05s ease-in; } + +.btn.fa:hover:before, .wy-menu-vertical li span.btn.toctree-expand:hover:before, .rst-content .btn.admonition-title:hover:before, .rst-content h1 .btn.headerlink:hover:before, .rst-content h2 .btn.headerlink:hover:before, .rst-content h3 .btn.headerlink:hover:before, .rst-content h4 .btn.headerlink:hover:before, .rst-content h5 .btn.headerlink:hover:before, .rst-content h6 .btn.headerlink:hover:before, .rst-content dl dt .btn.headerlink:hover:before, .rst-content p.caption .btn.headerlink:hover:before, .rst-content tt.download span.btn:first-child:hover:before, .rst-content code.download span.btn:first-child:hover:before, .btn.icon:hover:before { + opacity: 1; } + +.btn-mini .fa:before, .btn-mini .wy-menu-vertical li span.toctree-expand:before, .wy-menu-vertical li .btn-mini span.toctree-expand:before, .btn-mini .rst-content .admonition-title:before, .rst-content .btn-mini .admonition-title:before, .btn-mini .rst-content h1 .headerlink:before, .rst-content h1 .btn-mini .headerlink:before, .btn-mini .rst-content h2 .headerlink:before, .rst-content h2 .btn-mini .headerlink:before, .btn-mini .rst-content h3 .headerlink:before, .rst-content h3 .btn-mini .headerlink:before, .btn-mini .rst-content h4 .headerlink:before, .rst-content h4 .btn-mini .headerlink:before, .btn-mini .rst-content h5 .headerlink:before, .rst-content h5 .btn-mini .headerlink:before, .btn-mini .rst-content h6 .headerlink:before, .rst-content h6 .btn-mini .headerlink:before, .btn-mini .rst-content dl dt .headerlink:before, .rst-content dl dt .btn-mini .headerlink:before, .btn-mini .rst-content p.caption .headerlink:before, .rst-content p.caption .btn-mini .headerlink:before, .btn-mini .rst-content tt.download span:first-child:before, .rst-content tt.download .btn-mini span:first-child:before, .btn-mini .rst-content code.download span:first-child:before, .rst-content code.download .btn-mini span:first-child:before, .btn-mini .icon:before { + font-size: 14px; + vertical-align: -15%; } + +.wy-alert, .rst-content .note, .rst-content .attention, .rst-content .caution, .rst-content .danger, .rst-content .error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .warning, .rst-content .seealso, .rst-content .admonition-todo { + padding: 12px; + line-height: 24px; + margin-bottom: 24px; + background: #e7f2fa; } + +.wy-alert-title, .rst-content .admonition-title { + color: #fff; + font-weight: bold; + display: block; + color: #fff; + background: #6ab0de; + margin: -12px; + padding: 6px 12px; + margin-bottom: 12px; } + +.wy-alert.wy-alert-danger, .rst-content .wy-alert-danger.note, .rst-content .wy-alert-danger.attention, .rst-content .wy-alert-danger.caution, .rst-content .danger, .rst-content .error, .rst-content .wy-alert-danger.hint, .rst-content .wy-alert-danger.important, .rst-content .wy-alert-danger.tip, .rst-content .wy-alert-danger.warning, .rst-content .wy-alert-danger.seealso, .rst-content .wy-alert-danger.admonition-todo { + background: #fdf3f2; } + .wy-alert.wy-alert-danger .wy-alert-title, .rst-content .wy-alert-danger.note .wy-alert-title, .rst-content .wy-alert-danger.attention .wy-alert-title, .rst-content .wy-alert-danger.caution .wy-alert-title, .rst-content .danger .wy-alert-title, .rst-content .error .wy-alert-title, .rst-content .wy-alert-danger.hint .wy-alert-title, .rst-content .wy-alert-danger.important .wy-alert-title, .rst-content .wy-alert-danger.tip .wy-alert-title, .rst-content .wy-alert-danger.warning .wy-alert-title, .rst-content .wy-alert-danger.seealso .wy-alert-title, .rst-content .wy-alert-danger.admonition-todo .wy-alert-title, .wy-alert.wy-alert-danger .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-danger .admonition-title, .rst-content .wy-alert-danger.note .admonition-title, .rst-content .wy-alert-danger.attention .admonition-title, .rst-content .wy-alert-danger.caution .admonition-title, .rst-content .danger .admonition-title, .rst-content .error .admonition-title, .rst-content .wy-alert-danger.hint .admonition-title, .rst-content .wy-alert-danger.important .admonition-title, .rst-content .wy-alert-danger.tip .admonition-title, .rst-content .wy-alert-danger.warning .admonition-title, .rst-content .wy-alert-danger.seealso .admonition-title, .rst-content .wy-alert-danger.admonition-todo .admonition-title { + background: #f29f97; } + +.wy-alert.wy-alert-warning, .rst-content .wy-alert-warning.note, .rst-content .attention, .rst-content .caution, .rst-content .wy-alert-warning.danger, .rst-content .wy-alert-warning.error, .rst-content .wy-alert-warning.hint, .rst-content .wy-alert-warning.important, .rst-content .wy-alert-warning.tip, .rst-content .warning, .rst-content .wy-alert-warning.seealso, .rst-content .admonition-todo { + background: #ffedcc; } + .wy-alert.wy-alert-warning .wy-alert-title, .rst-content .wy-alert-warning.note .wy-alert-title, .rst-content .attention .wy-alert-title, .rst-content .caution .wy-alert-title, .rst-content .wy-alert-warning.danger .wy-alert-title, .rst-content .wy-alert-warning.error .wy-alert-title, .rst-content .wy-alert-warning.hint .wy-alert-title, .rst-content .wy-alert-warning.important .wy-alert-title, .rst-content .wy-alert-warning.tip .wy-alert-title, .rst-content .warning .wy-alert-title, .rst-content .wy-alert-warning.seealso .wy-alert-title, .rst-content .admonition-todo .wy-alert-title, .wy-alert.wy-alert-warning .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-warning .admonition-title, .rst-content .wy-alert-warning.note .admonition-title, .rst-content .attention .admonition-title, .rst-content .caution .admonition-title, .rst-content .wy-alert-warning.danger .admonition-title, .rst-content .wy-alert-warning.error .admonition-title, .rst-content .wy-alert-warning.hint .admonition-title, .rst-content .wy-alert-warning.important .admonition-title, .rst-content .wy-alert-warning.tip .admonition-title, .rst-content .warning .admonition-title, .rst-content .wy-alert-warning.seealso .admonition-title, .rst-content .admonition-todo .admonition-title { + background: #f0b37e; } + +.wy-alert.wy-alert-info, .rst-content .note, .rst-content .wy-alert-info.attention, .rst-content .wy-alert-info.caution, .rst-content .wy-alert-info.danger, .rst-content .wy-alert-info.error, .rst-content .wy-alert-info.hint, .rst-content .wy-alert-info.important, .rst-content .wy-alert-info.tip, .rst-content .wy-alert-info.warning, .rst-content .seealso, .rst-content .wy-alert-info.admonition-todo { + background: #e7f2fa; } + .wy-alert.wy-alert-info .wy-alert-title, .rst-content .note .wy-alert-title, .rst-content .wy-alert-info.attention .wy-alert-title, .rst-content .wy-alert-info.caution .wy-alert-title, .rst-content .wy-alert-info.danger .wy-alert-title, .rst-content .wy-alert-info.error .wy-alert-title, .rst-content .wy-alert-info.hint .wy-alert-title, .rst-content .wy-alert-info.important .wy-alert-title, .rst-content .wy-alert-info.tip .wy-alert-title, .rst-content .wy-alert-info.warning .wy-alert-title, .rst-content .seealso .wy-alert-title, .rst-content .wy-alert-info.admonition-todo .wy-alert-title, .wy-alert.wy-alert-info .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-info .admonition-title, .rst-content .note .admonition-title, .rst-content .wy-alert-info.attention .admonition-title, .rst-content .wy-alert-info.caution .admonition-title, .rst-content .wy-alert-info.danger .admonition-title, .rst-content .wy-alert-info.error .admonition-title, .rst-content .wy-alert-info.hint .admonition-title, .rst-content .wy-alert-info.important .admonition-title, .rst-content .wy-alert-info.tip .admonition-title, .rst-content .wy-alert-info.warning .admonition-title, .rst-content .seealso .admonition-title, .rst-content .wy-alert-info.admonition-todo .admonition-title { + background: #6ab0de; } + +.wy-alert.wy-alert-success, .rst-content .wy-alert-success.note, .rst-content .wy-alert-success.attention, .rst-content .wy-alert-success.caution, .rst-content .wy-alert-success.danger, .rst-content .wy-alert-success.error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .wy-alert-success.warning, .rst-content .wy-alert-success.seealso, .rst-content .wy-alert-success.admonition-todo { + background: #dbfaf4; } + .wy-alert.wy-alert-success .wy-alert-title, .rst-content .wy-alert-success.note .wy-alert-title, .rst-content .wy-alert-success.attention .wy-alert-title, .rst-content .wy-alert-success.caution .wy-alert-title, .rst-content .wy-alert-success.danger .wy-alert-title, .rst-content .wy-alert-success.error .wy-alert-title, .rst-content .hint .wy-alert-title, .rst-content .important .wy-alert-title, .rst-content .tip .wy-alert-title, .rst-content .wy-alert-success.warning .wy-alert-title, .rst-content .wy-alert-success.seealso .wy-alert-title, .rst-content .wy-alert-success.admonition-todo .wy-alert-title, .wy-alert.wy-alert-success .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-success .admonition-title, .rst-content .wy-alert-success.note .admonition-title, .rst-content .wy-alert-success.attention .admonition-title, .rst-content .wy-alert-success.caution .admonition-title, .rst-content .wy-alert-success.danger .admonition-title, .rst-content .wy-alert-success.error .admonition-title, .rst-content .hint .admonition-title, .rst-content .important .admonition-title, .rst-content .tip .admonition-title, .rst-content .wy-alert-success.warning .admonition-title, .rst-content .wy-alert-success.seealso .admonition-title, .rst-content .wy-alert-success.admonition-todo .admonition-title { + background: #1abc9c; } + +.wy-alert.wy-alert-neutral, .rst-content .wy-alert-neutral.note, .rst-content .wy-alert-neutral.attention, .rst-content .wy-alert-neutral.caution, .rst-content .wy-alert-neutral.danger, .rst-content .wy-alert-neutral.error, .rst-content .wy-alert-neutral.hint, .rst-content .wy-alert-neutral.important, .rst-content .wy-alert-neutral.tip, .rst-content .wy-alert-neutral.warning, .rst-content .wy-alert-neutral.seealso, .rst-content .wy-alert-neutral.admonition-todo { + background: #f3f6f6; } + .wy-alert.wy-alert-neutral .wy-alert-title, .rst-content .wy-alert-neutral.note .wy-alert-title, .rst-content .wy-alert-neutral.attention .wy-alert-title, .rst-content .wy-alert-neutral.caution .wy-alert-title, .rst-content .wy-alert-neutral.danger .wy-alert-title, .rst-content .wy-alert-neutral.error .wy-alert-title, .rst-content .wy-alert-neutral.hint .wy-alert-title, .rst-content .wy-alert-neutral.important .wy-alert-title, .rst-content .wy-alert-neutral.tip .wy-alert-title, .rst-content .wy-alert-neutral.warning .wy-alert-title, .rst-content .wy-alert-neutral.seealso .wy-alert-title, .rst-content .wy-alert-neutral.admonition-todo .wy-alert-title, .wy-alert.wy-alert-neutral .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-neutral .admonition-title, .rst-content .wy-alert-neutral.note .admonition-title, .rst-content .wy-alert-neutral.attention .admonition-title, .rst-content .wy-alert-neutral.caution .admonition-title, .rst-content .wy-alert-neutral.danger .admonition-title, .rst-content .wy-alert-neutral.error .admonition-title, .rst-content .wy-alert-neutral.hint .admonition-title, .rst-content .wy-alert-neutral.important .admonition-title, .rst-content .wy-alert-neutral.tip .admonition-title, .rst-content .wy-alert-neutral.warning .admonition-title, .rst-content .wy-alert-neutral.seealso .admonition-title, .rst-content .wy-alert-neutral.admonition-todo .admonition-title { + color: #404040; + background: #e1e4e5; } + .wy-alert.wy-alert-neutral a, .rst-content .wy-alert-neutral.note a, .rst-content .wy-alert-neutral.attention a, .rst-content .wy-alert-neutral.caution a, .rst-content .wy-alert-neutral.danger a, .rst-content .wy-alert-neutral.error a, .rst-content .wy-alert-neutral.hint a, .rst-content .wy-alert-neutral.important a, .rst-content .wy-alert-neutral.tip a, .rst-content .wy-alert-neutral.warning a, .rst-content .wy-alert-neutral.seealso a, .rst-content .wy-alert-neutral.admonition-todo a { + color: #2980B9; } + +.wy-alert p:last-child, .rst-content .note p:last-child, .rst-content .attention p:last-child, .rst-content .caution p:last-child, .rst-content .danger p:last-child, .rst-content .error p:last-child, .rst-content .hint p:last-child, .rst-content .important p:last-child, .rst-content .tip p:last-child, .rst-content .warning p:last-child, .rst-content .seealso p:last-child, .rst-content .admonition-todo p:last-child { + margin-bottom: 0; } + +.wy-tray-container { + position: fixed; + bottom: 0px; + left: 0; + z-index: 600; } + .wy-tray-container li { + display: block; + width: 300px; + background: transparent; + color: #fff; + text-align: center; + box-shadow: 0 5px 5px 0 rgba(0, 0, 0, 0.1); + padding: 0 24px; + min-width: 20%; + opacity: 0; + height: 0; + line-height: 56px; + overflow: hidden; + -webkit-transition: all 0.3s ease-in; + -moz-transition: all 0.3s ease-in; + transition: all 0.3s ease-in; } + .wy-tray-container li.wy-tray-item-success { + background: #27AE60; } + .wy-tray-container li.wy-tray-item-info { + background: #2980B9; } + .wy-tray-container li.wy-tray-item-warning { + background: #E67E22; } + .wy-tray-container li.wy-tray-item-danger { + background: #E74C3C; } + .wy-tray-container li.on { + opacity: 1; + height: 56px; } + +@media screen and (max-width: 768px) { + .wy-tray-container { + bottom: auto; + top: 0; + width: 100%; } + .wy-tray-container li { + width: 100%; } } +button { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; + cursor: pointer; + line-height: normal; + -webkit-appearance: button; + *overflow: visible; } + +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0; } + +button[disabled] { + cursor: default; } + +.btn { + /* Structure */ + display: inline-block; + border-radius: 2px; + line-height: normal; + white-space: nowrap; + text-align: center; + cursor: pointer; + font-size: 100%; + padding: 6px 12px 8px 12px; + color: #fff; + border: 1px solid rgba(0, 0, 0, 0.1); + background-color: #27AE60; + text-decoration: none; + font-weight: normal; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + box-shadow: 0px 1px 2px -1px rgba(255, 255, 255, 0.5) inset, 0px -2px 0px 0px rgba(0, 0, 0, 0.1) inset; + outline-none: false; + vertical-align: middle; + *display: inline; + zoom: 1; + -webkit-user-drag: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-transition: all 0.1s linear; + -moz-transition: all 0.1s linear; + transition: all 0.1s linear; } + +.btn-hover { + background: #2e8ece; + color: #fff; } + +.btn:hover { + background: #2cc36b; + color: #fff; } +.btn:focus { + background: #2cc36b; + outline: 0; } +.btn:active { + box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.05) inset, 0px 2px 0px 0px rgba(0, 0, 0, 0.1) inset; + padding: 8px 12px 6px 12px; } +.btn:visited { + color: #fff; } +.btn:disabled { + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=40); + opacity: 0.4; + cursor: not-allowed; + box-shadow: none; } + +.btn-disabled { + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=40); + opacity: 0.4; + cursor: not-allowed; + box-shadow: none; } + .btn-disabled:hover, .btn-disabled:focus, .btn-disabled:active { + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=40); + opacity: 0.4; + cursor: not-allowed; + box-shadow: none; } + +.btn::-moz-focus-inner { + padding: 0; + border: 0; } + +.btn-small { + font-size: 80%; } + +.btn-info { + background-color: #2980B9 !important; } + .btn-info:hover { + background-color: #2e8ece !important; } + +.btn-neutral { + background-color: #f3f6f6 !important; + color: #404040 !important; } + .btn-neutral:hover { + background-color: #e5ebeb !important; + color: #404040; } + .btn-neutral:visited { + color: #404040 !important; } + +.btn-success { + background-color: #27AE60 !important; } + .btn-success:hover { + background-color: #229955 !important; } + +.btn-danger { + background-color: #E74C3C !important; } + .btn-danger:hover { + background-color: #ea6153 !important; } + +.btn-warning { + background-color: #E67E22 !important; } + .btn-warning:hover { + background-color: #e98b39 !important; } + +.btn-invert { + background-color: #222; } + .btn-invert:hover { + background-color: #2f2f2f !important; } + +.btn-link { + background-color: transparent !important; + color: #2980B9; + box-shadow: none; + border-color: transparent !important; } + .btn-link:hover { + background-color: transparent !important; + color: #409ad5 !important; + box-shadow: none; } + .btn-link:active { + background-color: transparent !important; + color: #409ad5 !important; + box-shadow: none; } + .btn-link:visited { + color: #9B59B6; } + +.wy-btn-group .btn, .wy-control .btn { + vertical-align: middle; } + +.wy-btn-group { + margin-bottom: 24px; + *zoom: 1; } + .wy-btn-group:before, .wy-btn-group:after { + display: table; + content: ""; } + .wy-btn-group:after { + clear: both; } + +.wy-dropdown { + position: relative; + display: inline-block; } + +.wy-dropdown-active .wy-dropdown-menu { + display: block; } + +.wy-dropdown-menu { + position: absolute; + left: 0; + display: none; + float: left; + top: 100%; + min-width: 100%; + background: #fcfcfc; + z-index: 100; + border: solid 1px #cfd7dd; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.1); + padding: 12px; } + .wy-dropdown-menu > dd > a { + display: block; + clear: both; + color: #404040; + white-space: nowrap; + font-size: 90%; + padding: 0 12px; + cursor: pointer; } + .wy-dropdown-menu > dd > a:hover { + background: #2980B9; + color: #fff; } + .wy-dropdown-menu > dd.divider { + border-top: solid 1px #cfd7dd; + margin: 6px 0; } + .wy-dropdown-menu > dd.search { + padding-bottom: 12px; } + .wy-dropdown-menu > dd.search input[type="search"] { + width: 100%; } + .wy-dropdown-menu > dd.call-to-action { + background: #e3e3e3; + text-transform: uppercase; + font-weight: 500; + font-size: 80%; } + .wy-dropdown-menu > dd.call-to-action:hover { + background: #e3e3e3; } + .wy-dropdown-menu > dd.call-to-action .btn { + color: #fff; } + +.wy-dropdown.wy-dropdown-up .wy-dropdown-menu { + bottom: 100%; + top: auto; + left: auto; + right: 0; } + +.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu { + background: #fcfcfc; + margin-top: 2px; } +.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a { + padding: 6px 12px; } + .wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover { + background: #2980B9; + color: #fff; } + +.wy-dropdown.wy-dropdown-left .wy-dropdown-menu { + right: 0; + left: auto; + text-align: right; } + +.wy-dropdown-arrow:before { + content: " "; + border-bottom: 5px solid whitesmoke; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + position: absolute; + display: block; + top: -4px; + left: 50%; + margin-left: -3px; } +.wy-dropdown-arrow.wy-dropdown-arrow-left:before { + left: 11px; } + +.wy-form-stacked select { + display: block; } + +.wy-form-aligned input, .wy-form-aligned textarea, .wy-form-aligned select, .wy-form-aligned .wy-help-inline, .wy-form-aligned label { + display: inline-block; + *display: inline; + *zoom: 1; + vertical-align: middle; } + +.wy-form-aligned .wy-control-group > label { + display: inline-block; + vertical-align: middle; + width: 10em; + margin: 6px 12px 0 0; + float: left; } +.wy-form-aligned .wy-control { + float: left; } + .wy-form-aligned .wy-control label { + display: block; } + .wy-form-aligned .wy-control select { + margin-top: 6px; } + +fieldset { + border: 0; + margin: 0; + padding: 0; } + +legend { + display: block; + width: 100%; + border: 0; + padding: 0; + white-space: normal; + margin-bottom: 24px; + font-size: 150%; + *margin-left: -7px; } + +label { + display: block; + margin: 0 0 0.3125em 0; + color: #333; + font-size: 90%; } + +input, select, textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; } + +.wy-control-group { + margin-bottom: 24px; + *zoom: 1; + max-width: 68em; + margin-left: auto; + margin-right: auto; + *zoom: 1; } + .wy-control-group:before, .wy-control-group:after { + display: table; + content: ""; } + .wy-control-group:after { + clear: both; } + .wy-control-group:before, .wy-control-group:after { + display: table; + content: ""; } + .wy-control-group:after { + clear: both; } + +.wy-control-group.wy-control-group-required > label:after { + content: " *"; + color: #E74C3C; } + +.wy-control-group .wy-form-full, .wy-control-group .wy-form-halves, .wy-control-group .wy-form-thirds { + padding-bottom: 12px; } + .wy-control-group .wy-form-full select, .wy-control-group .wy-form-halves select, .wy-control-group .wy-form-thirds select { + width: 100%; } + .wy-control-group .wy-form-full input[type="text"], .wy-control-group .wy-form-full input[type="password"], .wy-control-group .wy-form-full input[type="email"], .wy-control-group .wy-form-full input[type="url"], .wy-control-group .wy-form-full input[type="date"], .wy-control-group .wy-form-full input[type="month"], .wy-control-group .wy-form-full input[type="time"], .wy-control-group .wy-form-full input[type="datetime"], .wy-control-group .wy-form-full input[type="datetime-local"], .wy-control-group .wy-form-full input[type="week"], .wy-control-group .wy-form-full input[type="number"], .wy-control-group .wy-form-full input[type="search"], .wy-control-group .wy-form-full input[type="tel"], .wy-control-group .wy-form-full input[type="color"], .wy-control-group .wy-form-halves input[type="text"], .wy-control-group .wy-form-halves input[type="password"], .wy-control-group .wy-form-halves input[type="email"], .wy-control-group .wy-form-halves input[type="url"], .wy-control-group .wy-form-halves input[type="date"], .wy-control-group .wy-form-halves input[type="month"], .wy-control-group .wy-form-halves input[type="time"], .wy-control-group .wy-form-halves input[type="datetime"], .wy-control-group .wy-form-halves input[type="datetime-local"], .wy-control-group .wy-form-halves input[type="week"], .wy-control-group .wy-form-halves input[type="number"], .wy-control-group .wy-form-halves input[type="search"], .wy-control-group .wy-form-halves input[type="tel"], .wy-control-group .wy-form-halves input[type="color"], .wy-control-group .wy-form-thirds input[type="text"], .wy-control-group .wy-form-thirds input[type="password"], .wy-control-group .wy-form-thirds input[type="email"], .wy-control-group .wy-form-thirds input[type="url"], .wy-control-group .wy-form-thirds input[type="date"], .wy-control-group .wy-form-thirds input[type="month"], .wy-control-group .wy-form-thirds input[type="time"], .wy-control-group .wy-form-thirds input[type="datetime"], .wy-control-group .wy-form-thirds input[type="datetime-local"], .wy-control-group .wy-form-thirds input[type="week"], .wy-control-group .wy-form-thirds input[type="number"], .wy-control-group .wy-form-thirds input[type="search"], .wy-control-group .wy-form-thirds input[type="tel"], .wy-control-group .wy-form-thirds input[type="color"] { + width: 100%; } + +.wy-control-group .wy-form-full { + float: left; + display: block; + margin-right: 2.35765%; + width: 100%; + margin-right: 0; } + .wy-control-group .wy-form-full:last-child { + margin-right: 0; } + +.wy-control-group .wy-form-halves { + float: left; + display: block; + margin-right: 2.35765%; + width: 48.82117%; } + .wy-control-group .wy-form-halves:last-child { + margin-right: 0; } + .wy-control-group .wy-form-halves:nth-of-type(2n) { + margin-right: 0; } + .wy-control-group .wy-form-halves:nth-of-type(2n+1) { + clear: left; } + +.wy-control-group .wy-form-thirds { + float: left; + display: block; + margin-right: 2.35765%; + width: 31.76157%; } + .wy-control-group .wy-form-thirds:last-child { + margin-right: 0; } + .wy-control-group .wy-form-thirds:nth-of-type(3n) { + margin-right: 0; } + .wy-control-group .wy-form-thirds:nth-of-type(3n+1) { + clear: left; } + +.wy-control-group.wy-control-group-no-input .wy-control { + margin: 6px 0 0 0; + font-size: 90%; } + +.wy-control-no-input { + display: inline-block; + margin: 6px 0 0 0; + font-size: 90%; } + +.wy-control-group.fluid-input input[type="text"], .wy-control-group.fluid-input input[type="password"], .wy-control-group.fluid-input input[type="email"], .wy-control-group.fluid-input input[type="url"], .wy-control-group.fluid-input input[type="date"], .wy-control-group.fluid-input input[type="month"], .wy-control-group.fluid-input input[type="time"], .wy-control-group.fluid-input input[type="datetime"], .wy-control-group.fluid-input input[type="datetime-local"], .wy-control-group.fluid-input input[type="week"], .wy-control-group.fluid-input input[type="number"], .wy-control-group.fluid-input input[type="search"], .wy-control-group.fluid-input input[type="tel"], .wy-control-group.fluid-input input[type="color"] { + width: 100%; } + +.wy-form-message-inline { + display: inline-block; + padding-left: 0.3em; + color: #666; + vertical-align: middle; + font-size: 90%; } + +.wy-form-message { + display: block; + color: #999; + font-size: 70%; + margin-top: 0.3125em; + font-style: italic; } + .wy-form-message p { + font-size: inherit; + font-style: italic; + margin-bottom: 6px; } + .wy-form-message p:last-child { + margin-bottom: 0; } + +input { + line-height: normal; } + +input[type="button"], input[type="reset"], input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + *overflow: visible; } +input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="date"], input[type="month"], input[type="time"], input[type="datetime"], input[type="datetime-local"], input[type="week"], input[type="number"], input[type="search"], input[type="tel"], input[type="color"] { + -webkit-appearance: none; + padding: 6px; + display: inline-block; + border: 1px solid #ccc; + font-size: 80%; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + box-shadow: inset 0 1px 3px #ddd; + border-radius: 0; + -webkit-transition: border 0.3s linear; + -moz-transition: border 0.3s linear; + transition: border 0.3s linear; } +input[type="datetime-local"] { + padding: 0.34375em 0.625em; } +input[disabled] { + cursor: default; } +input[type="checkbox"], input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; + margin-right: 0.3125em; + *height: 13px; + *width: 13px; } +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } +input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus, input[type="url"]:focus, input[type="date"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="week"]:focus, input[type="number"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="color"]:focus { + outline: 0; + outline: thin dotted \9; + border-color: #333; } +input.no-focus:focus { + border-color: #ccc !important; } +input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 1px auto #129FEA; } +input[type="text"][disabled], input[type="password"][disabled], input[type="email"][disabled], input[type="url"][disabled], input[type="date"][disabled], input[type="month"][disabled], input[type="time"][disabled], input[type="datetime"][disabled], input[type="datetime-local"][disabled], input[type="week"][disabled], input[type="number"][disabled], input[type="search"][disabled], input[type="tel"][disabled], input[type="color"][disabled] { + cursor: not-allowed; + background-color: #fafafa; } + +input:focus:invalid, textarea:focus:invalid, select:focus:invalid { + color: #E74C3C; + border: 1px solid #E74C3C; } + +input:focus:invalid:focus, textarea:focus:invalid:focus, select:focus:invalid:focus { + border-color: #E74C3C; } + +input[type="file"]:focus:invalid:focus, input[type="radio"]:focus:invalid:focus, input[type="checkbox"]:focus:invalid:focus { + outline-color: #E74C3C; } + +input.wy-input-large { + padding: 12px; + font-size: 100%; } + +textarea { + overflow: auto; + vertical-align: top; + width: 100%; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; } + +select, textarea { + padding: 0.5em 0.625em; + display: inline-block; + border: 1px solid #ccc; + font-size: 80%; + box-shadow: inset 0 1px 3px #ddd; + -webkit-transition: border 0.3s linear; + -moz-transition: border 0.3s linear; + transition: border 0.3s linear; } + +select { + border: 1px solid #ccc; + background-color: #fff; } + select[multiple] { + height: auto; } + +select:focus, textarea:focus { + outline: 0; } + +select[disabled], textarea[disabled], input[readonly], select[readonly], textarea[readonly] { + cursor: not-allowed; + background-color: #fafafa; } + +input[type="radio"][disabled], input[type="checkbox"][disabled] { + cursor: not-allowed; } + +.wy-checkbox, .wy-radio { + margin: 6px 0; + color: #404040; + display: block; } + .wy-checkbox input, .wy-radio input { + vertical-align: baseline; } + +.wy-form-message-inline { + display: inline-block; + *display: inline; + *zoom: 1; + vertical-align: middle; } + +.wy-input-prefix, .wy-input-suffix { + white-space: nowrap; + padding: 6px; } + .wy-input-prefix .wy-input-context, .wy-input-suffix .wy-input-context { + line-height: 27px; + padding: 0 8px; + display: inline-block; + font-size: 80%; + background-color: #f3f6f6; + border: solid 1px #ccc; + color: #999; } + +.wy-input-suffix .wy-input-context { + border-left: 0; } + +.wy-input-prefix .wy-input-context { + border-right: 0; } + +.wy-switch { + position: relative; + display: block; + height: 24px; + margin-top: 12px; + cursor: pointer; } + .wy-switch:before { + position: absolute; + content: ""; + display: block; + left: 0; + top: 0; + width: 36px; + height: 12px; + border-radius: 4px; + background: #ccc; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; } + .wy-switch:after { + position: absolute; + content: ""; + display: block; + width: 18px; + height: 18px; + border-radius: 4px; + background: #999; + left: -3px; + top: -3px; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; } + .wy-switch span { + position: absolute; + left: 48px; + display: block; + font-size: 12px; + color: #ccc; + line-height: 1; } + +.wy-switch.active:before { + background: #1e8449; } +.wy-switch.active:after { + left: 24px; + background: #27AE60; } + +.wy-switch.disabled { + cursor: not-allowed; + opacity: 0.8; } + +.wy-control-group.wy-control-group-error .wy-form-message, .wy-control-group.wy-control-group-error > label { + color: #E74C3C; } +.wy-control-group.wy-control-group-error input[type="text"], .wy-control-group.wy-control-group-error input[type="password"], .wy-control-group.wy-control-group-error input[type="email"], .wy-control-group.wy-control-group-error input[type="url"], .wy-control-group.wy-control-group-error input[type="date"], .wy-control-group.wy-control-group-error input[type="month"], .wy-control-group.wy-control-group-error input[type="time"], .wy-control-group.wy-control-group-error input[type="datetime"], .wy-control-group.wy-control-group-error input[type="datetime-local"], .wy-control-group.wy-control-group-error input[type="week"], .wy-control-group.wy-control-group-error input[type="number"], .wy-control-group.wy-control-group-error input[type="search"], .wy-control-group.wy-control-group-error input[type="tel"], .wy-control-group.wy-control-group-error input[type="color"] { + border: solid 1px #E74C3C; } +.wy-control-group.wy-control-group-error textarea { + border: solid 1px #E74C3C; } + +.wy-inline-validate { + white-space: nowrap; } + .wy-inline-validate .wy-input-context { + padding: 0.5em 0.625em; + display: inline-block; + font-size: 80%; } + +.wy-inline-validate.wy-inline-validate-success .wy-input-context { + color: #27AE60; } + +.wy-inline-validate.wy-inline-validate-danger .wy-input-context { + color: #E74C3C; } + +.wy-inline-validate.wy-inline-validate-warning .wy-input-context { + color: #E67E22; } + +.wy-inline-validate.wy-inline-validate-info .wy-input-context { + color: #2980B9; } + +.rotate-90 { + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + transform: rotate(90deg); } + +.rotate-180 { + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); } + +.rotate-270 { + -webkit-transform: rotate(270deg); + -moz-transform: rotate(270deg); + -ms-transform: rotate(270deg); + -o-transform: rotate(270deg); + transform: rotate(270deg); } + +.mirror { + -webkit-transform: scaleX(-1); + -moz-transform: scaleX(-1); + -ms-transform: scaleX(-1); + -o-transform: scaleX(-1); + transform: scaleX(-1); } + .mirror.rotate-90 { + -webkit-transform: scaleX(-1) rotate(90deg); + -moz-transform: scaleX(-1) rotate(90deg); + -ms-transform: scaleX(-1) rotate(90deg); + -o-transform: scaleX(-1) rotate(90deg); + transform: scaleX(-1) rotate(90deg); } + .mirror.rotate-180 { + -webkit-transform: scaleX(-1) rotate(180deg); + -moz-transform: scaleX(-1) rotate(180deg); + -ms-transform: scaleX(-1) rotate(180deg); + -o-transform: scaleX(-1) rotate(180deg); + transform: scaleX(-1) rotate(180deg); } + .mirror.rotate-270 { + -webkit-transform: scaleX(-1) rotate(270deg); + -moz-transform: scaleX(-1) rotate(270deg); + -ms-transform: scaleX(-1) rotate(270deg); + -o-transform: scaleX(-1) rotate(270deg); + transform: scaleX(-1) rotate(270deg); } + +@media only screen and (max-width: 480px) { + .wy-form button[type="submit"] { + margin: 0.7em 0 0; } + .wy-form input[type="text"], .wy-form input[type="password"], .wy-form input[type="email"], .wy-form input[type="url"], .wy-form input[type="date"], .wy-form input[type="month"], .wy-form input[type="time"], .wy-form input[type="datetime"], .wy-form input[type="datetime-local"], .wy-form input[type="week"], .wy-form input[type="number"], .wy-form input[type="search"], .wy-form input[type="tel"], .wy-form input[type="color"] { + margin-bottom: 0.3em; + display: block; } + .wy-form label { + margin-bottom: 0.3em; + display: block; } + + .wy-form input[type="password"], .wy-form input[type="email"], .wy-form input[type="url"], .wy-form input[type="date"], .wy-form input[type="month"], .wy-form input[type="time"], .wy-form input[type="datetime"], .wy-form input[type="datetime-local"], .wy-form input[type="week"], .wy-form input[type="number"], .wy-form input[type="search"], .wy-form input[type="tel"], .wy-form input[type="color"] { + margin-bottom: 0; } + + .wy-form-aligned .wy-control-group label { + margin-bottom: 0.3em; + text-align: left; + display: block; + width: 100%; } + .wy-form-aligned .wy-control { + margin: 1.5em 0 0 0; } + + .wy-form .wy-help-inline, .wy-form-message-inline, .wy-form-message { + display: block; + font-size: 80%; + padding: 6px 0; } } +@media screen and (max-width: 768px) { + .tablet-hide { + display: none; } } + +@media screen and (max-width: 480px) { + .mobile-hide { + display: none; } } + +.float-left { + float: left; } + +.float-right { + float: right; } + +.full-width { + width: 100%; } + +.wy-table, .rst-content table.docutils, .rst-content table.field-list { + border-collapse: collapse; + border-spacing: 0; + empty-cells: show; + margin-bottom: 24px; } + .wy-table caption, .rst-content table.docutils caption, .rst-content table.field-list caption { + color: #000; + font: italic 85%/1 arial, sans-serif; + padding: 1em 0; + text-align: center; } + .wy-table td, .rst-content table.docutils td, .rst-content table.field-list td, .wy-table th, .rst-content table.docutils th, .rst-content table.field-list th { + font-size: 90%; + margin: 0; + overflow: visible; + padding: 8px 16px; } + .wy-table td:first-child, .rst-content table.docutils td:first-child, .rst-content table.field-list td:first-child, .wy-table th:first-child, .rst-content table.docutils th:first-child, .rst-content table.field-list th:first-child { + border-left-width: 0; } + .wy-table thead, .rst-content table.docutils thead, .rst-content table.field-list thead { + color: #000; + text-align: left; + vertical-align: bottom; + white-space: nowrap; } + .wy-table thead th, .rst-content table.docutils thead th, .rst-content table.field-list thead th { + font-weight: bold; + border-bottom: solid 2px #e1e4e5; } + .wy-table td, .rst-content table.docutils td, .rst-content table.field-list td { + background-color: transparent; + vertical-align: middle; } + +.wy-table td p, .rst-content table.docutils td p, .rst-content table.field-list td p { + line-height: 18px; } + .wy-table td p:last-child, .rst-content table.docutils td p:last-child, .rst-content table.field-list td p:last-child { + margin-bottom: 0; } + +.wy-table .wy-table-cell-min, .rst-content table.docutils .wy-table-cell-min, .rst-content table.field-list .wy-table-cell-min { + width: 1%; + padding-right: 0; } + .wy-table .wy-table-cell-min input[type=checkbox], .rst-content table.docutils .wy-table-cell-min input[type=checkbox], .rst-content table.field-list .wy-table-cell-min input[type=checkbox], .wy-table .wy-table-cell-min input[type=checkbox], .rst-content table.docutils .wy-table-cell-min input[type=checkbox], .rst-content table.field-list .wy-table-cell-min input[type=checkbox] { + margin: 0; } + +.wy-table-secondary { + color: gray; + font-size: 90%; } + +.wy-table-tertiary { + color: gray; + font-size: 80%; } + +.wy-table-odd td, .wy-table-striped tr:nth-child(2n-1) td, .rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td { + background-color: #f3f6f6; } + +.wy-table-backed { + background-color: #f3f6f6; } + +/* BORDERED TABLES */ +.wy-table-bordered-all, .rst-content table.docutils { + border: 1px solid #e1e4e5; } + .wy-table-bordered-all td, .rst-content table.docutils td { + border-bottom: 1px solid #e1e4e5; + border-left: 1px solid #e1e4e5; } + .wy-table-bordered-all tbody > tr:last-child td, .rst-content table.docutils tbody > tr:last-child td { + border-bottom-width: 0; } + +.wy-table-bordered { + border: 1px solid #e1e4e5; } + +.wy-table-bordered-rows td { + border-bottom: 1px solid #e1e4e5; } +.wy-table-bordered-rows tbody > tr:last-child td { + border-bottom-width: 0; } + +.wy-table-horizontal tbody > tr:last-child td { + border-bottom-width: 0; } +.wy-table-horizontal td, .wy-table-horizontal th { + border-width: 0 0 1px 0; + border-bottom: 1px solid #e1e4e5; } +.wy-table-horizontal tbody > tr:last-child td { + border-bottom-width: 0; } + +/* RESPONSIVE TABLES */ +.wy-table-responsive { + margin-bottom: 24px; + max-width: 100%; + overflow: auto; } + .wy-table-responsive table { + margin-bottom: 0 !important; } + .wy-table-responsive table td, .wy-table-responsive table th { + white-space: nowrap; } + +a { + color: #2980B9; + text-decoration: none; + cursor: pointer; } + a:hover { + color: #3091d1; } + a:visited { + color: #9B59B6; } + +html { + height: 100%; + overflow-x: hidden; } + +body { + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + font-weight: normal; + color: #404040; + min-height: 100%; + overflow-x: hidden; + background: #edf0f2; } + +.wy-text-left { + text-align: left; } + +.wy-text-center { + text-align: center; } + +.wy-text-right { + text-align: right; } + +.wy-text-large { + font-size: 120%; } + +.wy-text-normal { + font-size: 100%; } + +.wy-text-small, small { + font-size: 80%; } + +.wy-text-strike { + text-decoration: line-through; } + +.wy-text-warning { + color: #E67E22 !important; } + +a.wy-text-warning:hover { + color: #eb9950 !important; } + +.wy-text-info { + color: #2980B9 !important; } + +a.wy-text-info:hover { + color: #409ad5 !important; } + +.wy-text-success { + color: #27AE60 !important; } + +a.wy-text-success:hover { + color: #36d278 !important; } + +.wy-text-danger { + color: #E74C3C !important; } + +a.wy-text-danger:hover { + color: #ed7669 !important; } + +.wy-text-neutral { + color: #404040 !important; } + +a.wy-text-neutral:hover { + color: #595959 !important; } + +h1, h2, .rst-content .toctree-wrapper p.caption, h3, h4, h5, h6, legend { + margin-top: 0; + font-weight: 700; + font-family: "Roboto Slab", "ff-tisa-web-pro", "Georgia", Arial, sans-serif; } + +p { + line-height: 24px; + margin: 0; + font-size: 16px; + margin-bottom: 24px; } + +h1 { + font-size: 175%; } + +h2, .rst-content .toctree-wrapper p.caption { + font-size: 150%; } + +h3 { + font-size: 125%; } + +h4 { + font-size: 115%; } + +h5 { + font-size: 110%; } + +h6 { + font-size: 100%; } + +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #e1e4e5; + margin: 24px 0; + padding: 0; } + +code, .rst-content tt, .rst-content code { + white-space: nowrap; + max-width: 100%; + background: #fff; + border: solid 1px #e1e4e5; + font-size: 75%; + padding: 0 5px; + font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; + color: #E74C3C; + overflow-x: auto; } + code.code-large, .rst-content tt.code-large { + font-size: 90%; } + +.wy-plain-list-disc, .rst-content .section ul, .rst-content .toctree-wrapper ul, article ul { + list-style: disc; + line-height: 24px; + margin-bottom: 24px; } + .wy-plain-list-disc li, .rst-content .section ul li, .rst-content .toctree-wrapper ul li, article ul li { + list-style: disc; + margin-left: 24px; } + .wy-plain-list-disc li p:last-child, .rst-content .section ul li p:last-child, .rst-content .toctree-wrapper ul li p:last-child, article ul li p:last-child { + margin-bottom: 0; } + .wy-plain-list-disc li ul, .rst-content .section ul li ul, .rst-content .toctree-wrapper ul li ul, article ul li ul { + margin-bottom: 0; } + .wy-plain-list-disc li li, .rst-content .section ul li li, .rst-content .toctree-wrapper ul li li, article ul li li { + list-style: circle; } + .wy-plain-list-disc li li li, .rst-content .section ul li li li, .rst-content .toctree-wrapper ul li li li, article ul li li li { + list-style: square; } + .wy-plain-list-disc li ol li, .rst-content .section ul li ol li, .rst-content .toctree-wrapper ul li ol li, article ul li ol li { + list-style: decimal; } + +.wy-plain-list-decimal, .rst-content .section ol, .rst-content ol.arabic, article ol { + list-style: decimal; + line-height: 24px; + margin-bottom: 24px; } + .wy-plain-list-decimal li, .rst-content .section ol li, .rst-content ol.arabic li, article ol li { + list-style: decimal; + margin-left: 24px; } + .wy-plain-list-decimal li p:last-child, .rst-content .section ol li p:last-child, .rst-content ol.arabic li p:last-child, article ol li p:last-child { + margin-bottom: 0; } + .wy-plain-list-decimal li ul, .rst-content .section ol li ul, .rst-content ol.arabic li ul, article ol li ul { + margin-bottom: 0; } + .wy-plain-list-decimal li ul li, .rst-content .section ol li ul li, .rst-content ol.arabic li ul li, article ol li ul li { + list-style: disc; } + +.codeblock-example { + border: 1px solid #e1e4e5; + border-bottom: none; + padding: 24px; + padding-top: 48px; + font-weight: 500; + background: #fff; + position: relative; } + .codeblock-example:after { + content: "Example"; + position: absolute; + top: 0px; + left: 0px; + background: #9B59B6; + color: white; + padding: 6px 12px; } + .codeblock-example.prettyprint-example-only { + border: 1px solid #e1e4e5; + margin-bottom: 24px; } + +.codeblock, pre.literal-block, .rst-content .literal-block, .rst-content pre.literal-block, div[class^='highlight'] { + border: 1px solid #e1e4e5; + padding: 0px; + overflow-x: auto; + background: #fff; + margin: 1px 0 24px 0; } + .codeblock div[class^='highlight'], pre.literal-block div[class^='highlight'], .rst-content .literal-block div[class^='highlight'], div[class^='highlight'] div[class^='highlight'] { + border: none; + background: none; + margin: 0; } + +div[class^='highlight'] td.code { + width: 100%; } + +.linenodiv pre { + border-right: solid 1px #e6e9ea; + margin: 0; + padding: 12px 12px; + font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; + font-size: 12px; + line-height: 1.5; + color: #d9d9d9; } + +div[class^='highlight'] pre { + white-space: pre; + margin: 0; + padding: 12px 12px; + font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; + font-size: 12px; + line-height: 1.5; + display: block; + overflow: auto; + color: #404040; } + +@media print { + .codeblock, pre.literal-block, .rst-content .literal-block, .rst-content pre.literal-block, div[class^='highlight'], div[class^='highlight'] pre { + white-space: pre-wrap; } } +.hll { + background-color: #ffffcc; + margin: 0 -12px; + padding: 0 12px; + display: block; } + +.c { + color: #999988; + font-style: italic; } + +.err { + color: #a61717; + background-color: #e3d2d2; } + +.k { + font-weight: bold; } + +.o { + font-weight: bold; } + +.cm { + color: #999988; + font-style: italic; } + +.cp { + color: #999999; + font-weight: bold; } + +.c1 { + color: #999988; + font-style: italic; } + +.cs { + color: #999999; + font-weight: bold; + font-style: italic; } + +.gd { + color: #000000; + background-color: #ffdddd; } + +.gd .x { + color: #000000; + background-color: #ffaaaa; } + +.ge { + font-style: italic; } + +.gr { + color: #aa0000; } + +.gh { + color: #999999; } + +.gi { + color: #000000; + background-color: #ddffdd; } + +.gi .x { + color: #000000; + background-color: #aaffaa; } + +.go { + color: #888888; } + +.gp { + color: #555555; } + +.gs { + font-weight: bold; } + +.gu { + color: #800080; + font-weight: bold; } + +.gt { + color: #aa0000; } + +.kc { + font-weight: bold; } + +.kd { + font-weight: bold; } + +.kn { + font-weight: bold; } + +.kp { + font-weight: bold; } + +.kr { + font-weight: bold; } + +.kt { + color: #445588; + font-weight: bold; } + +.m { + color: #009999; } + +.s { + color: #dd1144; } + +.n { + color: #333333; } + +.na { + color: teal; } + +.nb { + color: #0086b3; } + +.nc { + color: #445588; + font-weight: bold; } + +.no { + color: teal; } + +.ni { + color: purple; } + +.ne { + color: #990000; + font-weight: bold; } + +.nf { + color: #990000; + font-weight: bold; } + +.nn { + color: #555555; } + +.nt { + color: navy; } + +.nv { + color: teal; } + +.ow { + font-weight: bold; } + +.w { + color: #bbbbbb; } + +.mf { + color: #009999; } + +.mh { + color: #009999; } + +.mi { + color: #009999; } + +.mo { + color: #009999; } + +.sb { + color: #dd1144; } + +.sc { + color: #dd1144; } + +.sd { + color: #dd1144; } + +.s2 { + color: #dd1144; } + +.se { + color: #dd1144; } + +.sh { + color: #dd1144; } + +.si { + color: #dd1144; } + +.sx { + color: #dd1144; } + +.sr { + color: #009926; } + +.s1 { + color: #dd1144; } + +.ss { + color: #990073; } + +.bp { + color: #999999; } + +.vc { + color: teal; } + +.vg { + color: teal; } + +.vi { + color: teal; } + +.il { + color: #009999; } + +.gc { + color: #999; + background-color: #EAF2F5; } + +.wy-breadcrumbs li { + display: inline-block; } + .wy-breadcrumbs li.wy-breadcrumbs-aside { + float: right; } + .wy-breadcrumbs li a { + display: inline-block; + padding: 5px; } + .wy-breadcrumbs li a:first-child { + padding-left: 0; } + .wy-breadcrumbs li code, .wy-breadcrumbs li .rst-content tt, .rst-content .wy-breadcrumbs li tt { + padding: 5px; + border: none; + background: none; } + .wy-breadcrumbs li code.literal, .wy-breadcrumbs li .rst-content tt.literal, .rst-content .wy-breadcrumbs li tt.literal { + color: #404040; } + +.wy-breadcrumbs-extra { + margin-bottom: 0; + color: #b3b3b3; + font-size: 80%; + display: inline-block; } + +@media screen and (max-width: 480px) { + .wy-breadcrumbs-extra { + display: none; } + + .wy-breadcrumbs li.wy-breadcrumbs-aside { + display: none; } } +@media print { + .wy-breadcrumbs li.wy-breadcrumbs-aside { + display: none; } } +.wy-affix { + position: fixed; + top: 1.618em; } + +.wy-menu a:hover { + text-decoration: none; } + +.wy-menu-horiz { + *zoom: 1; } + .wy-menu-horiz:before, .wy-menu-horiz:after { + display: table; + content: ""; } + .wy-menu-horiz:after { + clear: both; } + .wy-menu-horiz ul, .wy-menu-horiz li { + display: inline-block; } + .wy-menu-horiz li:hover { + background: rgba(255, 255, 255, 0.1); } + .wy-menu-horiz li.divide-left { + border-left: solid 1px #404040; } + .wy-menu-horiz li.divide-right { + border-right: solid 1px #404040; } + .wy-menu-horiz a { + height: 32px; + display: inline-block; + line-height: 32px; + padding: 0 16px; } + +.wy-menu-vertical { + width: 300px; } + .wy-menu-vertical header, .wy-menu-vertical p.caption { + height: 32px; + display: inline-block; + line-height: 32px; + padding: 0 1.618em; + margin-bottom: 0; + display: block; + font-weight: bold; + text-transform: uppercase; + font-size: 80%; + color: #6f6f6f; + white-space: nowrap; } + .wy-menu-vertical ul { + margin-bottom: 0; } + .wy-menu-vertical li.divide-top { + border-top: solid 1px #404040; } + .wy-menu-vertical li.divide-bottom { + border-bottom: solid 1px #404040; } + .wy-menu-vertical li.current { + background: #e3e3e3; } + .wy-menu-vertical li.current a { + color: gray; + border-right: solid 1px #c9c9c9; + padding: 0.4045em 2.427em; } + .wy-menu-vertical li.current a:hover { + background: #d6d6d6; } + .wy-menu-vertical li code, .wy-menu-vertical li .rst-content tt, .rst-content .wy-menu-vertical li tt { + border: none; + background: inherit; + color: inherit; + padding-left: 0; + padding-right: 0; } + .wy-menu-vertical li span.toctree-expand { + display: block; + float: left; + margin-left: -1.2em; + font-size: 0.8em; + line-height: 1.6em; + color: #4d4d4d; } + .wy-menu-vertical li.on a, .wy-menu-vertical li.current > a { + color: #404040; + padding: 0.4045em 1.618em; + font-weight: bold; + position: relative; + background: #fcfcfc; + border: none; + border-bottom: solid 1px #c9c9c9; + border-top: solid 1px #c9c9c9; + padding-left: 1.618em -4px; } + .wy-menu-vertical li.on a:hover, .wy-menu-vertical li.current > a:hover { + background: #fcfcfc; } + .wy-menu-vertical li.on a:hover span.toctree-expand, .wy-menu-vertical li.current > a:hover span.toctree-expand { + color: gray; } + .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.current > a span.toctree-expand { + display: block; + font-size: 0.8em; + line-height: 1.6em; + color: #333333; } + .wy-menu-vertical li.toctree-l1.current li.toctree-l2 > ul, .wy-menu-vertical li.toctree-l2.current li.toctree-l3 > ul { + display: none; } + .wy-menu-vertical li.toctree-l1.current li.toctree-l2.current > ul, .wy-menu-vertical li.toctree-l2.current li.toctree-l3.current > ul { + display: block; } + .wy-menu-vertical li.toctree-l2.current > a { + background: #c9c9c9; + padding: 0.4045em 2.427em; } + .wy-menu-vertical li.toctree-l2.current li.toctree-l3 > a { + display: block; + background: #c9c9c9; + padding: 0.4045em 4.045em; } + .wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand { + color: gray; } + .wy-menu-vertical li.toctree-l2 span.toctree-expand { + color: #a3a3a3; } + .wy-menu-vertical li.toctree-l3 { + font-size: 0.9em; } + .wy-menu-vertical li.toctree-l3.current > a { + background: #bdbdbd; + padding: 0.4045em 4.045em; } + .wy-menu-vertical li.toctree-l3.current li.toctree-l4 > a { + display: block; + background: #bdbdbd; + padding: 0.4045em 5.663em; + border-top: none; + border-bottom: none; } + .wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand { + color: gray; } + .wy-menu-vertical li.toctree-l3 span.toctree-expand { + color: #969696; } + .wy-menu-vertical li.toctree-l4 { + font-size: 0.9em; } + .wy-menu-vertical li.current ul { + display: block; } + .wy-menu-vertical li ul { + margin-bottom: 0; + display: none; } + .wy-menu-vertical .local-toc li ul { + display: block; } + .wy-menu-vertical li ul li a { + margin-bottom: 0; + color: #b3b3b3; + font-weight: normal; } + .wy-menu-vertical a { + display: inline-block; + line-height: 18px; + padding: 0.4045em 1.618em; + display: block; + position: relative; + font-size: 90%; + color: #b3b3b3; } + .wy-menu-vertical a:hover { + background-color: #4e4a4a; + cursor: pointer; } + .wy-menu-vertical a:hover span.toctree-expand { + color: #b3b3b3; } + .wy-menu-vertical a:active { + background-color: #2980B9; + cursor: pointer; + color: #fff; } + .wy-menu-vertical a:active span.toctree-expand { + color: #fff; } + +.wy-side-nav-search { + display: block; + width: 300px; + padding: 0.809em; + margin-bottom: 0.809em; + z-index: 200; + background-color: #d94f00; + text-align: center; + padding: 0.809em; + display: block; + color: #fcfcfc; + margin-bottom: 0.809em; } + .wy-side-nav-search input[type=text] { + width: 100%; + border-radius: 50px; + padding: 6px 12px; + border-color: #2472a4; } + .wy-side-nav-search img { + display: block; + margin: auto auto 0.809em auto; + height: 45px; + width: 45px; + background-color: #2980B9; + padding: 5px; + border-radius: 100%; } + .wy-side-nav-search > a, .wy-side-nav-search .wy-dropdown > a { + color: #fcfcfc; + font-size: 100%; + font-weight: bold; + display: inline-block; + padding: 4px 6px; + margin-bottom: 0.809em; } + .wy-side-nav-search > a:hover, .wy-side-nav-search .wy-dropdown > a:hover { + background: rgba(255, 255, 255, 0.1); } + .wy-side-nav-search > a img.logo, .wy-side-nav-search .wy-dropdown > a img.logo { + display: block; + margin: 0 auto; + height: auto; + width: 160px; + border-radius: 0; + max-width: 100%; + background: transparent; } + .wy-side-nav-search > a.icon img.logo, .wy-side-nav-search .wy-dropdown > a.icon img.logo { + margin-top: 0.85em; } + .wy-side-nav-search > div.version { + margin-top: -0.4045em; + margin-bottom: 0.809em; + font-weight: normal; + color: rgba(255, 255, 255, 0.3); } + +.wy-nav .wy-menu-vertical header { + color: #2980B9; } +.wy-nav .wy-menu-vertical a { + color: #b3b3b3; } + .wy-nav .wy-menu-vertical a:hover { + background-color: #2980B9; + color: #fff; } + +[data-menu-wrap] { + -webkit-transition: all 0.2s ease-in; + -moz-transition: all 0.2s ease-in; + transition: all 0.2s ease-in; + position: absolute; + opacity: 1; + width: 100%; + opacity: 0; } + [data-menu-wrap].move-center { + left: 0; + right: auto; + opacity: 1; } + [data-menu-wrap].move-left { + right: auto; + left: -100%; + opacity: 0; } + [data-menu-wrap].move-right { + right: -100%; + left: auto; + opacity: 0; } + +.wy-body-for-nav { + background: left repeat-y #fcfcfc; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC); + background-size: 300px 1px; } + +.wy-grid-for-nav { + position: absolute; + width: 100%; + height: 100%; } + +.wy-nav-side { + position: fixed; + top: 0; + bottom: 0; + left: 0; + padding-bottom: 2em; + width: 300px; + overflow-x: hidden; + overflow-y: hidden; + min-height: 100%; + background: #343131; + z-index: 200; } + +.wy-side-scroll { + width: 320px; + position: relative; + overflow-x: hidden; + overflow-y: scroll; + height: 100%; } + +.wy-nav-top { + display: none; + background: #2980B9; + color: #fff; + padding: 0.4045em 0.809em; + position: relative; + line-height: 50px; + text-align: center; + font-size: 100%; + *zoom: 1; } + .wy-nav-top:before, .wy-nav-top:after { + display: table; + content: ""; } + .wy-nav-top:after { + clear: both; } + .wy-nav-top a { + color: #fff; + font-weight: bold; } + .wy-nav-top img { + margin-right: 12px; + height: 45px; + width: 45px; + background-color: #2980B9; + padding: 5px; + border-radius: 100%; } + .wy-nav-top i { + font-size: 30px; + float: left; + cursor: pointer; + padding-top: inherit; } + +.wy-nav-content-wrap { + margin-left: 300px; + background: #fcfcfc; + min-height: 100%; } + +.wy-nav-content { + padding: 1.618em 3.236em; + height: 100%; + max-width: 800px; + margin: auto; } + +.wy-body-mask { + position: fixed; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.2); + display: none; + z-index: 499; } + .wy-body-mask.on { + display: block; } + +footer { + color: gray; } + footer p { + margin-bottom: 12px; } + footer span.commit code, footer span.commit .rst-content tt, .rst-content footer span.commit tt { + padding: 0px; + font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; + font-size: 1em; + background: none; + border: none; + color: gray; } + +.rst-footer-buttons { + *zoom: 1; } + .rst-footer-buttons:before, .rst-footer-buttons:after { + width: 100%; } + .rst-footer-buttons:before, .rst-footer-buttons:after { + display: table; + content: ""; } + .rst-footer-buttons:after { + clear: both; } + +.rst-breadcrumbs-buttons { + margin-top: 12px; + *zoom: 1; } + .rst-breadcrumbs-buttons:before, .rst-breadcrumbs-buttons:after { + display: table; + content: ""; } + .rst-breadcrumbs-buttons:after { + clear: both; } + +#search-results .search li { + margin-bottom: 24px; + border-bottom: solid 1px #e1e4e5; + padding-bottom: 24px; } +#search-results .search li:first-child { + border-top: solid 1px #e1e4e5; + padding-top: 24px; } +#search-results .search li a { + font-size: 120%; + margin-bottom: 12px; + display: inline-block; } +#search-results .context { + color: gray; + font-size: 90%; } + +@media screen and (max-width: 768px) { + .wy-body-for-nav { + background: #fcfcfc; } + + .wy-nav-top { + display: block; } + + .wy-nav-side { + left: -300px; } + .wy-nav-side.shift { + width: 85%; + left: 0; } + + .wy-side-scroll { + width: auto; } + + .wy-side-nav-search { + width: auto; } + + .wy-menu.wy-menu-vertical { + width: auto; } + + .wy-nav-content-wrap { + margin-left: 0; } + .wy-nav-content-wrap .wy-nav-content { + padding: 1.618em; } + .wy-nav-content-wrap.shift { + position: fixed; + min-width: 100%; + left: 85%; + top: 0; + height: 100%; + overflow: hidden; } } +@media screen and (min-width: 1400px) { + .wy-nav-content-wrap { + background: rgba(0, 0, 0, 0.05); } + + .wy-nav-content { + margin: 0; + background: #fcfcfc; } } +@media print { + .rst-versions, footer, .wy-nav-side { + display: none; } + + .wy-nav-content-wrap { + margin-left: 0; } } +.rst-versions { + position: fixed; + bottom: 0; + left: 0; + width: 300px; + color: #fcfcfc; + background: #1f1d1d; + border-top: solid 10px #343131; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + z-index: 400; } + .rst-versions a { + color: #2980B9; + text-decoration: none; } + .rst-versions .rst-badge-small { + display: none; } + .rst-versions .rst-current-version { + padding: 12px; + background-color: #272525; + display: block; + text-align: right; + font-size: 90%; + cursor: pointer; + color: #27AE60; + *zoom: 1; } + .rst-versions .rst-current-version:before, .rst-versions .rst-current-version:after { + display: table; + content: ""; } + .rst-versions .rst-current-version:after { + clear: both; } + .rst-versions .rst-current-version .fa, .rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand, .rst-versions .rst-current-version .rst-content .admonition-title, .rst-content .rst-versions .rst-current-version .admonition-title, .rst-versions .rst-current-version .rst-content h1 .headerlink, .rst-content h1 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h2 .headerlink, .rst-content h2 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h3 .headerlink, .rst-content h3 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h4 .headerlink, .rst-content h4 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h5 .headerlink, .rst-content h5 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h6 .headerlink, .rst-content h6 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content dl dt .headerlink, .rst-content dl dt .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content p.caption .headerlink, .rst-content p.caption .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content tt.download span:first-child, .rst-content tt.download .rst-versions .rst-current-version span:first-child, .rst-versions .rst-current-version .rst-content code.download span:first-child, .rst-content code.download .rst-versions .rst-current-version span:first-child, .rst-versions .rst-current-version .icon { + color: #fcfcfc; } + .rst-versions .rst-current-version .fa-book, .rst-versions .rst-current-version .icon-book { + float: left; } + .rst-versions .rst-current-version .icon-book { + float: left; } + .rst-versions .rst-current-version.rst-out-of-date { + background-color: #E74C3C; + color: #fff; } + .rst-versions .rst-current-version.rst-active-old-version { + background-color: #F1C40F; + color: #000; } + .rst-versions.shift-up .rst-other-versions { + display: block; } + .rst-versions .rst-other-versions { + font-size: 90%; + padding: 12px; + color: gray; + display: none; } + .rst-versions .rst-other-versions hr { + display: block; + height: 1px; + border: 0; + margin: 20px 0; + padding: 0; + border-top: solid 1px #413d3d; } + .rst-versions .rst-other-versions dd { + display: inline-block; + margin: 0; } + .rst-versions .rst-other-versions dd a { + display: inline-block; + padding: 6px; + color: #fcfcfc; } + .rst-versions.rst-badge { + width: auto; + bottom: 20px; + right: 20px; + left: auto; + border: none; + max-width: 300px; } + .rst-versions.rst-badge .icon-book { + float: none; } + .rst-versions.rst-badge .fa-book, .rst-versions.rst-badge .icon-book { + float: none; } + .rst-versions.rst-badge.shift-up .rst-current-version { + text-align: right; } + .rst-versions.rst-badge.shift-up .rst-current-version .fa-book, .rst-versions.rst-badge.shift-up .rst-current-version .icon-book { + float: left; } + .rst-versions.rst-badge.shift-up .rst-current-version .icon-book { + float: left; } + .rst-versions.rst-badge .rst-current-version { + width: auto; + height: 30px; + line-height: 30px; + padding: 0 6px; + display: block; + text-align: center; } + +@media screen and (max-width: 768px) { + .rst-versions { + width: 85%; + display: none; } + .rst-versions.shift { + display: block; } } +.rst-content img { + max-width: 100%; + height: auto !important; } +.rst-content .highlight > pre, .rst-content .linenodiv > pre { + line-height: normal; } +.rst-content div.figure { + margin-bottom: 24px; } + .rst-content div.figure p.caption { + font-style: italic; } +.rst-content div.figure.align-center { + text-align: center; } +.rst-content .section > img, .rst-content .section > a > img { + margin-bottom: 24px; } +.rst-content blockquote { + margin-left: 24px; + line-height: 24px; + margin-bottom: 24px; } +.rst-content .note .last, .rst-content .attention .last, .rst-content .caution .last, .rst-content .danger .last, .rst-content .error .last, .rst-content .hint .last, .rst-content .important .last, .rst-content .tip .last, .rst-content .warning .last, .rst-content .seealso .last, .rst-content .admonition-todo .last { + margin-bottom: 0; } +.rst-content .admonition-title:before { + margin-right: 4px; } +.rst-content .admonition table { + border-color: rgba(0, 0, 0, 0.1); } + .rst-content .admonition table td, .rst-content .admonition table th { + background: transparent !important; + border-color: rgba(0, 0, 0, 0.1) !important; } +.rst-content .section ol.loweralpha, .rst-content .section ol.loweralpha li { + list-style: lower-alpha; } +.rst-content .section ol.upperalpha, .rst-content .section ol.upperalpha li { + list-style: upper-alpha; } +.rst-content .section ol p, .rst-content .section ul p { + margin-bottom: 12px; } +.rst-content .line-block { + margin-left: 24px; } +.rst-content .topic-title { + font-weight: bold; + margin-bottom: 12px; } +.rst-content .toc-backref { + color: #404040; } +.rst-content .align-right { + float: right; + margin: 0px 0px 24px 24px; } +.rst-content .align-left { + float: left; + margin: 0px 24px 24px 0px; } +.rst-content .align-center { + margin: auto; + display: block; } +.rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content .toctree-wrapper p.caption .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink, .rst-content p.caption .headerlink { + display: none; + visibility: hidden; + font-size: 14px; } + .rst-content h1 .headerlink:after, .rst-content h2 .headerlink:after, .rst-content .toctree-wrapper p.caption .headerlink:after, .rst-content h3 .headerlink:after, .rst-content h4 .headerlink:after, .rst-content h5 .headerlink:after, .rst-content h6 .headerlink:after, .rst-content dl dt .headerlink:after, .rst-content p.caption .headerlink:after { + visibility: visible; + content: ""; + font-family: FontAwesome; + display: inline-block; } +.rst-content h1:hover .headerlink, .rst-content h2:hover .headerlink, .rst-content .toctree-wrapper p.caption:hover .headerlink, .rst-content h3:hover .headerlink, .rst-content h4:hover .headerlink, .rst-content h5:hover .headerlink, .rst-content h6:hover .headerlink, .rst-content dl dt:hover .headerlink, .rst-content p.caption:hover .headerlink { + display: inline-block; } +.rst-content .centered { + text-align: center; } +.rst-content .sidebar { + float: right; + width: 40%; + display: block; + margin: 0 0 24px 24px; + padding: 24px; + background: #f3f6f6; + border: solid 1px #e1e4e5; } + .rst-content .sidebar p, .rst-content .sidebar ul, .rst-content .sidebar dl { + font-size: 90%; } + .rst-content .sidebar .last { + margin-bottom: 0; } + .rst-content .sidebar .sidebar-title { + display: block; + font-family: "Roboto Slab", "ff-tisa-web-pro", "Georgia", Arial, sans-serif; + font-weight: bold; + background: #e1e4e5; + padding: 6px 12px; + margin: -24px; + margin-bottom: 24px; + font-size: 100%; } +.rst-content .highlighted { + background: #F1C40F; + display: inline-block; + font-weight: bold; + padding: 0 6px; } +.rst-content .footnote-reference, .rst-content .citation-reference { + vertical-align: super; + font-size: 90%; } +.rst-content table.docutils.citation, .rst-content table.docutils.footnote { + background: none; + border: none; + color: gray; } + .rst-content table.docutils.citation td, .rst-content table.docutils.citation tr, .rst-content table.docutils.footnote td, .rst-content table.docutils.footnote tr { + border: none; + background-color: transparent !important; + white-space: normal; } + .rst-content table.docutils.citation td.label, .rst-content table.docutils.footnote td.label { + padding-left: 0; + padding-right: 0; + vertical-align: top; } + .rst-content table.docutils.citation tt, .rst-content table.docutils.citation code, .rst-content table.docutils.footnote tt, .rst-content table.docutils.footnote code { + color: #555; } +.rst-content table.field-list { + border: none; } + .rst-content table.field-list td { + border: none; } + .rst-content table.field-list td > strong { + display: inline-block; } + .rst-content table.field-list .field-name { + padding-right: 10px; + text-align: left; + white-space: nowrap; } + .rst-content table.field-list .field-body { + text-align: left; } +.rst-content tt, .rst-content tt, .rst-content code { + color: #000; + padding: 2px 5px; } + .rst-content tt big, .rst-content tt em, .rst-content tt big, .rst-content code big, .rst-content tt em, .rst-content code em { + font-size: 100% !important; + line-height: normal; } + .rst-content tt.literal, .rst-content tt.literal, .rst-content code.literal { + color: #E74C3C; } + .rst-content tt.xref, a .rst-content tt, .rst-content tt.xref, .rst-content code.xref, a .rst-content tt, a .rst-content code { + font-weight: bold; + color: #404040; } +.rst-content a tt, .rst-content a tt, .rst-content a code { + color: #2980B9; } +.rst-content dl { + margin-bottom: 24px; } + .rst-content dl dt { + font-weight: bold; } + .rst-content dl p, .rst-content dl table, .rst-content dl ul, .rst-content dl ol { + margin-bottom: 12px !important; } + .rst-content dl dd { + margin: 0 0 12px 24px; } +.rst-content dl:not(.docutils) { + margin-bottom: 24px; } + .rst-content dl:not(.docutils) dt { + display: table; + margin: 6px 0; + font-size: 90%; + line-height: normal; + background: #e7f2fa; + color: #2980B9; + border-top: solid 3px #6ab0de; + padding: 6px; + position: relative; } + .rst-content dl:not(.docutils) dt:before { + color: #6ab0de; } + .rst-content dl:not(.docutils) dt .headerlink { + color: #404040; + font-size: 100% !important; } + .rst-content dl:not(.docutils) dl dt { + margin-bottom: 6px; + border: none; + border-left: solid 3px #cccccc; + background: #f0f0f0; + color: #555; } + .rst-content dl:not(.docutils) dl dt .headerlink { + color: #404040; + font-size: 100% !important; } + .rst-content dl:not(.docutils) dt:first-child { + margin-top: 0; } + .rst-content dl:not(.docutils) tt, .rst-content dl:not(.docutils) tt, .rst-content dl:not(.docutils) code { + font-weight: bold; } + .rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) tt.descclassname, .rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) code.descname, .rst-content dl:not(.docutils) tt.descclassname, .rst-content dl:not(.docutils) code.descclassname { + background-color: transparent; + border: none; + padding: 0; + font-size: 100% !important; } + .rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) code.descname { + font-weight: bold; } + .rst-content dl:not(.docutils) .optional { + display: inline-block; + padding: 0 4px; + color: #000; + font-weight: bold; } + .rst-content dl:not(.docutils) .property { + display: inline-block; + padding-right: 8px; } +.rst-content .viewcode-link, .rst-content .viewcode-back { + display: inline-block; + color: #27AE60; + font-size: 80%; + padding-left: 24px; } +.rst-content .viewcode-back { + display: block; + float: right; } +.rst-content p.rubric { + margin-bottom: 12px; + font-weight: bold; } +.rst-content tt.download, .rst-content code.download { + background: inherit; + padding: inherit; + font-weight: normal; + font-family: inherit; + font-size: inherit; + color: inherit; + border: inherit; + white-space: inherit; } + .rst-content tt.download span:first-child, .rst-content code.download span:first-child { + -webkit-font-smoothing: subpixel-antialiased; } + .rst-content tt.download span:first-child:before, .rst-content code.download span:first-child:before { + margin-right: 4px; } +.rst-content .guilabel { + border: 1px solid #7fbbe3; + background: #e7f2fa; + font-size: 80%; + font-weight: 700; + border-radius: 4px; + padding: 2.4px 6px; + margin: auto 2px; } +.rst-content .versionmodified { + font-style: italic; } + +@media screen and (max-width: 480px) { + .rst-content .sidebar { + width: 100%; } } +span[id*='MathJax-Span'] { + color: #404040; } + +.math { + text-align: center; } + +@font-face { + font-family: "Inconsolata"; + font-style: normal; + font-weight: 400; + src: local("Inconsolata"), local("Inconsolata-Regular"), url(../fonts/Inconsolata-Regular.ttf) format("truetype"); } +@font-face { + font-family: "Inconsolata"; + font-style: normal; + font-weight: 700; + src: local("Inconsolata Bold"), local("Inconsolata-Bold"), url(../fonts/Inconsolata-Bold.ttf) format("truetype"); } +@font-face { + font-family: "Lato"; + font-style: normal; + font-weight: 400; + src: local("Lato Regular"), local("Lato-Regular"), url(../fonts/Lato-Regular.ttf) format("truetype"); } +@font-face { + font-family: "Lato"; + font-style: normal; + font-weight: 700; + src: local("Lato Bold"), local("Lato-Bold"), url(../fonts/Lato-Bold.ttf) format("truetype"); } +@font-face { + font-family: "Lato"; + font-style: italic; + font-weight: 400; + src: local("Lato Italic"), local("Lato-Italic"), url(../fonts/Lato-Italic.ttf) format("truetype"); } +@font-face { + font-family: "Lato"; + font-style: italic; + font-weight: 700; + src: local("Lato Bold Italic"), local("Lato-BoldItalic"), url(../fonts/Lato-BoldItalic.ttf) format("truetype"); } +@font-face { + font-family: "Roboto Slab"; + font-style: normal; + font-weight: 400; + src: local("Roboto Slab Regular"), local("RobotoSlab-Regular"), url(../fonts/RobotoSlab-Regular.ttf) format("truetype"); } +@font-face { + font-family: "Roboto Slab"; + font-style: normal; + font-weight: 700; + src: local("Roboto Slab Bold"), local("RobotoSlab-Bold"), url(../fonts/RobotoSlab-Bold.ttf) format("truetype"); } diff --git a/source/_static/deciso_ruit.png b/source/_static/deciso_ruit.png new file mode 100644 index 0000000..3fdcc28 Binary files /dev/null and b/source/_static/deciso_ruit.png differ diff --git a/source/_static/favicon.ico b/source/_static/favicon.ico new file mode 100644 index 0000000..4af652c Binary files /dev/null and b/source/_static/favicon.ico differ diff --git a/source/_static/favicon.png b/source/_static/favicon.png new file mode 100644 index 0000000..3e6dde9 Binary files /dev/null and b/source/_static/favicon.png differ diff --git a/source/conf.py b/source/conf.py new file mode 100644 index 0000000..32fd1fb --- /dev/null +++ b/source/conf.py @@ -0,0 +1,382 @@ +# -*- coding: utf-8 -*- +# +# OPNsense documentation build configuration file, created by +# sphinx-quickstart on Tue Jan 19 16:15:33 2016. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +import sphinx_rtd_theme + +html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.todo', + 'sphinxcontrib.blockdiag', + 'sphinxcontrib.nwdiag', + 'sphinxcontrib.seqdiag', + 'sphinxcontrib.actdiag', + +] + +blockdiag_fontpath = '/Library/Fonts/Arial.ttf' +nwdiag_fontpath = '/Library/Fonts/Arial.ttf' +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'OPNsense' +copyright = u'2016, Deciso B.V' +author = u'Deciso B.V.' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'Wiki & Documentation' +# The full version, including alpha/beta/rc tags. +release = u'Wiki & Documentation' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# html_theme = 'alabaster' +html_theme = "sphinx_rtd_theme" +html_style = 'css/opnsense.css' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] +html_theme_path = ["_themes", ] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None +html_logo = '_static/deciso_ruit.png' + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +html_favicon = 'favicon.ico' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +html_show_sourcelink = False + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'OPNsensedoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'OPNsense.tex', u'OPNsense Documentation', + u'Deciso B.V.', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'opnsense', u'OPNsense Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'OPNsense', u'OPNsense Documentation', + author, 'OPNsense', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +# -- Options for Epub output ---------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project +epub_author = author +epub_publisher = author +epub_copyright = copyright + +# The basename for the epub file. It defaults to the project name. +#epub_basename = project + +# The HTML theme for the epub output. Since the default themes are not +# optimized for small screen space, using the same theme for HTML and epub +# output is usually not wise. This defaults to 'epub', a theme designed to save +# visual space. +#epub_theme = 'epub' + +# The language of the text. It defaults to the language option +# or 'en' if the language is not set. +#epub_language = '' + +# The scheme of the identifier. Typical schemes are ISBN or URL. +#epub_scheme = '' + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +#epub_identifier = '' + +# A unique identification for the text. +#epub_uid = '' + +# A tuple containing the cover image and cover page html template filenames. +#epub_cover = () + +# A sequence of (type, uri, title) tuples for the guide element of content.opf. +#epub_guide = () + +# HTML files that should be inserted before the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_pre_files = [] + +# HTML files shat should be inserted after the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_post_files = [] + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + +# The depth of the table of contents in toc.ncx. +#epub_tocdepth = 3 + +# Allow duplicate toc entries. +#epub_tocdup = True + +# Choose between 'default' and 'includehidden'. +#epub_tocscope = 'default' + +# Fix unsupported image types using the Pillow. +#epub_fix_images = False + +# Scale large images. +#epub_max_image_width = 0 + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#epub_show_urls = 'inline' + +# If false, no index is generated. +#epub_use_index = True + +# load PhpLexer +from sphinx.highlighting import lexers +from pygments.lexers.web import PhpLexer +from pygments.lexers.web import JavascriptLexer + + +# enable highlighting for PHP code not between by default +lexers['php'] = PhpLexer(startinline=True) +lexers['php-annotations'] = PhpLexer(startinline=True) + +# inline highliting for Javascript +lexers['Javascript'] = JavascriptLexer(startinline=True) +lexers['Javascript-annotations'] = JavascriptLexer(startinline=True) diff --git a/source/contribute.rst b/source/contribute.rst new file mode 100644 index 0000000..6f6b7d4 --- /dev/null +++ b/source/contribute.rst @@ -0,0 +1,209 @@ +========== +Contribute +========== +OPNsense is an open source community project that depends on your contributions +for its continuing development & success. + +There are plenty of opportunities to contribute and help OPNsense reach its goal +of becoming the most widely used open source security & firewall platform. +Financial contributions are always welcome and will allow us to develop parts +of the system that may otherwise stay untouched. + +The OPNsense core team wants to thank everyone who contributed already. + +------------------ + +----------- +Financially +----------- +"*An open source project can only thrive by the community around it.*" +We are grateful of all the kind words and support the users of OPNsense are +giving us. + +Frequently users ask us how they can contribute to the project. +To make the software better we need your involvement in testing and providing +feedback and if you can spare a few bucks that would be great. + +--------------- + +Donations +--------- +To enable us to continue development and keep on improving the project you can +contribute by donating to the project, this a simple non recurring - no strings +attached - way of supporting the project. Any amount will be gratefully accepted! + +.. raw:: html + +
+
+ Why wait? Donate today !   + + + + + + + + + +
+
+
+ +--------------- + +Partner program +--------------- +The OPNsense project offers a partner program where businesses receive project +benefits while supporting the project financially. + +Main benefits include: + +* Listing on our `OPNsense partner page `__ +* Access to the core team + +To get enlisted as partner of the OPNsense project means a minimum annual investment +of € 2500.Partners that made an exceptional contribution to the project are assigned +the Platinum Partner status. + +--------------- +Support Contract +---------------- +with a support contract we support you and you support us as OPNsense is fully +supported by Deciso. + +For support options see `OPNsense Commercial Support `__ + +------------------ + +----------- +Development +----------- +Contributing to the ongoing development of OPNsense can be done by: + +* Testing a development version and +* Report issues and/or +* Help fixing issues as well as by +* Contributing new functionality +* Share your code with the project by manner of a pull request. + +--------------- + +Testing +------- +Contribute by testing the latest development version to make the next release even +better than the last. If you like to test a development version then the easiest +way is to login to the console and type: + +:: + + pkg install -y opnsense-devel + + +And to revert back to the production version: + +:: + + pkg install -y opnsense + + +That is all there is to it to test the latest development release. +Development releases are usually built at the same day the latest production +release comes available. + +--------------- + +Reporting an issue +------------------ +Issues can be easily reported on github, please consider carefully if the issue +could be a configuration or user error before reporting it. If you are unsure, +report you issue on the `Forum `__ or on IRC/Freenode (#opnsense). + +--------------- + +Fixing issues +------------- +If you are a programmer or just know how to fix a certain issue then you can help +by either sharing your ideas on or send in a pull request on github. + +--------------- + +Designing new features +---------------------- +If you like to help designing new features then start with reading the :doc:`Development +manual ` and checkout our `roadmap `__ as well as our `issue tracker `__. +Before starting it is always a good to share your idea first with a core developer, +to do so you can use either: + +* `github `__ and `create a issue `__ + and mention you volunteer for taking on the development task (we will correctly label it as enhancement or feature) +* find one of us on IRC/Freenode (#opnsense) and see if we are available to + discuss your idea. + +------------------ + +------------ +Translations +------------ +OPNsense has an active `translation project `__, +currently supporting: + +* Czech +* English +* French +* German +* Japanese +* Portuguese +* Russian +* Simplified Chinese + +Working on translations is time consuming, but if you feel up to it and would +like to help adding another language, then please contact us via email (contact @ opnsense.org). + +------------------ + +----------------------------- +Documentation & wiki articles +----------------------------- +The easiest way to help with documentation is to write how-to type articles. +As the wiki & documentation project itself is written in **reStructuredText** you +can offer your content in this format (preferably as pull request), but other +formats are also possible, such as: + +* markup with ./images/directory including the used images(in any) +* word document with embedded images (if any) + +To include you documentation send it to contact @ opnsense.org. Make sure that: + +* Your content does not include copyrighted material if you do not own the copyright yourself +* State that we may use the content under our Documentation Copyright as listed in the :doc:`legal` section. + +------------------ + +----------- +Forum & IRC +----------- +If you are an experienced network engineer, know a lot about firewall technology +or if you are excited about OPNsense, then you can contribute to the project by helping +others on the forum or on irc. + +------------------ + +------------ +Social media +------------ +Contribute to the success of the project by letting others know how OPNsense helped +solving your network or security challenges. Let others know about OPNsense and/or +follow us & retweet our messages on `twitter `__. + +Anything you can do to spread the word about OPNsense will help to reach our goal +to become the most widely used open source security & firewall platform. + + +------------------ + +------------- +Closing Words +------------- +If you have suggestions on how others can contribute to OPNsense and it is not yet +listed on this page, then let us know. You can reach us at contact @ opnsense.org. diff --git a/source/develop.rst b/source/develop.rst new file mode 100644 index 0000000..73d71ed --- /dev/null +++ b/source/develop.rst @@ -0,0 +1,36 @@ +==================================== +Development Manual +==================================== + +.. image:: /development/images/ideas_join_the_development.jpg + +The OPNsense® project invites developers to start developing with OPNsense: +"For your own purpose or even better to join us in creating the best FreeBSD +based open source firewall available!" The development workflow & build process +has been redesigned to make it more straightforward and easy for developers to +build OPNsense. + +Being able to get the sources and build it yourself is one of the key factors of +open source software. One reason that for starting the OPNsense project is that +the team believes sources and build tools should be freely available and as easy +to use as possible. + +.. toctree:: + :maxdepth: 2 + :titlesonly: + :glob: + + development/workflow + development/guidelines + development/architecture + development/backend + development/frontend + development/components + development/examples + development/howtos + development/* + +------- +Sources +------- +Just looking for the sources? See: `OPNsense repository `__ diff --git a/source/development/architecture.rst b/source/development/architecture.rst new file mode 100644 index 0000000..1a539f0 --- /dev/null +++ b/source/development/architecture.rst @@ -0,0 +1,136 @@ +============ +Architecture +============ + +The main focus of the OPNsense project is to provide a secure and +manageable platform for all your security applications. This means high +quality software that is easily maintainable and bug free. We think that +having a framework with a clear separation of concerns is essential to +achieving these goals. + +OPNsense is a fork of pfSense ®. The existing code base of pfSense ® +does not always apply a clear separation of concerns. This means we need +a transition of the old (legacy) code base to a new one with a clear +separation. We have chosen a gradual transition to avoid a big bang and +keep the product feature rich while increasing code quality. This +enables simple addition of new features with less bugs and shorter time +to market. + +This article describes how this will be achieved. + +----------------------- +High-level architecture +----------------------- + +|OPNsense Components.png| + +As the above model shows there are two main areas in our stack, the +frontend implemented with PHP/Phalcon and the backend using a custom +service built in Python. + +The frontend handles user interaction and communicates with the backend +service. Applying configuration changes, monitoring and controlling +services offered by OPNsense is done by the backend service. + +By using a fully configurable backend service, we avoid hardcoding of +services and ease the implementation of new features. + +The frontend stack delivers a model driven approach to handle +configuration data, including automatic validation. + +Manipulation of the core configuration file is handled at the frontend +model; the backend service is merely a consumer of the information +provided. + +-------------------- +Backend Architecture +-------------------- + +|OPNsense backend.png| + +Configd, is responsible +for the core system interaction like starting and stopping of daemons +and generating configuration files for used services and applications. + +The daemon listens on a unix domain socket and is capable of executing +actions defined in it’s own configuration directory +(“/usr/local/opnsense/service/conf/actions\_\*.conf”). + +Currently there are two types of services implemented in the daemon: + +- script : execute external (rc) scripts +- inline : perform inline actions which are part of configd, currently + only template generation. + +| +| Template generation is handled by Jinja2 (http://jinja.pocoo.org/), + more information on how to create application templates can be found + at :doc:`/development/backend/templates`. + +--------------------- +Frontend Architecture +--------------------- + +|OPNsense frontend.png| + +Routing +------- + +The OPNsense framework uses components from Phalcon where possible; the +first layer initializes Phalcon’s routing, which handles requests and +delivers them to the controller based on its url. User content is +generated using Volt templates, which are picked by the controller. +Because Phalcon’s default Models function with (relational) databases +and we are using xml data, our model implementation is custom. But +wherever possible we use components from Phalcon (for example, +validation is handled using Phalcon’s classes). For a detailed +description on the routing principles used in OPNsense, visit Frontend +:doc:`/development/frontend/routing`. + +Controllers and views +--------------------- + +Not all parts of the framework are already implemented, but by deriving +all controllers from the base in the OPNsense project it’s easy to +extend and adapt to future needs. Documentation on how to implement +controllers, with the use of views, can be found at :doc:`/development/frontend/controller`. + +Models +------ + +All models are defined by a combination of a class and an xml containing +a (nested) definition. More information on defining models can be found +at the frontend model page :doc:`/development/frontend/models`. + +Communication +------------- + +Communication to the backend service is handled via a unix domain +socket. + +Core system +----------- + +The core of OPNsense is powered by an almost standard FreeBSD ® system +extended with packages using the pkg system. GIT is used for version +control and the repositories are split into 4 parts: + +- src : the base (FreeBSD ®) system +- ports : the ports collection containing third party software +- core : the OPNsense gui and system configuration parts +- tools : easy tools to build OPNsense + +.. TIP:: + + | For detailed information about the development workflow see: + | :doc:`OPNsense development workflow ` + +.. |OPNsense Components.png| image:: images/OPNsense_Components.png + :width: 600px + :height: 548px +.. |OPNsense backend.png| image:: images/OPNsense_backend.png + :width: 600px + :height: 575px +.. |OPNsense frontend.png| image:: images/OPNsense_frontend.png + :width: 600px + :height: 461px diff --git a/source/development/backend.rst b/source/development/backend.rst new file mode 100644 index 0000000..994d027 --- /dev/null +++ b/source/development/backend.rst @@ -0,0 +1,27 @@ +======= +Backend +======= + +The OPNsense backend consists of several components (see Architecture for a full stack description). + +Our core backend service (configd) is implemented using `Python `__. and provides two main features: + +- Service interaction (using configd actions) +- Generation of configuration data (using templates) + +Because some of the codebase still integrates with our legacy codebase, we provide additional plugin options for the following components: + +- Services (the services status) +- Syslog (define syslog targets) +- Interface (register interfaces, firewall use etc.) +- Service configuration (legacy service configuration, new style uses configd templates) + + +Services which need to be executed at system startup can use rc(8) or our syshook system. + +.. toctree:: + :maxdepth: 2 + :titlesonly: + :glob: + + backend/* diff --git a/source/development/backend/autorun.rst b/source/development/backend/autorun.rst new file mode 100644 index 0000000..17de581 --- /dev/null +++ b/source/development/backend/autorun.rst @@ -0,0 +1,54 @@ +======================== +Bootup / autorun options +======================== + +------- +syshook +------- + +OPNsense offers an easy method to plugin shell scripts during (early) boot stage. + +Syshook scripts should be installed in : + +:: + + /usr/local/etc/rc.syshook.d/ + +They can contain regular shell scripts using the following extensions: + +- start + - start script after normal system startup +- early + - start script before normal system startup. + +Example (vmware guestd start, filename /usr/local/etc/rc.syshook.d/vmware.early) + +:: + + #!/bin/sh + + export vmware_guest_vmblock_enable="YES" + export vmware_guest_vmhgfs_enable="YES" + export vmware_guest_vmmemctl_enable="YES" + export vmware_guest_vmxnet_enable="YES" + + /usr/local/etc/rc.d/vmware-kmod start + + +----- +rc(8) +----- + +Part of the bootup process of OPNsense is probing the available rc(8) configuration files in */etc/rc.conf.d/*, when a daemon is enabled, the system will call the regular rc(8) start command. + +In case the daemon needs some extra preparation, an additional "bootup" script can be provided, which will be run before executing normal "start". + +Example (from a configured squid proxy server using */etc/rc.conf.d/squid*): + +:: + + squid_enable=YES + squid_opnsense_bootup_run="/usr/local/opnsense/scripts/proxy/setup.sh" + + +The configd template system can be used to generate the necessary configuration file(s). diff --git a/source/development/backend/configd.rst b/source/development/backend/configd.rst new file mode 100644 index 0000000..ce2df85 --- /dev/null +++ b/source/development/backend/configd.rst @@ -0,0 +1,102 @@ +=============== +Using configd +=============== + +------- +General +------- + +To add new services and system calls, which can be used from the frontend system or command line, you can create configd actions. + +All available templates should be installed at the following location on +the OPNsense system: + +:: + + /usr/local/opnsense/service/conf/actions.d/ + + +*Please note that all actions which should be accessible from the frontend should have a registered configd action, if possible use standard rc(8) scripts for service start/stop.* + +----------------- +Naming convention +----------------- + +Service templates should use distinctive names to identify your service and contain simple / clear actions. + +For example, we will describe the template for ssh, which is installed by default. + +**File name:** + + +:: + + /usr/local/opnsense/service/conf/actions.d/actions_sshd.conf + +Our ssh service has two actions available: + +- restart + - starts / restarts ssh service +- stop + - stops / kills all ssh daemons + + +:: + + [restart] + command:/usr/local/etc/rc.sshd + parameters: + type:script + message:starting sshd + + [stop] + command:/bin/pkill -TERM sshd || exit 0 + parameters: + type:script + message:stop sshd + + +Between brackets [] you find the name of the action, the definition of the actual call is defined in the following parameter:value pairs. +When a service or module provides a lot of actions, it sometimes is practical to add another level of operation. + +For example, the restart service call for this service will translate to: **sshd restart** + +In case we have an action like **filter diag info**, you can create an actions_filter.conf which contains a section [diag.info]. + +----------------- +Action properties +----------------- + + ++-----------------------+------------------------+--------------------------------------------------------+ +| Property | Syntax | Description | ++=======================+========================+========================================================+ +| command | text | shell command string to execute | ++-----------------------+------------------------+--------------------------------------------------------+ +| parameters | %s for every parameter | list of parameters to use, example : /i %s | ++-----------------------+------------------------+--------------------------------------------------------+ +| type | script|script_output | type of call: | +| | | - script (only return exit status) | +| | | - script_output (return result) | ++-----------------------+------------------------+--------------------------------------------------------+ +| message | text | Message to send to syslog (you can use %s parameters) | ++-----------------------+------------------------+--------------------------------------------------------+ +| description | text | User friendly description. | ++-----------------------+------------------------+--------------------------------------------------------+ + + +----------- +Test action +----------- + +To test a new configd action, please restart the configd service first using: + +:: + + service configd restart + +Next use the supplied helper command to execute our action: + +:: + + configctl sshd restart diff --git a/source/development/backend/legacy.rst b/source/development/backend/legacy.rst new file mode 100644 index 0000000..94c53b1 --- /dev/null +++ b/source/development/backend/legacy.rst @@ -0,0 +1,114 @@ +==================== +Using legacy plugins +==================== + +------- +General +------- + +Legacy type plugins are located in the following location: + +:: + + /usr/local/etc/inc/plugins.inc.d/ + +And contain files with the extension ".inc". + +All automatically registered functions start with the name of the file (without the extension), followed by the purpose. +For example *vpn_configure* would be the *configure* handle in a plugin file name vpn.inc. + +----------------- +Services +----------------- + +To register services, the *_services()* function should return a structure containing its name, description and operating properties. + +:: + + function myplugin_services() + { + $service = array(); + $service['name'] = 'myservice'; + $service['description'] = gettext('My service'); + $service['configd']['restart'] = array('myservice restart'); + $service['configd']['start'] = array('myservice start'); + $service['configd']['stop'] = array('myservice stop'); + $services[] = $pconfig; + return $services; + } + +For a full list of supported service methods, please inspect *services.inc* + + +----------------- +Syslog +----------------- + +To register syslog targets, the *_syslog()* function should return a structure containing targets and definitions. + +:: + + function myplugin_syslog() + { + $logfacilities = array(); + $logfacilities['myplugin'] = array( + 'facility' => array('myplugin'), + 'remote' => 'myplugin', + ); + return $logfacilities; + } + + + +----------------- +Interface +----------------- + +To register new (virtual) interfaces, create a function called *_interfaces()*, which should return a named array containing the unique interface name as key (enc0 for ipsec for example). + +Every item should contain the following properties: + ++-----------------------+------------------------+--------------------------------------------------------+ +| Property | Syntax | Description | ++=======================+========================+========================================================+ +| enable | boolean | interface enabled, if so it will be saved in the config| ++-----------------------+------------------------+--------------------------------------------------------+ +| descr | text | User readable description | ++-----------------------+------------------------+--------------------------------------------------------+ +| networks | array, [network, mask] | list of named arrays containing remote networks | ++-----------------------+------------------------+--------------------------------------------------------+ +| type | text | "none" | ++-----------------------+------------------------+--------------------------------------------------------+ +| if | text | physical interface (e.g. enc0) | ++-----------------------+------------------------+--------------------------------------------------------+ +| virtual | boolean | Virtual interface, true/false | ++-----------------------+------------------------+--------------------------------------------------------+ + +Example: + +:: + + function myplugin_interfaces() + { + global $config; + + $interfaces = array(); + if (isset($config['myplugin']['enable'])) { + $oic = array("enable" => true); + $oic['if'] = 'tun0'; + $oic['descr'] = 'myplugin'; + $oic['type'] = "none"; + $oic['virtual'] = true; + $oic['networks'] = array(); + $interfaces['tun0'] = $oic; + } + + return $interfaces; + } + + +----------------- +Configure +----------------- + +When your plugin needs configuration after boot, you can create a function called *_configure()* which will be called upon boot. diff --git a/source/development/backend/templates.rst b/source/development/backend/templates.rst new file mode 100644 index 0000000..e403dea --- /dev/null +++ b/source/development/backend/templates.rst @@ -0,0 +1,147 @@ +=============== +Using Templates +=============== + +------- +General +------- + +For config file generation, we provide a backend service which can bind +config.xml data to templates written in Jinja2 +(http://jinja.pocoo.org/docs/dev/). + +All available templates should be installed at the following location on +the OPNsense system: + +#. /usr/local/opnsense/service/templates/ + + +----------------- +Naming convention +----------------- + +All templates should be put into a directory structure containing the +vendor and package/application name, our sample application is placed +inside the directory: + +/usr/local/opnsense/service/templates/*OPNsense/Sample* + +Template package content + +Every template directory should contain at least 2 files: + +#. a content descriptor, containing the actual targets, named +TARGETS +#. one or more template(s) + + +------- +Targets +------- + +The +TARGETS file contains the source template name inside the template +directory and the (dynamic) target filename divided by a colon (:) +multiple lines may be inserted per file. + +For example : + +:: + + example_simple_page.txt:/tmp/template_sample/simple_page.txt + +Will create a file /tmp/template\_sample/simple\_page.txt using the +template example\_simple\_page.txt. + +.. Note:: + + Optionally you can specify which file or files to remove on call of "template cleanup", which can be specified by + using an extra tag next to the target, such as: + :code:`example_simple_page.txt:/tmp/template_sample/simple_page.txt:/tmp/template_sample/simple_page.*` + + By default all targets will be removed when calling cleanup. + + + +If you want to use information from within the config.xml file as output +filename, you can use tags to address the content, like [version] to +input the tag version from the xml file. When generating multiple files +from 1 template, you can use one wildcard (%) to address a section of +the config file, for example [interfaces.%.if] loops over the interfaces +and outputs the value of **if**. + +----------------- +Target overwrites +----------------- + +Every template package can specify overwrites, which can be used by vendors who implement and maintain their own templates +for features in OPNsense. + +Simply add files using the target definition in the **+TARGETS.D** directory of the templates folder using as extension **.TARGET**. + +For example an overwrite for OPNsense/Sample can use the following name and location +:code:`/usr/local/opnsense/service/templates/OPNsense/Sample/+TARGETS.D/custom.TARGET` + +.. Note:: + Be vey careful using this feature, you need to maintain these templates yourself and features may break after upgrades + of OPNsense. + +--------- +Templates +--------- + +For more information of the template language itself, please look at +http://jinja.pocoo.org/docs/dev/ and the examples installed in +/usr/local/opnsense/service/templates/OPNsense/Sample. + +There's one special case when using the template engine, every wildcard +used for the output file generation is also provided to the template, so +you are able to determine which filter let to this output. + +Those filters are stored in the variable TARGET\_FILTERS. + +.. code-block:: jinja + + {% if TARGET_FILTERS['interfaces.wan'] %} + {% endif %} + +---------- +Test usage +---------- + +The templates can be rendered via the backend service (configd), to test +this functionality on a running OPNsense system, use: + + +:: + + # generate template package + configctl template reload OPNsense/Sample + # cleanup files + configctl template cleanup OPNsense/Sample + +| + +----------------------------- +Python template usage example +----------------------------- + +The template system itself is a separate module which is used by +configd, to use (or test) the system without the daemon, use: + +.. code-block:: python + + # import template system and config.xml handling + from modules import template + from modules import config +   + # construct a new template object, set root to /tmp/ + tmpl = template.Template(target_root_directory="/tmp/") + # open the config.xml and bind to template object + conf = config.Config('/config.xml') + tmpl.setConfig(conf.get()) +   + # generate output for OPNsense/Sample + generated_filenames = tmpl.generate('OPNsense/Sample') +   + # print results + for filename in generated_filenames: + print ('.. generated : %s'%filename) diff --git a/source/development/components.rst b/source/development/components.rst new file mode 100644 index 0000000..31289b2 --- /dev/null +++ b/source/development/components.rst @@ -0,0 +1,18 @@ +========== +Components +========== + +OPNsense® **components** are not directly related to the front and backend. + +For the OPNsense framework we've developed some shared components for common +tasks, this page indexes those components which aren't directly related to the +`Model View Controller `__ (MVC) framework itself. + +.. toctree:: + :maxdepth: 2 + :titlesonly: + :glob: + + components/menusystem + components/acl + components/* diff --git a/source/development/components/acl.rst b/source/development/components/acl.rst new file mode 100644 index 0000000..32cc196 --- /dev/null +++ b/source/development/components/acl.rst @@ -0,0 +1,55 @@ +=================== +Access Control List +=================== + +.. sidebar:: Access Control List + + .. image:: images/acl-finger-print.jpg + +-------- +Overview +-------- + +The current ACL system is targeted at delivering backwards compatibility +for legacy code and being able to extend this a little to add new +features without having to reimplement the whole system. + +In the legacy system the access control is using the following steps to +determine if a page can be accessed by a user: + +#. The user, stored in the config.xml file at system/user (one item per + user) +#. One or more groups for that user, stored in system/group which + contains priv sections. +#. A php file binding the priv section content to a page mask (including + wildcards) + +Our temporary solution is to keep the user and the group in place and replace the +php file with a simple config in the model which uses the same mask construction +there was in the old codebase. To bind priv to pages, edit models/OPNsense/Core/ACL\_Legacy\_Page\_Map.txt + +-------------- +Usage from php +-------------- + +Using the system from php is rather simple: + +.. code-block:: php + + $acl = new OPNsense\Core\ACL(); + if ( $acl->isPageAccessible("user", "/firewall_rules.php") ) { + print ( "/firewall_rules.php is accessible" ) ; + } + +----------------------- +Usage in Volt templates +----------------------- + +The acl scheme is bound to the default UI controller, and can be used by +using the acl keyword: + +.. code-block:: jinja + + {% if acl.isPageAccessible(session.get('Username'),subMenuItem.Url)  %} + this page is accessible + {% endif %} diff --git a/source/development/components/images/acl-finger-print.jpg b/source/development/components/images/acl-finger-print.jpg new file mode 100644 index 0000000..84ac4fe Binary files /dev/null and b/source/development/components/images/acl-finger-print.jpg differ diff --git a/source/development/components/images/menusystem.png b/source/development/components/images/menusystem.png new file mode 100644 index 0000000..81730f1 Binary files /dev/null and b/source/development/components/images/menusystem.png differ diff --git a/source/development/components/menusystem.rst b/source/development/components/menusystem.rst new file mode 100644 index 0000000..ae5144d --- /dev/null +++ b/source/development/components/menusystem.rst @@ -0,0 +1,66 @@ +=========== +Menu System +=========== + +.. sidebar:: OPNsense Menu System + + .. image:: images/menusystem.png + :width: 300px + :align: center + +-------- +Overview +-------- + +One of the shared components of the OPNsense framework is the menu system, which +is wrapped in a single class and part of the base model. + +The only responsibility of the menu system is to create a tree like structure to +represent the menu and being able to keep track of the mapping between a location +and the hierarchy of the menu system. To keep things clean and understandable, +the menu system doesn't know anything about users or authorisation. + +Currently the main focus for the menu system is to support the legacy code, so +we will be able to reimplement the menu in both legacy and new code. + +Our base UI controller (\\OPNsense\\Base\\ControllerBase) implements the menu +system for further use. + +An example of how to create a menu, is given below: + +.. code-block:: php + + // create new menu + $menu = new Menu\MenuSystem(); + // append an additional dynamic item into the system + $menu->appendItem("System.Advanced", "test123", array("url"=>"/testpage.php","order"=>1)); + // test, print menu as structured named array + print_r($menu->getItems("/testpage.php")); + +The current version only implements a static menu defined by one xml file +(models/OPNsense/Base/Menu/Menu.xml), but extending with additional xml files +is already supported in the component for future use. + +-------- +Menu.xml +-------- + +The menu xml is defined as follows: + +.. code-block:: xml + + + + + + + + +The top level should be named "menu" to let the system know this is a menu +structure, the next layers will be used for the structure of itself. To map the +attributes to the menu objects created there are setters in +OPNsense\\Base\\Menu\\MenuItem, in this version the next attributes are supported: + +- order, sort order in our menu +- VisibleName, name to use ( if not set the tagname / id will be used) +- cssClass, style attributes for the frontend system. diff --git a/source/development/examples.rst b/source/development/examples.rst new file mode 100644 index 0000000..4dcf6fd --- /dev/null +++ b/source/development/examples.rst @@ -0,0 +1,10 @@ +======== +Examples +======== + +.. toctree:: + :maxdepth: 2 + :titlesonly: + :glob: + + examples/* diff --git a/source/development/examples/helloworld.rst b/source/development/examples/helloworld.rst new file mode 100644 index 0000000..1f0746b --- /dev/null +++ b/source/development/examples/helloworld.rst @@ -0,0 +1,987 @@ +=========================== +Hello world module & plugin +=========================== + + + +.. sidebar:: Creating the hello world module + + .. image:: images/Hello-World.jpg + :width: 300px + :align: center + + +---- +Goal +---- + +.. rubric:: Goal for this sample + :name: goal-for-this-sample + +---------------------------------- + +The goal of the "Hello world" module we're creating in the example is to +control a program on our system named "testConnection.py", which is part +of the example package available on GitHub. It will try to send an email +using plain smtp and will respond with a json text message about the +result of that attempt. + +Our application will need some settings to operate correctly, like an ip +address and an email address and we need to be able to run that +application. Because this application returns some valuable data for our +users, we need to be able to fetch the response data back. + +|overview| + +----------------------------- + +---------- +Guidelines +---------- + +.. rubric:: Guidelines and coding style + :name: guidelines-and-coding-style + +For all OPNsense modules and applications there are some basic style and +coding guides which you should use. + +Naming +------ + + +When creating modules for OPNsense, always name your components like +this: VendorName/ModuleName + +In our sample case this will be: OPNsense/HelloWorld + +PHP code +-------- + +Please use PSR-2 style (http://www.php-fig.org/psr/psr-2/) for all new +code. + + +Architecture +------------ + +Always make sure there's a clear separation of concerns, back-end calls +(like shell scripts) should be implemented using the configd system, all +communication to the client should be handled from an api endpoint. (the +example provides more insights on how this works). + +Back-end programs should not access the config.xml directly, if data is +needed let the template system handle the desired output (most +applications, daemons and tools deliver their own desired configuration +format). There's generally no good reason to avoid the standards that +are already there. + +If you follow this basic rules, you're automatically building a command +structure for the system administrators and provide a connector to third +party tools to the API of your component (as of version 16.1). + +-------- +Skeleton +-------- + +.. rubric:: Setup a skeleton for the frontend / middleware + :name: setup-a-skeleton-for-the-frontend-middleware + +First step for our project is to build a skeleton which holds the +structure for our frontend/middleware. + +Model +----- + +For our sample application we want to setup some configuration data, +which for all new style projects should live in it’s own model. + +First we start by creating two files inside the +models/OPNsense/HelloWorld directory. + +The first one is the boilerplate for the model class, which should +contain model specific methods and (by deriving it from BaseModel) +automatically understands the second file. + +.. code-block:: php + + + //OPNsense/helloworld + + the OPNsense "Hello World" application + + + + + +(/usr/local/opnsense/mvc/app/models/OPNsense/HelloWorld/HelloWorld.xml) + +The content of the mount tag is very important, this is the location +within the config.xml file where this model is responsible. Other models +cannot write data into the same area. You should name this location with +your vendor and module name to make sure others could easily identify +it. + +Use the description tag to identify your model, the last tag in place is +the items tag, where the actual definition will live. We leave it empty +for now as we proceed with the next step of creating our skeleton. + +View +---- + +.. rubric:: Page template (View) + :name: page-template-view + +We should add a (Volt) template to use for the index page of our module; +we will use the same naming convention here. + +Create a template named index.volt inside the views/OPNsense/HelloWorld +directory containing the following data: + + +.. code-block:: html + +

Hello World!

+ +(/usr/local/opnsense/mvc/app/views/OPNsense/HelloWorld/index.volt) + +Controller +---------- + +Next step is to add controllers, which will be automatically picked up +by the system routing. A controller connects the user interaction to +logic and presentation. + +Every OPNsense module should separate presentation from logic, that’s +why there should always be multiple controllers per module. + +Our first controller handles the template rendering to the user and +connects the user view we just created. We start by creating a php file +in controllers/OPNsense/HelloWorld/ with the following name +IndexController.php and contents: + +.. code-block:: php + + view->title = "Hello World"; + // pick the template to serve to our users. + $this->view->pick('OPNsense/HelloWorld/index'); + } + } + +(/usr/local/opnsense/mvc/app/controllers/OPNsense/HelloWorld/IndexController.php) + +At this point you should be able to test if your work so far was +successful, by going to the following location (after being logged in to +the firewall as root user): + +:: + + http[s]:///ui/helloworld/ + +Which should serve you the “Hello World!” text you’ve added in the +template. + +|Serving the first "hello world" page| + +Next two controllers we are going to create are to be used for the api +to the system, they should take care of service actions and the +retrieval/changing of configuration data. + +They should live in a subdirectory of the controller called Api and +extend the corresponding class. + +For our modules we create two api controllers, one for controlling +settings and one for performing service actions. (Named +SettingsController.php and ServiceController.php) Both should look like +this (replace Settings with Service for the other one): + +.. code-block:: php + + | IP address for the remote smtp host | ++-----------------------+----------------------+----------------------------------------------+ +| General.FromEmail | sample@example.com | Email address of the sender | ++-----------------------+----------------------+----------------------------------------------+ +| General.ToEmail | | Email address to send our test email to | ++-----------------------+----------------------+----------------------------------------------+ +| General.Description | | Description, used as subject of the email. | ++-----------------------+----------------------+----------------------------------------------+ + +Adding Fields +------------- + +.. rubric:: Adding fields to your model + :name: adding-fields-to-your-model + +When building the skeleton, we have created an empty model (xml), which +we are going to fill with some attributes now. The items section of the +model xml should contain the structure you want to use for your +application, you can create trees to hold data in here. All leaves +should contain a field type to identify and validate it’s content. The +list of attributes for our application can be translated to this: + +.. code-block:: xml + + ……… + + + + + + 1 + Y + + + Y + + + sample@example.com + Y + + + Y + + + Y + + + + ……… + +All available field types can be found in the +models/OPNsense/Base/FieldTypes directory. If specific field types +support additional parameters, for example for validation, they should +be registered in the model as well (just like the default tag in +Enabled). + +Presentation XML +---------------- + +.. rubric:: Create a presentation xml to feed your template + :name: create-a-presentation-xml-to-feed-your-template + +Because creating forms is one of the key assets of the system, we have +build some easy to use wrappers to guide you through the process. First +we create an xml file for the presentation, which defines fields to use +and adds some information for your template to render. Create a file in +your controller directory using the sub directory forms and name it +general.xml. Next copy in the following content: + +.. code-block:: xml + +
+ + helloworld.general.Enabled + + checkbox + Enable this feature + + + helloworld.general.SMTPHost + + text + + choose a valid IPv4/v6 address + + + helloworld.general.FromEmail + + text + + + helloworld.general.ToEmail + + text + + + helloworld.general.Description + + text + +
+ +(/usr/local/opnsense/mvc/app/controllers/OPNsense/HelloWorld/forms/general.xml) + +All items should contain at least an id (where to map data from/to), a +type (how to display) and a label, which identifies it to the user. +Optional you may add additional fields like help or mark features as +being only for advanced users. (The Volt template defines which +attributes are usable.) + +Now we need to tell the controller to use this information and pass it +to your template, so change the IndexController.php and add this line: + +.. code-block:: php + + $this->view->generalForm = $this->getForm("general"); + +And we are ready to update the (Volt) template with this information. +Let’s remove the "

Hello World!

" line and replace it with +something like this: + +.. code-block:: jinja + + {{ partial("layout_partials/base_form",['fields':generalForm,'id':'frm_GeneralSettings'])}} + +This tells the template system to add a form using the contents of +generalForm and name it frm\_GeneralSettings in the html page. Based on +a standard template part which is already part of the standard system, +named base\_form.volt. + +When opening the page again it will render like this: + +|Template with fields without content| + +Create API calls +---------------- + +.. rubric:: Create API calls to retrieve and store data + :name: create-api-calls-to-retrieve-and-store-data + +The framework provides some helpful utilities to get and set data from +and to the configuration xml by using your defined model. First step in +binding your model to the system is to add a method to the +SettingsController to fetch the data from our configuration (or provide +the defaults if there is no content). + +We start by adding the model to our SettingsController, by adding this +in the “use” section: + +.. code-block:: php + + use \OPNsense\HelloWorld\HelloWorld; + +Which includes our model into the controller. Next we create an action +to get data from our system, and put it into a json object for the +client (browser) to parse, by using the wrappers already in our model. + +.. code-block:: php + + * retrieve HelloWorld general settings + * @return array general settings + */ + public function getAction() + { + // define list of configurable settings + $result = array(); + if ($this->request->isGet()) { + $mdlHelloWorld = new HelloWorld(); + $result['helloworld'] = $mdlHelloWorld->getNodes(); + } + return $result; + } + +(/usr/local/opnsense/mvc/app/controllers/OPNsense/HelloWorld/Api/SettingsController.php) + +You will probably notice the return value of the action, it's a standard +array which uses "helloworld" for all attributes from getNodes() which +will automatically be converted by the framework to a json object for +the client. The getNodes method itself returns a tree a values, as +defined by your model. + +You can test the result (while logged in as root), by going to this +address: + +:: + + http[s]:///api/helloworld/settings/get + +For saving the data back, we need a similar kind of call, let’s name it +“set” and add this to the same php file: + +.. code-block:: php + + /** + * update HelloWorld settings + * @return array status + */ + public function setAction() + { + $result = array("result"=>"failed"); + if ($this->request->isPost()) { + // load model and update with provided data + $mdlHelloWorld = new HelloWorld(); + $mdlHelloWorld->setNodes($this->request->getPost("helloworld")); +   + // perform validation + $valMsgs = $mdlHelloWorld->performValidation(); + foreach ($valMsgs as $field => $msg) { + if (!array_key_exists("validations", $result)) { + $result["validations"] = array(); + } + $result["validations"]["general.".$msg->getField()] = $msg->getMessage(); + } +   + // serialize model to config and save + if ($valMsgs->count() == 0) { + $mdlHelloWorld->serializeToConfig(); + Config::getInstance()->save(); + $result["result"] = "saved"; + } + } + return $result; + } + +(/usr/local/opnsense/mvc/app/controllers/OPNsense/HelloWorld/Api/SettingsController.php) + +And include the Config class from our base system by adding this to the +“use” section: + +.. code-block:: php + + use \OPNsense\Core\Config; + + +Support jQuery API calls +------------------------ + +.. rubric:: Update the view to support the API calls using jQuery + :name: update-the-view-to-support-the-api-calls-using-jquery + +Now we need to link the events to the backend code to be able to load +and save our form, by using the OPNsense libraries you can validate your +data automatically. + +Add this to the index.volt template from the HelloWorld module: + +.. code-block:: html + + +   +
+ +
+ +The first piece of javascript code handles the loading of data when +opening the form, then a button is linked to the save event. + +Let’s give it a try and save our data, without modifying it first. + +|Form with validation errors| + +Next correct the errors and save again, on successful save the data +should be stored in the config.xml. If you want to change validation +messages, just edit the model xml and add your message in the +ValidationMessage tag. For example: + +.. code-block:: xml + + + Y + please specify a valid email address + + +Changes the “email address invalid” into “please specify a valid email +address” + +Add actions +----------- + +.. rubric:: Add some activity to the module + :name: add-some-activity-to-the-module + +Our basic module provides a way to read and modify configuration data +using the web interface (and in time also other consumers using the +api). Next step is to add some activity to our system, all backend +applications should use their own configuration, which in real life we +would keep as standard as possible. + +For our example we will follow the same process as for any other service +and start writing some configuration data for our sample application. +Which means, creating a template and hooking it into our save action. + +Our example will write a simple configuration file, stored in +/usr/local/etc/helloworld/helloworld.conf + +The configd system is responsible for updating the contents of that file +when requested, it does so by using a definition found in its template +folder. This sample will use the following path to store the backend +templates: + +:: + + /usr/local/opnsense/service/templates/OPNsense/HelloWorld/ + +First we add a content definition, by creating a file named +TARGETS, +which should hold the following information: + +:: + + helloworld.conf:/usr/local/etc/helloworld/helloworld.conf + +This basically tells the engine that there will be a file in the same +folder named “helloworld.conf” which provides, together with config.xml, +data for the file in /usr/local/etc/helloworld/helloworld.conf + +Next thing to do is create that helloworld.conf file in the templates +directory. We will keep things very simple for this one and just copy in +our data into an ini file structured configuration, when the module is +enabled. + +.. code-block:: html+jinja + + {% if helpers.exists('OPNsense.helloworld.general') and OPNsense.helloworld.general.Enabled|default("0") == "1" %} + [general] + SMTPHost={{ OPNsense.helloworld.general.SMTPHost|default("") }} + FromEmail={{ OPNsense.helloworld.general.FromEmail|default("") }} + ToEmail={{ OPNsense.helloworld.general.ToEmail|default("") }} + Subject={{ OPNsense.helloworld.general.Description|default("") }} + {% endif %} + +Now we need to be able to reload this module (or in real life, this +would probably be a service) by adding a service action into our +ServiceController. Edit +controllers/OPNsense/HelloWorld/Api/ServiceController.php and add the +backend module to the use section, like this: + +.. code-block:: php + + use \OPNsense\Core\Backend; + + +By doing this we can use the backend communication in this class. Next +add a new action to the class called “reloadAction” using this piece of +code: + +.. code-block:: php + + public function reloadAction() + { + $status = "failed"; + if ($this->request->isPost()) { + $backend = new Backend(); + $bckresult = trim($backend->configdRun("template reload OPNsense/HelloWorld")); + if ($bckresult == "OK") { + $status = "ok"; + } + } + return array("status" => $status); + } + +(/usr/local/opnsense/mvc/app/controllers/OPNsense/HelloWorld/Api/ServiceController.php) + +This validates the type of action (it should always be POST to enable +csrf protection) and adds a backend action for reloading the template. +When successful the action will return “status”:”ok” as json object back +to the client. + +Now we are able to refresh the template content, but the user interface +doesn’t know about it yet. To hook loading of the template into the save +action, we will go back to the index.volt view and add the following +jQuery / framework code between the braces of “saveFormToEndPoint”. + +.. code-block:: javascript + + ajaxCall(url="/api/helloworld/service/reload", sendData={},callback=function(data,status) { + // action to run after reload + }); + +If you save the form now (when enabled), you should see a new file in + +:: + + helloworld.conf:/usr/local/etc/helloworld/helloworld.conf + +Containing something like this: + +.. code-block:: ini + + [general] + SMTPHost=127.0.0.1 + FromEmail=sample@example.com + ToEmail=sample@example.com + Subject=test + +What have we accomplished now, we can input data, validate it and save +it to the corresponding format of the actual service or application, +which uses this data. So if you have a third party application, which +you want to integrate into the user interface. You should be able to +generate what it needs now. (there’s more to learn, but these are the +basics). + +But how do should we control that third part program now? That’s the +next step. + +---------------------- +Controlling the sample +---------------------- + +In stead of running all kinds of shell commands directly from the php +code, which very often need root access (starting/stopping services, +etc), we should always communicate to our backend process which holds +templates of possible things to run and protects your system from +executing arbitrary commands. + +Another advantage of this approach is that all commands defined here, +can also be ran from the command line of the firewall providing easier +serviceability. For example, the command to refresh the helloworld +configuration can be run from the command line by running: + +:: + + configctl template reload OPNsense/HelloWorld + +First thing to do when registering new actions to the system for a new +application is to create a config template. + +:: + + /usr/local/opnsense/service/conf/actions.d/actions_helloworld.conf + +And add a command to the template like this: + +:: + + [test] + command:/usr/local/opnsense/scripts/OPNsense/HelloWorld/testConnection.py + parameters: + type:script_output + message:hello world module test + +Let’s test our new command by restarting configd from the command line: + +:: + + service configd restart + +And test our new command using: + +:: + + configctl helloworld test + +Which should return some response in json format. + +Next step is to use this command in our controller (middleware), just +like we did with the template action. For consistency we call our action +testAction and let it pass json data to our clients when using a POST +type request. + +.. code-block:: php + + public function testAction() + { + if ($this->request->isPost()) { + $backend = new Backend(); + $bckresult = json_decode(trim($backend->configdRun("helloworld test")), true); + if ($bckresult !== null) { + // only return valid json type responses + return $bckresult; + } + } + return array("message" => "unable to run config action"); + } + +(/usr/local/opnsense/mvc/app/controllers/OPNsense/HelloWorld/Api/ServiceController.php) + +And now we can make our user interface aware of the action, place a +button and link an action in the index.volt. Using the following +elements: + +| +| (in script section) + +.. code-block:: javascript + + $("#testAct").click(function(){ + $("#responseMsg").removeClass("hidden"); + ajaxCall(url="/api/helloworld/service/test", sendData={},callback=function(data,status) { + // action to run after reload + $("#responseMsg").html(data['message']); + }); + }); + +(in html section) + +.. code-block:: xml + + + + +(/usr/local/opnsense/mvc/app/views/OPNsense/HelloWorld/index.volt) + +Now go back to the page and save some data using the save button, next +press test to see some results. + +|test the application action| + +----------------------------- +Multi language / Translations +----------------------------- + +OPNsense is available in may different languages like english, german or japanese. +This works because we are using the gettext library which is available to all GUI components. +While the XML based user interfaces are supporting it automatically, +there may still the need to call it manually (buttons, tabs etc.). + +If you have a static string, you should add it like this into a classic php page: + +.. code-block:: php + + + +And this way into a volt template: + +.. code-block:: html+jinja + + {{ lang._('your string here') }} + +If your string is not only plaintext because it contains non-static words, HTML tags and other dynamic content, +you need to use a format string. This way, you can use placeholders for such elements which should not land in +the translation file. + +For php it works this way: + +.. code-block:: php + + + +And for volt templates it works this way: + +.. code-block:: html+jinja + + {{ lang._('your %s here') | format(data) }} + +.. Note:: + You should NEVER split strings which should belong together like a sentence. + This makes plugins hard to translate and will decrease the quality of OPNsense in other languages. + + +------------------------- +Plugin to the menu system +------------------------- + +Most modules and applications need a place in the menu system, you could +easily arrange that by creating a Menu.xml definition for your module in +the model directory under Menu/Menu.xml. + +Now let’s register our “hello world” in the user section of our menu, by +adding this content into the menu.xml: + +.. code-block:: xml + + + + + + + + + +When you refresh your page now, you should notice the menu system +automatically picks up this new information. + +|menu registration| + +------------------------------ +Plugin to access control (ACL) +------------------------------ + +If we want to authorize users to access this module, we can add an acl +to this module. Without it, only admin users can access it. Create an +xml file in the model directory name ACL/ACL.xml and place the following +content in it: + +.. code-block:: xml + + + + + WebCfg - Users: Hello World! + Allow access to the Hello World! module + + ui/helloworld/* + api/helloworld/* + + + + +This creates an acl key named “page-user-helloworld” which authorizes +access to both the ui and api urls of this application. You can now +grant access to this module from the system user manager. + +| + +---------------------------- +Create an installable plugin +---------------------------- + +All files are created in their original locations (on the OPNsense +machine /usr/local/…), now we are ready to create a package from them. +To fully use this process and create the actual package, it’s best to +setup a full build environment (explained over here: +https://github.com/opnsense/tools ) + +When everything is in place, we will create a new plugin directory. For +this example we will use the following: + +:: + + /usr/plugins/devel/helloworld/ + +Add a new Makefile, containing the information for our plugin: + +.. code-block:: kconfig + + PLUGIN_NAME= helloworld + PLUGIN_VERSION= 1.0 + PLUGIN_COMMENT= A sample framework application + #PLUGIN_DEPENDS= + PLUGIN_MAINTAINER= user@domain +   + .include "../../Mk/plugins.mk" + + +| +| Then create an src directory in here: + +:: + + /usr/plugins/devel/helloworld/src/ + +Next copy all files created and located in /usr/local/ into this new src +directory, which results in the following file listing: + +:: + + src/opnsense/mvc/app/controllers/OPNsense/HelloWorld/Api/ServiceController.php + src/opnsense/mvc/app/controllers/OPNsense/HelloWorld/Api/SettingsController.php + src/opnsense/mvc/app/controllers/OPNsense/HelloWorld/IndexController.php + src/opnsense/mvc/app/controllers/OPNsense/HelloWorld/forms/general.xml + src/opnsense/mvc/app/models/OPNsense/HelloWorld/ACL/ACL.xml + src/opnsense/mvc/app/models/OPNsense/HelloWorld/HelloWorld.php + src/opnsense/mvc/app/models/OPNsense/HelloWorld/HelloWorld.xml + src/opnsense/mvc/app/models/OPNsense/HelloWorld/Menu/Menu.xml + src/opnsense/mvc/app/views/OPNsense/HelloWorld/index.volt + src/opnsense/scripts/OPNsense/HelloWorld/testConnection.py + src/opnsense/service/templates/OPNsense/HelloWorld/+TARGETS + src/opnsense/service/templates/OPNsense/HelloWorld/helloworld.conf + src/opnsense/service/conf/actions.d/actions_helloworld.conf + +Next add a +POST\_INSTALL file in the plugin directory, to reload the +configd process after installation. This is needed for the new “test” +command to register. + + +.. code-block:: sh + + if /usr/local/etc/rc.d/configd status > /dev/null; then + /usr/local/etc/rc.d/configd restart + fi + +With everything in place, you could build the plugin package using the +“make plugins” command in the /usr/tools directory. The result of this +will be a standard pkg package, which you can install on any OPNsense +system and will be usable right after installing. All plugins are +prefixed with os-, our new package file will be called: + +:: + + os-helloworld-1.0.txz + +(-1.0 comes from the version in the makefile) + +.. rubric:: Reference + :name: reference + +- source of this example : + https://github.com/opnsense/plugins/tree/master/devel/helloworld +- build instructions : https://github.com/opnsense/tools +- frontend template language reference (Volt) : + https://docs.phalconphp.com/en/latest/reference/volt.html +- configuration template language reference (mostly the same as Volt) : + http://jinja.pocoo.org/docs/dev/ +- OPNsense architecture :doc:`Architecture <../architecture>` +- OPNsense creating models + `Develop:Frontend/Creating\_models `__ + +.. |overview| image:: images/Helloworld_overview.png + :width: 700px +.. |Serving the first "hello world" page| image:: images/HelloWorld_Empty_template.png + :width: 884px + :height: 605px +.. |Template with fields without content| image:: images/HelloWorld_Template_no_content.png + :width: 889px + :height: 535px +.. |Form with validation errors| image:: images/HelloWorld_form_validation_error.png + :width: 1098px + :height: 525px +.. |test the application action| image:: images/HelloWorld_first_test_action.png + :width: 1403px + :height: 624px +.. |menu registration| image:: images/HelloWorld_menu_registration.png + :width: 1400px + :height: 639px diff --git a/source/development/examples/images/Hello-World.jpg b/source/development/examples/images/Hello-World.jpg new file mode 100644 index 0000000..2cf9318 Binary files /dev/null and b/source/development/examples/images/Hello-World.jpg differ diff --git a/source/development/examples/images/HelloWorld_Empty_template.png b/source/development/examples/images/HelloWorld_Empty_template.png new file mode 100644 index 0000000..83e165d Binary files /dev/null and b/source/development/examples/images/HelloWorld_Empty_template.png differ diff --git a/source/development/examples/images/HelloWorld_Template_no_content.png b/source/development/examples/images/HelloWorld_Template_no_content.png new file mode 100644 index 0000000..0e96185 Binary files /dev/null and b/source/development/examples/images/HelloWorld_Template_no_content.png differ diff --git a/source/development/examples/images/HelloWorld_first_test_action.png b/source/development/examples/images/HelloWorld_first_test_action.png new file mode 100644 index 0000000..8136aa0 Binary files /dev/null and b/source/development/examples/images/HelloWorld_first_test_action.png differ diff --git a/source/development/examples/images/HelloWorld_form_validation_error.png b/source/development/examples/images/HelloWorld_form_validation_error.png new file mode 100644 index 0000000..2f05f69 Binary files /dev/null and b/source/development/examples/images/HelloWorld_form_validation_error.png differ diff --git a/source/development/examples/images/HelloWorld_menu_registration.png b/source/development/examples/images/HelloWorld_menu_registration.png new file mode 100644 index 0000000..f029e70 Binary files /dev/null and b/source/development/examples/images/HelloWorld_menu_registration.png differ diff --git a/source/development/examples/images/Helloworld_overview.png b/source/development/examples/images/Helloworld_overview.png new file mode 100644 index 0000000..a95107c Binary files /dev/null and b/source/development/examples/images/Helloworld_overview.png differ diff --git a/source/development/frontend.rst b/source/development/frontend.rst new file mode 100644 index 0000000..69588fb --- /dev/null +++ b/source/development/frontend.rst @@ -0,0 +1,15 @@ +======== +Frontend +======== + +The OPNsense frontend is implemented with `PHP/Phalcon `__. + +.. toctree:: + :maxdepth: 2 + :titlesonly: + :glob: + + frontend/models + frontend/routing + frontend/controller + frontend/* diff --git a/source/development/frontend/controller.rst b/source/development/frontend/controller.rst new file mode 100644 index 0000000..be8c811 --- /dev/null +++ b/source/development/frontend/controller.rst @@ -0,0 +1,101 @@ +=========================== +Using controllers and views +=========================== + +------- +General +------- + +After routing is performed, the controller takes care of the actual code +to execute for the request. Because we want to implement some basics for +every request that gets processed you should inherit from our base +classes to ensure basic functionality such as authorisation and csrf +protection. + +Controllers are placed in the directory /usr/local/opnsense/mvc/app/controllers/// +and should use the standard Phalcon naming conventions, suffix Controller.php on +every class file and suffix Action on all action methods. + +For a detailed description of how Controllers work in Phalcon, please +look at the Phalcon documentation at http://docs.phalconphp.com/en/latest/reference/controllers.html + +---------------------- +View based controllers +---------------------- + +For rendering standard pages we have chosen to use Volt templates, the +base controller to inherit from in this case is +OPNsense\\Base\\ControllerBase and should take care of binding a +template to the controller. Every template automatically receives +standard features (such as the menu system). + +The wireframe for implementing a single action should look like this: + +.. code-block:: php + + view->my_variable1 = 'test 1'; + $this->view->my_variable2 = 'test 2'; + // pick a template + $this->view->pick('SampleVendor/Sample/index'); + } + +And the volt template SampleVendor/Sample/index.volt could contain something like: + +.. code-block:: html + + the contents of my_variable1 => {{ my_variable1 }}
+ the contents of my_variable2 => {{ my_variable2 }}
+ +A full example can be found in the OPNsense\\Sample controller +directory. + +More information on how to write Volt pages can be found here : +http://docs.phalconphp.com/en/latest/reference/volt.html + +--------------------- +API based controllers +--------------------- + +For API calls a separate class is used to derive from, which implements +a simple interface to handle calls. The main difference with the view +controllers is that an action should return a named array containing +response data in stead of picking a template. + +A simple index controller to echo a request back looks like this: + +.. code-block:: php + + class TestController extends ApiControllerBase + { + /** + * @return array + */ + public function echoAction() + { + if ($this->request->hasPost("message")) { + $message = $this->request->getPost("message"); + } else { + $message = " " ; + } +   + return array("message" => $message); + } + } + +When placed inside the api directory of Vendor/Sample can be called by sending a +post request to /api/sample/test/echo, using jquery: + +.. code-block:: javascript + + $.ajax({ + type: "POST", + url: "/api/sample/test/echo", + success: function(data){ + alert(data.message) ; + }, + data:{message:"test message"} + }); diff --git a/source/development/frontend/models.rst b/source/development/frontend/models.rst new file mode 100644 index 0000000..a6caa78 --- /dev/null +++ b/source/development/frontend/models.rst @@ -0,0 +1,202 @@ +=============== +Creating Models +=============== + +A model represents the data which the application will use and takes +care of the interaction to that data. In OPNsense most of the relevant +data is physically stored in an xml structure (config.xml). The primary +goal for OPNsense models is to structure the use of configuration data, +by creating a clear abstraction layer. + +In this chapter we will explain how models are designed and build. + +------------------- +Designing the model +------------------- + +Creating models for OPNsense is divided into two separate blocks: + +#. A php class describing the actions on our data (also acts as a + wrapper to our data), +#. The definition of the data and the rules it should apply to. + +Every model's class should be derived from OPNsense\\Base\\BaseModel, a very +simple model without any (additional) logic is defined with: + +.. code-block:: php + + + //myManufacturer/myModule + A description of this model (metadata) + + + /^([0-9]){0,1}$/ + 5 + you should input a number from 0 to 9 + + + + + you should input a valid email address! + + + + + + + + +Now let's explain what's happing here one tag at a time. + +#. the tag is used for identification of the file. (this is a + model file) +#. Next in line is the tag, this tells the system where this + information lives in the configuration file, in this case + ROOT\_tag/myManufacturer/myModule +#. If desired, there is some space reserved to explain the usage of the + model, the tag +#. Last item on the top of our list is the tag, this is where + the magic begins. + +The content of a items tag describes the full tree based structure which holds +our data, in theory this could be as large as you want it to be, but keep in +mind that the content for your model should be logical and understandable. Every +node in the tree could have a type, which defines it's behavior, nodes without a +type are just containers. + +From top to bottom we find the following nodes in our tree: + +- exampleNumber, defined as a TextField + + - Mask, validation can be performed by a regex expression, this sets + the expression + - Default, this field is default filled with a number: 5 + - ValidationMessage, when validation fails, this message is returned + +- contacts, this is a container +- entity, is defined as a recurring item, which holds the next items +- email, defined as an EmailField + + - when validation fails, the **ValidationMessage** is returned + +- name, defined as a TextField without any validations +- someText, not part of the entity tag and also defined as text without + validation + +The fieldtypes are easily extendable in the base system and they all live in +their own namespace at *OPNsense\\Base\\FieldTypes* deriving from *BaseField*. + +------------- +Usage example +------------- + +Now let's test our model using a small php script (in /usr/local/opnsense/mvc/script/ ): + +.. code-block:: php + + exampleNumber =1; + $myMdl->contacts->someText = "just a test"; +   + // add a new contact node + $node = $myMdl->contacts->entity->add(); + $node->email = "test@test.com"; + $node->name = "my test user"; +   + // perform validation on the data in our model + $validationMessages = $myMdl->performValidation(); + foreach ($validationMessages as $messsage) { + echo "validation failure on field ". $messsage->getField()." returning message : ". $messsage->getMessage()."\n"; + } +   + // if validation succeeded, write data back to config + if ($validationMessages->count() == 0) { + // serialize our model to the config file (config.xml) + // (this raises an error on validation failures) + $myMdl->serializeToConfig(); + $cnf = Config::getInstance(); + $cnf->save(); + } + + +If you fill in an invalid value to one of the validated fields, you can easily +try the validation. Try to input the text "X" into the field exampleNumber to try out. + +When inspecting our config.xml file, you will notice the following content has +been added to the root: + +.. code-block:: xml + + + + 1 + + + test@test.com + my test user + + just a test + + + + +---------- +Guidelines +---------- + +.. rubric:: Some (simple) guidelines developing models + :name: some-simple-guidelines-developing-models + +#. One model should always be completely responsible for the its mount + point, so if there's a model at mount point /A/B there can't be a + model at /A/B/C +#. Try to keep models logical and understandable, it's better to build + two models for you application if the content of two parts aren't + related to each other. It's no issue to create models at deeper + levels of the structure. + + #. When using more models in a application/module, you might want to + consider the following naming convention: /Vendor/Module/Model + +#. Try to avoid more disc i/o actions than necessary, only call save() + if you actually want to save content, serializeToConfig just keeps + the data in memory. diff --git a/source/development/frontend/routing.rst b/source/development/frontend/routing.rst new file mode 100644 index 0000000..3b59930 --- /dev/null +++ b/source/development/frontend/routing.rst @@ -0,0 +1,85 @@ +======= +Routing +======= + +------- +General +------- + +To retain backward compatibility with legacy code, we try to keep the +old pages at their original location. For the new code, we define two +root folders in the url: + +- /ui/ for the new user interface parts +- /api/ used for webservices (REST) + +This part of the routing is handled by lighthttpd using mod\_alias and mod\_rewrite. + +---------------------- +User interface Routing +---------------------- + +If you look at the controller directory in OPNsense, you will notice +there are different directory levels under the root controller directory +in /usr/local/opnsense/mvc/app/controllers. To support different apps +and vendors eventually, we already used a structure which is +automatically used to setup the routing. + +At the first level we use the vendor of the app, in our case that will +always be OPNsense. + +The next level is used to name the topic (or app), for example we use +Sample for our example application. + +Finally you may place your standard Phalcon classes for controllers in +that directory, so if you want to create a page helloworld, that should +come with a controller helloworldController.php (and a indexAction to +define the index action for that page). + +The complete path of the helloworld page would eventually be: + +:: + + /usr/local/opnsense/mvc/app/controllers/OPNsense/Sample/helloworldController.php + +When publishing the page, the vendor part of the controller is not used in the +mapping, so in this example the helloworld index page will be at: + +:: + + https://{url}/ui/sample/helloworld/ + +All the parts of the url are automatically converted to lower-case, so **S**\ample +will be mapped to **s**\ample. + +This routing is setup via the index page of our new code base and uses + +:: + + /usr/local/opnsense/mvc/app/config/services.php to wire it all together. + +----------- +API routing +----------- + +Routing for api functions is quite similar to routing UI components, +just create a Api directory under the app path and place a controller +class to handle the request. The only major difference is that it's +handled by a separate php file (called api.php) in stead of the +index.php file used to configure the ui part, details of the routing can +be found in /usr/local/opnsense/mvc/app/config/services\_api.php . + +If our sample app needs an api to echo something back via a controller called +tools it could be put into a file called: + +:: + + /usr/local/opnsense/mvc/app/controllers/OPNsense/Sample/Api/toolsController.api + +And called via the following url: + +:: + + https://{host}}/api/sample/tools/echo + +When the controller has a method called echoAction. diff --git a/source/development/guidelines.rst b/source/development/guidelines.rst new file mode 100644 index 0000000..a5e3a10 --- /dev/null +++ b/source/development/guidelines.rst @@ -0,0 +1,18 @@ +================== +Coding Guidelines +================== + +.. image:: images/guidelines_new.png + +------------------ + +.. toctree:: + :maxdepth: 2 + :titlesonly: + :glob: + + guidelines/basics + guidelines/psr1 + guidelines/psr2 + guidelines/peps + guidelines/* diff --git a/source/development/guidelines/basics.rst b/source/development/guidelines/basics.rst new file mode 100644 index 0000000..e1f22d5 --- /dev/null +++ b/source/development/guidelines/basics.rst @@ -0,0 +1,92 @@ +================= +Basics and Future +================= + +This article explains the basic coding guidelines that apply and put the +development effort into perspective by explaining the difficulties of legacy +code and the interaction/migration to new MVC-based code. It also explains guideline +differences between new and legacy code. + +-------- +PHP code +-------- +For PHP code the PSR1 and PSR2 Coding Standard apply. + +------ +Python +------ +For Python code the Python Enhancement Proposals (PEPs) apply. +See the `Python Developer's Guide `__ for detailed +information. + +------------ +Architecture +------------ +Documentation is available about our :doc:`architecture ` +and used :doc:`components `. + +----------------- +Ideal Development +----------------- +Our ideal OPNsense system looks like a standard FreeBSD system using our +pluggable user interface for management, which supports both real users as "machine" +users (REST). + +When developing we want the code to be clean and coded as DRY (Don't Repeat Yourself) +as possible and do not want to invent the wheel when not needed. + +The user interface should to be able to run as non-root user instead of root by +restructuring the way commands are passed to the system (configd). + +---------------------------- +Reality: Overdue Maintenance +---------------------------- +In reality we forked a system that went without code maintenance for a very long +time and we needed to transition that into something more structured. + +One of the first things (on the programming part of the system) we did was build +components around an existing framework (Phalcon) to create new modules, which +could use validated configuration data (from the config.xml), supply a RESTful +API and generate html output using standard templates (Volt). + +We created the configd system, which can generate system configuration and +execute system calls using predefined templates. And then we started using those +new components for our first newly designed modules (like the proxy and the traffic shaper). +More information about the “to-be” architecture can be found in our +:doc:`architecture ` documentation. + +--------- +Strategy +--------- +Knowing we can’t change the world in a single day and having a lot of legacy to +drag around with us, our strategy consists of three parts: + +**1)** Cleanup and maintenance +Restructure old (legacy) code, basically all code in the src/www, src/etc/inc to +make it better readable, easier to use and remove unused / unnecessary parts. By +doing so we want to extend the lifetime of the old code a bit and make the +transition in new code easier eventually. + +**2)** Detach +Move system configuration calls to configd where possible, which gives the +administrator the advantage of running those commands from the command line and +helps removing the need for root user access in the future. The ipsec VICI +implementation is one example of this stage. + +**3)** Moving on +(re)build new parts, using our new modules, which provide a layered development +system to automatically support api calls from other systems and xml based model +templates to describe configuration data. + +*See also:* + +* :doc:`Hello World Module ` +* :doc:`Howto use the API ` + +Our guidelines somewhat depend of the stage the code is in, when writing new code, +all actions should use the api system for actually changing configuration and +performing configuration tasks. They should, of course, use the normal PSR coding +standards for php code and follow the python peps. + +When moving to the legacy part of the system, our goal is to stick as close to +PSR1/2 as possible, knowing it will never be perfect. diff --git a/source/development/guidelines/peps.rst b/source/development/guidelines/peps.rst new file mode 100644 index 0000000..b75e571 --- /dev/null +++ b/source/development/guidelines/peps.rst @@ -0,0 +1,7 @@ +=========== +Python PEPs +=========== + +For Python code the Python Enhancement Proposals (PEPs) apply. +See the `Python Developer's Guide `__ for detailed +information. diff --git a/source/development/guidelines/psr1.rst b/source/development/guidelines/psr1.rst new file mode 100644 index 0000000..d17e10c --- /dev/null +++ b/source/development/guidelines/psr1.rst @@ -0,0 +1,196 @@ +=========================== +PSR-1 Basic Coding Standard +=========================== + +.. Note:: + + | The PSR1 and PSR2 Coding Standards are provided by FIG under a MIT license. + | See license details: http://www.php-fig.org/bylaws/licensing-policies/ + | The original content of this page can be found at `php-fig `__ + +This section of the standard comprises what should be considered the +standard coding elements that are required to ensure a high level of +technical interoperability between shared PHP code. + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in `RFC +2119 `__. + +----------- +1. Overview +----------- + +- Files MUST use only ```__, + `PSR-4 `__]. + +- Class names MUST be declared in ``StudlyCaps``. + +- Class constants MUST be declared in all upper case with underscore + separators. + +- Method names MUST be declared in ``camelCase``. + +-------- +2. Files +-------- + +2.1. PHP Tags +------------- + +PHP code MUST use the long ```` tags or the short-echo +```` tags; it MUST NOT use the other tag variations. + +2.2. Character Encoding +----------------------- + +PHP code MUST use only UTF-8 without BOM. + +2.3. Side Effects +----------------- + +A file SHOULD declare new symbols (classes, functions, constants, etc.) +and cause no other side effects, or it SHOULD execute logic with side +effects, but SHOULD NOT do both. + +The phrase "side effects" means execution of logic not directly related +to declaring classes, functions, constants, etc., *merely from including +the file*. + +"Side effects" include but are not limited to: generating output, +explicit use of ``require`` or ``include``, connecting to external +services, modifying ini settings, emitting errors or exceptions, +modifying global or static variables, reading from or writing to a file, +and so on. + +The following is an example of a file with both declarations and side +effects; i.e, an example of what to avoid: + + +.. code-block:: php + + \n"; + + // declaration + function foo() + { + // function body + } + + +The following example is of a file that contains declarations without +side effects; i.e., an example of what to emulate: + + +.. code-block:: php + + `__, +`PSR-4 `__]. + +This means each class is in a file by itself, and is in a namespace of +at least one level: a top-level vendor name. + +Class names MUST be declared in ``StudlyCaps``. + +Code written for PHP 5.3 and after MUST use formal namespaces. + +For example: + +.. code-block:: php + + `__ + +This guide extends and expands on +`PSR-1 `__, +the basic coding standard. + +The intent of this guide is to reduce cognitive friction when scanning code from +different authors. It does so by enumerating a shared set of rules and expectations +about how to format PHP code. + +The style rules herein are derived from commonalities among the various member +projects. When various authors collaborate across multiple projects, it helps to +have one set of guidelines to be used among all those projects. Thus, the benefit +of this guide is not in the rules themselves, but in the sharing of those rules. + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in `RFC +2119 `__. + +----------- +1. Overview +----------- + +- Code MUST follow a "coding style guide" PSR + [`PSR-1 `__]. + +- Code MUST use 4 spaces for indenting, not tabs. + +- There MUST NOT be a hard limit on line length; the soft limit MUST be + 120 characters; lines SHOULD be 80 characters or less. + +- There MUST be one blank line after the ``namespace`` declaration, and + there MUST be one blank line after the block of ``use`` declarations. + +- Opening braces for classes MUST go on the next line, and closing + braces MUST go on the next line after the body. + +- Opening braces for methods MUST go on the next line, and closing + braces MUST go on the next line after the body. + +- Visibility MUST be declared on all properties and methods; + ``abstract`` and ``final`` MUST be declared before the visibility; + ``static`` MUST be declared after the visibility. + +- Control structure keywords MUST have one space after them; method and + function calls MUST NOT. + +- Opening braces for control structures MUST go on the same line, and + closing braces MUST go on the next line after the body. + +- Opening parentheses for control structures MUST NOT have a space + after them, and closing parentheses for control structures MUST NOT + have a space before. + +1.1. Example +------------ + +This example encompasses some of the rules below as a quick overview: + +.. code-block:: php + + $b) { + $foo->bar($arg1); + } else { + BazClass::bar($arg2, $arg3); + } + } + + final public static function bar() + { + // method body + } + } + +---------- +2. General +---------- + +2.1 Basic Coding Standard +------------------------- + +Code MUST follow all rules outlined in +`PSR-1 `__. + +2.2 Files +--------- + +All PHP files MUST use the Unix LF (linefeed) line ending. +All PHP files MUST end with a single blank line. + +The closing ``?>`` tag MUST be omitted from files containing only PHP. + +2.3. Lines +---------- + +There MUST NOT be a hard limit on line length. + +The soft limit on line length MUST be 120 characters; automated style +checkers MUST warn but MUST NOT error at the soft limit. + +Lines SHOULD NOT be longer than 80 characters; lines longer than that +SHOULD be split into multiple subsequent lines of no more than 80 +characters each. + +There MUST NOT be trailing whitespace at the end of non-blank lines. + +Blank lines MAY be added to improve readability and to indicate related +blocks of code. + +There MUST NOT be more than one statement per line. + +2.4. Indenting +-------------- + +Code MUST use an indent of 4 spaces, and MUST NOT use tabs for +indenting. + +.. Note:: + + N.b.: Using only spaces, and not mixing spaces with tabs, helps to + avoid problems with diffs, patches, history, and annotations. The + use of spaces also makes it easy to insert fine-grained + sub-indentation for inter-line alignment. + +2.5. Keywords and True/False/Null +--------------------------------- + +PHP `keywords `__ MUST +be in lower case. + +The PHP constants ``true``, ``false``, and ``null`` MUST be in lower +case. + +--------------------------------- +3. Namespace and Use Declarations +--------------------------------- + +When present, there MUST be one blank line after the ``namespace`` +declaration. + +When present, all ``use`` declarations MUST go after the ``namespace`` +declaration. + +There MUST be one ``use`` keyword per declaration. + +There MUST be one blank line after the ``use`` block. + +For example: + +.. code-block:: php + + bar($arg1); + Foo::bar($arg2, $arg3); + +Argument lists MAY be split across multiple lines, where each subsequent +line is indented once. When doing so, the first item in the list MUST be +on the next line, and there MUST be only one argument per line. + +.. code-block:: php + + bar( + $longArgument, + $longerArgument, + $muchLongerArgument + ); + +--------------------- +5. Control Structures +--------------------- + +The general style rules for control structures are as follows: + +- There MUST be one space after the control structure keyword +- There MUST NOT be a space after the opening parenthesis +- There MUST NOT be a space before the closing parenthesis +- There MUST be one space between the closing parenthesis and the + opening brace +- The structure body MUST be indented once +- The closing brace MUST be on the next line after the body + +The body of each structure MUST be enclosed by braces. This standardizes +how the structures look, and reduces the likelihood of introducing +errors as new lines get added to the body. + +5.1. ``if``, ``elseif``, ``else`` +--------------------------------- + +An ``if`` structure looks like the following. Note the placement of +parentheses, spaces, and braces; and that ``else`` and ``elseif`` are on +the same line as the closing brace from the earlier body. + +.. code-block:: php + + $value) { + // foreach body + } + +5.6. ``try``, ``catch`` +----------------------- + +A ``try catch`` block looks like the following. Note the placement of +parentheses, spaces, and braces. + +.. code-block:: php + + bar( + $arg1, + function ($arg2) use ($var1) { + // body + }, + $arg3 + ); + +------------- +7. Conclusion +------------- + +There are many elements of style and practice intentionally omitted by +this guide. These include but are not limited to: + +- Declaration of global variables and global constants + +- Declaration of functions + +- Operators and assignment + +- Inter-line alignment + +- Comments and documentation blocks + +- Class name prefixes and suffixes + +- Best practices + +Future recommendations MAY revise and extend this guide to address those or other +elements of style and practice. diff --git a/source/development/how-tos/api.rst b/source/development/how-tos/api.rst new file mode 100644 index 0000000..2b67818 --- /dev/null +++ b/source/development/how-tos/api.rst @@ -0,0 +1,121 @@ +=========== +Use the API +=========== + +-------- +Overview +-------- + +All components that are using the full architecture of OPNsense +automatically receive API capabilities, for this simple tutorial we use +the firmware module but others will function in the same way. API access +is part of the local user authentication system, but uses key/secret +pairs to separate account information from machine to machine +communication. Secrets are not stored on OPNsense and can be downloaded +only once, if lost, a new key has to be generated for your application. + +A user can have multiple keys, our advice is to create a unique key for +every application in use. + +------------- +Creating keys +------------- + +API keys are managed in the user manager (system\_usermanager.php), go +to the user manager page and select a user. Somewhere down the page you +will find the api section for this user. + +|Usermanager add api key.png| + +Click on the + sign to add a new key. When the key is created, you will +receive a (single download) with the credentials in one text file (ini +formatted). The contents of this file look like this: + +.. code-block:: c + + key=w86XNZob/8Oq8aC5r0kbNarNtdpoQU781fyoeaOBQsBwkXUt + secret=XeD26XVrJ5ilAc/EmglCRC+0j2e57tRsjHwFepOseySWLM53pJASeTA3 + +-------------------- +Code sample (python) +-------------------- + +For the python code sample we use the nice "requests" library +(http://docs.python-requests.org/en/latest/), which makes http calls +very easy. + +Before you can start, make sure your OPNsense has a valid SSL +certificate (or choose to ignore it for testing purposes by setting +verify=False), don't forget to verify that the selected user may access +the firmware page. + +The web interface uses the same logic that will be available for the +api, in this example we will collect some status information from the +firmware module and print it out for the user. + +It all starts with creating the request and waiting for the response, +all data interaction is using json format, both for the responses as for +the request data (when sending POST data). + +First step of the example is importing the required libraries, then +define the endpoint url and credentials to use and finally fire the (get +type) request. As soon as we receive the response, we parse the json +string back to a dictionary and print some data depending on the +response. + +.. code-block:: php + + # import libraries + import json + import requests + + # define endpoint and credentials + api_key = 'w86XNZob/8Oq8aC5hxh2he+vLN00r0kbNarNtdpoQU781fyoeaOBQsBwkXUt' + api_secret = 'puOyw0Ega3xZXeD26XVrJ5WYFepOseySWLM53pJASeTA3' + url = 'https://192.168.1.1/api/core/firmware/status' +  + # request data + r = requests.get(url, + verify='OPNsense.pem', + auth=(api_key, api_secret)) + + if r.status_code == 200: + response = json.loads(r.text) + + if response['status'] == 'ok' and response['status_upgrade_action'] == 'all': + print ('OPNsense can be upgraded') + print ('download size : %s' % response['download_size']) + print ('number of packages : %s' % response['updates']) + if response['upgrade_needs_reboot'] == '1': + print ('REBOOT REQUIRED') + elif response['status'] == 'ok' and response['status_upgrade_action'] == 'pkg': + print ('OPNsense can be upgraded, but needs a pkg upgrade first') + elif 'status_msg' in response: + print (response['status_msg']) + else: + print ('Connection / Authentication issue, response received:') + print r.text + + +---------- +Using curl +---------- + +Simple testing with curl is also possible, the sample below uses the +same credentials, but ignores the ssl certificate check (-k) for +testing. + +.. code-block:: sh + + curl -k -u "w86XNZob/8Oq8aC5hxh2he+vLN00r0kbNarNtdpoQU781fyoeaOBQsBwkXUt":"puOyw0Ega3xZXeD26XVrJ5WYFepOseySWLM53pJASeTA3" https://192.168.1.1/api/core/firmware/status + + +And schedule the actual upgrade of all packages using: + +.. code-block:: sh + + curl -XPOST -d '{"upgrade":"all"}' -H "Content-Type: application/json" -k -u "w86XNZob/8Oq8aC5hxh2he+vLN00r0kbNarNtdpoQU781fyoeaOBQsBwkXUt":"puOyw0Ega3xZXeD26XVrJ5WYFepOseySWLM53pJASeTA3" https://10.211.55.100/api/core/firmware/upgrade + + +.. |Usermanager add api key.png| image:: images/Usermanager_add_api_key.png + :width: 700px diff --git a/source/development/how-tos/images/Usermanager_add_api_key.png b/source/development/how-tos/images/Usermanager_add_api_key.png new file mode 100644 index 0000000..e526e05 Binary files /dev/null and b/source/development/how-tos/images/Usermanager_add_api_key.png differ diff --git a/source/development/howtos.rst b/source/development/howtos.rst new file mode 100644 index 0000000..6d0bf4d --- /dev/null +++ b/source/development/howtos.rst @@ -0,0 +1,10 @@ +==================================== +How to's +==================================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: + :glob: + + how-tos/* diff --git a/source/development/images/OPNsense_Components.png b/source/development/images/OPNsense_Components.png new file mode 100644 index 0000000..8f17481 Binary files /dev/null and b/source/development/images/OPNsense_Components.png differ diff --git a/source/development/images/OPNsense_backend.png b/source/development/images/OPNsense_backend.png new file mode 100644 index 0000000..35dbd18 Binary files /dev/null and b/source/development/images/OPNsense_backend.png differ diff --git a/source/development/images/OPNsense_frontend.png b/source/development/images/OPNsense_frontend.png new file mode 100644 index 0000000..665373d Binary files /dev/null and b/source/development/images/OPNsense_frontend.png differ diff --git a/source/development/images/flow.png b/source/development/images/flow.png new file mode 100644 index 0000000..afeb5cd Binary files /dev/null and b/source/development/images/flow.png differ diff --git a/source/development/images/guidelines_new.png b/source/development/images/guidelines_new.png new file mode 100644 index 0000000..0bfc10f Binary files /dev/null and b/source/development/images/guidelines_new.png differ diff --git a/source/development/images/ideas_join_the_development.jpg b/source/development/images/ideas_join_the_development.jpg new file mode 100644 index 0000000..0c1874d Binary files /dev/null and b/source/development/images/ideas_join_the_development.jpg differ diff --git a/source/development/workflow.rst b/source/development/workflow.rst new file mode 100644 index 0000000..1bf7ab3 --- /dev/null +++ b/source/development/workflow.rst @@ -0,0 +1,181 @@ +==================== +Development Workflow +==================== + +.. image:: images/flow.png + +It’s pretty hard to approach a larger repository you have never +worked with. The biggest issue is that few projects have defined +development (as in actual coding) workflow laid out for new +contributors, so one is just going to be stabbing in the dark for a few +days or weeks until things start making sense. Speaking of *sense*, +let’s explain how we’ve designed the development experience for +`OPNsense `__ and how you +can start contributing code in no time. + +--------- +Structure +--------- + +.. rubric:: Source, Ports, Core, Tools + :name: structure-source-ports-core-tools + +The structure is pretty much FreeBSD: we have a `source +code `__ repository and a `ports +tree `__. Historically, we also have +a `core code `__ and `tools +repository `__. The tools repository +is project shell code gluing all repositories together, producing final +images, while the core is the important GUI and system configuration +bits. + +.. Note:: + + As of 16.1 there is also plugin support, the source repository is `plugins tree `__ . + Plugins are a modular way of easily extending the existing system. + +.. rubric:: Why core is not a part of source + :name: core-not-part-of-source + +The first thing that’s interesting is that the core is not part of +the source repository, because it depends on third party software found in the +ports. We can’t stick core into source, because ports are things that +don’t fit into the base system. It also helps to keep source repository +changes to the minimum to make major FreeBSD upgrades easier in the +future. + +.. rubric:: Why core isn't part of ports either + :name: core-not-part-of-ports + +Why is the core repository not in the ports? Well, we have a couple of +custom ports in the ports tree, but these are small. The core repository as +well as the ports tree itself are so big that it made sense to keep them +separate. Another reason is that the core repository only contains scripts in +Shell, Python and PHP. So the tools repository actually treats the core +repository as a package that depends on all the ports it needs. This +way, on the images, it looks like the core code is just another package. +**That makes upgrading the core code very easy and fast without modifying +base.** We can even upgrade to newer ports pages and add and remove them +as we go forward. + +-------- +Building +-------- +.. rubric:: Not Clobbering the Build System + :name: building-not-clobbering-the-build-system + +The tools repository is designed to run on a stock FreeBSD using `chroot +mechanics `__ to keep the build +contained and consistent. There’s nothing worse than a build system that +modifies the build system and at some point starts to dash out working +images–only to stop working some time in the future. No, no, no. + +You can also “cross-build” between FreeBSD versions. We’ve successfully +built images on FreeBSD 10.1 when OPNsense was still running on FreeBSD 10.0. +(version 16.1 now runs on FreeBSD 10.2) That’s not a huge gap and the ABI is the +same, but we expect this to work with FreeBSD 11 and beyond as well so that if +you have a FreeBSD box you will always be able to produce your own images if you +desire–without spinning up extra machines, jails or virtual machines. + +Here are the `build instructions for +OPNsense `__. + +.. TIP:: + + As of November 2015 OPNsense is equipped with a tool that can completely + reinstall a running system in place for a thorough factory reset or to restore + consistency of all the OPNsense files. It can also wipe the configuration + directory, but won't do that by default. + The `opnsense-bootstrap `__ script is + particularly useful if you want to convert a hosted FreeBSD system to OPNsense. + +------------------------------- +Virtual Machine for Development +------------------------------- + +.. rubric:: Running: Use a Virtual Machine for Development + :name: running-use-a-virtual-machine-for-development + +It’s just easier and less tedious if the kernel crashes, to revert to a +previous state, or isolate and test different features. A VM can be set +up easily using the ISO images. Also very good for testing installation +and upgrades. Of course, at some point you will want to bring OPNsense +to your actual target device—just make sure you know the system well +enough before you attempt this. + +`VirtualBox `__ is a solid tool for the +job, but be sure to check out `FreeBSD’s Bhyve `__ as +well (it was added in FreeBSD 10). However, If you are only interested +in GUI coding, you can skip all the build parts and directly download an +image and spin it up. Because… + +-------- +Packages +-------- + +.. rubric:: It Gets Even Better + :name: packages-it-gets-even-better + +Once you have a running instance, how to produce and push code? Well, +there’s a couple optional of packages that help you to be productive: + +:: + + # pkg install vim-lite joe nano gnu-watch git tmux screen + +The most important one is *git* for obtaining the code, the rest is +optional if you need it—mostly editors and terminal wrappers. It is also +possible to mount sshfs or do sftp to sync files from the repo if you +would like to use a graphical editor from your own system. As the root +user do the following: + +:: + + # cd + # git clone https://github.com/opnsense/core + +Once you have the repository, you switch it live using: + +:: + + # cd core + # make mount + +Yes, the changes that you make in the repository will show up directly +in the GUI now! Unfortunately, this will mount the repo over +*/usr/local* so if you modify packages the changes will light up in git. +Be careful. To prevent that from happening you can temporarily unmount +using: + +:: + + # make umount + +To finish that off the boot sequence will mount the core repository set +up in */root/core* as early as possible (if it’s available) and will use +its modifications for booting up (with the exception of +/usr/local/etc/rc itself). This makes it possible to work on the backend +configuration and boot sequence improvements without having out of sync +system files and repositories. + +------- +Summary +------- + +.. rubric:: Easy Access is Key to Collaboration + :name: summary-easy-access-is-key-to-collaboration + +Although this is just a peek into OPNsense development workflow it brings to +attention a key aspect: moving barriers out of the way to enable as many people +as possible to produce quick results. Yes,there are barriers like +`git `__ +and `GitHub `__ +to deal with, maybe even learning FreeBSD intricacies, but once you have +your code in the GUI and working fine, you’ll feel proud enough to +endure the hardships of making sure your patch will have a place in our +upstream repositories so the community as a whole can benefit from your +dedication. + +The OPNsense core team looks forward to your feedback; +"We are seeking for more improvements in the build system and eagerly await +your pull requests." Take care and code responsibly. :) diff --git a/source/fork/images/fork-lift_new.jpg b/source/fork/images/fork-lift_new.jpg new file mode 100644 index 0000000..e17ec41 Binary files /dev/null and b/source/fork/images/fork-lift_new.jpg differ diff --git a/source/fork/thefork.rst b/source/fork/thefork.rst new file mode 100644 index 0000000..26350de --- /dev/null +++ b/source/fork/thefork.rst @@ -0,0 +1,135 @@ +============== +About the Fork +============== +Welcome to about the fork. This page is intended to explain the original motivation +for forking, but keep in mind that currently less than 10% of the original legacy code +base remains. As it stand today, OPNsense has evolved from being a fork to a whole new +security platform with leading innovations such as weekly security updates for +all components, a REST API, inline Intrusion Prevention and intuitive modern user +interface. + +------------------- +Debunking the Myths +------------------- +There are some myths surrounding our project offered mostly by pfSense enthusiasts, +if you have read their comments on us then we'd recommend to just ignore them and +install OPNsense, if you have not already done so. + +.. sidebar:: Lets fork and lift the project! + + .. image:: images/fork-lift_new.jpg + +------------------- +So why did we fork? +------------------- +Back in 2014, after having sponsored pfSense® for years we felt there was no other +option than fork the project and keep the spirit of the - original m0n0wall based +fork - alive. Below you can read about our original motivations and the birth of +OPNsense®. + + +Technical +--------- + +We had technical reasons to fork. +As much as we love the functionality/feature set of pfSense, we do not enjoy the +:doc:`code quality ` and dispersed development method. We like structure, achievable +goals set forth in a `roadmap `__ with +regular releases and a decent :doc:`framework `. + +Security +-------- +On the security part the main issue was the need to separate logic. The GUI +should not perform tasks that require root access and potential security issues +should be fixed before they become a real problem. + +Quality +------- +As for quality, all new features will be built using a solid :doc:`framework ` with a +Model View Controller. For this purpose we choose `Phalcon `__ as it is the fastest +open source PHP framework available. And we will gradually migrate parts inherited +from pfSense to the new framework to avoid a big-bang approach. + +Community +--------- +A thriving community can only exist when people are willing to share. We want to +make it easier for people to join and help to build the community. With pfSense +this has been rather difficult as the tools to build it are difficult to use and +often do not work in the first few attempts. And since 2014 year they are not +freely available any more, you need to apply for access with ESF. We believe a +good open source project has nothing to hide so access to the sources should be +there for all. It will remain a mystery why ESF made that move as commit rights +and read rights are totally different. + +.. Note:: + + ESF has since changed their policy several times with different license models, + including the ESF 6 clause license and the latest being a Apache style license. + +Transparency +------------- +A real concern with pfSense is transparency. Since Netgate bought +the majority share of pfSense and renamed the company to ESF it has been +difficult to understand the direction they want the project to go. Removing the +tools from github without prior warning and using the brand name to fence off +competitors has scared quite a lot of people. Also the license had changed for +no apparent reason… + +Restore a firm open source project +---------------------------------- +With OPNsense we have restored a stable project with clear goals and a very simple +license that is suitable for forking and making OEM versions. We think a community +project is there for all to use and work with. + +------------- +First Release +------------- + +Much work had already been done before the `first official release `__: + +* The build-tools had been completely rewritten from the ground up + with clear and easy to read build scripts that are portable and small, + +* OPNsense is now a package that can be installed on top of our custom FreeBSD + build (you can literally do pkg remove opnsense and are left with an almost + standard FreeBSD base system), + +* The firmware upgrade process is now done with pkgng, + +* Captive portal has been rewritten and does not make use of kernel patches anymore, + +* New features (captive portal) have been implemented with a clear structure, + +* The check_reload_status functionality, effectively the backend daemon starting + and stopping components, has been fully rewritten in Python (configd), + +* Fully reworked the GUI to a modern Bootstrap based one that is also easier to + customize if you want to. + +-------------------------- +Future Development & Focus +-------------------------- + +Moving forward the focus will remain on code quality and security. + +.. Note:: + + A lot of work has been done to improve the code quality and with weekly + updates we have proven to be able to act quickly on known security threats. + For current status of the project and future development see our `roadmap `__. + + +Deciso's involvement +-------------------- +That being said it is important to know that `Deciso `__ has been a long time sponsor +of pfSense and invested a lot of time and money into the project. Deciso helped +to make it a success in Europe. Until Netgate bought the company there was room +for many others like us, but that has changed unfortunately. + +Closing thoughts +---------------- +In the end it all boils down to the direction we will go both technical as well +as community involvement and transparency. + +You are invited! Try OPNsense, be part of the community and help the project move +forward. OPNsense is rapidly becoming the number one open source firewall platform! diff --git a/source/images/OPNsense-Deciso-Screenshot.jpg b/source/images/OPNsense-Deciso-Screenshot.jpg new file mode 100644 index 0000000..1e785f0 Binary files /dev/null and b/source/images/OPNsense-Deciso-Screenshot.jpg differ diff --git a/source/images/OPNsense_Logo.ai b/source/images/OPNsense_Logo.ai new file mode 100644 index 0000000..9eace2b --- /dev/null +++ b/source/images/OPNsense_Logo.ai @@ -0,0 +1,4585 @@ +%PDF-1.5 % +1 0 obj <>/OCGs[5 0 R 48 0 R 90 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + OPNsense_Logo naam + beeldmerk + payoff_PMS + + + + + 2014-12-17T10:21:12+01:00 + 2014-12-17T10:21:12+01:00 + 2014-12-17T10:08:08+01:00 + Adobe Illustrator CS6 (Macintosh) + + + + 256 + 52 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgANAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8An2haNrXnnU9RuNVumsZL XgzF0MigSluKxDkq8FCHcNhQm3/KqNP/AOpih/5FL/1WxtXf8qo0/wD6mKH/AJFL/wBVsbV3/KqN P/6mKH/kUv8A1WxtXf8AKqNP/wCpih/5FL/1WxtUD5j/AC3TSNAuNXh1P68IOAWGOGnMvIsdAwkf pyr0xtWe/lskyeStOWZPTkHrVSoNKzyU6e2ApTzVdTtdL0641C6JEFshd6bk06Ae5OwxV5h/ytfz jeO8ul6NG9oGKr+6nnI70Z0ZFrT2w0h3/KyfzG/6scf/AEi3X/VTGlab8y/zFVSzaJGqqKsxtbkA Af8APTGlZZ+Xfm7UvMtneTX0cMb28ioggVlBDLXfkz4lKWebvzMvdP1ltH0WyW8u4tpXcO45kcuK JGVY8R1NcaVJ/wDlZP5jf9WOP/pFuv8AqpjSHf8AKyfzG/6scf8A0i3X/VTGlTfyP+YGv655gk0v Ura3t1jid2EaSJIHQqKHm7ePhjSU688+eIPLFtCFh+s31zy9GInioVerud9t9h3xViS/mb57ZQy6 ACpFQRBcEEH6caQ3/wArL8+/9S+P+RFx/XGlUbr82PONoge60eK3RjRWljnQE9aAswxpXqOl3T3e mWl24CvcQxysq9AXQMQK/PAlE4q7FXYq7FXYq7FXYq7FXYq7FXYqwDzD5K+ppJNpN6IDKjKbaaQR llIoyq5IqCD0b78NoeC3P5aaKmqtDeajNpNsep+r/Wwpr7SRNx9xyOKbZhp3/OMen6lard2HnGO6 tn+zLFZBhXwNLnYjwxVXf/nFRI0Z381hEQFmZrGgAG5JJucVYNq35Y+XLS8W207zI+sOGpKYbP0o /kspmk5H5KR74rb1zyH5FmOl2uny3gtdOh5Nb2ZlDykuS7n06/CSSa139qYoer6dp9tp9lFZ2wIh iBChjU7ksST7k4Ese/ND/lBdT/54f9REeIVR/Kj/AJQq0/4yTf8AJw4SrL8CoTV/+OTe/wDGCX/i BxVgP5Jf8czU/wDjOn/EDhKoTQP/ACceofOf/iIxQ9UwJdiryvyj/wCTa1n53X/JxcKFH82AG846 MpFVMcYIPTedsQr1rAl2KvO/zr/44Nh/zFf8y2whWaeXv+OBpn/MJB/ybXAqYYq7FXYq7FXYq7FX Yq7FXYq7FXYq89/Mryj5e85R2ckmrwxSacsxhhV4mErS8DxYswpvHT6cplmjRoi/e5ENPPiFxlV9 xeA2XlfTbXWHhvb250M14zPBEtyle3KMulV9wW9swcXaBG0w9HqvZ4THHpzt3H9B/X830l+V2hWG j+WmhsdVj1iC4uHuPrcSemtWRFKceclCOG9T9GbKGQSFgvMZcM8cuGYosh1uyjvtFv7KSUW8d1bT QvORUIJIypcglfs1r1yRNMAL2D5T82+UvL8VyLW18wz62imjxQ24t7YEdKMZJDIa+1PA5r83aERt Hd6HRez2Sfqyngj9v7Pxs9M/Kr8ttD0i50zzLc6hHY30Hqn9Gs8VOLo8aliXLA8XrQ5dp89wuZFu B2hpBHMRiBMBXf8AF7VDPDPGJYZFliavF0IZTQ0NCNuuZIIIsOtlEg0dixn80P8AlBdT/wCeH/UR HhCFH8qP+UKtP+Mk3/Jw4SrL8CoTV/8Ajk3v/GCX/iBxVgP5Jf8AHM1P/jOn/EDhKoTQP/Jx6j85 /wDiIxQ9UwJdiryvyj/5NrWfndf8nFwoUvzW/wCUz0b/AIxxf8n2xCvWcCXYq87/ADr/AOODYf8A MV/zLbCFZp5e/wCOBpn/ADCQf8m1wKjfXh9X0vUX1f8AfdRy6V6dcHELpPCavovwoWPNDGyq8ioz fZDEAn5VwGQCREnkvwodirXqJz9PkOdOXCu9OlaYLTRq2+mFCyOaGUExSK4HUqQf1YBIHkkxI5r8 KFizQtIY1kUyL9pAQSPmMHEOSTE1bzrVG1tdekKSTi95SelEpqxk5Tm3Ma0/ueIhDkNx68hXkRJi kl7+Rek2UDzXGvOiojPQwoCQgqeIMgqc1EuzqF8X2fteth7TTkQBAb+f7HmNpo7alqBg0xqW5aiX F48cCgeLszcB8gx+nMHHhlM1EW9Dn12PBG8pAl3D9HV9C/lloMOieWRZx6hBqJMzySzWrBoldgoK BgTWlPb5Zu9LgOONF4PtTXDU5eMChVMh1e3judJvbeWUQRTQSxvO1KIroQXNSBRQa9cuyR4okd4c LDk4JiXcQfk+Y/MPlS60aegubbUbUk8LmymSUED+ZVJZPpFPc5os2mnj5jbvfQ9F2vh1GwPDLuP6 O9mPlX8p9D8xaRb6hb61LAZ+Q+rSQx8wyEhukm422OXYNF4keK/s/a63W9u5NPlOMwBrz/Y9f8p+ Xk8veX7XR0nNwtr6lJivAt6kjSfZBPTnTrm1w4uCAjzp5XXao58pyEVxV9gpLfzQ/wCUF1P/AJ4f 9REeWhxFH8qP+UKtP+Mk3/Jw4SrL8CoTV/8Ajk3v/GCX/iBxVgP5Jf8AHM1P/jOn/EDhKsav/wDE n/KytT/w7/x0vUk4/wB19jiOX998GKE7/wCQ5/5/o/FLv+Q5/wCf6PxVNPy98la3p2qXWua69L+4 VkEXIO1ZGDO7stVrtsAcSqS/mt/ymejf8Y4v+T7YhD1nAl2KvO/zr/44Nh/zFf8AMtsIVLfzN13U tN/L/QoLGZrc3scKTyRkq5jWAEoCOgYnfNd2hkIiAOr0Hs7poZMpMhfCNnlEOhXMvl59dim5tHer aNbKCZQWiMolJHQfDT55quD08XnT2EtTEZfCI/h4r6c6p6L5f89+YrL8sdVmuJHa+s5o7awuJgS4 WenUt14DkVr8szcWpkMR336PP6rs3DPWwAHpkCZAeX63nun6XqGvjVr6W6Mk1hatezvMWd5ArKpH In/KrmFGJlZ7hbv8uaGDgiBtKXCK6M5/JPzbqi64NAuJ2msbmN2t0kJb05Ixz+AnoCoNRmZoMxEu HoXSe0Ohh4XigVIHfzBee6VPqc2qWcNvdSRzyzxpDIWaiuzgK30HMGI32d/mjAQkSBQBV9R/Smge Z7kLds2o6fcsovATyZ42py+Kp3p0OSlcJeYLXi4M+AbeiceXvZT+bvmbVb7W4rFpmjsY7W3kFsjE IzzRiRmYdz8VMv1eUylR5UPut1nYWjhDGZV6uI7+40xy60zVtAutPutPuZGlubWG9iuLYOvD1hXg SO60ocokDAgg9LdhDNjzxlGYFCRjR8urO/zL89a4/lzQLSOVrWbUrNbrUTFVGaoChBShVSwYkZm6 nUSMIjvFl0nZHZuIZskiOIQlUXnsmi3dpoNl5gWfit1cSwRqtQ6tEAeXL3rmCYEREnfjURlllirk Afm9w/J3zVf675emi1CQz3enyiL12NXeNlqhbxIoRXvm40OYziQejxfb2ihgygwFRkLrzUfza8q6 Hri6fcalqrafJp4lMMUUayySeqU6KSvT0/lmdVujBp4r/grTp9U9JLsSE/Yk1GaG3jCj9ogkL9FW 9sYxAFBlOcpG5GyXt/5enyr5U0FtOl8x6bcSyzNcSMlxCqKWRU4LV6kDh12wsU81fzD5Q1HSb3Tz r9hGLyCW3MguYCVEqFOVOYrSuBXzrr3kDTrK8UDUbW7DH93e6bcxMzU/njBYg/NfkcKvQPyv8k+X INfsdZTW5pNQtA9LK5iROReNo9nDEN9uvj7ZERERQDKeSUzcjZe2YWLFvzQ/5QXU/wDnh/1ER4hV H8qP+UKtP+Mk3/Jw4SrL8CoTV/8Ajk3v/GCX/iBxVgP5Jf8AHM1P/jOn/EDhKoTQP/Jx6j85/wDi IxQ9UwJdirsVeTfmt/ymejf8Y4v+T7YQh6zgS7FXnf51/wDHBsP+Yr/mW2EKr+aPLuka95E0q1vr 6HTrhIIJLK5mdUX1BCAVPIiqkHenzzD1mOM47kA9HadkavJgycUYmYrcB4zx80+T7/6zZ3Po/F6a 3lpIs1vKVAbiWXkjbGvFt/bNODLGbB+T294NXCpC/KQoj9PxDMte89zea/yyvPrcSx6hY3Vss5j2 R1k5cHAPQng1R/tZk5dQcmLfmCP0uo03Zo0utjwm4yjKmF+U/L1xrJ1L074WMFjaSXV3IQ7BoY6c xxTc7b0zFxYzO/IW7jXaoYeG48RlKh72U/lfpmhweetMltdZS7nX1+FuLeaMtW3kB+JwFFBvmTo4 jxRv+KdZ2xmyy00xKHCNt+Ifzgwny1/ykelf8xlv/wAnVzEx/UPe7nV/3M/6p+5G+fv+U11v/mMm /wCJnJ5/rl7y09mf4tj/AKoeg+f/ACVp+rW1jqVlqdpb6ulnAlxY3E8cRkCxjgyliOLUNPi2I8O+ XnwxIBBHFQ2vydD2X2jPEZQlCRx8RogE1uwnQfOPm7ybdi2jd0gBDyafcAtEwbfko7chuGQ7++Y2 LPPGdvk7nU6DT6uNnn/OHP8AHkU1/NvWodbuNC1WFDGl3p4f0zuVb1XDLXvRgRk9Xk4yJd8f0lxe w9OcIyYz/DP9ASe18sJJ5Xt9Yv8AV1s7Ca4eCGBo5ZaSKKk0SoFQMqGL08RO1uXPWVnOOEOKQF3Y G3xen/khZ6dbWurCy1Bb8M8PMrFJFxID0/vAK19s2PZwA4qN8v0vN+0WScpQ4o8PPqD3dyUeSLnR vNEuqyatO1ssSoLaa4lVGlaUOGejGp4cQftd982bzSUzf84+eSZ5Wlm84vJK5qzs9uST7ktilT/6 F28h/wDU3H/grf8A5qxV3/Qu3kP/AKm4/wDBW/8AzVirY/5x28hg1Hm41/1rf/mrFU91Xy/5X8qe TkFpqh1fU7ZgsbeqjSTK8lSGC86emhND7AYoeg+QdQfUPKOn3jmQmVZP777dFldRXc9htgKUP+Zy s/kfUlUFmPoUAFT/AL0R4hXnPln8xNZ0HSItNh01Zo4mdhI/ME82LdvnhpCa/wDK49f/AOrRH98m NKo3n5seYry0mtI9KRHuEaIOBIxHMcagdzvjSsq/Kny9qGkaHNJfxmGa8l9RYGFGVFWi8h2J32xK Ul0K1ul/N3UJmhcQkzUlKkKaqP2qUxQ9PwJdirsVeUfmpFK/nHRmRGZRHFUgEj+/bCEPV8CWOeeP Nk3lrToLuK1F16svpMpYoFHEmtQG8MVeZ6/5n1/z19V06z0ziscnMCLlJ8ZHGrOQqqoB74UMp/NH yfqd/wCStOgsIzdXek+nzijBLOgi9Nyi9SagGmYGvxGcQR0d72Bq4YcxEzQkKvzeNnWtRh8uSeV3 t+Mb3ovSWVhKJBH6fGnuAM1HiHh4el29l+Xgcwzg/wAPD5c7Z35Q/LjW7zyDriTQtbXeoNBLp8Mo 4sxtebCoNOPqeoVFfn0zMw6aUscvOq+DpNd2tjhqsZBuML4q/pV91MJ07U9Y8rtqtnNZmKbUbSWw nS4VkZFkoGZQab0zEjOULHeKdzlw49TwSErEJCQryZp+Svk7U214a/dQPb2dpG4tmkUr6kkilPhB /ZCsanMvQYSZ8XQOn9odfDwvCiblLn5AbsJ8uaTqq+YdLZrKdVW7gLMYnAAEi7nbMPGDxD3u51ef GcU/UPpPXyRnnrS9Tk85azJHZzujXcxV1jcgjkdwQMnnB45e8tPZueA08AZD6R1T780/KWsC4sda gtZJrKeyt0meNSxjkjjCkOBUqKAb5bqcMhUuhA+5wexddjqWMmpCUviCejFdV1TVvNN1p0UdoZbm zs4bCJLdWdpBFWjMBX4m5ZROZmQO4U7TDhx6aMiZUJSMt+ls487/AJca3D5O0GeGFri8023aHULe Ic2VZHMoIC/a4MxDU+fTMvPpZCET1HP73S9ndrYjqMgJqMzcSfl9rBJNa1G48v2vlkW1Vt7p7lOK sZS7rx4cfbftmHxkx4fN3Y08I5TmvnGvJ7b+T3lS+0Ly/NNqEbQ3moSCQwNsyRoKIGHZjUnNvocJ hEk8y8b29rY58oEN4wHPz6sAX/APEcf0px7U+r0zYOib/wCdE/7Wn/Tvirv+dE/7Wn/Tvirv+dE/ 7Wn/AE74q7/nRP8Ataf9O+Kq1p/yr36zH6/6T9HkOfL0eNPfh8VPGm+KvbdP+pfUbf6hw+pemv1f 0/senT4ePtTIpRGKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2K v//Z + + + + + + uuid:1941ab7b-9f57-274b-ac3e-b598051f07eb + xmp.did:09801174072068118083BDA75EF23E88 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + xmp.iid:08801174072068118083BDA75EF23E88 + xmp.did:08801174072068118083BDA75EF23E88 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + + + + saved + xmp.iid:04801174072068118083BDA75EF23E88 + 2014-12-17T10:05:40+01:00 + Adobe Illustrator CS6 (Macintosh) + / + + + saved + xmp.iid:09801174072068118083BDA75EF23E88 + 2014-12-17T10:08:09+01:00 + Adobe Illustrator CS6 (Macintosh) + / + + + + + + Document + Print + + + False + False + 1 + + 419.999514 + 296.999959 + Millimeters + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 0.000000 + + + Black + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 100.000000 + + + CMYK Red + CMYK + PROCESS + 0.000000 + 100.000000 + 100.000000 + 0.000000 + + + CMYK Yellow + CMYK + PROCESS + 0.000000 + 0.000000 + 100.000000 + 0.000000 + + + CMYK Green + CMYK + PROCESS + 100.000000 + 0.000000 + 100.000000 + 0.000000 + + + CMYK Cyan + CMYK + PROCESS + 100.000000 + 0.000000 + 0.000000 + 0.000000 + + + CMYK Blue + CMYK + PROCESS + 100.000000 + 100.000000 + 0.000000 + 0.000000 + + + CMYK Magenta + CMYK + PROCESS + 0.000000 + 100.000000 + 0.000000 + 0.000000 + + + C=15 M=100 Y=90 K=10 + CMYK + PROCESS + 14.999998 + 100.000000 + 90.000000 + 10.000002 + + + C=0 M=90 Y=85 K=0 + CMYK + PROCESS + 0.000000 + 90.000000 + 85.000000 + 0.000000 + + + C=0 M=80 Y=95 K=0 + CMYK + PROCESS + 0.000000 + 80.000000 + 95.000000 + 0.000000 + + + C=0 M=50 Y=100 K=0 + CMYK + PROCESS + 0.000000 + 50.000000 + 100.000000 + 0.000000 + + + C=0 M=35 Y=85 K=0 + CMYK + PROCESS + 0.000000 + 35.000004 + 85.000000 + 0.000000 + + + C=5 M=0 Y=90 K=0 + CMYK + PROCESS + 5.000001 + 0.000000 + 90.000000 + 0.000000 + + + C=20 M=0 Y=100 K=0 + CMYK + PROCESS + 19.999998 + 0.000000 + 100.000000 + 0.000000 + + + C=50 M=0 Y=100 K=0 + CMYK + PROCESS + 50.000000 + 0.000000 + 100.000000 + 0.000000 + + + C=75 M=0 Y=100 K=0 + CMYK + PROCESS + 75.000000 + 0.000000 + 100.000000 + 0.000000 + + + C=85 M=10 Y=100 K=10 + CMYK + PROCESS + 85.000000 + 10.000002 + 100.000000 + 10.000002 + + + C=90 M=30 Y=95 K=30 + CMYK + PROCESS + 90.000000 + 30.000002 + 95.000000 + 30.000002 + + + C=75 M=0 Y=75 K=0 + CMYK + PROCESS + 75.000000 + 0.000000 + 75.000000 + 0.000000 + + + C=80 M=10 Y=45 K=0 + CMYK + PROCESS + 80.000000 + 10.000002 + 45.000000 + 0.000000 + + + C=70 M=15 Y=0 K=0 + CMYK + PROCESS + 70.000000 + 14.999998 + 0.000000 + 0.000000 + + + C=85 M=50 Y=0 K=0 + CMYK + PROCESS + 85.000000 + 50.000000 + 0.000000 + 0.000000 + + + C=100 M=95 Y=5 K=0 + CMYK + PROCESS + 100.000000 + 95.000000 + 5.000001 + 0.000000 + + + C=100 M=100 Y=25 K=25 + CMYK + PROCESS + 100.000000 + 100.000000 + 25.000000 + 25.000000 + + + C=75 M=100 Y=0 K=0 + CMYK + PROCESS + 75.000000 + 100.000000 + 0.000000 + 0.000000 + + + C=50 M=100 Y=0 K=0 + CMYK + PROCESS + 50.000000 + 100.000000 + 0.000000 + 0.000000 + + + C=35 M=100 Y=35 K=10 + CMYK + PROCESS + 35.000004 + 100.000000 + 35.000004 + 10.000002 + + + C=10 M=100 Y=50 K=0 + CMYK + PROCESS + 10.000002 + 100.000000 + 50.000000 + 0.000000 + + + C=0 M=95 Y=20 K=0 + CMYK + PROCESS + 0.000000 + 95.000000 + 19.999998 + 0.000000 + + + C=25 M=25 Y=40 K=0 + CMYK + PROCESS + 25.000000 + 25.000000 + 39.999996 + 0.000000 + + + C=40 M=45 Y=50 K=5 + CMYK + PROCESS + 39.999996 + 45.000000 + 50.000000 + 5.000001 + + + C=50 M=50 Y=60 K=25 + CMYK + PROCESS + 50.000000 + 50.000000 + 60.000004 + 25.000000 + + + C=55 M=60 Y=65 K=40 + CMYK + PROCESS + 55.000000 + 60.000004 + 65.000000 + 39.999996 + + + C=25 M=40 Y=65 K=0 + CMYK + PROCESS + 25.000000 + 39.999996 + 65.000000 + 0.000000 + + + C=30 M=50 Y=75 K=10 + CMYK + PROCESS + 30.000002 + 50.000000 + 75.000000 + 10.000002 + + + C=35 M=60 Y=80 K=25 + CMYK + PROCESS + 35.000004 + 60.000004 + 80.000000 + 25.000000 + + + C=40 M=65 Y=90 K=35 + CMYK + PROCESS + 39.999996 + 65.000000 + 90.000000 + 35.000004 + + + C=40 M=70 Y=100 K=50 + CMYK + PROCESS + 39.999996 + 70.000000 + 100.000000 + 50.000000 + + + C=50 M=70 Y=80 K=70 + CMYK + PROCESS + 50.000000 + 70.000000 + 80.000000 + 70.000000 + + + PANTONE 1665 C + SPOT + 100.000000 + LAB + 52.941200 + 60 + 64 + + + + + + Grays + 1 + + + + C=0 M=0 Y=0 K=100 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 100.000000 + + + C=0 M=0 Y=0 K=90 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 89.999405 + + + C=0 M=0 Y=0 K=80 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 79.998795 + + + C=0 M=0 Y=0 K=70 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 69.999702 + + + C=0 M=0 Y=0 K=60 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 59.999104 + + + C=0 M=0 Y=0 K=50 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 50.000000 + + + C=0 M=0 Y=0 K=40 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 39.999401 + + + C=0 M=0 Y=0 K=30 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 29.998802 + + + C=0 M=0 Y=0 K=20 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 19.999701 + + + C=0 M=0 Y=0 K=10 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 9.999103 + + + C=0 M=0 Y=0 K=5 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 4.998803 + + + + + + Brights + 1 + + + + C=0 M=100 Y=100 K=0 + CMYK + PROCESS + 0.000000 + 100.000000 + 100.000000 + 0.000000 + + + C=0 M=75 Y=100 K=0 + CMYK + PROCESS + 0.000000 + 75.000000 + 100.000000 + 0.000000 + + + C=0 M=10 Y=95 K=0 + CMYK + PROCESS + 0.000000 + 10.000002 + 95.000000 + 0.000000 + + + C=85 M=10 Y=100 K=0 + CMYK + PROCESS + 85.000000 + 10.000002 + 100.000000 + 0.000000 + + + C=100 M=90 Y=0 K=0 + CMYK + PROCESS + 100.000000 + 90.000000 + 0.000000 + 0.000000 + + + C=60 M=90 Y=0 K=0 + CMYK + PROCESS + 60.000004 + 90.000000 + 0.003099 + 0.003099 + + + + + + + + + Adobe PDF library 10.01 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 7 0 obj <>/Resources<>/ExtGState<>/Properties<>/Shading<>>>/Thumb 100 0 R/TrimBox[0.0 0.0 1190.55 841.89]/Type/Page>> endobj 92 0 obj <>stream +H ]DJ9b 3?n#1[)IQ$/O_y}^wUP>.d{e{A-QlҞDەОs1co9".%i\ɔm ReԖ m:N1{$A$c\|SpMmpLSC4I3,'E-9/{H& r-Nfj2\x:A"<},cFF|X[Ahw \s2 $MdPZ,R%"D$5-%%C۩M\!Rl-JoTpWd1C{A]'R+ɬ/n}[޾m}{? +.Sq@1VYphnB6+AWZ3dg.$KA]g{ʜ$3n@*RARIWۧ߾ۗ폿oH??i?l?oHB0[R[}2jMt7 yx|,wTDUH+27zM<غF9R#윅j`: +ّ3>LfU]QdQwC쨻4P-5'RAᗂ#=8}Z뎆vw#-W#I&Y]# lK.τ&aP%Jq %R"4IdF$mo7YLBZ4NFpDq=uɴzt( R&Ae ԝHB;6Rd>A|%bmJPLJ94S2)H.e [M~N4& 1hhO ͩI tBn$Ov %vQvR2I H uD MbS4uF2j9O ]X|\iy&QפLNt$YzV'u;īWshj B[LQUnWrL>^mc~3 s|-'G?ׁG%>=?l40k{؄;]x|FAgx5 o?VubؼTit+8<0Fi C)Sb[6x]STuId}_)iO [CaV]}>>|]}QQqkuT4{.]s3.` =$*]gZlj. vfxr{I}Z1\BBMi7+Ȯ.#Z@\_aRUwm ۢ0"2Pol-{+k-_SH[3^X]GRFM(3 &8p~eXԗS`.e(v3uU)f^TTU&q_,5fNgNHgj,KvR]32OIk4V +%“=uaq[RZY%FrC./z0ͥ<$CJ1̐.wI_RgR^FH%RQm65"B}XVS R^ +*O]$yZBdĥeCY+k^2“qv`'*\SF4겶j&=32K#BFΘN.ԃl7Sk+|%䱱]& +ǿ/$mkހ?5 P%GQ])f˽EɾY͑Abk.ߣYޛrn^g}^2[Wa}G&?k guYSNo}TUt/]h}ze^|:6}JfZS +py=|yt!AfT&G9GjZȗOܞ}0̧uyy$`17P.Iϵw3-J`k 'Xgg$MA-ԮFʼJ4g5>zMTo <`\NxuY4V6ʉS^ UT۫"^!DӽT(h%Be{E t%ziː{ -Mߕ9 ͉ +ITܽBf^S듊B&0 K_yuW. fe 'Q޶)#\^a^s2mDA1e} +x2/l+b3Ք̩T5߼^xHEe*RQSgu͂:*\˃S^^vG&Җ0UU^E5.A<)JH.PEl  +ު˿_>pc7@ +ţmqZ癯3?zݝ;xf'|> 'g|]ut}2™[Gn9rz3׭\wfM' >G"WSHoȽFqVQmȂAMm:YG; +(gE^룶*a}Cn*e -1Ao6C(A_!.Jxyy2Y [*i~keQm@w dL#w}>S<.@4JyEk͛k?n@?L*в^o ټS.UNU}(VUfF,Ǟ|Q475ݜ=&>TwSH2r6i0?n^ z7@GMш;nT#h i\h=׻~5;Rh׻UP +{S9Cpiv в y`{awK )ƄG8!Q0Ѻʰ)(RB`nW%D\Ts(F4x> ԆJ9-$M%@ՎSO@vK.J%*SJF@Iۜ2퀅yQڱh7g^##B#`-IMzv|iUu+JHÀL&DAk۲,9 I"_ aɽ}k }$e857jM*mkD#̽ 9ϏuJY|83MwYr7KܠWc, jVq*j'HfL]{AՀ/XujTxU'-(U  Ƞ./rÿ?lxSch9У a=*TJy>2Asc:(@>PP Z |DM}iFg&<|vcğoGb.+?XmJI)x@5Unˇpׁs,;hA=#Sz4^2ݣsi,re1Kxsv**jǦ >f;Pt^ 9z7qAٙ`l6ONQ1}HУ~z }Uh+KHQ 4<;tШ?HsTv3l8gVYܣ + *ȳx.Sp m+E|$ )С:C0<*Ko@& ?٥Zy|![2lt| D@Gt{y9J ö[:LQp;cDM>gj@+;|He?Pw5£E >X[QdnF72;j6K_%Gu>C[t0 yYL3~t`}BnMߴhYwtGNԭt9$ S`dZ(Ca:!wZ8|049;_&XhԶ/Fc?JхM 2O #()UЂYx]\\ !)9}~:Vf ۶@Xq#XdRQ5BjQ8a^4{ؔ,qyye0z׿Ng- Y}Vd~K36'cmyEpyqk-EUM u=dB Fҫ󐋬/S=TX +WO{*ѳCܒhz{^bΖu|X_PF‘m1;zkSB\u6a}{̝lv2vV[˨K]QPIڛbXYr7& v}P%l{+B CՈPz\k2xRidJlmUiq ay|mzR>s@7ND/Z(s u?oeToU%օU0\Ta&'~ay"_z.0'׼A.^WةZ-qbJOaG[zgB n/|qXCXXd0n_|pZc31§;86$MLFL9;i__sV ++Ɉ?m?2-S3yJ)(No6Q֐5'{zƢ%gi{0*>lI<5齬6բHR*)LS|Ntvv-< +k ,K—q*ʘ)U ME9UBUIU@=֗M4tl݌(Tr2$Х|3w0&ct2jH 05\A=ߋݪ@GA~TpHk:01L~y +C,;&0)[]\PbP-S^9K'R.BDQ\)pcusDP6*Q5KR\0䉻T:K3slf_O m>=h7e(^T>I!4jI8 aSTLir-cx2QLiSe +`e­gqKz@,IՇ:'䯗);b ha/]S mb H҅:-ix!9(+HrG#`ߚZg0::(y o)Xk&̛cr4Jۓ9\5n!d%Q!i *ZՅch,{.ox,d%< ,mlj@ILؤhQFMXtk4⌁b6"zHV.QAMEH&񾗏1jIr7^WY?? N3KxuatbmdUyN4?rA54 י}4f~HXmDͷDJ-Hեh?" K$B8ޑI[/DJ(:Ri;Vw8G,% zr˥%OIL&&{vS=-tBšK?4O6RP+T4cUiQW7?J6{u˪c]=; +V ?eů1mKZ2 K[<~ĕSPWLӒWhG_9*=ˉ?A@Bvx4f%FPȬ:/hJyǀn"==Gn9F󡭷x/F%f}Kq9R\hޒ *OdlK0 ཧIkǥ /`3"b/ vPqfdzrkF@ɫB -w2%2\Ŕ_H}t}xk4V0ZAQ@P c0PCXi(ɰewbw;𠱨K (f7i05aii67s {bHc'.2?Iŏn2 +e}_]ex<Ee4^q1xU]cIǙtChD%4T&P4hSiVҕ"uy>stream +8;Z\u_/[C9$q1OJonX:#aJVuK2;o&=ZrO&q8-4HSYOS\A3FkV*,D0PEnL]E^K-1GO ++:*SW?\;I"A*1r?W5`)sN5#s['gHenG&Q65[5mpYr)Ir6BqoWbMT.&0P +![++2?-loWP!e^;LJ4b%asog]-2$o38;l/IVQT`&ZKc]\846UYIfN>\$FmK^BtDkg +:O5VXGI$D[-9R +eJ""&jYl/L2%*r?qBAo?dN8!Z(%G=gN'";&83jo`/E0H"I@+ZKgt(QZ"M2hgRX@C? +9qIoh9`o7Y#a@)VY9t=_1r;o:mV7np+UrCilg?.U:6Ts!ZZMn_NhCs+geU)Z:=j#( +@')ZJVr[SLNMlCj7'l^I+:*QA#_F0)K&BH"*WYaJdcp~> endstream endobj 101 0 obj [/Indexed/DeviceRGB 255 102 0 R] endobj 102 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 97 0 obj <> endobj 98 0 obj <> endobj 99 0 obj <> endobj 95 0 obj [/DeviceN[/Black]94 0 R 106 0 R 107 0 R] endobj 105 0 obj <> endobj 108 0 obj <> endobj 109 0 obj <> endobj 94 0 obj [/ICCBased 110 0 R] endobj 106 0 obj <>stream +{1.000000 2 1 roll 1.000000 2 1 roll 1.000000 2 1 roll 0 index 1.000000 +cvr exch sub 2 1 roll 5 -1 roll 1.000000 cvr exch sub 5 1 +roll 4 -1 roll 1.000000 cvr exch sub 4 1 roll 3 -1 roll 1.000000 +cvr exch sub 3 1 roll 2 -1 roll 1.000000 cvr exch sub 2 1 +roll pop } endstream endobj 107 0 obj <> endobj 111 0 obj <> endobj 110 0 obj <>stream +HuTKtKKJI,t(݋4K%ҹH4J#Ғ(H +wqyy~3̙g<3Y9El +@ ]!O-@\+BVKK :OX~WCaiHKL0qY `5ck +X]x= 8 XĿ׽>.f#aPn D^{y8  dp H st:Y׬cxc IV?S!:_9[YbQP~+rA +ShHht^ '0߅™kYXY9Yqqpl'WzEE$%D>,^|t*K)%/`\ҫ:&D [7dplDa5|mb4,yy{e5 3⚅,t+whlA   m k +xYUH&%Ȥ +qO'Mz3KT@v[NUnn^\o]abTrtlmE]e~U+jאZ:zaqi5};CS[\_ۆwCaQ1;>L$Lz}4:%8M7l̎Χ/}XT^]X>\Ym[n!ycskkƶʷ;v{pIs0Xݯ3s󝋒&$WWW*)!$$%!e$cHNOAKIMEq ƕ;KLw@YX;ؚ8^+DspfKOTCPpJ%D=++O%$*8IZ\Z^UK_wL"dx]}>9=;s_G8/̹N!Gz[<=2|B}PQzlH0Wc(Een|Pds::5&89yFT"od䳔i/ZK^&gd:fgQl kJХeJ*+篍kj5U[ZUh0|em6]B@`PpH?QM1Msψ*iϛ.Z [JYZ)X-]R޸Ѻپw?@?5 ǖ'vNg +W3gLC#u!MMMEvAms˔FVNA̝GLwA̬,llؿsݛnͽ+!B²" 'R&k?3?4+:6oT\ұڿ6VʝoF?LT;:>::>:;eqvx^sawݥʕ'_EFO\DKLtAnFF)F|ԭ6\`@z?m+F;LwiAhy͖)Mgw~_ @ZH_XA,"F)%/*9aZ:Q,\B^_AU񡒀2 +*'[j o5[uR1uh`fm$1xJgBdrltlyyEe$feg-g#`dGbwj0TOC9; ܨݿxz6zx8IP=A!.aAxۑϊ}bG-ޒēx`G/Ԝq_O?0"۬խЮ˯ǰı²µŶȷ͸ӹۺ 0@RfzƏǦȾ *GcЀџҿ'LsٛFsM6+1MZ:{T?~ò~i~L}~cbA~Dad~ty~W~O>~\/~|~`Cx}%H}1X}%z}K} {N}׋<_~7A~-ψ||Dz|+E|[s|z} ^}wO@}-~ċ {Gu{Dz{]Ĭ{f{Zx|[]|ϕM?}R<}Ǝz]YzHħz|z={LNw{\|=>|v|ېI8z/r z;bz'sMzd6zɬqv{D[{0> |;|yyaIy?yazYvzݮ[{^=c{ФI{R*y߄yfUy`VyyuKzZi{ <{z%zȎ~+~}͇}W0}3}HtЄ}Zk}=~zɇ}!~Єd*s}Y<9wpSwuuVrUW؈|;,뇔{RsѲ;:8q)PCV:4.8Ȅ2񡂡?Up Vu9S c bփR.ՁNn U388A/ͬδz6߆өn1T\e7݀tXT)$̯̕6;eCʷˆ imw3SƀV7M +\lGNػځNāa5tNzlߴS<H6*-N}o2ن N%է>w֣A}⇤\fXMݘ2, KԐ3g°[} +0e6M _1 ? 1ӣǾI^I|B̯dܪwLe1$: rW] 1S{z|diL g0\ U{[G{!{ ޔ`{&yE{xbie{Jr|/c5}~ +~:f#MKx+Ca|uI~.yW ώәߎ%¡唘[w!^T`^H*- 5GȨ瘎=Π4rv_ҍRGf,ދ̋|,ƕ{ Ҙtٕ^1Fő,;',#h%T,Qۥ{[s:9󅼓&^!Փa@!" y +.Jl6mHju,bU6+s hܸd-ʥ}wi-sun=0Ľi-_*)U_ˈb$na+;ϧT;ppA7C4.*Iߥa8Mm.ACi7\j|fiԫ)]ޭjʄU]3(í whJch-4x7h׿*P0H됎L랇ڡuÂ,{Bz}8vggҲd[!XTZZ.vlAg +{;Sm`vؿ`~?ga. +3Ì{L^WYe4]L7ok!wI~Ira^=C#Zh`Wu}p)"z7ff&3$FJ8Ҷ5m +uR_,^VS&aR~PfLL_Dw*`\-9]q  TI6)>u6 D`e͢/xqY%9ʜ;åOd\˾P&eRz;].R<oΡ]P{?: r̨\ʻb Ҥ3|m s؟W9oZt]RnÅ\cW#+nI&gyAjsN06HiD'@J+a5V~cRI̫vwtUc[3+?F|l(iU^+O?Rs1Hqil$Wþh=(RE +1BvџnF/ BsGMY9>ܖ3ȗqI ڣ5V_1ȣβiJiX0WVH[8g_/ +n3 ` 38A.|f|ј0I6bv%& ;Y㿜҄#dD.).p'3J12K[Duɥ$s8IƊ.z^48e!R6}vcMiozo0'=~i,3:?-?oS,9w#ROa; ?pB +֞IO ݟe#}ԯN$\l?], y,>&Рq]yh0AqK)ĝBFҍcH:-h-ǟcf)K9T127]qEjL<>h;|U +dpG +ƫ`&!8al`83>.qɂnA9 +; `HByg KB*k㰗2fF=#OM eT? +mTm_OBۊV<ɆF('n3uG~Ȯ#7Њ9[١`Ns.P..콤 'KnpF\? B>-`NWOOWBlfxW^b-_x&*/(j_=߆󑊢zF`LdE:SNʔ@S 03|TOKokto}bFz$4-,.m'j*J|)J6BP ^3ewܫpX.*,07xPڳ:2XOT21|"7=0ߴy}ĸB)H[Fs V+̯+Y(I(x&9JAI'tXmyG=X[8TK)2<TSRvxlȓGO|g/{>4/gRFȶ&A52 uЯ*B幃AuFǞѧuD)B,*?n` 'qQIzK֗4{B_g68#ʉ2.A$69!̒ub1&D3Qx" >ɏnνxVG&TۨÓ)sxd-5KxߣD&1±jdGjJ|J{Z ޲f6/vTp̄ub PmBU#gBg˷)-*E +ar>>Ƶrn[ɭF-IByѸP=ĶKUC wG D}"vN.p]]Q8uY{#qCv}sax_oyiNr( d8aw2CQ}V8UWO\g \yk@dcZt9$u +p-1z(=f) +vě92 w u煼ת#{P6+Dq3HIi%BCb!kc5&U ):X$܎[b2*@PkcӘdoTB_L1Uwi")=2#pI9,RO>T@>;bnDPuCfk^^\G~ oLRcHqܮ=-8^5Ońy*9:-\g8:T<?*C;[yX+I;lRL߭$DvYTQ6DyVmfy%/sIsmXP1Lռȭvow)QBb_LVwupeėO*|+](uHװ4WU.{ 4\m.QwR~MAiRz+%BKz?'{ k҉aa{H]sX}da~3_auQz VM\ĵv5I0LM)DŽp1:5,&4 %!$}ocޤA]R^xT◬M&/B:DwA24?cd&g]5b4a?iǐ Ĉ.OA 6vfvsd(5yTH/P=(a;zUs bWxDa)Eʼ $sgPJreY3w`cFo0|U[j5k.5J&eTor È´}I lpjC8c5J=g%Uo|L58E" +ِ[Ak]J͆VBM"{NrQihЦ@Y?6^߫ZWٯ]ذc؋hKSLj:>O ɲ.ݰQ{5mm<ٷ?^v"}ъw9O&vX7km[ ,70nΒ7|eP\I;-wgFN cIP#qWI ;NٶA)H~7i thl~~dzY Cx2>*c&mb{9f1X*L #> + V@g蒼]7n249=MK% ;,F\j 1klZi؊ΐ.|Q9а$_.!;̿lE,ɥDi}D3^a`Y5g{J=mɳy3CM'jM-iЦm n5? SJE+U~ ;q.tXd~~p*QeS%.Ћ"ưBsZ6-6[\d;^z4`;64藸ͱw;|+&AfLU3XTm)lF'l VɺgcGObbɜ9;v \CL, >B?KGCe"z -@EHILp<5'҉$>8#gL2m c1 c Fw)P+rkC qp/u8#!*g°Pa`vu@oH`"Ž:z_Q<,D>'ӅWP .`xW3|!6 +5 El[",0 e[Oz0~lUO+&xkPc|u$k.?{Qp""kr6isVa=~@W_ +.<7 +2#h?c~m'rE_xs6aG+K 14L^kUp^^_mS^dШ'>}5$:τ!E[bJx&n t(m;ZsF5uqX.ՂBqKP *l%{ٓ{'f';,TT,bhUq2Z3;}T9vwRR;GD + K*/@hUv$j!@ vyבm,W|-͢ ^ ~D_􆭍"ĉ#c禘*X/Ϝe>|XH;:)d9gƖ4aBQ4Ew,C +ۯBU#>SV$L-5gV ϯ*B#} npþtdU$Db&$^\^&Z"/˺+-}%Z:}9AYu rTlP0"~! ͚*@5K?߫Z-P=j>܈[O?)a5 +?WUsy5^(ge${Cm> "Gգ+$踿ϫ& Xw8?g,'ō="/xNM)'EFqrf CįQ9ZY$r!6m)4 V9kJ$# FьX٥Cp[ģ)CS;rFP#ImKGɺzj>>X9,ZL-jIbkȉ8˚?vtxPIO}_ay@:|Ve6ubd/e3<֭ztea'cLaM +lz&,f^_!?l2x2Xyń3D)\?ye ~4O+9$  +EVDTSؓ7X?MM!ԼuOtP Cbt;iްa@gW#@4c9.Do z2>M5i~u0 qswQ9ǸLt삟Mz)>kɝI;io"U)]$YL >$$T:gUo$UK,C`sCMAJMÄKC(g]ٮ9sUG0?L5QM%0Ol5&`Ƒ1,x'{k+mY}-Js#\d:i/NK\8HstQ#-ND).s*Zymnf\1l{(E=VGW9s:?wǟQZsC6A1ƃ6K@8OUY^`7j6@9?,yt4&}"T- +\Y&kVx녣391ٵqQ=beMq\`/nņ|2͌JkzDmͫIR4\~5NlօKɁZ]TC3l̅D3jSS)tWw$IX[wV +WTUw^PeUhWE^ؓ~Wchs sIg`wgs (5mr] B`7JfAaA3ƓG?{O[ ?xj/Z*7exXz Ά})C?`KcMՌ&)Y5J]q':]$؞]Yv x(ıH1eU>_0b?*񸨎b¤،D;Wxm]|N7U13*;.=>SÜj)CM>.eI1/QvН6Tkk+Ɯn\\FFV#Xde&~WE7"bju^I@j@bQ Wk8w_D ^z xZKA _`T}] +x}ЁM0S,rV+ KO&ƈ`;E{irf0F] w86f fm_8c3V<)r1p +hs|p!QP'Ղʛ2rӤej4Y r, r?4! Uq]f(*&umM+;1 +-c8CjL=L1TDJ7>)BH*cHY}~xI,{7WjWާʇhg_YovMKiN> QRǧ}AQj^G syJG"?txt,L>֍p_>Po$^<%}KDS4 +*S<ܖyd;éIJ~JMn>ȸcI6uɖژ䩊i77_5W2' 9t^}/8%wd0k)ͦF9kih3ShPBULzs'0$Y/L3ol|f ɪ\AW#siS-O^I+36xas @M +A hm45V-' ѵ1S+ ~*%~k˝ʉl * +lك=3_2~OgPs +Ccd[aے{<ХjA {! ߲ۓ;O'9+wEHE&JV?fiӺ j05瀶bhWZxo=ƺ 0zhK5mov (YOut;e=R*yMVn,$v:QڳE.yVl;svn,Wi.[@34SD_!MF>J柣ND @$Y~-CMu (+lBpБ^#$~2è /@̣6 3nh +;۪.3Fq3\َvZnZ"/vNFNJ2V{#ΚVse_쑮Ta8C¢!Η>FL\M{5eH~7;F AB?VY=۩Q i9J.sӿc%FVbdեiL`a)kD=W \ne>NX7Ƒ†2IYf-to7/~Uas[`W*v3_`~:kjR("E +* +e)DDIss,f_n6":hmh+]AqñQqSa9{~8|~bh6GZĠםN\h+(E30~kTMGβ1:zka'LG2>,gt X&@?e% +=@Ihs)HUOeX^m7R7~,, \jJԌfͬ8!*]JR:WR]Mɚ PZ;JN.8ɦ,[r*Α]MM"waX)Lbjd`>:?|:?u>^G$fa. +ʥ_S%ED8 J=ĕK{6r zGG Ui<Kg"^ q +I6vPWy^,uc/5@:ǹ+[N+li{P#^yv,ñ-NѳH⺣<֡gxV</nb6󴳜Ρ +nhB˾PoT(W##ĉTwZU} w-vT-9O᭺HIz) z9R'dI5aZGS˟agW=.P1ٜ y?2X)r4VaGXBe`9Q1͚@85$W?D}z2* +pt +;Br\ܕ'> -vCNeʔL-ʌqKHr 7I d<BgNelB^փRγF2AqCR&t7߄{" D9u)Cw1t}?"'[7o̩~1{>Ru* ʖdClutqf2[l~{S4>J$.nQnlP#x])By`r+wLH?VD:|iUG~ժ+&+Rb gP>}WԹkQǖ]WSkqwZ +DQdVd24KGMvU35KJ~4&jwJ*y;X߉˔O@5hw)񘴕o-9E:_̂o&6#V(ѽS-te$ פp}4%4mrnzhe4KX*KÃ29ʩ~'Ǥl|O5ÍB +;^j㛑Q`exH;J\*`l˴Khk +&tF|(8VǡܷR:ϳoG*UjSKknRgl ޅ-6&Nŗ7O4rGmO[du_TvY{ ̏Iy\aRKy&P7ݪJ)l"W5{K S_j0WSW;wixF1^lО伴^'1b%OAXhq)L7j}=9PX=n`ɗKX#CùA *7{ jWܴTByufכd=Af]F=_u*`q+_i݋\^`BaE|S&%Z a8+QgQ[IK-jIKr2Tcju=A ʧQ"7{ٮם*X|,Yzѽ}ƈf:jCo[>]x^hlhNrϳEDkcCǪ ת9c Ht<)}z!hE~DBӳ2S͆i{;ouIp??砃46ٺ^"1R<-65sjpCSjqi6dzھİ紈 41.$5EG9:=ob쾄 v#[xﯦAF+T(C@RQF772I$^a$Eq>.AEbiO0]ТK5ΫPÛG ZdJ*$d ^}E*֤>?Ƅ$dO _tl%$^7[KSECqz"$]*B]}W zT[Rk"n]EUYvFUW\B6-RB^Me2B4/wͺh4Ek5˖<1U[tD>Q!.kR涧7uJc>c +l/i^3;iڐ0sĀZnS +qW7Np:([568ViAFޜ~h9Pldüj2dO ++61--1Ewv =JCHW34܏&x8,&#Rc3Dvz6RSyu_N/nmكvT֥Y˼?RFװKzn9Q4gC^5l`P\ܲG&ޫ` 9PҞٲXr6 +V4,{a؄\tcY`]lǿԾar鴯؏=b!&Yb ^[\aYt$w +[R)i[{$7f"o Xp +zBz'hO|Ō4ǐ|-j +:}̴a%Tv5Y9QK d0 ?$ćH|#uD3 phrd@,@XmVKY@ou([8#!OM~.7SoJn%OG" +Ü3N|/'O-R_1Vh&׺ NPz8de 勊ZTH;XQ6}+'h_|ȋCcuHjBA,NOS{3 L`]1> A rxӴ*E^.ؐ`Q5 v{`=W6뼟\9avGOXc& v1w~0W:ʎ~f: 0/˵%m KRKAcR% P#CSߥfmD5oEx17B0<&Yd8"1wܡ5 TaaJ3p57A>+yIMcu Zd?Bk1x-rsV9sH6p]DGgO| y5S$aE`$Ls +[Ym ~u8p`6*I ߕ`S88sn9O3nXOE /7f^lbN[PBFO.9Z_.5>F S̉R'}ΪѬ`_dX|{dHXԾ3QlZe7PRqشO5OkZrx5u`aǂ:*`T), +DPQʮdߓJRk=H+ +*#u)h) )B6s9߹瞏HZGzGT"93hDͺ sr|b4y $TK "$I~$v(B#].qi?CN ~ޱ|ܷLcOnT~vxj̦5<.f\K<2p:CpSy,66>|zC +E +T)f/:X1}J+>_~Q;^ㆪvs&۸>.k7yZS:˩㜍rݖۜaKa!l.g57Kv0!;ڗfe %]"XT J3aժlwVj=v姠αe=bI/gH& :g,(y 27>aba88fVVqɌT0NɉB`( _"fo! t}Wg_0}HX 9,Qx=~Jٹx>ӱe9M2mFS)Vk-eZFF٥btg0O?Dǐ%7eyښ6WSCyeUS}l`a8i g"1лJ"|PKڝc,$+&PvꖴGBoj_t4I vqf熚(eC!b׼^SbYi1¨;2W`/7uh?4 +!z@#(T 6 ^!R S#>E/Sq9z_ /G%ӈ0C9[ۼ@(٩P ,}XTOkpQȫUG6 x2e,> -?ϭQެYz/T5FL^`tީ3\#̬D:,vw[mDW)TBZ`0Ֆ`3tBQ˟kks41y `\޸cV#z`XHhwA0چFTyqӵܫ*F˪%*/>9 +gS'"b'zL=N)cs*bR)W<#S 癛)K +&L\9WtW!Y17i*%wJ_ 閥nWJ!p-0T`:K6B+SzlL,~J#ZLHBEe߈Eq1 +ڸTD}bB;*OTCnՍl$OYQ0mz7o9NŻ|hDV[Ve֩b7YZÖHl~I)ܻJ5oOݑ%(,hZGҼmRd!/NEWutV57z;jjs^^lDǾ0-a_aL؁w44簍b^ppi&nX uƻ-݂ -cY4_g ?jGIfH %J҂[%ϩC6OzvWzoZtA$?z;ؼFT2/+0@@S<@>0bSuqw;j4S'/4sEթ(P[V^5ƊHkg/ۄw 0*֭ ajyB5TC J(_F4!m, RN ?S9 :״OfOV"յڇ1,V)S@._ +#Q`K|ͨ%cj/&\: [Ft^Z"q٤Jm뙊jMarח`VCg +w"~>< 8i}XT8dzQVY<p%HG/Û`rq;Nm~Ms\/Zh:(MXа^F.꜋.Ys}5`a((X0T+JS 4&~|iB!! !)$)ʰ WFY]E븎3x,˽}|dc +|i-0Ws +Q_GpRjy0׿tjT̎ԍD1څڍ›N:ka? 7ek_%]a;זF=9-b= &Mm0-vD'^j+/5(er^+EL F1$1KWE|fOFMKm::1`ڥfXЩM*i9 +l?+Lw?-Nx͈wɳ\C0瑃f sM;iđ`$O0z*RٹB9@"k5v~.lB?ug]ed8JAj͹um.DO^^v:y;ske+,L¶vŝҼخd_5Z;q#k> MU\J{l*͟ґ3Doy"UDcu#H)BPit/ v`_Sʝ{e5mpPpy=-2[m+v6*.WۿSǔ] +^DMk,2.#ɲ\!{^I4Ԉ.~çlDcBU\b"c jvJG|H`_2rHѥ tHHBaG :Bf{'9 +[jaЧe +&hz6Fdy?>gۑx&l$^:^nx-'-]O 5@S Uڏy]Tu _,zWPT|BJ,ɕ}`8ߴy?p7gˢu\JO(_vOUue4+Qbi?A.jCxyRJ駥Pt㸲rTfdd$ֺFR>PaL'v2M*׵T]`W*cD*hAe#"ɆKO9JKL2J( KgK3jԉfZnL5oM(_>FOӹGi}<@w#Ndhoo4Y ̾Fٸ2YAz$W֜5Copli\ 32l;a<;S?B>zprjsm1tZc̥{s/J{c*#3ހfϡneh->Bc9SJ"չO8'8ހ `yHϤu-*` x[c')Oy\x!QS9q*;$;d'=NY ,|ܶ34qT=ka%hs䬺UX7Fl[ o1apuxf9QGk4;e +˸7荇5xB:yZdͫ,`2?_a[0~9iY Fs3g Ë9u<,yx87 1Ja,O@/gO㔛94 |.]16'^@1'p:XtwL,jVQv@wl{έ̱\?R^UV\GI+9D03oyd[R<""" +.2}"!<4tH~(-r25DH@l"K濣,/S}"+~wF}V dRz,:w&?C~FqJ}JݢJirjzEgU#p]ZF%+[PjewVjlW7wR/*C%%jGx @EFH)&0_Օ|Xu +DRNXA\0JSH307͛73 CWc+U#r# aQOL4Eљ?s~{sIy?y>ҒLָKd-ޣJ1v*fH 6hz+~BO:IQqZUՍP[UD#BM >$ z|?^!J0W8N WzXfщ@'h< +%sdR۔e[$z,Z2H5[&Ht L UO 췯+52j&P6uRɮ! +a+rk!o4 `ܗP)f%VQTF(Z]s,TR|O)O?ho# ]6yл)OU,F٠E})gsٴGyҘp/kw~˖I'Y;TdgYU'I8@F* 8 $I+A2((+y8OϋWȗE {բbW"@}@C׌teYgvֈHofE`eagbN_4!/e%O;mhtWv6[iyFy4ʔat V] au #QYm3rM/q{~tjD 7fiɷ  . =[n`4qShBrx_5wԐ %nQ~x'G[ `+qb]Q2Ըi=UGn~ڋJ(Aݪd E7Kz +M]!} jnh-Cզ_魺a٭Dfrj6$-4nUZF)Zpux'@]U/ٳۿ3Ug`iU}ڰULWu+SU[;uXJPvOŀ{$KF,qQruH.}imfZh~atMBb0*iWC䶧jZmn[nKfi c+.&oV.&ʭ{5_s9dmIA. *s5: 1Ů m!|fl'6#N +Z>\oMkCZ8)*bEE@(27{I" $!0a=+vUZŁ`-xEJUǺ +~~7TSsV6i1=2J眆Jh@ Uu;7!0 +߽\醮%-;=.e/T7D$v{.ʫ|ZѮmcDֲ+-Cu_{>1H1]"D^nR ٺ:E3[h9 7TJOW+3 vœLimc @6'[c`Ǧ8v!bR{1_ӵuoPE2\@;4"mO m{ ߺE1dA}C=WB}[3']\PJG5VmnYG Xyahd'J[U~ vWۅWo]WnGnR9H7ѨAu 1vZm]lUrTVA +sj6lhm,My4A*0vJR? Ĵ>2C!*#q0MJ!:ŏCR|dFa?2݂ch3dBzSIt?%LmF[AxYGҏ0m;GY1űh%[sጒ@9 q_8G>r Wn)jodEzC.qJviN&If8bg + v|sd%:uTf&L0~p.(RU +; _)w%$/ t# +~#u`u[w.qsY_-*'̳ɩk/)2* i9$7fUzflc9}],툏WYCIkS-ty7>T! 26Kݲ m&cӣh' ..+upC6&@j5tdP0=I˂Ė +C{޶$tR:(ϭuOR4$=jluq1?פ9Si|cqF!_z^SK}`d%DT wV>;<'V=(5H%jWMV#9YD2֓p~~J }D]gNSsjJmn->,vg&SLl#>^i8ʞ%4'RJDhRN0hBA0(r0K+aMY|"EGE_R^v4/?m[˨yN`K/5[71[Gؒ' '铯RGhqꭁ]>iIX +5'\GB ćd^ux+[^%e ֪pxE + 6%!Itި@Ҿ#% :*h$r7שׁ55׈Ց'I+6*ЮwȰ%U#zD+Jt BaUؕ 6}uOr7dP Cu}FEua7RV"KST20 EN{^lkƕ$vW(,F7b ˢÞOy<"_).kh[n 9W?gڈ7yș*ӼuA@ OpIRrP($e[iVYR +n#(aFq&mq3%\g?%ӆM5XD3b$ʁW ƿ5&͔D4®KcᏊ . +1Zo +^`~¿`6z q aXǰ)Ӽ܄'84 n"Db.yC<K d},{*h +ڸh>wMv^ c8Iƻ(~j? +eoyl/Dl5Żרpy1ܣܵ^004{ .%CA22dWuQ>okL<5.ſȠiffh7S-|^TjX[wCY*sG^1Ve֗+˃L3 /2y{+.;CtJ } ->٫y6q< WxA_PZ? Q y1>yK\.!OqM +0Cl];Sk)=RZ@[ɷ5JBeǐ$Ni"0 -úR4H~9.☫|Dϸah-)r~"eoMK%4 _7"‘e +QD~0T.>"x*O>酧.Ey+HVy55RWsEk*PxEGB;(J X(8hiqmh^ 0`}_APWDLZ‹]<4zG֦`oyZR|u^gCF#nr)Va5ƪw9njyIt +xI1bIy>}-AگOShKFx6xqqQ +3SU\ka椚̩Di~ ?{>J3mtߐZt]YNju]ɒQYlZZsNѴѷW>Sݥ0Bj+7q҄fU7m :8^;#eտ+*,_CY3MSU*LX.jQȖg_IWJ5a"9R'C\y׳qH)VU-Z.\+Ѥ/aen/|F[?SPkr" +^Y>VH9 &yaIxQfd}+] +U.o.=q-y][viRgk*`/pLBu+A@[)&PYQ?im/K,Y*gu(i2`؀V"fJSs=RU@7+>dْsmY)w=U?ο3D qjv83׽} 1r@vy:{Eͩԡ.޸,珈~CH{ksv_l毁@"lOR."0Fl]]C˧Mfi nq˶Q{56ef e l[IuY_(i&;to 5kZ/ jjp~Ch⨿䦿iRs!G-֠5 +&wa7WAƫXUr8+}E)oVӃIÌ}qZlh<gw +A?=$6-ޡ|,)!<*ǘ*z!8߀ϸuPpD|Ŝe=sm4'ҢؽYaPOZ(vj?VGgxI=V-̹uMCJH_-C]B~2A\8*E8PTΔTo 9/whaߣby\'F,Ռo%wU/ժnM*T Ƌ{5NJԢT9L;y _fXD\uַA:x")V%V/*]1# )ԋ@X"SVӅ4u.f?Uչk%Nj;c~?]Pۺ˄WҌ=V듍1 +E ֻqd{q׉; +NYHdfttc #&vPtQjd1o ­R)ʽ@}<7 &8wyybH04͂@>o` ~M`Oi#T2"-!NSn\ z$SC%Q%;OzcT)!M.wf.Po1U=Bl1F#F0HD\u̞rڜ*ujQO5u8E$7:"І(UuANgulWYE*Z"cT\kTxlx)$8(YBIY`[}.Bb T$=U8Oŧ yP-x$]0_ +j(sOH|/=wKR` ptl>f*ӡuU<=Ts(&zpKA?sLo`N0Mq+~*m-~F7^5惬H]${|-Ҷ9Y&=X'Vu+^ϖEm +Y/0X cAdPc_X VRx6b|C6^FeC]o-F?f7Q3V>͝yFsy]ݯMF͊k^NնI#FZ.7ƆQfeϫCJn;AjB JFw +mԗ6t(I5beElXQ͌ i,)6QS 1zJezVBf ۹ʹ/ HQ89SnE%o-4NJ``,)~utyQN]vحp+e"xN6y*,7$'x\CQL[8.d@}CɏE)1D?@晹b$?7 + YM N| _Td'wa}0Z<9|3閗3~o=Y>l0Wb=P1jmE XR[louv:.C=;.a.BřS[nWJ3ǟN1='\Xr8۲:KXj6e g΀ap%z"K1.c1ɇzɭGTRiVBe-)K@iͬ!u@_`&2q up%P +SЧ|NWP !o-t_ nyV|ؤ賐e`HʏE=>\Tǀ|cҎkIST!%Gu,%[IR'+#T}m3\/df)`n2#\M(CQd6flqGv첵).Z&wITe{JQܕQE\m`p`Ҵ\z[v7OVo9ݜQ}$SSFMWdnyuя: *o[3 O FRJ0ոl+L+&oE+d- +@?^fEkoo\fyJ8zΰXmi  -Nw}OYpz&@>gݪHc. ]7Mz#fe"g\a@\qyºJc\3ܔ r'WQVE D|PLs\h_h#9Z-TdL>˼!WS/bniA3.1Fx@Ǡ3UNN^nPOZdtvWO&-8ךshveSȉ`wPU_cař=շ}m`<<$+UV66do88{ηzkG}ڻ<<7\jvg!5M!w&GmpfSgO3x? +wZsLRq/~lK]QV:om<Q' R]AMXyu ^ȩ $}! 9LHaH8hʡrTtD-*fY]]wuu[bgg޼ߛ"ȹ I7HR7HBHudt *Ჲ=eJtj| #TI/W?{ΝO^'`v'$^E=7ITF2˵7-^'Z"[x ;[U7,QyWrr9E6cy'I gIRm2ZQ +{0K,^H/>>G@l`T=FZnZH ѳ$m¯鵩KA3D;w7ŏw^J<`i$M_x8wU-,/h!pbP1|*k _U;N45jX_:]$ %ͫX+é Miwzz{7`fOE5FohX}fL}k%Jq_b_A54WK'h?:lTHmm. m&"X7rV7l̨b]r+ OpK[{0EuwrfӵFajCCPktMݻVw[FR(Y-VE8 P?)p>͛5 #TtF%3 qhk ;`LVOpZۓ. j&\Cʡ <*g!r)J;ȁ&xK0N\B&Գ$bԍ7fpt(0H23ӲG1d?ź +bVֆ|\[w+tjj?b7hwJCmm#b.^VBDRb8E]4J 7LGc.Xd/a&ڎ @顢zQuֈ4Tqi˽èb˕ 43~,ymoθ[0 +l} TCuLBt 2ZW>Eh@+[Řy0= +sU"r];û](̏{e E=ma^2'FKv~.Оm0Oj(esߺ Pk*!3IBЦs4{^|{6k\* }XYǠD=A %$hǹWǂORV UBꯪr+Ca6 Kԣe :Zڿu6&?W&k).]%],lb7MX][H"}WL)RIrfr?AƁY&I~_IB${XlZXE&|w#؆`_vߢfu3fm89?9 +̟NՎ`jz1*.@爎܋`oْJ_+-4α6@/DWEjE}HRDl;Y+ z/1Dѓ(z)oι&;.4aZ#gsbZ+XWi;<~n"( M'b6!G lP<^\nM8--aG+dyXP^s:0q \p3bWu.,R&rm#қs)lej(^ ,=/FV6fj;ex%Dk%!FW@ao2QTvs 5h0B{UHiGCOzL'pbIq+'_1Lv +QA%$[H~}{1fKٲ:HmWS +ëd}2w7 j< O7i2G;SWݒ!@YsZ~*PƐ6xQܡ/9i7cGHVf3R>K2jZxH"Z")vHD} @} YJ64T(P_(*C]miSJqOZgA(ny8}wν37;?߇*x"D6HaeZ +5K e +tE=H\ƒW8 72ym]Ly 1N<8͍@:> >6pӹ$.7$C$pA)hJewT*FmKg-lm*{{v\ܲsJa>3_*ݑہ>V5|WG_>RR_YL!RFjz S5fځO2< `}I\:XiZkRH*4[(xX$u|I9̺TkVzl_׼gC%*wXR nY)N.9+wZ[E9ľWJ%wp`Nj[.b|JOsdW,R~#* ĽyFdwCp*L(8OelL˞)A vfFʹ.Knd~A򥾺]Di(i]YʯJߟ?>w[侾7KK6w"!eDp5V* 3VEa{:KoEDcɾJ#oOU44lTjFk,>{S?ýSk>Su=|j}T +SU.nk.mcŮ)RxbT<TV*yÙ<+`RC;S^0-itp<ȗ2IZ_0ȡVVKHWol9=fd jb%}DCy{sI*{ZL1r`n}+D_*Uz3}i779_kjxL+u ;FxL.mmQ`sKzK#>&ޗxiBV^\s3_XX_رC+ҭj|S kϽ|j|[X +ΆBL.?\DCqߢ7nO(M&JOiݖw0IJLM,NCOYPoQRSTUVX Y#Z:[Q\f]x^_`abcdfgh#i3jBkRl^mgnqozpqrstuvwxyz{|}~ˀɁǂф{pdXL@3& ֜ȝ|jWE3 תū}kYG6$ڷȸ~kYG5"ŵƣǑ~lYD.оѧҐyaI1ڲۘ}bG,{W3qHvU3sIa)\ Z, +     !"#$%&'()*+,-./0123456789:;~<|=|>|?}@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`acdeefghijklmnopqrstuvwxyz{|z}o~dXMA5)ۈʉq`N=, +ٖɗmZH6%ؤʥwog`ZTOLIFEDEFHJNRW]cjr{ĄŊƐǖȝɥʭ˶̿*7DQ^kyކߔ ,8CNYcjnoldVD/h 2 +R e r xzzzyuph^RE7)4=@?:4 ,!#"#$$%&'()*+,-./|0p1d2Y3M4A566+7!89 ::;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{||}v~oiaZQH>5+! ؎͏Ðxpjc^YURPOOPRUY_fnx̰߱ 8Ql»!Ceª9^ɂʦ2TtҔӲ6Lat݇ޘߧoX\[VL=*b/fMq T + p_L7! }tfUA, !"#$%z&d'N(9)%**+,-./01y2g3U4D526"7889:;<=>?@}AoBbCUDIE~% ہ‚rW; ϊ}bG-ޒēx`G/Ԝq_O?0"۬խЮ˯ǰı²µŶȷ͸ӹۺ 0@RfzƏǦȾ *GcЀџҿ'LsٛFsM6+1MZ:{OX͙~ʹ~y~eL~j~Qc=9~|4~cl@~]̳~nf~C~لOiZ/gP8v}6q}0}>ϲ:}i^},~ ׉_LpK-~~,*~&E()D9vyowy=TS3wI!D)J%OBvwN64;>FVWm +S^Di*bPkpة?%"1#!ϼK`L<n-e2*+) X䥂C@v2l Q?(=0q MzǃIz7MEY; Y@K (-\U&>rI^2IMe;Ya"VN,S;o_%sD;fƎ.R?l ;0Dq>8zDKG)3o+&<4@n͗0EO94#ҐnW9 b_7}B2yːv/ąJH삻Ȧp$ȫވy;Æǘfo虔F¨LsI,KhW2!AjHE^τ _wdlXggΩr!jU)[%B\DCfp <_\?k,.wȲirJRݐ=>0+cvZ{HllLVAc۠ ^{6oCҏSمbȏ:sz 7jP@Q;[wg|z30Uq`!P-~|X3+z2lIђ:_p-FOJ*Yr(".O'qäfrCRJ'dc~h!€?`}WzBd;hѲGϲmT SAij9< +ߨ%@`8xLTqė=,Mk $hJdx_r̰gʱhtG,KytomVK0X?R=Џ ]ٛa`sʠ7g&Grŀ?>r&z`b>&z%sxbw&{~څ]"WR%c"zD zA rs!֝=jcf]rmANJl$ے#ؑ >wTfGFF699<׵.'SZ*˺#-Jl.ZZx%m*| o 2ӝ_TWK4eRsu33'jRFBWl| +Fgml0L1, y+Hu2f;[T0BE{:qntoT]okI, + LgV_R:Kϋ0dP?= vE̷փ(M4m\Tk׉o,H=Zw/EI-LQ[ 8F/g֖'$?[u~fghXjݚ- VImKՀ,%ibQ*e97WKMYiHtXTBUDw-49#iԗ/r]hGވ/ + +lD2 h‘%TTT*Fdw">GY?"[f r5ʊ4`TAo4H5rWS8Xy;$Yr'q vUPV&4m/5LJE:S7Hvy.. kPXAl` +,e: E$@BKr.!{A$A,CY[EA;| TJkU>41aƜdcT.Us R&BchR) + Pd;ʟHbl?1;_:i^mMh9Ӝ+,x+(‡j3=P6u>a}&b (0=.À<2&m%u9_~zL!S`(6͟>թVlW䨸m5ypg!2< PR%wC>ubvbF.0UK$K;؂P,!rA5%\v" +[2gwdxJ:_'Eښ_+^Cژ I! v,V72UJLNITUKɎIy/R+=+(֨v6!M @PB%R--3|4-)#ͯ w.ܘ<;b#;*>$eG +>3"و~AZ$xOUx f𜓜x;٥Q h X(Zx=`dš 8b†id, ϐ!enZ +b /޲І2P0~ +1baktT ?g)˧9 С`.ޓ`>'4\DRdPaxԗ?i|9,t Ĵq]"m-9OD'Ex>#Bz6Nk%tm6BDzVQGq,2O: y{iHcy[]vaZT5 ȨR 345N@qG!fYXr{3^M7HX1ey87ҙ;NP9tn/D=}*I:2s̋%G{7abTBm6ۺ4JZmI׶Fהz\FD*rEyք ̣V-8ˉi#7XmZLW:2 +$Iⷱd`U+z3 8"}Y\E^\Qܵ)<&uZ!FM)V"ڟ}&à/ ď 5 O546PW눤0 fGlEbdc 'ƪrӬ[{K("M/y%0=zFBx}{w6{Y50%,40R}ԓvTp>K@fR$7HU( /10f<,1BS>٨RI3#&&pa5j19#yTH9cI[էjU̟~? +7NzM`k|-kqJ}(Ҙ2SaӼGi ; b:`uǤayU}T 2Ftm̔%OpuDU0m~L-_:qWg0~huw-] NVrP =<]x;Y1iw@8,n\(zqb !$zB&5dn61Q& & CuЎy#c%$7]w'z\0Lk{8 ;fGS Fx¬P~Km%t3MccM(bCB$ _ J,@՜ %ӸZ;.6B)PT~~:_tHNITScΤ5_3bO6-[o 7$cn:zNqnE2~7\NT' "[fTT^2F&+c5r~ԕ(jl 48mWDC]X#<n_ T 45 C0 V~ m&AGA7w@w;Q8Q ?d9#1yʕq_eS]y|d*&6Q30J(WG>HN vAg+[o:y1ډGmUV'pJ{"M@3X|*oƙޞ%sfJ<ߔ[-0R'G i++qNPF\&XT~ykPx>–~u2LX'P MOW rة Z?qU\+w>-q}y/sRQQJ@737Ka[t̷E8X,Tp!PVK$`Κ׵bu~*LlBz-f{i8DbMp/ŲF_<`w[Uq. Y!'i7L' Rz$v]c-ީ%HY~ٕ 鞀ws{)Wa˹ԑ`{[z ϡZ& z +- U@uBP.8jz B{GtϤ1ޕq# ^o2N*`DZm錞c@QY@Oy`ŕ^ )H??s %J@f-H%{#}řPKn@u5w:=YX9(5#p 9#Av(~-"]Qb'䠡ya +'£ +vO@%7_*Z-r*~z Ց4!wBpG-q.a+c"wmqk=WfB +k^0>npu5㞃= m]0o-1:ǒ~%ui;pVO/a3;0oKܼL6Ed@ZU%{ ^ ͰyOVNHLmu?uMBEQ1\IُOui@L7Nk\dd[i|lRܰ3"rW^  +19~(VZQjsfb5~Nl, $LAE \Yv3k"*Ie.gj4uDk"*T~~g^ ~<|1cPx7kF84K(/AI\%HG;'6`kK +ZJAFqKq$5GT#.a;1 p't.t-SSUn;QY(sў*M8= +BHZ# GcDS{d',Utl=,}*vcr+](_1rØ@?A[KDlv'”o>=ԏ[?Q ôn!ܘeoiB]u3PzP'ߧ%44Qw L7@?;gSVjgohop7syR\7V%xL| 3n|2Q|-GotuV֘Gk}fd'̐yQ/;^+b#&~ي2(ɚpTֆ)$Dru:5zj,|~0T\~>*,6Y +]7E9!7;au*8Y?Ң#WfiA~\mB\$OwDhE16:_JqBR%*X3 !O:`Iok2+}Y'1%Y GPMJ{rK w_ L&N NyA'ճmﺾo4gz"v;L je %Ɯ{NS6U'*@djNcvo^=Bi 795l€Aⶫ627ICkyV_}B.I=YR2U^c~o\Ƙa3Ƹ2@eU*Tlmcӱ~ xnNU)o`Iχa]PFŚVTC&ϣ࿋Y=d]/..FBXs+$=}buM>RWm6Ŗ6ᢐFX 5x{v*j;zv<_~AVUJϐ^IjQxシuQo=lK_ՑEkZ\4sqU7vOa J?Q)4C^\k[{3y~M|J'g4Ay,$0( jHl:Q"V҉1X&e s)MZ(W |Ϲ\88&tcpҔa͔ CC GU$^fb|8u̸&A֍9ke7;㥦koAvՏ0o5y'M3q"y$[Y@SgÓ=ݎP1)L \!B;U!)/C$N$A³ueuU},3Y'/Jc .8_[ON-<"NawGm_+yj~P]ſ^\y X,r-|㒒ܳ<L^T},^eDR,nkqց%|r,!gJx=~p{"\eeEN;Þ=${q@Q_\?/иLe>u#Mp'Yn_e<q㼅Ra8pLB=(YK[l`BKB#4;c;HS^OA>Ʉx\+0lkOԼ`Fcfup.wlCnKJIi]&fXPAn1کFTKBoI!ӮZ f)~Xhy9 ݨOC5&|T2ӲnSLB5eD0:yP;(w9mΪnWhKu{`wk +kH>*ڲ1 wp5Q݌$;LvvJ1f3n*Tg@oO#9|}?V0M5.ۀz{" NK?C_$ P&B̆e>(qIu`|ob|_0l2WꂝsCܴLTIa?f(/+PIwB WhgšH EiŮ(G6 +"  +"(H2̙dfr $xZEP>ţC~EF:}< \{ +% rH6N$(߫Nᷘ_%1]2:$o-8ȥ I-qt;'kTjJW^}kfQUr\ulNkHn᫂H*Wd6M2 *{`V%VRoJJ`+"yO|s86Vy8 :+;9ɨ=.qqѝ=ɥ^ӏwldG;fH^2`zBȳ ŞO*{M2MoR0i:T~%$9ED~cj<}${.-+P]c=Vzpwz\S;!?C:GFIױqYŞ ݇>;]mS)yrEz_n˕aI"l|sGvmߵ_7e]֭>ГU)i:D΂G}V W5*{f? +($p\)9D$ZYr|(4D܁OHʳ ;ܫv۱jxLr_r ;Wi nV|Rudܦ;@YNl-QnJȲc/14C:'K&̕BOJ{ߴzfsW|F-q2 ?}Y[pXdY<\v+M{ir8~LJޯ vlL: ?@o[g`}>?UrǛI2Lk.}GpI8QRV%܂L0/PUE ?ɹTcۼfHs^QMC!)$ ; ej uIy W6#LMi9ĦͱP*HʘFg]mߝn+|X$Z6K'OQJq m(B~ljSuZ ťbhWP"z@UVJ΂\,<\HA 5Oaf΍C75O Uݮx7F>QL~:ʥ#][eTS2%c Æ~EWg9i%3W4ފ:}޼0_X|-ƣµVu8H{YF"qĔ-F95E!L/3zLw@"FRmOQ&[#ZO/xˤr~9T00bܬ 4Pߋb>_nMFY%MOaN$ʡ˖~ &($~>tBM%^i3ϐEf8UB '`-icIaͨ+ دR=ZȾŁ=5U#5HR>njky/s6H؃E oLyCG/?QE%FvMMz)=ZB.ϡƋ/•3O85&YKլ(ST eҝZVx'xaV4Ë*H]z~h~ i0d,K8CZy{jCF')b|xNJ>V{0e#|SE1b狛*_R"37Boξ(p3_<ݥ%-tɫBetƓpx HuRuɵ)H?mf@Iz͂qrgM_D|Ce +ӯ_wCՄYK/Ԩ 佨/Y0y̸7.]*ѳa !d[m9#{-;W[ U$mb?ci3ؘsq6ĂT t֠} dlv{Fyt/ټt̰KQ8 N"4ʻc'׸Ns6I ][#?wsb,4U_ f)Eď* uä6Go76ɵ{'CGa+RUA=@5_rgs1OUG*ʚO&Q͡4%nlc=%Z vY Zeਝ4? eC` _wvĦ10KB/*Brv4όwM 0r `$CܝGa6;g-N_&ɰ.` `0M/s\PMf`p3 $A7 i c(y jӍ 5!UiMSD-rBFL&^:OF-T4w T3c q]2Rd/3U\;?Up=@b +TYRJ3O)*+sWu.[L6ǼA. 귒hoN_=C|HW Gz}w\2h{?Ur_ס,[<4DmD〷C/Fl Mr_򑹾g"P\TMIiDw$=` IӐ }6.jYx^h}]"]l +8"ӽ΃ǐL"Hڝk:^֖Tm.^@1~qxTlU#U75:LE|4&W25exz*̖̆;M0do^lpmaIS7kD#'͊$"lL?bADINmEh 8Ԍ*"vұE݌5Z5 `z~x[MN&a|b(ǁ$ch |cq)M_Ɔw>bSО$  Dpz!G@o3a]PnN2);K4 U"p+q 7bLay$04iCc9(6>E3a{ R䏡0`?s07y9'`Lq`ScLr&MP.ڽ,_ru/F=܏=1ltŜ 9>1lם +KX_t+ =#ثL +uuWK̹ u)F@jR_$YuBśGbQl+$,o8qlg!) n2QήU>Ytw(^'Y! %GU9, &>YcwU Mj"Zo6VWF9=al mynqA/2AI̐i +qAN?!9NxlbO{eiYQ̶>SZ .&sbj?1_ǡPkٟx`дY!n6fVJ?ffon06l)7BuyMAѢ&m>>Nj#4J%&|E]ۊ:i2g0io*6zXh +҂3;1"2ҍ+O?KjaY|nMHpA/LsI5cu*ΐDx!W {|mpq%qehrYbBt M7uA- +w%5,x+ z!Ί}|%wpȩxeXx|Yy$M}yAz5{+=}5"6~{άq~p^Q~Md~*XŸ~,LU~S@~5 ~+f2T"P{pUIpf P[AE;Z1ٓ0U)Fj"0΂op~7f ![BPY_EE;T\1撠C)k"djpmfr=[M,1P\ǑES;`Ћ1')}"Ρmfni=pkqr^mtolVurX wtDyw'0|Yz>̾jqźjlr`ntpu0rnvgkbtgwWIv~yCtxz0b{x|bh|~j|l|^n|~pp|j\s}AVtu[}Bw}0z~l;fׇ i +9kDmh5})oviNqꂿUtXBEv=/yVǧeP{qgi卞|l{nohLp(TsuSAv@Z/ryX_dִ2f}}hƖMk/zmtLgdojT3rxAKuI/8xσ[c&5e[}gܞrQj.xylfoDSr d@u/x\ębp vdܫg%iwy3kyenbSq@to.wUad`RfWh-xkkemn)Rq\@?t@.wZtf4uhvjxxm0xyosekz.qR|{itP?|w-~zK'rp{sqԜu#svFtgwwtudxw*Qz%x?E{zb-}|Xpzr'zssj{@(t{vxv|cwy|Qy +}>z}-R|~H(oYpq݃^s=uPt;bvSPPx <>Ay-|0m{opzrt?s^auQOw+T=y>,{¹luSmoou{psGrlatqOvk?=txj,{ @k mܖnlprxqؔM`WsNuȌ=&x,zj׫4lgmomqq0_s*9N uI_|2so|u]}@vLO}xT;"~z-*|Ly(x*yyr z$y gWTaˢĮkTd@D\dPPp-HG&]30;sCg( 1DE*n6ܵaz*&>P3ĸg| ,X񦁓`S$>BG DǕu#i#܌-`xJ!wم:(`[HWeQ2UFD`|:Cd2~TvkdEeUb2̽p ʠ~[@QdF!7H$ #dLt!BOK*G-iCrB.UlmO> ,B2W<+367ߛ@ )۠&KO 0ޏO igm82=D 4FB[!AIb4~Z *fz\OtF&ӝN&3xF[Hjz&3n14bM zB! |+ +/hw{V\lsTjg?қ۟u 깮D}û.5ʺ(wM ұ=Ljeo(u\ yPXƢ8p2232"uh0 ;(3-ybݷ3WdsF@w ,8#!H*9)iF^ +P7Dg3I33D_)JQNdOm2ta':=J.۱ +s`d+uu- ǵiȵ\L +kw/i&G1|91:H^gW@-Eif?QF?/KvřMkz݈uN0:ӎ3BJ]PU@׊VVzDPC9>RTl{=EY^ScyjN96b~mwj[ Zl'd}[YގM:tU9WI-#d=sѣS IKuƷ6i/JO{s{c@6oPU,'9cV~M6IQ1WwoT+mlF0\Od?oi4M4MC%HfM[r0p[p|R’/Ld/_c8]׍ YpFKM(Ewo@jjI0/kad[H>|/ѓL |00SVRׂV2Cæav4x,'L82'7&n&CĿf]9-f]i{Ta4EeNٟή"V_ǔ3tf65ҷ, jP6Ex)ͻUSu@6M6dFVSˬGŦwƠuy@>.TȆVOdj?#驺sycA)w,zl<ـB*7ij,\P#;}}~r4fxO"ZhNMBe@(78,iA#FaN}qǖ*lf Zۋ M2HB-7߅,yY#p9|qeےNYƐ*M}"A튘6؈U,ۅ#||(qW,esY!MANJje6Ç,}#5tPcjOf=_`rhTkHm=op2s(Hv "zbtu5k#jl_-$nnSjpDHrB=tytn2ݑOv)yL |triIs ^ٟtSuSHt#v=_.x02y)B{! +}~st(o.w]^`cCcHlVf+;t)i0aldOȯ>tsw[-wnw\-_AMb0ke#SsShA!a7kO|o>#r -v0[Dn^aaShdL%rg{`j哟On-=rfv-vm3Zp]­ `܄cr f؝C` jRNnb=q-vBw~o`^q&ccrfBti quk_wInN1yq<{u8,-}pymjynlpptnRrp/qsr_;utMwv2>@?nC)HKс#Eu$%`^>[ +(?`~^x0_+OËv&"YD>s5x']~-if~>NF" P^OG# ǖ0<7ӆ7 :sXL!kݱrx{6Rt"+@q*7k1U誘Y}(~\H`J䞂\ +52[{F;Onݦ *C{2Hpuw0D(MHOB$vKѻX{'V' 5c + +sh]T4I DGãTD(2BNlz9eB_ ݫ.#JUbGɰ Pc36߅!3?o/˼ 4Ta1l-vKWZApɾ<>\Щހka8Z5$GdW#{{ߢ! e8l&Vlu4ʚ@ԸQWJ"쎛)9(6gf y'1?JL)b쭢l]4LkۘPpuﲹ)nCA Ŷ+2dEH'Hm&Y3uѷkѽӭ1n]_Z<ڮRvӛpjm9G݂#j}dA-uڠ +0\C"dhK>مٸ:IFq\BVhF'$[I&3BtK\ D'`;I ["%#N\I +|?a8+ş3"-Aש_ZZKO%u6`X{cͯw1 $+OM{'E],jz6+~ Qk a=_/E qbVk&S7fg\"&]KOÑ: %ijeB>%j:l=T1e~/ߪg I0^YV)<^ϑ% +զՏQS-WGpaθD8ߠ9D֑ՃXM' +UJ]I"mteuuE)-3`Ҍ SoO6Ju@$ZZǚ;oam>݄92)@m{>-V|WU>r$Ӳ]qّ¸zEYuɔ>GT@蚩\'}њG9mp.d.@L4c&,r;b ӂdlt3ݦ]Q<b-w Nk k bK%H@ j"W4sf|Aa{8c%J@bW\E':Ehsř=}9fǹTW !3ߔ% פԘ]YzĀ&XIkWdPيb]9gbIi $ O1wu_)xS$P)m/UI .mpsf5Uwl}oyh 4;=DUIKSDSjj:?2*w0P4o+G4O6jeu HW)ϛ=ݮȆs51 okaIӽ֒Wo0%>#}?V5N_r}%7 +Լ{!`D}K_4 +!Q\HҽzȔHN>uA-^Ჰbg%+k58W #wi+q0khcuTT[`5Z[`J &-v**cs0:-7o3G(Z!d  z Q}vx'E}aQ#*'viƷ|'in˵Y;eR{E1vikYT24o/;K |O c +Rr_T'UtKyγzaL= zs#k)|OĀ܇:axim&&^cŽoIѓ` +W82K/ױϬ˽^ipuO:JD:WtG<8YJ] + ՄyiZP-|xm4rQe`dZH ;4SX1̚`wpu>7 H2%Cd>zES?+&e{\Q>+) ^T9ZPFV+@l@ A B +r3L2$$x *,^-ڷ[]<**RInpdk ŻΫ :C>KXi<_TTՖqcs.JmZEŒ:^΄hsVIbm8tSX&^ a*Ɋn^m=A2s^mICca|k`K{"Y١:nf,ڱW x_n~ +!f睥# Aɧo(u +gįVg攷E)?n/ؠbdSu3QQIB`\C!d +P,2QC[Pһn`RXYU^',|Y5G4-},V{:T5zGFdx|4Zٲ u'ʦ"Ww[f^'0Xcx2rKJJDJmB|CÁ=55oc/hNL9'0jI. =$!_3s^>pX0]ScԹ`gi9Q?+,O|ekkC)6bf!),MjQZF_Y[-ۈfiv&mH!`5oIxudP#F +P&h_2nnmMsC?wOt[Pk+jnA ǐHځY*zל`L﵋TL01|w:44o(%j̨5YJ_|fyl00DO+/.5T"$8[g)T`MH?Ɠ\fިÕyL/\Zj@Ν(Wڢud>P"Yd'$$ʗVJ+W>pG[^Gڻ2|M 5kci{ZJbILFPCR7<]'wKÍQXb* +$f»~ ^̈́:)]}pA(+RXzE;b1t!9ݠBj` d> !L7gh%7nׅ _Qg1R2Ǽĸ:@n\KX)'WIC0hݤ!XL}4l5 Vh2,?bLb#(sÀytk]:ibP_"2S&F ߆*:/~5l6fݻ Ӡv(l1u;8qi7mL[@Wxlg Y<#nMDyYZOEX;/C<_IfGuROM++c7S +4ƊaZԃu Mߊ]>]o/m^&=Nh̕.g*>d_$ +]koj-]wz`g`@XRSZ^6uV^og~XQ 濮a%{s Tp4{HLydW)YU&R?FD/'gH7yOG +S0᪄g :po)-.XF:e*diG{.㯙nwn.tY<"`7dsSC!x$g:SX9Y%r_']4K . q cYv.㏢Mrm*ADbW냊M1Dqby9mT'buq7Or }yXK8`微.;~1K}wҭrB;ҏޒ &6 Rr*?j䆑lugICkM|vhZYHn8VzQ3N??֫zGP5|No(RGJ[5&Hs)qq}^&2n:zǰkFmP03;7Nsi+ZiӍ ^zs7Tm , zb@p22{96ʄ/= 4)c x +t&83B-(;^SedSy7yG^H@Es7<AQ|h[\jeZҎy1|i-M']|k!3h{&m5&[KiK%}UEk̀u hT[*FkkOZ e ev]G ؼ;GLW[d;oo3xY{OEk[@|l2섐^򒼗F6a 9uUQ[Em'*uWAw:^WfAw:Rc$DZ9-N7~c + +?;A34VfO 5*DvUe_Rqr_pMv]{қ[;f4( c5ڑGdxEjO-n +| g8 KٶŲ]{r3J(?ұqlu;S7qWA}ǰ=o +nxg|GCTpTaH͗O0U`llڤClt0jh~pڱY_,x',IUjn\[M zDBb<Ô]T7S0Co}2%sF͘MQ ś!7fSѕ&.!mFk(+O Oȏ@ W1fG 0JZ-#=qb>@@gIxFz|޴\E=Yg6atҺ*SY5T9vh  %2{}n}I90v zRf8kOʼjVo:*xH3_ 6WWx4\;5juK::i7rʶYAd~X:J1<;e +(;MsrlڪU[y5vw(k +-OlHWeG㐣݆L9sŠFp6i&xИp0C2}TxmCH#ѽZyڇm{+EAaWdVSy%ې8bש"SLL14$Bs&Bj&d@Y?O+82}-D^ݒD(PR{Ѭ.s!$4Pڣo\i(#u"D8 +:]C>6ڒ׶*m@1GQm lìOrusg# tk-ۤ^G) yۂ2b+PgDWB;T+4Qv{9輵;!f6~/ė|@r~EM$,<`2+oMҿ$ȵk뤆)<$\nnu|LX+z-]:r"Xꗺ.KW;–YFC :Aǔ+IU u+U>.+͋;SN@] LUXKx6 ͑8=*U4^qݗۥ>S韒+Ż eLsf v?m!'粈Yv0zْ2GwT1e{BHM, &fr(y)% P Ehl% +$EVDĶt o \~6-s//E 2<뤪t :mbpVn(Q7:ziZNl*3miИ` snX +U\Пbi0^Kc=!!{pwpyKH&Ș/UDg#M@1&yf_sIrŔ\ Bc7HexXltbu!hI +&) ֩ršbps;Cu GFq~~c6RbO'l"<͖z [T0}5y V|EWrф\2aAA0 /ɷW&aA +AK]מ q\kPU"Jѻ?W{j#'rG^$U)~VHDTup7eÊ⚊R"I^w0^+mOXiMi-T5ȝ'N]~{e r5Ճ-wA-VYF~UgBOJt8y0.{KO(vlJ uS0փyk^?6Wc+ +Cl]Eko%ݼ脦g}h0[[tVۃw,U^|}X?4:a<X s%هU)<@ZQ/[6 . 0A=fxIҗQl3\PBoJ]Դ\>[3?,ЛMOyIOi> '|2kxo6oy*Zo9XYifNP?1k𾠣 *_BupֲB[ 4Xφ}P73d"dٮ&<ăT>x4Y"GXF%Ngt2S 8.hpq܏#~2HleҢ(j =~n$ Y9PKC‰/q䢘&lrS1|8+ۺp5q Z(QӸAX!\$$$CsrL2$L%,*OQuOłBuUX뵊]xV~n,[|nC +-bY@X?(e92"կ)fm6@>_|Xȼ L N+VJ2v&ǂga:y*=>C,꽅zqwΣaVbP$Ԇ3H* +|tc^7CvfCUʆN\A X)MȊQrK{Fۏe"j%hCi24.$ҲɹDӮ?2]HMtaPZ+C9J*_r%QNH4r{W) |em}^e ٻ +.v_.e'T)V4(FoUgzf0=rƣ[(hGjKҢy}%]ʟ%(y쭬0L1sR1w^NJO7 نyoxõO`i0)¿6T@JJL#״C[!)9!w+@,&TQ0GU5a +5\1(-9]s41y3yʍ/ G䇫~IĴ41_35g%@.1N§ N̡Pi'74@rz8Z? i;f +cENOri@Du{A6.ѱ>1_:, Jf?/LCNN*E]٭!mq=p)ݍ +cFMH?b;t% 7r~L&3>ﰞ~6slD'9?6T­ϙ^ 5; +k[}gX0^hq$WKJm3qV/f̔&|}31sO[9"6ε6 9K+|dj8a&kɐ=9wUͩ?|0,lugzeU,}* e-^uGSoy77bC#Qşn[,( l^ 6!ʌ>":jbiq2$V1\$ǕwkGԣQ%[`ѐJ Ή `]+Y)u!*5(HIdaoElw17hYxЈrMyA39ScLYgBل*dlQ P/Džml)IR`i?ĞAY訌:et/ ysn琸M>dSG&HPe*p:vFӫ}9|%*CdڌTm ؍θSVkq~VQ< f +CB'LH? 6ǍZWzjxA|+cshi#a43 KZr?'H:m2AĽ eЭdcM^k^Cj#,@DL2I~tHGǫJ̀e W`_qZb +"pp߄CH I&d2L)xʪ*jXEtJJ]EZ_=@XY#>(UT#tgE UO4E]cDix`Ffw0b(U +Y]sAvjfhw@A,bx#iu+E_Xx˼U-EW'_@ce2b1( h^EN +`V[@-kbn_Pe:60lu-'\j|Dme;tHGD˪&աD!ߪ@M?B=rΕtSwo2Y!;DLž]򮆁˶Rf;˷-r0ۏ첸R}"?5#mk+3((.RxP{K$ ~?uX m(U$C[KIl9vL"F]C2q.OI61Qx 1iQZxle_)O&uZCj7$6} A~8zXmb|n^i>]fQBchJDj^ k]rou#Ih +8ЂTc1)üW+-*kxueI~PE:LR] &t-¬^*$M4-bB c鎳A9ZuKDۄT}pp;dzx0w + 7 ? rlJU/3BK3hf@jm1RזD*p֓2O(Vv +ndmMAO;1S`M-a6)N˛,_ +l[c.Hі%Ŗش+#]lcٶ$ s~&b~In^Y6-쪸ʟ/FRa` Ei|o$Գh:)=kZv6g|V'E;R^t\"ZW +YnN'⢒LiK[!6bjnf$=+ *.ӃKvIchP*%zډ,1-pGsD8DC7x&X8e!j5kL4Y &XqYLA)$]s_g^.[fx́{sHq  o݌ KFaa)1$PoגיDO̐Ńwq?0$װޮxYZN8$8 _ُ$`lcZ6ݐ?ȇY+0H5zቔkQ}Ö!~QQ2&P{BcH|7gz9^sylu^A ;RckU>)vQ 8:oVcsK68#7>^nNk_<w*>mڹ3"ΨŢl` D#ޣ7W-#hD:G"DxA4 >X( 6b-X>*'qkxOOX+{5| fP|~NEzEy?|S-2<3}=`[~#ltGPj_ _߷,cn$kaM=UlMQ"gɆ 5iЉ5M%7R%qvLSG[]]M vKsw>q| +7pL=#.[CjϨ^wUOlTvCe]j20uuFfձʪ:AƆ"E*S'_ +!Z:Qpt47rv윽Ys9{<Fr׃d+G1 F~ /bm1&&x, ^ LtZnDz4g?x7o߽06m3fB|=ksΛ 4|K5~Xp%&(*,.0<664^?|X@`PsB#b$ PX<1A͹O3l.O IrOS#?UBP' +BPT;} *~>22 +EOL_~[ g ,v,cy]zFl(}FVύPq㫪J6A$*H$Ρ`v0;f×9zL2ٞQC|QM5xzAR+Ԕ k*xGjsH%Ť^Vaݼr~Lȡ3h5$؋#2'$ +,FP].V!foDc&2`* _'ǹ{# ݰw%{2>aQ*X SV*5r1V/\2dL9x~dE ]0 +^z[AKmILŤSK``;m\ojc{.]w{]}A][UT5䄚T9"#֑$-QJ֙ +(R;7n^윆a:VVTST@e& +PkLlvw6ԷU8{`>5#8-Eʦhc5Ij ɱUx(EUu=XU=ux}{tjG +4a(=Gr(nËqZTivU肝 F7 :&|ؾĮȬ8CLNlG\nt{Bvx~T2?]ъ?:B': nAS+w."nG%PBRBz^MLpz&*T@ mHh؇Dc΢&ZT_Wj 5yI5LOї5m + һE/`v0;fˡp;ϙ־A}UlK8SQC#kדtYFUVErAF̾!b7E|{e wY쓌E8T@V4U4<7IIiA(R@: j:8vug*tE@EQ*r 럄B; !rIC@V@]_ӇQ5UW/)aY/-Ry%F2"  InK/i"tY{p8d|Q\Đxi'6ĩ/UUi5gԧyebLY(ke&\1q(h-Ev;wΛ6 !5kC(xH@m՝N&וy UFeaf5n\+#$,۾.wAڐ&T%_}ؗY6"s 9G&j ơR9aWLt~-m ANv$&! 2p0t{z$?5Z uTj]Ġ`9t& f,h؈!%gS$&T<6ncK /'z&bp`F*8b(@H3x!}': yo8IP&\P{C@Rt(ɓʌ*rH1𵐗&dx'McČ`$f>m|S~䃱ؕ$x0mq]Pe& i#eF6AWB~8QChiTɞ <|]z[u*nz!bg9Ԓr3lq Xr3" >4SPh=m@A8 {Ͼ+\Ǖ--F3a@4M6;ҩ'Z8JԐpjj6 DzQ0'չ=;Qv(X N#0-z#}2Ң>ƾ#Ahw8Vw5C/[r:mU5fYH7H)N6S PX'>}<5ӽe~y'NNdtOݗdjM Z̓x3YAdECM&-ڀjG ož>ْm\-u ZTS#%xG;Ѣ8]0^`#Hƺb~ںnA-9*ViTR8 +`'yM>aATm#GђZVZ˪ݐETD_l }mϒdo8zPc)VdjGT *:YϪ z*MSqKP}W7K۫Ov*om;Czzqt}JeVl|eryItV2j)kb腳h ?|lIlN^mzQr}\E+ݫl([Xp1ٔZ[m@_Xi䮠pvfy?q)?GZ3=@W =T2lvsdrڰP챢ށzE     q5YTp +yOCŻReb &l[Ghmb9M%>]8!p~{gkl’B42?ȩVnI6 +e%2G-8o QP6ncN/J/FQ&= }-9>#, +>nƙ,Π z,>3'ЏԍI6Mo$GWdosfܐT:jGyhKڻ)k[Leٓ#ceA>Vl oiEǪ2p˪lMe.{J~IT"Cvnc53}-"ÐhI'ِ,kHM"D[YjsUZCM:fD˂+)U +Naa␽Zfk@ 0,"IBLtrAlĐ  N9Vr:#Q1ha x!coDjԀE_dLqi&]8NLSNIS/)WKlƜ5==\[jTv]٨@(WKsm!fwO)iiLڤ?鑓#tɕOL=?ٯ9,o9̳t2UAP@C6-!d!@ BB6BĂQDkop94Mre9*ӍRMd0W:rB5*G1GRBd; ib"P'dh8^`B5yϕJ\ L΄*nW2b߭L)3t*E&' sdr* i@s?/=:Vh,~ߗ;{u15k}6EnA;xobhS$u,N%ɕ8j 'q/qO=`S)г ,Tרs=@o5-z$^˚Fk3(lUA?5(!4v(_uw1ff:w-}hXKvzqAOQ NϜ@:&z$B/ $Gc*8?z0;ߗ]/ZZV#sY]X&qzlKNCd P¶GFޜ=;èj!,z5ϥ+D`C^n"NJf90 2?}ɉ=yΝi*mJnL6M$_e A ($eEU Ȁӏ^9,>IoGs}YEHBWh֯յYTwL3rS1MOeS-)*d`[hh%؝jӣ͓\$|[XRK@-_JoЌ+כŋ8V"]?/&{d_$]B?,kʯ2xF5xun#s +[oyDs?{how1,8 fL?CVAyE% +K.?)-amU [5[ڜȺMtM0o?s}*Ϝ|-.̩ {JZVu (lIneC6%FQnj̍;\M{w 564q@p${{bKXQVx &\^fA{O򒻭m.B0b @ħ/d?4m/o +y0wA6kloz=vVtbd.RC{,DŽ4]@Г zӁ4#L#y,xK|}]XÿC>A𵲇i6pD1|܎,HψP(@c ii@Rq2[eaU^FR6Jz!` {v' fQm)0}^(6Rc$5 (r~P,y9wM:(^։gDHDϡyl"0A4t!5F5bl ”#@ +)ۚ+Ou`;\ mqׂZ4++'8bqu2ǬN Gt$ F7 G,)O '6bgSo/+WuQ.mlc`rj($oQM +0rIF?i#@I_S>8Z7gW-[ܫ J?&[1Ck\B"mф;[ + 7qD +$fØt;Sj͖%qzfg,;-^Q`-}"ҘGHv- 35Sl.J7oÉ@ 5pNgmwٱٙmu*ꊸ/#7H NH  @HB\$77!PxE.ov[O8bD>Π)Q6AY-aWjLGU-oF7k1Fj@3\=ۉ <'#Gޙ?uߎo qxeP IÉh1nzY=Wu Mզgԥ'(e]-gCGi.];^ɹ>~o[?) oOP^M!=aǠtRl69m^rU4\ O%%-,O]TB*s;?Mw+Pmv{ւC)#HܥO)ih\LC.!K'b1 HQs.w{ϟ/2Tp c6#s6"bI)i+˰exVz:;9 sYAnSKG?vOW{$a R*ը1o7l ˯WC^kh+qf7 :B|J+*u}B2#PCѦˋS%e*:g cCh܁li) +`Fm5{kï 5!>s^sUXt9UJ厓7YΆ-P7 $*gz0W]yl`\:XA>s97<5'&cE=ffӕDdyix M8ZH6."4Fm Iz9)d1 ź F+)mju@a7gDfFiUcԝRڊXxi>6|XG/@@+$kaQbќ0/nMҋ]%:c!רZTxY jq4Fּ]Xyw?=5a'v:u]㌵u=,"@n9 $$!+E@AHGBBpEA."(hA P뷙ӗ}Їw +oPEiԑ9qͩ[ q)Q<\Uh.gY}WS(35QEJYj)zS h/Pk<^~'?aS| A :8}F/R+|cha + 4Y^HjZU7 +[C1 ?w<}Aw{_Kyē]Pmp\+ؐ- TźˠRVYĐ[tX;-i(i7[9GPq4zg6@0=4kֈ\c-MANTij *A+7V |ZQ4fmld/ 5@ +ݽ#]w̋Usri07mN wˌ|!WQRQIc fWlerU:Gg&{ q? +n. |f0rg$u͚B869A$Vˊ:bVoi L,EUJ@!Og)Л@v4>4=A[+g $fy4"nv,9r1gJc:5J-AYL +:J匞Y*ϗȭy5Zg!W6@@6,GDOMBӆF`+٘^-+*uj/iuUcnC9K)7hsz 5]Nٰ;Td~>TJ4& *ow} u?zXcΑggS+~P2u.3MV&*1Z,_e%I#\iPpYRg/PphmsY}~'kGs4Tj`ޅX~>3en؈24"y 'ʸq~tZh/5kofصOa8s߸F_$@3q˰>'n9;7^^^=1.5?jD'_X,D,Qn?t/J\p &w!ב0؋gTStZ*j| D„=bCB3WYx{ot}5[,w$ 4LBA#oaQQ\xąʈ}IHNK ȇߠ Ke's}*_};v$p;$p\,1~ ?$ + + ! +9~|?}SRwp^@YH{VDrqQ"Ş'VpoTU$VdDױJtzt +*BM"{i1a=~oضR[ Q!q/eUV.yVH[(`IʪYL 1KWiE2c9rg0]DgQ])ܚd]ѯWiMU}:o@:vN?ćѱ@Fq?.[cT(y1oM70œh~8Jh.#lQDҭWF[3j;E#@O<~.;YKhk&qtd=rT}J+zPUX}Ψ9gTz<#8:<1)y/%O$yevUm:>Cn^!R$,@P18Qr .eFҺs&o|<#AD1@q47剜_NJ5yvAT8a@Â*2 +hc^3~13JEi颸r!:Aj$U^NMrs!&xt~8ۀ>4@sWѴm)9PV-kQŸiP8SYFR4c4Kl] IC4<Q zás!{2 ЅfNxfKH~JμΟuF^4܊prfJ@г:6BRBd +Am-[[ꍏm@Ch[kd+>~r`vS!CkBD+Y]d=a&JD;Dlw؛7c_so` + y툈z6tk4 6֗7Z *-Kآ&%ת#qfB׆cʡ2 GMTC?.X [ZH5:Wt6譥dUEFIҬŋ(ZǗkxZ,z0= >=P~?Y9=1y~4tV$aix%A!jLsLdEԶrV!tZQ<s`i ,{߸?xQ#/Ne`%zyx+UnGz)xVY'iNCV`k"|FyT&`y'_z>#n/F\Lz2Cs/)Tb%Ӌ\8yU B+|Ȫ/: {7Ӟ޸ho;A[,8N(V'O7* xUzjޝ;Wd(aCV%l`PPyp<}捑^gՕBkQG5wa…g7pkŭYlhd˿L^b/IİK(9w} ۿy7S[Zh=(L0~l.}-ZYn@."@P +gSDFd{W5d˸:n8 \o3K>^=ݻ_%%4$&8 j%| A +oմĶ^Ƿî:fԌ& 6-LzH| b?ӑu[}U +^^_b6QYU82Tݘi-434o'iͩZRn +ZoH͟sӹ?}W>ߪm7 +b#1en ?#s"*aQ{u5k ixtJK} +LjH +0}0:[gAM vtv3tљvZuծ]uC;rCDD @ !`BBHHBr;\BZPXnŋu ؇}f~/76ذQ @Bbh\Yuun^R! lQwLs6H-M{#RpRʒKʓ7k׌MrM'?gİkS!" q8@& xw3KsޖG!禼:􊑟 %X~H<齾vmWkaİu~AD +(Dh>F,AC~I)o|J"&xŭԤǮ03bgF}PM}3-z[6|ǓoK@C' 룐A PtD`#c{xʢHjl80bÀ!s'<jc/q/Ӄ@ | +8- QMxFeU>iHR|/1{.K<['-<+AIgPW7 K g + N H]iD/X"IYEMo( +g]Ytd_6]8|pR~ =)L}Uz{@ yf4HsRA:VPRX[CYqDu*ܹr. Y%3XlsZ~=*UN^i\U^,t{gP5y - AEr(ӣAeQq>IY`<<)`?5Y^2]b+0gnϪn]T_\Vc/=˚%>x[@A#I=,-B- g Vm<Ǿ_%߭PfZewJ-۸?{5# %SryUC ݠ>Ф'XʂRlFyCrsTI0%ŭҐǞ݌!Wi KFMvWZfC?]>jqF-VTyl?d^6b#Sl0bYKO̹4KftDuE5spx!DGSvWLv|j'mmcUZգ_E&Ѕmc~0 ֑ܙyWk:nv}þv sv$4y4A֏K磻2nuJUaDG222qwQ؃RpaWPgM/ uLnmXivu:3_0%yN䍡I/ɴQ:8nj %bP,|Tv@^@q;$8ΐBOGhOtP___r:!͆i`=li_(x1ra q#Ь$ $v@mdx8$ F{8 +;("a)^STS 7 +Ә>ɟAdL bc!3쨠bUom`kRS2i@1ȏlr>>^@=͚#K+ڴW+lc4`}_81CQ~u6hxF 0l? y;H !?)|$Y"3?iV徊H!fLSI̝Itx#{vMH!!M@0cr?H+e.%fNMcH͐/dLk V-I9wȫ_G 7^P6P%Ȩea-\`XL)jYFX| ך3"紒jro/&ꀣmjv;!NzA1 +1+d)VasYV.o*X0N?'Tg<'TZs{ZI=yw)=?S4О\ p|*N{?(ы +Q#eMeXqiJѳRSFz9XFRwOMnUzwOqKqOVgKx}E5qcu(:ʢ2 R^P)R @JHC"BE0 A\ gnև}99? ^!HyYz@-F*#1KcH9}b_Rh2/s/gf 97y7 HPa 0WRX3aA *v=A)%(j*5ybf?7 +@\MH@2 P7]APeB<*#q +r|h%x\N/bz|VViè- +5(n@ +^$k +$ub +wkd߁zf0]1>F)\d7KheRUr:[Dx%2Q5I%euaYI+tJ^%(G-il \~NSyU0.FyaM𔋵dCPq d&؜L,QdJ)BJ)dB֋$SC wNyߧ6Ʈ6/> +qJhMIlm"Y+q &WQ%+ŕm +Tbs@@ӞEoܭ-~b0䤶2'rą >UepKyBBc^3XVVIqUz1 >7O;AtzB;~ICțF-LZ,8GK(^4#J]cz9@YA}O_\;nzGPLh%%lƲ.I*\Y(ؼX%mK$ik ^-!Bs@i +?lu?ov9цwD%HS2{31| +n)c!5*!/Q)Hj&I A |sPsp3F>M/Gl|tĺκ>mw3ȭUNӑ98żbt,Bw2IjVs:L&9Z&9&^ MaݕɤvOeq'Ey+_hbh'GDzCȺB(kAzE*f5Ό0"4ӌ)ftPnjXo]+o?سB쨅手e36M$Po(u +v02`Ry=0^G/z*TN k㷩a#3 +sr%ۿ +Ve ˴?si1ߓAԇaqIw3SY*v5(Y51讆to40xQ9rl|Wӆus^Y~mKw|NQ^#Bqsғi1s̈9Zn0/GϷ`{|{cn[:6-2vk-oVZm-FC q4Fcqƴ(c j&Rߕ}L{#}9,Wϼ3 , S!VCfi}ؼþMGNK?z8O.{—`bc?[BD/b>bSPo93){J<#}Yw:W@F4 WAZY۾[hΪ8,v +]#xA7̀}@a zZ`C? O-"ܖ#>65ڷ;2"{+vM%\ -ypI^vq2_gQMg9=ǥ=Gg>(*(Ȏ;Hd%| ,심@EERVOU0l*wo{_;Ci zCg н|_H)Om;ݠ0ʃ]ʬ_Y4("65p`63q' ܭc~3!>G P~؎wr+ ..:rN@uᎅEc *lظ +zHMQ xzAԾDkW pN8t8@`s$@fka;PYln "b HQƺoc.᮳cً9 ܹ11?` v뀍5}wG!Bj/YD}鈿S ++5wqY.棇xcy/q14o(v7kHx AAn8x|A +e=1ı.${5pנq +&+0ȋ9 55l eԄJtJ{UK?Mj>"k>G>EOsE7ڙ+2k1`0)쉑KxP{ +]D#؄t +J2:xՙ&V"_8Cj71RuӲ +6YPsMҹ>jY,BOz;[Rd:MRhg75V]={__Зsbc kAENBv?k|?0j78H89PE +-aoPoꤜYB#k 5*a\pP&k, +E|>O<3KbXC㟡m+y~oߛ`b<&Uȥ\59颦lY€VɋTg*uũ 6cdJ3Ft@6cv`^GKq;}^] +h;c;H N]/eS  VUfRe $7eMZYWF0W-3|@oΗ l1a ؜um%]V;B=vB\pW-%\gKERSy*ʐU(E_0}&79 @͟ +S߮\tncuO:>hp{+!Z#9RM2Ǫ* KH)T*mN6M2յ4\DgB9_2?B p%MumwuL@#pBA^ ST::8iQimlY"YY9}^Pd9(R6 D)LI3 %8)|'r2$E9)yW ro?(}Sӑ) ֩ COǥ]%c7M5Y,iY!iFy-_RM-ϻR?{9,Rl|RRF$5tYqE7 )ɏ<ޑ)  Y4PSF5;/xWg-^f72.ԊU!AyW2*R/}8Bfzc%9gʥAgjĥ:NwJCrgECzu6Wzsmsw~a5eJmN qȈԪkRbWH:&*_V/+w_rDgfIkU[4Pe1vGO}MO@ٛK_omϕY' YwFHNM?x=G_sb:Uݔɬyɮ|ɭRAb/+զtU|J +WmR}mNW)6'|cDŽ6%ňw3\Heܩ%w_J{1 GV(d2*uTnVyxիE5.vmyN5ҏ.b< >oDrZc}[-U$rD$j {.TB2/^#.SjПS3gi{ݒ>'Oqb_B]\~gݑ&ft{w t\ ꨎltz9)z68D WoZ?u#ꇗT ,iCzҏNF<,iQL?ЛO`S,W}ueyUL+vS;3$~S' j#*eߩ]o^T,7Y+O;'=#e4@ӑ/rdbO,B&xȏYhuX#wvݗ +C3깢L!rL:{NFN&&%ST˴}P<4Mt +/fVwWkS%*4ҩǡ; Ra:6p`F~ 0cFnuF##G! +E$Ks@9]0D Te8v,`X` N70I>~ r>ę["fȱ2E>ރwf6uw r3W)˕ 0b +WS $x9[LkpXBA{c7$;C#@!MO/ X/AbAh)c52 +E0"Z+l xj=ir$5w« /Urc3\嬃hD1w!av%8?)b|Jؠs~S6$ o=OQ3MAdpm:f2ɷ@Hq$KˡS YeLT~Sz7I}t _(Âh#t! NuM5exuH،x1bCp = Ȣ{v)Ki5)Zޤw=@0A}N7PF,`Ȅݾr<`&OlX+m$9CiFg#Zd= ̠W5o*oQ+~(F{.0F0Lw$sD% lggEw:v/@2ڿ.bϰ=l.R-:{RUp#V$BB Y$9Y$0Baod(PW+^!,E^y>9/yw}qzP!qO( CT=gd W o#oŸ_F M"#Q/IѯȷP(7b5. 0w~B~`9PXT?9; @X\V?, !tǻ4̡Y%ԴjH#uz:~CCoX}:No\{5MU?ͯO+r3nwfB` 9HY}LpuD(09ZMF5M.t+y&A ?,'L2򤨈2% `uM%;Ěsy~QC| %'bzjb72zjRXMI\I-)'Kb mB\@ḨOH8Ww~rCsk 3s63Q64r6[!¶K&~˙F"D]?L 49.5%Y =7pH`1],Y1W|rTMOweC/0m|L"H +Qo\JhKٍU}_6HϵIӹ{n OO?|{e/ʏU{Pu''L٠KT2^fq OhgK ^\RQ?& +lLjwxѬw݂{"YMв֞\;Tw}˄ nʦD֤ctB5YN7)S92 C'NEEC,PGI1YR PJ[rY¹}'}K5Uv Y/Ηg1c|I'SCR(NYd*R!Z2_ɞ*!hTAc2px3H]}=@]_Y0^}gwt# cOU EttAVJNSrY&U+UJJE1HaU@5ikwxN|ҹk5zC'KԘ<^-j3$/K5u&-Qp5 J暒Qr4rn,Am@7dK[>Tluٰ}së otxՕ`ߦ*P'B2p5 (\R' G&w5\gZ׻^<|}WwVPr9꘩{.+a%R!(Pq9g83mRa. $rt >SWV:rk>WX}rKEGK 2؀9ZG@$Ub\TDc+شB-h.YK}6(E[%XӸ$.wBly; +OU+ڼGr꽳ݳҚ7y(n)(A=Ǯ52:ZVf$+̂J]#EOP)=@/q֯/qxpoӡrΟ}=K+3FNȺ :VMi ӒLC5vDS7<]~QmP.rF/Pm`C߽yݏ:6Žў%GVg  uDЏ fB)7^^Lu)6Z2>u䝆c Ъh](VED$ +*d/FI + Œb#ngT-.uGܷ0n +B39+r?%RC]9˻RzU.y;w;l`Wqy-g?cS_iy=*| BKZJO6>b)MSXT*4VUj^cu:ZvctWn`>ӳ~˴[9N;W/9'%j:f8#mϲLviTv:^֚ۖǔ.[Wd1uV#eߴj%?Pbv$k4mv!&2yҶ]7tG۝8 /t)]8IWN0׵^bvWrRsLyc?=*˷ /m $KQ TL eP`F80+c_ĴŦXJU$& U% J>=r25j"#C##KnD]=q=ɑgDGw>ѝW!p|!ݲ7=^Jp|Rq^>(9!Q( HaY1!;BG.;QȞX?2n )~c3:Q/H&à r"d(|!/1B?T`GMG b ֶj+}<Aw#` 'p3nI`ǃѴ(ȦG@=# :d Ry=[9}Ʀ߷ V|aStD}Hp GP''C>i>ԓ}<9S|P6%_z=P5uv1 ġP/r. ܙIH@Z^(%Q| DJ/&8X`a:$I!a xa;{K!Ȉra93aӡ@ +eqqu1Syn-\Hnlf裆XT?go"aHi9C +crY3aaH @FVҖECm<$ 1n&x k&i}V3 #~{Pi کaa5, >.A C+Ĺ!<20DC:oe@Xu QS|pS\(nD{;rPo,'!6@f A c8Lש( _6 hLj] +䛙āh'#NwY3a)X<,a&Fc42Q)mkD,Bg_ ܒZTO.P&6+%_e- / _'E}4pR4Bo`,L\jV[x~IvX%=!+9x-7+__)[T-=YsSn\V/*G5f. 9sPl8PY^X#*EP.r`i^|onI)k-筮EҗvElSecM셦Y֓~G>A^W֯;8"߇UcPwGs-}5bc)pڳS2$kw[4UՇ5wtO7T]Kzuᔦp?VM63rz\?Y Brs9z!p2;ik#|r[a[!g=,Ʈlׂw1XWef ƫVD)tL^Nn?Γ8rFJF7qxg3Pr|UO3& S5`їƽ}/0~_5t<᳷9h[C䙆xO$_TN r0󖻍\g'9YߎAZ-՘MOd%LM59U}v!5J@XĖ1fGyPdвp.O80v9f< smOvcb8fZp(%-$T,,5K34HDuQP"KٗdZN<9\vupdi}{>Q `>7ZNHM$RCÆGda+2ZB'pĂp2SHr] +j yhC_K^hyb5b=lО# pQ,[8XG*cE_ODNCVNš)i8GU;ۈ&_HfPHZ!I!q"EmB"~>"pg#!(Ohg3aNQ4NB8kC{-!v,t5J d @T~|p7c1?#HKAo*V"t@' @ P{}dY7` +b u: Z34b(@,i!֡%`D(0~N} G69?CL  [(B[= q.Ш=4Bqq%xg`]y=;{5x5,k 2)Blp'0\Wx@c2;U ._ QM;#tp[\6scc~pG{ÜʘT e0} 5alZ(~'gYb.cny8=לOO11v +{*D̿D[!އ-L쑾h hśH 1%:K谺8|H!rP6 ca=,(^%~wBx/[bE܋=!9a grܑN6C=ڵQTUnE/?%'bW/wsᓸےRȬCAIɃL;8bXɜ!|n>sZzs~Ē7 ѯ4[؝>sQSYr_?ߓߑǷKWҋayu!CNF +;ڢ0xǡؐ|Ѹ#i{KcmJqkjobMZ:Oo tgw%;y}w,p>zݭB/M6小\!8D߲^7ZՐUPq̸%5:=iszGRUgcefobEf +b,g":z_Jמ 獡#NvF:unrsԱLvSQpxWZy}&6K&w*簩2yCgu9Irr{A"rYLtފ#oserɁ`{&^ɛu6LfJSdSy:qMP\Tee`KBE~Cb2isjrqؤϷ&,%!T ; (]@{:!PRB( R'DD H*" qwPagȇ99ߒs9I$(BVK S%> ~"^=7y^as`&ETSYAʨcGq'y3좂s‚nÔ/.w-XOlDde1%PD _*s:bhqИvN~Vqt`~xv>ǵ6Ç_TSq4Һ"މDnW49z)p}8EGדrlD@`VFExߡ³JdT=bH2`#7>"ak{?~л>;0y&6)!3)l09l:`9e̒ (FPyyX햅#`\/X˜pQ<cr9Ut(PZ=/2*PmC|zu;+lrJ'&I̩ZgTn$VlDt_$ X' ڤEmۓJper7ujRzdYgg穾P3Qֵ]SNA&&t.C#I.^hz-;XO#v>c>N6nkRlrk}xg.+98=7Q; pa``4ݣARP.F}CycJO$ ]ㅾjQPpav:MaC/ao,lfʹ%?wHo, ןDY\$o4(^U5"kUfJglYsVXV^ R x_md-;]:fֳ{l`^`h>jd~rgc" t^hXx@@!`CӘJ*䣃t'w9O~[=>*~fnsK;jZ|[=8t#42B/kd@su:pPQD-JSь6t7t䌞[_Ce!S +"gf(`*`Tݍ=.ne4.OH"Q(D'P\ЈhCFG t}JaFK!k.:7ict5A=Ș0EƬ_lWXi?M12qJ$ވ:&$*eQyPEY+:긺 (# ~| G E 3N:8ͺ;8Oz@5!8&cǴ +|5;Gk :{nq#x9g 8fӸ/<.ou[@1?s!p@3 if o^9-j y;Rf5@nrv' tR/2}e_^S\?zqfLxÞ7$>hp ANAF\2r6hjіI,[t;RZq3~.Ӿg\^3E&$ߑN_%| +, @`iRkCٽV@8y5l 9H:ff +(wĬMқ\?'?z u:Lw~v{ S?xJ;oe;5CB"/oSlKlYk3)Nd;9ut3{ܟ1N|ʸI/WIs >@e@>AngkJXO]%i2Bӟ֯eǤ鎣2Մ!n 1!ktkk:K7J?(}\[0G}Eb=l AdHQ@[!Mڮ{W{zn4yX)(6~;aj<ⵠ*+6EI>9?nj3qf K10$H 0<_^ ꝉh4 ]\ܒ\w,_!5{omwrqqQ{/3=.iH}!徽jϾ&)id`Oˬc6'vMUE]sz=H٤[ ע/Kj{FܕXRgkܴ?ZWLdUE7pQ=’_DőEQoQ3C:~AW= 1%ޙhFIiV V\-[SOxgWVS{zTg*|$1ZpqXqU_-khbOc/scs^r⦅sx!!n꽫QZM}y6Tvnj +Ҁ' ;#=T>)2U>(I*ي.Q$]qWVS4)u߀`_vP@cMjM給`:IkOk[ +lZ +ϗΉ#j3I%iCibVvr/]$8)NIC5Cǝ/: ;/1n&K `ŏX4jFtM@- + aPBzVYaLYㅘk|kObX3ٱ~&6r6ȻOOG6ɠDW9i"ӽQEhƜ ,0b*e9,'aՖS3c3{DQ4H0)ځPqE! +<Q=0i` 4LOt=.a.ʰ"aDCE4TQDU8 cPf([ .Rn(ASxX9xG r09ACڗZ1Jj ֨IGբ8hJ*\'8(>M\'ot b`8dLT;YR6*q~uF.J=QrNި?(KGyR$%zQQţGC1 0Vg်Qf@e;b/CxbQި$D*,,  ]彂w9zЧ[0OE-z c LZ` +c16\0j +#ڭaMzo0|?@uDЧj*[>*/x}P~|ݣ|ݥBY0< }c% \*fS1wM\H tdrtqƽ7jCd n]7{G}^kNtiD/5D/4Dj=|f~Rc5uԙqIDQ⊈ȾCHrsH }; + +#xZʴiZԱuZ>sx9||񐊵n.5YMAJ"KA 5 *#pL6#-pͶz7ӦJWn]Rc&S٥";H+,%p jHVJbe)Qa^b(,D y)|Z)qn3כ X)a zmVoRG,K)kȫvٕɎ|3LV&V%XU?@Uw(1ſ!1Ő(ZeW0Wi x6}=A{a.'M6eKȞ&!>6!$.ݙ[+tOfUUFW#ȑWy{R"wypьÝs8>Zﵡ7"fi-hgMoKKiIuHl7Iz7QCi +n +\+k{'B>p6?7{qevCd]@?ߓv> eЛbw8Gv廝xw{S;|)W[E?r/~V迒g9jfjk`s@=aSN3w1_3"ܑН]QM^i@AH ,!!   aȢ ѶNjkkGfܵ"hE .qj3/s{{sfW/=4rl4:&eUԉU'br(PV_}P#>NW8,9u >K~i]ԅ܋/a坟ÝyDUD^Rj NOD{Z\oO#"V7ЊwXN)iQOͿjr˹jʺZ\25/$7'6}&o 7}״Gm:i=ic l:;wP^Ս Ϳ㌊|QMD[}fpNۊ<zǷ1tmk|cm_blԶݜǸv ?6OvwP;;ye*pALdRԩ3vΰOJuvuO*vt/v^^ٳK޳[s.=͐^cHzak=U>GhùwK[w@9(+JcԾ"_L+)qZ;@U=h̦E;ȇ#J$ëpKi +נZV7n7ˁp;8]~QBi8 c>H7'""zBJ*'T"}kC]dR!EBXd/48pܑ~p֑ ͎,xx5quoC('u"4c )d $L.9t?$\0Q ‚̷C|n Pݠ}f>g#Ѕf!8w + +W(|!g5q ̤+$a.9N )Br=H$$(H-@TPiwgpZwl!_t1 b v{ cbh01dU!$Ą Va8*Ĥ@= >re(>/}K _2AR]`O!tZ +WR`HR~E$bP +ev0CKq'@7' - r\>&@~ aأ+{X>߀8rɀ7(qVH pIj*$&9f̙!vh7z+bMDbGd*FU'9oTת+-Πӧ<S@?IH䓐0)IO0M_=_3[|5略3h5gx/4x57xk}10=c ֟.)~ HEnZ{4:ML5y$҇V'c0l{nj]^An}SwQDMЮ$M|[:A8n@,ҘHB>#/~|qĒ2U<}̷;u 3+ޣ&Op/Bh3Pxtp_t=ᙨ*рK_걺I& (NBQ(e(:\ Ź77ǽ#g={ U[Zm7SH!zʿE-!ƚ+ƛ9ji&"N}} {o7sY Rʳj)s\ΞMoBVkNŲZД!cR֐ȧ̻$VqSmDcYi@~<4VJ' s<0,bK%!dW"fŹbR~]ʀs> *SINf패';Q̨<Ѡs,AeԽ"xBBZuh)MְBXRȶ[ȯ)\.<9q]QMi$((H*"@V,f5@ !LK@(h5x92NGǶsȇ߹~z}c)̓*u96Ϝ e^*3WuZM?YP2r}mob ZfkVPa~RM|%Qz|Ǹ$~(ŵO%n +%ZnUSOPj8=G`ߡ_ҥhܟ)<fA%z)U#%ܫefeE䶉ò3. ҼMBZ P+ڰ¦9$P%+2-%&DqlZ`ߗ+ ks9l3k2"Z*?﯊"you@+a{6 }jKKKbA*huE!j iTo5&#YP>e~L`C&ZSXQr5\k޸qM>ʮSkMmeCJ)׻_V& *W"5QXN< @>Bsoh\!B-"y3$0T`½z5:<̶ɖøPFm[ÉZUGJ>EMʪ|oHY8T*Wy-$W6Ec-sFF*"odRJ,48X`f:` -ؼbt̡Bpק{+y~š@~,6<_ɮdUL2d tt[Z?tBɐ!䭐\oJީr1p {@0uָ]r]Ky뀨1dzX]ksTu +BV&*)LU*CqP|Ce¬Aȿ!mpLp~Wy z{ô1){˻O9w&)HWԖu㕧4K3!i03"Y3JJTϑ+ r|ȭ^:OuW) {hshF}p|f+iZ@՜#H1\%wc홗.:3.f$p㦥NNzj5y˟>?}?Oq$6nfDgpG p =I=@+B;D7xxK>ؼ04+6g|`rŁfڵCk3eO=IW_zFοC#fwv~Qir +os+ k cLV-&۞˲?f`;Dx; ejgA'зhv 7|fkg/] z ٿկ{x`),@ [ߙ@C 8`64f1ƳGm4c5ȵ4W+jv8N Z] _;{ z LpA8"4```"pP, RFC` +l¥zb'&jA'^R +4TxPQ HG</chm6F&Vjr +l&e +#n#D +eSNCCC@:*"=S,kP%;LQRBlt$js_%nsFΐـ޻9sG^xWSo-Tj}'润 MuyVMg/hF5DӠDdEa0$L!g*Si=j0DG3t9G.ߌzFZd-tm%mӅZ!?9rNGؠq;EQ=QGNZ (M4LfΙIJz{zX[3ح ټkqyVcW\YgCSǟ"8(s9~P~Tx>좸6xx!IM8JEo`iǒ7g`Yûl;x +ʩg[at5#}!UgєPp6i 6-)>$VG7yTE_UF?UcP=LxI ds0<Z@{-ΑR.¸j8]ECF.-D +ǣ_:N N&!Ƚ2~"RVws܏^ZqO%(ߓok"!dc@13E4wкXD]c[lظ ]lq|,úՙ3 +\+ֹM.}7מEIRN+g^3?*I1ބS8Ä́!9&1<&_b7r2Wi1_ì͍dIUTfgT6k^QIɷ<^3{{j϶:-畅w_u+7nJG騘=C<R}ZVry^).jpdI*/Wy`vs-q-[ 5gdBV.YMY2O(g6yK.omZ>a"^.#NzK\ g8@U+beV%y:Ewn_Bu.Ϩ<PD H)#LQA,"tІFpF RD *1XQp]f%'nf=G}s=WR*x-^nAIܐ84wQSQQ;aQP_B61xCTT0^,p̕_-]Qךnܔm^`UfWH+v)OmRIޒ)ܤ޹oEDBLH$ oA26.98]pfnt.*[;hQ]&8+e6lDzBY[Q+HouSEg|2R>H{-H#BK&E20\ߖpQ )qXt)*+4W֕V"ҭ &ۖg:J $\IN^vNWFv -h[i Q^R"K0T꺭bQ#U+,-}).$)" +&{d1pq5k7٨&+46r5 j:^q:(X̝),dEK9wkE5/snAph}OQQQF_,Õ2ڃJwfm4Յlț5{V5d7DbRd+>6)uSu墈&ކ.uCq~hН) +Sxgz7.^܃ZZi>5Pt:2e^iRuI*Knm7rKs=M2 JnHC{p OpCpC:=zW? +-4 ]@e*{磤ϖ)sg.VY97[pp֮(f):v!;ikw۪n{B.^R=lRMPzA]H-u̕IrbVύ>u4BcuGLBd.XPWvﰢqy7N}7{;s& 9:t}C@HĶQc$:2%@`u#BF6_s*ppqp5~'[-LjL.7h2h1=D[!b܍Y?.b/Qߪr#icؤ#7&s,17]Կ+_6dǁ\DU#c$&3+Y+&lU}'|2爦4SJM&-m):S]{ýqwx+}P2 +d.W)6ncmm,m +ib191 qBG|KV@E1aɂ:3jQ!9N,vP>'Sߨ־XԤN]O}&gI}D]\wa% R)i~=>BO͂82ٙ!.g.CX~خe6JlQ*\iTS@H.!y`b FdA@A 4 aJ"cD'( +(
Pϱ+߱}`:{uI ,c`#ց]{I|OdE?Xc{< +8b¯37*535.ClU4-B 8۰::paQpڱX'v1e| 2F9#a[ lA{̷Sɥ,s0\; +"_ h@ |9 fрW2:pb5 a|'&Gq b{̽D|^'Fa7BMhXt'=o) <_YؗڝW(5ܞdZnQcU!-[j!.z5{%-dp_jI:Pw1 d_hwWеL*D:臕fJ>Y)hץ(Sc +e&Ir2j}S_l_W- TC|)3I]':&ͺ(f^zLd/.XBVJ/)y+nd)˼hYh=w2٬ )vQ,yvi%)YaYYWCoadbτd`Π6AfҊ`u ؋M,hSbE nU/*H,X%%.ls>abAǐSN7=p w +%!9kųx)-vbE8{`u,= +*̃/ŖŔ fL7=[+"|WhW+BwK' ,:}mDss^R(shRX\)wPCTffU*'EL;mV1$bل-mWC_^!S~\[~ uI}q-v P߻`G)@N9@ΡKհSk +km N3<:fjm0ormڹ55K֤Uk|YxWWENѨQ?Jw0%wrf@Rɼe%ǘג3Ly)P@w_wOqץu*N:ڕyw[6~_U%1/;{xb ؅>K= c.Ul&׮VsǭX[-uMu^uY~%U4uyqx"*ʡvlC5ިxxŃJs`Vm\clTf3iwNl׶ݴMnc3w<>]لmqN +`TRiyFxs.q|r۵yyo띭}w8>9|nrolʖҵ-ˤe=UΧ䋜o)`"<#“QZ2\b$D+ mk ݾKvxr~Kqf(/]p6Q43` (; e /r*x> ].K< ^9e>gx:,fٌ M`tWDL+p`_+ǐ5|U"wxP w`EĄ+͸EQ"\!dAל8#P ܆Vk=!㼽ay4gTh֩ȑtG] ;z6& +,}sQD%IV%~pYJFii~Nu?V,'ZBsS` 9}yt{\T_b޼1zDw5Q]_Z|#x~sKn)$U9 48U*婄\C"⁒RX?"ZB =zOᨮFgyfG*˒V{3f{OBlMz 4eεFO >pZ`JUD/y:Ľr y̿_ # C{-4k-CF(^ԽfjppQ0f|7\^a3d{wUҕiM դ 0ь]}QNbWT.ŪUV^+1\"h:еg=Փp>j +-b oЫ*CH׵Gh(MAcj1:QLtwxBOg tZf݈kVߙ^b]jP!SXIsGN/l7O3y|-0?a LYB6b>@p-3(.7RFvsնD7ó2?YWyĪw6vXhŽ]ٖ eɳјJgg]ȳfPQ%L^`}a`aQ PD0÷Q )Fal7Ls:q&3sޜ0e \[%%I8ù s>pٴi +]ʞQK @ ?IoUWp㠻6DC{=7ff:47BsP u~ڪ`v? lo>mnVGA '&:n1ߒBӡC U(| YO"$=3!Q2 @ׄBz=HfX0IF)_u@wPlP ( PC2hM? tB"A +kSRsӚEs@a=2`8Ȩl3q}JCHb >$L$)^>8qZt^wK-uD'3Ÿ2q'vABpaRNH^ɛB~ CXHPCnnDOZu T 52^HF"$W셺=W3uЯGnj6{ΆF.f#W'~#{;֫e=֥?:CןdNvå_…VW.D.rah+i 8Jc=a} Xa2bak7lcwݿfwܳmЗH=_2p5YIr4'jqbjQ3o7>xDxG#G퍼y13K~{ԷofÆ_$TT.nTwR7\v43g7p$I42w7y Y<=Aߎ~m1[b~(h-hHh\`%li<?"ﻝAtWΰ)83Aq^aQYpZӀ4ۥWsN)LjK$4%Ygu 煵Dğ |1SPk_yd`ZT[0VFr2zeN +K<׭EhJ3y5YxS}k]|tDP%VHEfuIcQؘo1}c%殺9Us0clƐfӧveٷ͙.J[}FG]z%WPt!A|BT*˗$S^X`EаtP7)r>0Oc m@o6Sm9`ߨIvV8ת\+Urg̬-l/VʣBYNxBKdń3_ ܣگ逋"`~ǸCBGGAӢñG%8XrӜ+wcNg3de7 }|aQ$G}%@~HJQbB'Ry"es8Ba+z|tٰ֠iEU9H.%:!_YW˫mks{H=%Qi/dj )Բb-in({HWFG'5ԗ25e;8a\sI}iqp)2t|b +~VA `T;!V.J亻r'?$ +K߱!u="!{KsH_[p"$bP[*( b ݜB~xmuSv%2MYY^aS̃$0(8qKQ[Q&']%3ZZ:WtCY?֠ȺYwrpnvC}V}^8vw֕z&Vk}j15,(-aW¨/U V]uTz>+C4-(lA~*h7#};jdEqmim2Gi9%5\y볿_x,?:_/aa ճ`>GSʹ -]=m]]@^7^/dٿA0Xnb>/!W[cv 幷%ޮB:B:㦉fz~t.tV.=Q7![@$oGx(3͉OF"Ʋ9u5ctmim##?r>o<Y, Q}hPv ec@¤b=%F:ފ] gBgb=3) ΙmU?nqxkzq 7/ޜS'Xc@ +v>ʵ sH:D&u9_[sc>oχ`|mq2oTh3q6٬܍~Ivl?ᮝn9~Wc2 Ng9ឋ@e.,x p iq6.a]xj_Ǻ%,e%V/YUKʥ#LyFr6#Y,/<爯1E#T{'trcIICm׀759`w +ﮃ^ł_9}PV )x=χ_u1>FH}oM+@ lzx> չle D((`W% 1`A,H@Dņ(< C-O1D!ODQDĂg0;=;{9F 9PY0s C Yҿ#DHNb:D X +ACFr<(g3J,Z=X=OZ8 `] h%+"6!j&;@:5ͣ1n@hm +}k7jGK(]48Zw }0`W.e@~5Gn+jM :kRsG?:=@ON}DoG=b{}`]$7bu)bѽ5t?+f 5(F?C?b>`hUŗ`RwŮ`0o4H%$"H>)k xCxjth(m0k0QLɼLDcOWI%KrW߀|ExNyn@߅BV5ջ ]x)[,<:t6ᑬt7J+&BZ7pC]h2ehTsE9塡|(T7Tj +:U3PŸ@7QMVen)wr{q]yMWՌCkp^øZsƝ{=fKm`f9/c)QDy P+Kz?'\z?#qnU듸c>;sC V}ҮBܾUXfLXD%L3lw`φ1H6G[g\qǜqy,wy"y_sW8-q;-v\#,s:Jvv:;9:wlqfLm|N:h{u A!8bnqm* +[u_epKؐ**2,m7֛l1l5)0.7TJ6 W\:dk\^V2Yg`(vF#9. % }#cwJFscS[ŋ6-X f%YZ=_ڽXU9 ֥t'+mZ#PM88>(cEV~O8qT oDѺk6+Y"ʐ-ʑg{fzmS,maeye//L:}?>4sЬD}>͟Po ;`k@xry`A1Zѓ٣L2eit,ET-RBg}[~=h(1:ӑ (X2 d 3lj2|/N&I I?Wbиlqr1_5׸S3Xejf<.iSGCp" +80(ٯ[u^ȉ̘AȈҢ}QXqR9Ӥ'S E ]|j)ǻMk"-&1sT?pjPEq췍Ҽ3NZ,ҿqBj;(v<.@0wlpvL8!f)xy\ԨLȵ" uyGEuqwgfd`.誈i*e60 URUZb2XYK(nQ@M\)GO-hknQ999s{}b<31=uO\u]D1D[~:s[<ס='ˍykP0e P0I(HҜy2s&3.N#56CiuXShvNޠGGp>36o_kE QY|7jdYc?4bIQ4I\tl-4 6)1D")!ΐc/T+b۵ \z/NFŋ~>\3T`'ٔuy%&G,5E^rR!+ea򗤚a6IѶE +$}LR¤r'Vaܦ 7w 3wY`%Rf5Q|'&`_ԥ;I 2ۭ^8cGbt8Nşi kܭz a5_b[7 W`=.Z +׆]4T[]Mo:`+@. +L p? f' iA̓0 8 ׃S +{t{Ȁ>-fn)Eϖ:4@ro9tXr0y TO&`R3`Q19*hZ]nusp2Nm U{0C{2OAy +vP7A%PJ^uqW}@w&cN7sG80u +p>-*ka{l(H/xArA$upup}DwPA;6yDt3=S-iw8O.ձ]#Zr_`HD)PY^K:_KFn )kp9}5O= G; pKŦ@ ؋+p By:xyDM?} :[KWO21 F.~EG+#ɗK q_po-~#nT]:˪^nb +8K!N>C<O}'iǠd[[k;ϯEf\ wNrgũ!p/394L`""}*/@%Spk6\KÍ8†NQp: +jp2`9Nű yy9t>`:G}vm(/cH?5'Ip?P;2z4.c: 'i8ڍVW0.bfzWt[=h/ + n{h˸_E zyɓTb5 O7?OEOHhq`t Dg)`Cʘ!]Zv{*vkphsѦŭ!CΉׇ7OZ4gI{Y*w}? A/zPg&2S:Qh MP3}:5<@SnT6hZ4uuqUҠ%YVkNq+5WSHOQZ*HyYITꩤމ&8biޡ'H}1 +"'b{d86Gji`6D3-vv]m / %^^%^DR[- & +[v\^'_H {BWG7&3ҿ| )-F{lM16ͱhIbƤ2l}C<@,L\5G$jW3NpZzfyմyQG}*.*D=P̎NQ-xyO |JOi:D'mxZѬSQ7uOg x $>[TujZ*W+F^kSRΌUighUjP yj9n/L]ns!I!X2)!K CmJ,S,HNe'e%9ĕىeܬJiybLR^[(TĻ|~$A& \9 4{IF ǪXnZ㻨1b12h![\npI%\BZ_ +/7+)ەN}?&zAI(^s?dN~7_mSJ<ñ TMAeZ$Sa2s +[jfKS\q7K]*Ӵ'Ԥ1n},)F??2 J/W袙h!kS.s(N9]Q;yIq#IlĦ3Ein8U(1} +$pGn?cUk(b,% J,v-I.. Eu݊#ʘOʘA'GHotE,9g0@X3}9ݓT84ɬOOZqIP/y_,*ʷ8o{PzN-gߑn1>c ӧ#% iJ-,KRĦwIp^4;D!:gk{Re܋$$ӻ0 +Lg6)C8cl7FgaTV?x B\,Il|ଥҨղYeY&rM"<'"*WB[+XIYIoR٢M^s=\wD\C5`0D"83ƹBqfL7JHCvKCviH#iȆe!Ԧ.e.I +^ ̦{~F`8[֘B99c@"u(AxI$ %_2JF_Tf!شzS۴Ne*Kv +PrQ? +_H +\ la d5i!݉tOR r+ZJWޕeE9X 0e,sòb 3КB[m(xuQ!b#IY}XLa[8 l5N /xF6#n7LŖ-lڶ* joAe}u͏Dt##s*g16Jҿ< pnPBUNP6t>2 kgBCfQttR@Z| 01O'06 z? 'Q@86!=Õx-~ 0h兠V>xڸ\[ 9/G0+"<5`#Ha 8iAu#y㼖➼ ŜG;/"WX_B_-'{9ȍN2I{F(;޾^S@y\|N u'^5Mw6'݁t$jV; . ={\\ ry =f +0^-z~I8m|E&w͜>ɤDtح;DM"P2$ydIOK exJVғ;؀DW!-tUU񭸆2Gq?"G@ο\!/"o™89iͦ=zГQ3pkMrpqUFjFgъSm$3‘O"%Cpb.đh8!x ܒNuY"o$[ TY:Sf*/G|6Eр&E :=؝~@JDd j|<\5x]7\uK18 Ψ)ؐ<޷=||E>86pcQgvǡJ? +`>e TNXI(ћ`Pl67HCNI6ܒCHrCEIίx̲\fimc?p}a2lEa$&4lLY(6COBao/}\)A55J .{]8..]n r[ۊ(%*XԱmSӦi3δv!mӴt2M3Mil/2f9ߞ>f&mJ`OfO-'_Ʌɍˍ "ܱj}6p/{Vp\qz܊5)hF+" ӚjLjIMs"fÙ!v43gNsCܠ"\4wYSe}~@DPCܦ+;t/m"hUc*7'sMέdFNfXa젶 i{~0ק=hgnK.UEg_  yyBrpeCmnNSgcDǐނA}ۘ~#ۥ悺\noӝQ ~+BY_٤+Ш>BIN1@QD,60aL@ش æ4g"dGٌt*tUVG5U~B$Zʜ5!M^Z{&Mpݵ6W&dw*&]g] ] ++"\F5uWep2CiJi +zE{RpqbS#uEuSnCw}jwςb_c٘B5Y3xwZ. +וywy_sjJ`&FOy]7Gif-PO՟ +f"1j=d\?_T䴼n"[n~i~-J#0GLQ;;ZPŽ0wn)j2@eE~W9tYV2s܁wyu65WGyu7HJxZ)st~P@1лoA^nhRqp@P>CfdJ U!#:¤zq65qMMKr)=kJu.ӞF D5-ʞ[ +d!st#2ƶc8ia=R|+,a_؉pH0ç] M&)|II74eָLZqhcq=dLO ej=N'$$O`fbI"qH+FB3sH\3oFH28O1p#Mύ!Z-v87 dRLL=e\,'`f< )H\8شhlX|s/#~qxqo n=<9) Ch_$uh +ПfIH^6]p) D"\ށX"vŌu+XEJʕA|-p~I|gėPG@pS%gi9i%ҿL/וP1M}SQQB_CRJSNhHER !|dB29>eȲZfǚ550żmw\]繟њ@ҚCeSeSE؈xxu`E D994|Cݬ`@c\ 0^_o !(`$' NRp>ٜ69mV<Z[9ɭ u;yr)ɘ+ƫf0jRӢ P676 +}@R;Nl_lL:X;:8 u'F7yۀ܋ouQ`= PSy +*_6XAEl<sDw' L7;0x0ZSלV/R"ȭN'w97?=G3sǼBOٌ<݋*%_꺑aуBFqd$$o+%9V)6 *5 Gp-'.o Y]> C+"/NyYG(2ꬢ:lΧq&9[<`_Gz)s 1'#`uQ/Z)ʤN`uSJY1ks4r.f~/Ȣ!ӝ7:WGP3ٌV"uC.b,lN%3_gpqoZ躙Y<8I + ᧾dJQϟ0ԊhI>K\P\͜E140M\ts :k42JC斒e.F` J.$A"gѦV84%^:e^.R/NZ*4؉zzu uawc3vE= 2,wwȍ>6^X㴱;MI(M"pX2 ʏqPze6>WNbOr۱t?63/QmvU揱-xN,+? bIaJ.l?=*q|]?o쵘ݖѨ)nyfQ%*W`U56YQ1 ^GXmnzxj3%Gyg{GFhh:!m3;m}PcjQevlMv`7v9Xgka}9VoE{X^nA+'C %bY(zԿ=}bi}z5 56t38zc?*ð1ӱ#9JYXR<,u*BSPۓ C%(Cg( +<'bg$LCRimE/R. aǜ|+W㬰@=ծL?2ԡHWO,TcNiB:[H+~vHZENһ\b͡\l{Jza|7[ +Θ_!90IB|B\`/.> \/E(TL : <&JAigV29Rz)d>rIv!cv RC⎙!c1# !a ؐHĄ +ѡIBTh0=4W -mSL +'-kzaRYA#[]dK3f H0$h\FFhM04ᘮiBdx0%|09_#M273(Bj+7& +"0#2L*8y2T2E$\Ct2_ۮfFmo^R=|yߔ-}ԋRR-)>Ϝ"3*{$efEim4%wW^zQM ʶ&fPndXVL#1Z[W,2Z2cI>&6j!<@ۖh!Y>q4M`,e,x 9*#fT{RclO8MIE,%eF+amڭku!u +j[5Vm8պʭVU_Z-mߺC[[7䷦A-Vsy\۾HJ1eRl4^kЯBnfs nԢ:D~aj^)K`eổf+]M"ˁ샓4(-wZ^;ir) 㞓nwF[Zi&sMk.:⽏B8jijpkxju-HN~spRb]05g9#э܆AV +xE{M\0pvƎ4Gh 1.::6zIù:bQG, r/ֱ>[#>AVG%h8ٜh[mӝihml҉GccPϡ_ONIt=.9_9%tzuR glf13] &;Jw>%}iBPWf2PWIU̫8rf`Db405nt;xZj~yl ҧp>HKo[ȝkrf>7vߐ@a5쇃L  B,$B&'fѿHi5\Buz}M=żtC:~5V)@C(M44sћ 4棱XׯuSDg-:XsE]>c}X+]`F>/jh   M@'_\h(Ac{)ezO=lK59cnE鄩zj>^TPnBHȅ@B.@!B- !"BAQDTRuκεgzvvnݥ]9o|=y2|k1;nmmW׆p%f.Ōb^pe^wqbpGX}qQ,MB!R}[;q+67Dĕ8.n0np̆vr|'p"~b!MX‘8p1Slӛ+,ejwѽW6\ڔsxiXJ$+܂d'wc.#2-޺[b_77 I}O0vG1QݟP{WH{1jm }=]8c,Pxub'k&j~GIF(}Ls1.è( Qv 0 .E!qbz]BgNtW2)ZXKM於C~ʚ%X$|@5敏)pS=e勔Ǡd#$Jr#K*C@ZԂvenx:) -f$sSk48?&"fE9OO5_{Hcq2Kc^2F9)_<Ay)(ѡ]QVE9*(Mp+Фtl ;|Us^lcQQfU=|ƌsdL3NY)GQF@:,xphRRW€ + WzPW [jƙEsjN1Ǩ}|H@1jO'Pݛz49D&N7@9z_ЦG t|4j JQU*;,:7:?L>fԏ /1*Go6Gg!=GrO4\Q|̒մoѽ =?eiѬ_> Tx +`5\@mj#5uiBuc:NVefZq1^Tr*L#NKT֬`o+&&uh<͔zSy(CC xIe_3LVe(%dtSV@uʹ[hUIѶ +X6# D(ЯvB / ?02xmY/sd?q5iݧg&#?E^`!! rB*d lnFf2SH/!-|H }z+NRi2Bz'6@m W7Dd;灼i06@0{]1K%5edX+aXo/m` ƣP;612@:Xvp {KO"ޣbrϯ.˥*4q~d%dԳճ|$$;G؍=g~Iރs{Ecpnk*>'͓|]%5!qw4V BB%}lN:PBp$aIvg9s~DD$<Ɂ' =Q%_BfjDd{=YpN')|FLN3,19%]`aB.(}INPWʤ8xd8Du:1>J;돟Ч[o pp p&t;1({@}>np/p_b?'v5Q5M+[4[Rjcr}Ǯ{GﱷEsS{^ =9כ `.AFhC+qrCH_i!eWk2[EB ;ɳtUvZ+~~vuGMD]쟀F3A#bÎZ̙m e|??[#(FXI 5hHKS?(4HИ9hb4qR<_Zق5b.@dP+^?jFؤsbguC |h4)ڏ$/{;vk.rrkmOqR-Yۤk#ވ ?;@_e.hza}D Bc>رlÎر;ꔏ<-zUv5ZVJ*T)W x+>hv@Iy _bh4ICgV)B^fUllF-n~TTj{OĎ\봷hh{NC-U'5vk}?UV0īܐe-5LbCfaJh*w\*v:"*p~9.ϔbUnܜoGEچ{hsVDh_wTb-pMD(9IQ&1S9DqpŚjdt/ a44ztc-Mh`yн\g̣:0+*"EPEaeXT7( +.ǚb&Zq_c5֥1xXҨZMD? \{0t^>|߂3s1TG9y%41W1~PŌV1V$ٍ6es[2͔-WJ3-WAMJ`?fr1 6 k`T78bEqgO9+h`U9Kq&(%a,pFIJHc0'+ ?:cx#%S3=|K!1'tTN쉽/[P%5)J)Iq$[d-`.s\ŧ<+SJM2ZbSI Qg[)#Si)ZdQ5DJH5ʜ4LiK+Rm9-QtzƦoԘТKj0;1Ue +v~ۘ7m]Č~2g V|F2-cY1YVEg56@cehKoPxve +G +r+^eti)̇ ߶LUvyWMP*սj4ʳrUS99~nբf@ pWKXN/`^ @8)a3/ffl^˹-~**uv4{Wnuٕ-thFt2K` Py;Nn{7M.v77\ĵ7TN(WRjgpG˽_&h'?mM^!A918P~!0qGBAlp.|7ݾ\Gx`K:9:A$'1 +G f:GMhI ކ* ]{.CvyH8ZZg8 U|J}'|/Fk~Eo#v{n;tk`3?M—Nñ=]|m--M< W8/t?úB9sIm|y=C魇 +ЏF{ok:KkOB<u:=K[Dp\џDlAOЕp@F=+1ɤI *!q|@#q8մNjB)odJOXWGta(V2:h䳣:FGqK]k!*WmWxvjgvBm1<{/H.ΐ}"1++YO䱜LYvNATúuLM&آMG2ӤO<JpW0`6``6` +$&!IsM4I&kf]zd=Uuӎv6դQҺN:mkUv޷dz{>I}R/xW%^սŋ7Zʥc:\G&dQqXtS gb"㙏5;e2|+ +O =.V%?{ewV,Y ,de#l33a*pN79nek4y g((FsP;."7)R.JŎ].%Yˏg m K(dXѢV 2X4Lq턶GIPݦ2=Ke6ҿ7Q׾H_Ny5K/Ib$SCrM6MNJ)&X:@w8]eos[<7C_kҝ6GYyҾLh_Fͱ 3k6Tmqeioi⧣"D{(Uh:D,xlO}fۯ_\DVyFWf/k\2,'XL5v IM[aS4,d +48/QxKEDd'{VwQi> fѩ6n5zqmIޚNuk>VֶJTzx#f(-Q[仗G~C(7_eJ"(YRZ X;TvPљN3eՔ1[(80EQ`#.x O~S +U..HgI*1'k*j;ʃ(`KO>=&z(쭥z MIv Y =DFۤ~&~OF'dDwK렴ĔDPKINA? L!w("d U9@pA҆GI#ydGΈ$ ?KŻ$ }*wJkYEHM%ZcUVQ[cȘ06HD:)y$OyZ'$bcxMćOb_O7xG?#~<Ši1"ѡ5UIJQ٘U!}z I$m8Ms`/68e|/Hu^dD~@cL<0""2 +* 5"(Ȧ(( (8* ++˩₩1n&DQc%i[5ǦMjԨI44>99=Ǚg}T:++Hϖs''- ŏ;q?>Əq)S&ժt"_u~uyzYWz+TXGO~>/~طb-v7R(=zB>C,N)V|^)P+[]G9DFx!Ngu%yab Qh@#`52yi>ZUƏq@Vf*%cDuX;;M,$ǩW5Ġ1 +㱟LVUG$oV*V[rcգ_Ks4g [{/^g A' +hEc)hdc)E +ZV,""[.v._iswr# kG>>wpelwUSVw JhYG%Vu.ZꚢZL-q"|Y܊TVjZ֤y-*s?RwTcxJ1lD%G(1,V aAي /иrF,؈lCuR#~=;iAo m +1 +ǽl09C"J (EӸъQ)5UkTtFF[4b0dǼa1|`!vS\7ya&po +K#.M ̣>0dQvMvD}}GEepcĠ`Ԉ\Ƹ5qiFkUظ/MjzbNs5MSTk7IOsf`f{{K9YeIPfRIIHJWzrҒR%SJMJM]j%7)MG`A,W}́z@y>9JTqd2јTI)& +`ҧ)1ݮEXgޭX`>x7e8نV7m\30*ǔ.SR3(;[9%ʩVdLE(}t jK4l)w)We 7v2l {Emg6k|m~sn0(z8E BװH~Rr_&,K8p.+*.]tqíAaa= Gw1]_5 ͩPFs([\!k\>ZiJɩm*si-䱎jb`;6{[ Vf6SDEVFr{ 6xh$2.c}cc}ǹ}7TGKH1Ia1y5빑oz v^x2 + 3#jrK y36 Y+0;g6~K8N[ u?E\vih2@o!ނ18I59͌# </W/RK ե e_&*F;Djǒ7pjY`\ U +\eN>aFї2gl MVżuؠu <=w'-]U'mu}r uvxa}k}Ӹ_C<ω <74}tWE/JD3|t*Ш-6KANw}eE|y\Y"qyW(29?9<{=;BDzQDJ^Gt<ΐ))y|X5<\i0w|G'X4HG# |4J=ͫ O[;i$Nb''sqbױsqiRM6Z:umU]K+T(L\Mh B6&B Ć m0ډ3??~:w}~{cc/V0]b -|Q_75O op}$1s4WG + :kѡ\i5ϫ~j%?L FX0i*\ъvif/hGɋ*ɒ5Q&>d +eEi׸?-Ye,-5jԪJ-ЬyC =ij׌!ƔiM5a<NjĮ1]ר鞒ה0F,Yڬ^FzЧ}c~,lZsLf1;5mnДEami21˘F-Jn\U c>nzRqU Zju~?>./8l>Xz{f,3qږ)Q)&iU֦-,xwnm~LъksxUa +WާyEit-<3M2s36{f 5dw*nנݧG=9bVr\Ym(TO5wU:koÇgZI"r=I8ce^FːH_mUPY^g8[R&Au׎*X;EuTo͉[=?kh=Rioޡyd,}TckDָTߖۿG.Ljj7T2|[/iW?ճ@su~NB/ ]m|5j RC%w{jc@霑sE՝GT*^eٻހ_p7ά濏YjN~#?yJ +ZUVnTTeOLCS-isCO,| $[[&[=>Vy54ИVA:R#Շ}…rn1*bQe\HnUCe٢CFS]C;'Ḵ{Mb?9WY73hzϣ3N Aۄ%n໣RU_*KT>`RـUA6 j`#e )>s2/]_SIǴ0:tf|0^ B-'F)ՃRuPAED6$dLeHKɘJ 'w([*H^T^r*7C%~(cFgJ D H~hObl3ɘ*QIʤ&*Lժ ըT@aتuL.EL%*Pl܎3% Ce{ˇvLJmϳ?ݿ}" JH%:bv̠RѰ$H@phĈ`ּ>5&ym xyX{g(b5 s/w)1WΣ0JWAJc6ԔG1 #uơK?C"<˚eße.o-q3<{>Mzmx_ShB?ʹ |5[By=g®r'oϳ.0gK2{9 2{2r{ 8|oaׄnZr1xvfK04&{CYi>>椏 ~q>J%?A۹B>zƸ%9j]cF2ur9ACa?/~곟B;i8'U9@mcAg|FW(ćW$ ^~Ea{3ظ!'}q=/XRl $Ip.G&& ҝjKt>oKOlH1ӝS{7$ۘ~S M̫2ґZv>Ϫ@VOS;tF=ğI |ݞpOѩye \0]׹ i"'kL>RXf)'Z:%t,ev+-H|';!.'v5LqTa'&3iB/mt9.hXIdn9L?Ev( ,r5^qOCr1/$v9u&q'-[|c!.yds.3: +On1.̓ي +U2E|$E/"|,||\q7˺LOgTT2CeO8[S6[.R^/i8:4D# <4(GJ31yJ}P\M曓Tp$:`v [6 jV^?!=8-:qHCh(fSwԫMԡAS4>. Y2a ݩЃj +=!vA@{ql5[=0fO53\6;ܠICtgUaɚR{Xi Tkh79|uq 5D,P}JEnGBTaT,5VŶDٜ*e/Hy&)7U9]N%}Ik2*#\gsó֣T= W|$^h)Ub{ +Fʳ'+מle'I.;FY)LTc|Pr:#x>3zhL9eHc_#yVR!: qq)ˑLS,yJO-QZZRL#}R\ z@IGeǕ6|W<h5 ћȅL|}^d+ +W\QhŔX]tȑ_$4(c,J*t=TO\K%7MEF4 gR]AQg]wEЪ(* +-, +BmăD3iFUi;1&ͤNkNc̴L56i֣c,d?Y罾}FL+`WJQdv|dȕQ Jv\*C ~;+ιOcqX^8V±`>( *id_+;IFYIJdT'[y*u)ڋ'/ыp| <<_h&q;(@1τ;~$J ~dʼnJ**@0 :3"$ * !yURxP JlL_qÿ~Llu1JXbPt|R.Fz#ìCH Njų#aKgpK-/p +PH9ĜE̓}O?/Q_µEgKO F+k+:w%KF.(\/Qu`;ϰ-DMT\~vPBsy&1O _?f4`9VAZM.?Ppxs{Ez3r [d!m\@̳p}jΫ)$C7XlaX?X6N`LM6s6U|RMySpw+TQ"͡|ի^3uK a·A? XWY +q/O=r, w}qKCM~'q~g<>,O ڙzb/ku?#|agD:a/Caq0&Xku7F4(8!8G䠿&M sA ";`4"hu&x`x?NsfO8)w /:r΄;M6HhD9pɈH#88rpu\,b%% +~O +y.!MwAQj@|ν:+OQ8|H❧I~E?"sphBp;C->Un3o>$}|QX5=:7j ~{=Hj=k? +Ux3z]W]Rt+pk>\P\fFi3[GP'^uz|:z:~CE0-{/J'i : A ƸE+Zd$,%ض㷋\DKè!A6]Tyxscu9/pޏ#N[f|a +Gb]m;V]a;l/nvS<7v#dr EA+|2;17bۊtf.v#ʎ^DZ=B]F yBz}d%,ã%2vb\lQ*'a{:sυ.#U{~=7QBy5df'ީ~.=$8#`; ۓ=beد~ ?:CZEKo +rzSL9q,Ǭ`#vpFHo~:b&'2B". +8p@wtұkuԣj .3HxU32_ Vq G-*3VÑG&ȃceTY 1GT5Ii +De=G(\jycm+U5qr ?'L84^zJKXk'/SIF-6X3k,!K.l-HWMbHQuOzU&.UUfRqJL/tBEp |'6\p-^~w[62UcJӔjTM3Te|S**7WUV㖫hjͳUk}Eso*!=pm`cmzk.|q⛃SbUeMRŢ +MI*NS5[ֹ*ZS;IyW)7urR٩O+fL9p{HC +U |w*_ԖTRST:A575Kslʳ*VDEʞT5#}2.5-cD55,! ¿4`$|e}oJx  b I5AI*;œVYKfnVbUQyUۺuն]ﶹ]n9 d'y^z|*|̍W%Yety-Y*R OGrjU(Ek +&-V_vl4~PVg~”߬8Ki̥*PfYI(/TzT) jhQjE'Uo@ɾA%;Ċs2T\*>W?a;Rԃ|ǤJ pϊ|THپx&')ʨLiԪP*JnRbuDŚXFwlU|^U կ+|DUݬmo W +TP *1Q +<|.HF3ńٴF4P(NiO;JN3X3.kᡖ&lAĵ)0(41{$f[3K7E,^mfv)##ψvl/ dx:4z0^oQ&R1&J ȵ Ny=/亭Mԃ>!g}6blS|s>imd7yp.]6E,`c 5YQ>9fq/r9br9c/[yfg0% .mm,o:HCYk7f-Pl,`'&'ߡOQ!zt~"'(~sbϫ5*]Msv,!{_3hl<&Bh-TlDŽ0 ň2=r?F(8 +a:tPuVr4%-|4.F&1BJg蓳q\E?OAr3!pFpvR#<+;<au:Qx\(.A]6}fJ#+{^8i=syS~}=*:+G /P]Wiԟ%.~J~B.i\:ops0^/c_>Q\f +4G5t̻jL?~ʹy -JCxЙOEh47jvP}hũ߄3,ji0)(' +L5{ #u̼M`pEWhT՟W<~`;۹v0Ŵi%mx} %rǘ as9jj=7{L`e R5:%.Z;}Q`O#6Zm/u؞{݌VlEݥ Te е/iVқbX1\G.t욱k.l{]Z쇰V+#]Lb +Y:1~6ktv 5bׄE g?RX a2)snM?ӳٮ:e05&9(Fd}{\,XH.&=Fڍc~t!셱ۦv,n/f:z43UaKH}$A+oX&fp:9/:jQ6LC8JdRruaĉc;ǗN8NvlDZs:M$m״ K֭bBJAVSV1Dm0؀A h*h6&.ZQPG'e=:3Hì1V*f젗 c%Xz>A4lsGX 㰔gKH ;;Ѩ$:u42to>.& zg=;6%ʯc³x/U|8fwcniL".|5ը\nsL]:Yuv0-WxZ(m٣fA,ǔVr vM{RaG^{jSWKVZliDҸZJJ[;lWʺPɲ1%(n۬mjS" +ۧ:\G8N +6 +CC7]'caVDY]-vJ~%uJأjw)UԱ@ 1E(llVG!~*h<G +W^k[KBzNUy9-粼u7 ;\MZL3v@gi%r1O5m + ջ+rW]'OWT]HU+ީJ.Uq}\Kryr{oj'荓@.pm4$x#FE[תסץjWU DJ[զ~UT㟐ۿA |EFpJ偋rPOtk#Z!kR]'D~vy*婩&.W0#gGڅ2j<4)Gh/òRYcm݆]h44O#"YePP\u9rWɨUy}4t'[d"kdlUidJ%#DN *\d ԿEسA,$!=P ˀ91B4B6Lֺ"og4t@ mM@mݍ>T𚱮ib8d6cLll&qc|-0'3/<~w4\|tzFaɪ{Yנ6t-#Hb3ı8VjXCc1dOT +3oce}~z.hE75L\=5-Ch,I5$so%{sIFMı817v0&;XTVfH3׆A!s++z ))"ö[/:@ndwt/ ıv?~ޗ}S) +kyR{꣯s"!Rt{^sk^nh +Ƃz8K!Lt?I!q8feep#TxplCN.a0UXR|e>oH])a0K$SgX'0ٟq%=y2ղ1@ۏk#VR+{ @^y3xޔT'Y{.o?$ %KE&<{ŋsgW ml}y`}ò{ސ͚:Lm`VKs%O,~ccl:W {ś4썓dŧpO/yC/s /d"oGG,~~ͤyIKLWW^/}_%Կ,jg'ހ Ufyw?6sZ) +:2qӺ{Esxq~&̳gcۼ8m~v|;׉8iM鑶뵵)F=Cݠ$@cL ILHCC􏩈C$PP}~{<$% ݜ73 0(_fѯ=MgP^ O߰y ކ!$=~7V!Rd cse e:#h$>+xyK+Dgt*sB?Lm* у_u]S25t,v#Wȑq?>2S{R#aCdC/6k*< 3ϋJ\;-[Cw6Н@wY4:0 Gt7)T 2d V9-hm[=c0g!X=GG xl'[p3=ѲЄqQϰǦ![[-&v؉c'vة`;fL$GS\VY<:ށ(Na |ayjiȓ*ʝʕ3ݔ=$[愬epf(Hicc{SP2(:x$!(*n?/UK/w6$gGL*)r F%O9s* rg}-ckl@%!4 +AhߌM-]N9K-uma*$MG+],ljj@iCePPo)CН$PnNS!6J@e4U6]?MS'hu>[w4qu:@zJʱ{-hAz<2Lrr®Y~ΚE~A!ah66@A<0ǀfq&m&А ឦ ]` ta/)q ĮQaE{HYaNaV6 3]Qg6{9d7l[ Pb F +*e(P*SS +J/Pʥj-2 ʴ:ڱj 3Hm-ɞt;oel?V~YpYKbr5 c̉ջc,NY{&Μ&38]p~ᣴX,k:gHL6}?ѯ' v ?mI[-~x;gr!q68wsΕΒmQQ]·˨#rs[ 7c?}&{vdVĻH"8sIKi&xA;.Gd##h^e~WN0?HH3(qe3~VpNEj'[ٜ;nG<$H9X< WU~H<^W^ef\. euqDINۿ^p᳹ϏU6K<`,D$+5>>ɿJKb&>f- | +Ol.>IQAaM2z 2zQ{u΢k~8 p ޿z]uq-l$.%~u9Gem~~|?D~bz":'~BiUh +^VXe]SNڟ&hq48Zj%v؝lj~>^n.NC)u}v!~D_v<mv\pǝ;vd`IЈ"v;;eZu&v;#bl/"Vc(p< 4z"%kЙcp_/;muiG:ў؊ @ENA{;ӱ;arXeQÛ rW+b f8S a@䩾";=}ll>B~ *YoaT1v|*8=ط{Lcz\cQlz+۱ݍ>l`o6 ;s:>GNU QuCt~1lEоkپ Tc ~o~;@VdjYdg:YG-e:5c_ ;~σaWuMC,lr2ژT2c^y;u£)TE G7Y.wmkUh9WJ4fy$;B5ur%X| EΊ}ṗs&o/E̻,HK}ܥx#+iժDb񠂉jO˓˝lSMG;lqf܆i I|HbxSGdQh- ϻ|Iy"QX+3SD~ +& y24Xr5 9gϢ)K{caq+X³Yφ$/"\Cedj(fsI>'ݲ=&=#U0?;ӼMvū_nF5#\O&~mXflؒ! ||e6;A+h9/)>O&d\25 +r73D V:HJW xmǶAlcoC%K"K+>|pN+=`hiy׀)ޅ~F5}faX5 ZZ" +nUƱ3h:Z+neJ;=HYB6BIH@P !Ѻ/NT;նK2x:ɇ0p=!?}f^LRpφ`@Vr@G Aw"0<A!\ŜԪX<71 1 '#hGw_C0" 5m ṫ` ",B",BPGbP !BpS/ t3Ϟߧ"$/0` %:BrXa`F6;XApٕVb\r>i:_PK -:G/Ґ9c+.q|h"|X ~5.5uбFl 0a|x=u04.zE4)x C$Hl- yױ;'jn i\ W8tl-бk؎nA pNlEMlaY6{ר` +Y;y80_w97=Ecg@Ҁ= бQR$Ή {P1j` B΃Vݕ Yk`Õ(,7U +U+'F|` + ^EMB@n/+iQ'B/ paT/D;C!XB"0cr>Q88/l0݊M?xy~n07|cǎ0q)SMs^(d^^2l/WYn_zWl۾ܵ{"ވ־o|#G?>3L6ğ=w>1)BY"D-U5ڂ¢CiTSźƦffpvv]|nܼu}ŗ_o~OD%}y1<\'_ gK"0X8d$ D0QPp)#`@L6-F8n#mO@zH(=&c̾dݽz~x FEyy = % G X'$`(,K?W-=C o"[ ;=Qo;p0ȱ4Ï?!Idr -bXwAWM1 0 +z޻}_>xo=z;xɓOkMuDT__ba~CٖsJ:CR Z G#e&\WfHKi h0a@À 4 w|kfdKeUh_ݯAųs94HASe *g)AxӀ n_ToO*HSoTb.W]ޠZA Р%4(ײ3n膆>nE$YL!`*_mԝ/QsР 4y"ySIfuaƹgc,i0,5pCu~S9Ѡriȇ۝+]xWY"Z:ӸdM3^Dv 97V0N6CC4N۝#>1tdBG*@C'ie$5hͥotРUrS!\ʖrz$N:Ҡ#{脆ƒn#Hi КʷkJ +A˱)sNy6K"cwgI=q:E+6 Zg +Uo-/4CTРa;rV(ՕБu9'_4qbf՚ *ʶ̅ڸ|5ǢT۳,8Ȅ#Eƾt^鎗{<6XjwУ-VZzQQYkF}QLVנϋIh4X$&}49߻w?cW{YE˫}?Q +˱lpWDL|rV\`ƉмVmӰi4l6 m{Pdžg0|ǐ0aV]ց灡F!ʺ[Kn۹l{`?)`oh@lǧ"sf\޼-RtɌ)Nm-në= +5e'#1=0htHh#EAg"F Vh•Ibm0;;6 7`2>A :SvIQĢU]1W B% OXoL[n` `Q/c×hޫF'Jcs_+!DtU3(˗vjYy`xN+1™-x[VJf AƻC),ȗfjkۭTkëK/ck$fLGz(6lj;^i<)7m}Uɰw>&t%4aS&Hsĉe!e;l[԰0ݸ/WioƮOW}/>{cI_ᜲks,p!m,g9@Ov.Rgu6A$Ⱥ[5X=ښWǖͯslwrl$&";$&,aqJ'=ʲ[_vwMæaӰi7X?ښc˖9_ 0tJddD'%x:,&rA>'>\0EEh`NӽGWpkz^`x +Wc"R,Bq&<$Lci7_uA[=kV};Ǘ/ b$fǢ* ˱\PW@i.wEfx΁HmjiHW#-]`0(̩ IHL` HwEĴϙqrxsvB@E͌:yn8~ ^I3mfځ6MmҔK IJ qCwI֣yGﻭѾobKl˖%[^ p(t4uU}\?ɩk3Xb?<1{B1 )ʠ)u +e;5+jK״4Œ^S5x{z~q_=a8 ie/ŴxXj(Q@ӨʨVf =[rSPԤtuEhx{~ {/ͩ0/!=k[8P&ڪY V $7yMRULMogn`##4n%ubD@tPf*haTIȚ^ʸ,oe>OUq x -"8g3h.PԗMЬ] U,*WPW2M~K(d+\+x{ڍ^o_=NioYz!pg'ئb +Z(e^ik{dEDUۆa}B{_k_ӜB3sޔJ(6y +%<$iCPMAcqd"mnf:p~0HA\^0K Ì*QJ 82Eg`*)=P3؏6r[h/w`}o羣=\[u᣻nj:|ͶoZp7ȗ|ImKu:mlB%a50as5ޱwDGI^{Ivx\/$ٝh cD,IFIdB#mZ47"TՁ>m3V?1Yiޯ-:B}Ky/eN(^, +юd,A#$9Z6mtoJZmio=aqS5ݾ|OӂSacO0.v8hx'#TQ*LIHLʆt ޜYޖ~0˪a +аm=ć“!A)# xB1B 3QFg2R!@ R`, }owYr6[iì+auc71'R 9#lD}qNܱqZӝNUzuuk@zWEAAP I\Bx $F$@BȅpAEVԺ9;m-ʶ?*9M8bɢv:jh"(VV@ߠTei4EJtLpavwk}n䅜4~1+=n*(NU +<L;sYINiBx6 +_sZfFGܰZ)HB':!TUr_JDot$ H\$\VQ"Fa]|VaG ^j2#(Q6"*r*&!i"$]0 k A]0ݺ4!>DZр/rz[IV-9~`qL45z]ECmdULDD](ՀOICVt^DA$"C V[+{$SL:Q 1hG 5M|CF^kʇZx3UAPi/  n҄di=ۊ~i+zd%C6@>k\OX["d>Еq]iB6gx;iذ% +gd9 $*MM//uxUakfR2ȕ\o`*X( 0,OƤAq.<1*; O[T{j8lQƒ .3&Ba:A8/ W=hS g4IC΢/}ڐ:=kJ]* *8l]Kh-nH6j &_ciS 3Ҁir`xaؚDy]Mݧ 1M&o +Zr-s.j)kjTAAdGO۸7`pHGܤM$Հ!o?f*wm2~\?h2b۩z2lnʯK @1'TYY0FG)2UhӲ4`^2nK֬f{}Vm&pҁ-ZwZܥ5UUz(ԦMjJ m3GrA A%h4 `Z ЭlVy1>g~ |y؟~uG? ӷmHozޯ'|%:WS 8#^87Ѐ`SӏT]=r{L&u~C*gN{i%8 dp?3 x \aheeh jOy`~RMOU!KrUh>Du38lj,J0pzT~ޡ{&`jmյk˦t˸("R(HɼX&QoAqq˓2,ah6EeX=7eNަ ;63e0uOɧ4]jnH"QRĀvߌ帶la,/1 G#Œaܔ>ehi3~1k<ʞ1tȧiPQ'5D^LRMl)l8q(˛G| 0#xeX+)z 9Ys{xJ1?o'ud^H2kq2,9ʄq00|hahe>o옵fϘ+&;jpQNj$ +%h>鵐ifqfb5\Éߊys&``1k{ڦ4vTᢁ/AɩYL"2B5=+ v:̂*;\q`r!=\= ycʚqOZO:ᢉ/),duPbM97Fz\Wjz{Be7&H΋ ( un̬uyP>8Z?]'[E(fjY1)QUoh"^jN^l^$oGs4o-Ҁ28>u9Ƚyhlu^sKO3;(jzIyD. As\5KT1E7w>u>3mu *].NQ!iWcZDX ޲=7B^UtpQ+.hD2-hM;[l'Apd:d;,{OHgpj]<5jT:hCjJ +]QI%d@ [[ߎA;.}߆w[|pRB\G;A-٤}SKUT*K0)!D=eRoh`2xo.cxk{wt#;]ds=c?bv> k6`B:EM{MDZ"VE +Ӽgwo2oM{ ireӇŢ#3PS + }fj;8wym>3tE`uÅzAQlnwG6{xϫkE7]HH ~5_8ɯs뜀gq+>~?>].Lm`=acܜ>"ˑ~RJaiVUXaS/%(\bxa@ @Յ e nH\tzK?Y)ƶX f#fHvuqҨFą^DJ +a]XH:$?y.d_Y«ѶOo~~ZJ^]rrj[Eۛb.A\Ԓwͽ xYbN8ww`{-CplInF'LǬ/F>-/,zTB^O>{.V~1vtnYHI׽{Bc{C: >gώP:}$%_z^US~nˢeϪq%kҔIe?R˒6^L|,Oxri' ޥ^y/ >9}Ǿ+22AnB:@$dPɈğ?Ǐ۠d~u9;3'ܝd}/Ds;d~>O`?T.@WY4v,dG$xPt2\11 ЧO| @<(1>0nN\x??G )eUMuƥ6-k8b#S͢v횮馐J~Ү*`wo2`i(`!8):W@KD|Ъj){g3Wzǫqdq 1>, Ay-"8YhfNS%o_%B)X7oǶ;LyeT;- DA  p[ZT ͷ4zS>KkL7tDa 3fY`l^{j{~8 &x@ ?= +R7 +EUne2^dQDLr9I[M#D%@P؆~?VN8 o @A$o @ (pM@/6,qkًxդfu㍼*d %vk\Cn\ӂ9Xgh ?)lń(9 +R7DkPPqKf9T$Y?. c(w 5A3xی{6gsv` ;llHklԪa *,ђY.I38aOr791fkpoui6ٶ0 ( KJlK-Xo;_*%/K8 P*cK3\iaY< r|^|ǐk2L=>_USI;İ 6mNH OHT$+U=Td웒rl+Z3! 6?9(zI!73`zѯP^e-'ڜ2a@d#LҖ*1:HFמӼ(/J pEHy,pWt:;7 ^)m.3ȷ '=Zs&6qg +6q[ͷOG$$_py"!hgT6! !E f_+Rl.[buũ@36.}"~'>]W6SL + 1f񌒢Su<*qOhfuqi6gAm8%h?w=Oe4Ĕ=1a$P[k匭sH_g7)hv!oFVϷ0&96gtdul`5( _YT8PG]s߉5{4;~elH&{aL0Ejm<,P2|sszl e1- +?N٭s׏oPʝ~w8 JW14Gu'C0VЮ#ԫ%JFWV]R-fE`%la*2 +& 7Ym((C U5XB~dgr[7h~ }hč87w*A?:Lڞ64^or]҆Xѝ&jL/RiYvCA)Tu6Ae} +{48=?pkbPVg(3]BGiK{hnzicgXeTCP T!١} փNt[>59w#;vމ)/)+F $ev+Ӥ(󻒔.RPtSj]Τ +eGrJc(D 5f&P}j-~&swl&n.Yh)YQtвE~Nkbr[iWra;=VCjRic.TڄjP E &P)46_.K{OkVW<>D:Ewa>r:lHd(qm6r[uKT[|ks+AutpP.0Vhaf' ,լR:!]: sep1"@L)FK%tەYݑ@ 29!kZb.zۖ7.nޭY["B>ߝ1cEGC z)?"WWc{5: DUՄ/ +jDA?iW7lZ7ʷ;[%NJd&Dr'IY\hR60r-ʺ6WC`}UI$P,1oDAÖ/V:eņ-`,oY/ݱ)|! 1iTܽشDιt^73h0!-/]6(֣5~c#턉ӗR05nl:CLy! a1Q_sOq!)%5#03g!0̃T2^6:ע4C_XW L: ip='>sCa@Ci4kP z#T=saTؽ;`fVg  ;`xN@vvG! R\!pJCPy8Otغ.̾߄?m?.N8BpDt=~8+[Z!H[Ck#`X 0- - "dl2.b" >c @gaЫ\BXK&=ה%?}*_Ŗ͐iŢIbhX<" JFA0(&~> C e Cfpc/شLVbJ-?k.A7_"NDˊǣ%cƒ1;;AͲ^bYgT2Cb!,OK= yЫ7DvZC&3O&L%Hq1|4JYqZy->i':OJ|C> 1d#LĐ3ѫorٔTÛcM'M$cؚr]0IU=uf# ȮZT!΢<0ZOsjӞqkuQj-"eA` @XB$d%!@VI %$lj@AA VG;ߙuzݼ٦$DbRfw9WiQ^cUT-U3f5URmJ*0P 5ṗƝK@ޱ C? + ;61|3$-!xUF1x&(bJfX,tf(FނOg5p}o1(f|Sv/%V})$;͚F.MeםuEmvC'hQCݢYаsh],^trx77n97Lw@,Ddu,B %k{=eե:uS.uܥʐt*ڿB۷/7&V,tOmx} o*<^DAxbyލ0>P,8OkĸDT6.HO:{9F#OV{xAW~%=3ϭ/?ulmWۂ%/=J=:U|?HdeP2дpy7g3w{jd8⇃ȀX <&(Gdl1?Ƞʨ13?3vjjqBn8J:j`G'`21| ;7`&oPh1G a}C )ȁedD#O/6 P{]䈪F (䠀Kc.#KqgKhpu?ŀ׊@ؿtAC}"c_zAW;(v@ہ;\BPn  :w#-ya~ C'z6 UC_ + B 9t ;{p?*NN& n +nlw p?8_QC< +Lq;FVk)+>eRƜ%Y8ωgz4Q0kMa?M47q1콌!} Xu;1pC:b`!7Ey!%x„LiRK33oT-"֋2$+Ill2_;$'I$ʻ厐7Fz, \ GN-M"EǚT`R%~BL&6.dN(&pG~H988l' +]mE P7ȌE2&GrpI/9iγ"Szx2*}L|DjP'^81Nh~ʾ}8K ii1U vp9l Z$N0gy4x2L6AT'f=$7< Kl#&s)' /S՗@ A +N*1hb d| Q&O%xΗL(Ɠ+jU) QS4w75}M{Ҁ6D6%h'h ĈADA pm|("F-lTže 'Z88kaVmFwII7 +i~~~}FY;A2 Πq@PB ^WfΔT! sF.JsѯzJrИk8W\+e^_4 1b ,oB! APw}A"NUqSJxBrR9aC۴s%Ime]+nnYfSV)) !cHɽ_oCP% I/ ֔J zP*5aniԚ>Z*|a98fkz.7q{ʹ=O@dA (F0aDY0H R'uJP + ;-ִWSXmzNf+2~D]nt1k%~fo2 0~Py]܊?K +ՉLMeQkj\rU[kתKmVHaыLzqWb1CO@s0 +&߷uasQOԑLe-ZyUqR+ +Ygԕ[j2ZkkU6NQt.bA&b#VgL{BPz7CF7}V3GvHwVeU+mŲ.5[4my6kR-4UN#rH|jx>A2 91PRo<݂x.NW@Ʋ5΅ʃvz!0$lŜ KHH"N_Ԥy=Hzg04Ay,Ey٬,G} "}bg}OXeeK'!vD _0Yǩo"ȋąs^kJ86׍z99`t2~@2ȓCByvK߿靐E?)ԯ&X׺5\L^sv:F"ed? ƿK \⇻)t{]ue5yn4nq2ueI 1@&d tGeɍRR؞Z`nvb, S!O" +Hu rK}*e:.װ~vxcOѥ$Z"oieLMoʲ@[ F{^ ؙΜ.zD{@,D۵rZ ?8rD݁A bfL6lL0V;f`Kdp3% d 7 l+Gq@#[8ko G-x +,=j] bOrT!H4dT2-pSbj'tC>ZMISs?Ç k +LDFr$j@#H$C!ױAU&46Aw'(vGUNkp+o5SB!JbD}ӃP*CD}qIE3 aQ*qGt7Z#`&gV[VpV0wEJz@٦ }}/DІ.ݐr%`U 0j(6 +pUa/S 1f-u%o/&|E@j R|iA +~9_y" -c>CzϐBT0Bh2@EjpB e(;`uzP/R e@SWI-A+vw>o/e<{g@|˚]b={ǖ lMi24kp/70D'^' RʚBka~mg}#|%#3a&ϰ&5==-:+ZQԣuTD+ʅuBf! H,'$!Ҡ("e(U(Lx@e(λO}s7i /l>BG/`X/Ш[ DՄ.3#6'=0] 3ĉjқ:kci!i{JFӚ0#NI@Z +݀xr 9{"=qH{\v[laSBzYF +Hz1|`D>e1̦X 5Q5P7y7@?H @O< qzܻ,\>5F})b_d < y`ۣpnapE?tݦ,p89 ٹi$,~'<=E3ch/qǘcӬ*h䥄gx=?1x~M\!_;_[ 8> yȷ/5 Yt Ac|bIo#e\=;0 cÑ͢GV\_͘>؇:Cɹ>q%y?h] zjPo4L A f~ 'J8=leC5Q QI^M|or=񁬊@vܛ|ܛ,`:jp!ul,Ap#@䐏bv/f<#|`l \QރR܎V^N9OJtQ'i= +G,`Ow& iנ8 `ڹ} 3 ѻkJ&DD0 GMIT: wc;rjޑnct3:S ])lG en G `2w, oo~g1Ag[$KiPyRT'5kkCWlǷiYjl|(9Uѱrfr% 503o':M,s&[W8nR)UK]^6a֖ 6X~%dgEl|AWIg)E + b K1F|q B̳(V=1mxCY0;̂c&εk\,č `rlLjxcWʴ|Yu6NQaK:|a6.ݮX:ҝbMf*7CIC<\:W{}w/<صSS~ՍuquDPQT(bIl$$,D*0:ŒZ;NZ:nǵZP*2)UdK9}m^|^K.7VzaZjBK5}F_\c<\mzGiafӛ0ܻ=|j|4쳨Ǟ$MW?l{I]voqf"k[եm+UnzZh|:^Eh[m[?QIT"bŋxFR.p\T*m?;1te!WrΉDyjx,k#]!ԳQ>ňX&gk *Y>cȎcd%rQ)#5Ңq+QhG3bwF-!?&H#!EjZQq_qY_iRH #ܰ8΋ŊhM\ sp1nq9fG!~%d͠3Y /RLtFkӡ\Ob ICo2 : Ʃ:KayU4c&ϜBp,4? #G2_%dBR+>a.| sxF=qs@ ݄Y0)։AXISQ-~bOqp?;"s;TR4HH6•%t0 `Hp\"b4GvnM-13Vw_,Q1_@? `g]!gCzztPh +á.r=3'CM*${yCBEXtY m Rw26MV/z/钼vH?i3 lhS`¨DFf(Ь\_ܜvCrH1D%3O ;r,jߥh@aEvy7;S0 A1lz, +8HA6 MPnK|bH- z9DWUB𘂠z'~٨]BfoU A %@ǰlr2p`^cI<BW(w8 V)%$uWT5!zJ _6+_(ltrH e&f|U7h2}`t06 +cP2A J$7?OCj!L0lSAG~DuAYgV\7?QtR6?I:?K 94d0 \`Qr$TOCl6Vh%o eLpq__ӫڣI7?k~"-ցjWuDd !I 2 hQP(ThI ǭ{{̋yy~y$A'b*37EmJO%\OŚx4C  b'iݑ/f F}KF-%:v22vfAi:Oǡs=_H`0Z:*J?,m: 20% qqChmݨ6foT?'j݆49u NU<*А^ _b`406YAP24]f2e\w|D x~j&TxXp%=6s@4j rѐǓ +) [`bc1` i,p<f;/_ +|A;sT!5஘I 7X- eI$->CX?\Ij(cO3 4#76N0 Zd{߽\ml׷m#šC.9 !ƶ˜LV]Q[j6,KeDŽ =<Àd0 x9h@ZjKf{p?pjw˓S?+<ڕߡcSX8Z-PKj~!Bl0{R2Y:=,VGr=/mDP\s`z[k sBfjv,t^<{ j]7wZu@E מVET$xb%Rν)S $"B˸D5ŕhڷxHGz,߾ோ;^5YovYcS%]7+Îj~jrXUPPl,S.)Du2qrgH\&餢aH8, DO7"@@*,XSiy}-z.h umǟѨ1yHJ%e+f% b~jږʑ!K餈tXHFy1_d 9i9%FWa`FN֏oU6>\w1ҧ"6TU"Oe!<32%Q*f<%Ii#b|TȖ 8)GjD́dtm-,_tmkŃ]_t_w]|`eDAmLpfV"tnKR%q)yI㲇%dՈznLHK +B@ +6X֬6c7WG0}wv]:֋5-a9AZRNV +T#$Jđ%"\hrLǟ7J#rn<[%/sڥY-xg ~5=?Xt,S~gZxB/sI$4IŎ gj/C5z*4 F.!gCȚ0 -Em-xlۀl@З}pƁ}U7ܭ>"Ϳ{IŒ81k5Rji`MK vXQdbF0 v<[_o7l@陣UeEmz]~?hn/$%8vC2]$ow/4WԀWKկh!Ab;,å` +tYk24cGfMcݬ?Q }#ف!'Gz6⼆pq^o 7}:Y0y!`XNKg j,eUL9or^!p]/?4$BQ.X=㴞0&+Am;2]>0GzbL;Z hk ,A}kPdk-[me{Vg]1f=Ϝt{jx&{9:jo|}{׉ϾGt~;߁pF:0Yc>:̓|ޖy9ӡ7Fy:-p.]gQMy? q +.,* l!!!{ I 7kKGwKU#-X+:uA=zL[8 +B|潚|w]=hil*5{.]0wp3GN RqU"֘[>asbOn"){>G6bڸ-Gx}HY|HC4ЄaX(AQ> a@TNq Gq2͓$ߡ(2)*%`8z dE!; qL.}6D3e|4|Es262'aqh/Ȣhf3 2* (\GAi,; <As +Ru t:3ALd> 1y +J ' JCʀÄF KTaP-!DXK/ldAV'ɺ.g Ivg|[xbd=xM4d'ѡ`1IgB'^9pGCI<ے!ٟ +tNf@x&v.Ywg!>Y/yB t&xCȀ. &E [D(@/8nBܖ>BE<C!ρ ُQx /(#hPy#o1&BPPCUꓠ4 ʝ =GBH#3 KGR9 &'}HNJ1&QOn=[}KAݝ <Ϡ#4>(:qLT}å +A1(Iy -|v{8TgP^RWhʟk4Owyw:?.)4½a#*}P23L}*QhAd$?ҵj}jzoW ˦QӅQ9g0"7x&XśU@|e渱jGʰs)wtuV+neEc88ᑾx_~aKyrpf.l=tГ|{]Ċ:&N'ؐ=ա#1+mWU]GF&K_ +n[nZd(0[mmECSC-_zl/yAo"ؔ-Y#zY[|%+p2\+9TcqK?gK:-;,J/Y_8Z4h 8NJ),9yL~#d+ȷ.ͱLlK2ȟ9( vmpo]_JSMk{As_%Q{k7%γfGpYeM>'( dȾWOz4̣a[4;Yp؛=n[m .ѕ++ۗn)ztAGd9׉+eU|Yy+׾ʾݮ~.'0FfQC5&2%?1Ad袻[~mC?h9|{ɉǪ]]mK:j\]Etm_Wly8yƟ8H%CESf_˖889v!5dl!ҴeFiK4L^XYA@3AZ6]MDj+.;fw9&G7%ƞgTF.8M$, +%tIIlb樒I^֥N{:+vxof:4 kRe i"anH^lYXVt/#\Ԉ 5=/%z*"9z&,9j649j>$)j%=֓0{"_B4{YS.uEp@ +k%Y5_qOfKf|Pw .F +&BWLxYN\;.v% +#<{+UͤHߴzrLNM~jK +ODdg%222YI„)x䇑 ~d7*a:<:~7ǎ.DDaDrxY~nSћjᮽ&ʷmZ_s2P"wZ~ܙ *d 8ᇧOq#Rgy)~[& `A O_B'=q/n&yd,@؆%`mY`Yn`ug=w4{@7|I:H5 ?BHI t`{R"n>|bf/s/m!?삐OV"xF`'!,ɹ 0z}OX ҂Ag,7{Ɇ_g"D.ǃ +QvGlYMtBt"s+]*W5Fh+ !:i__#;?=G+b `>7ҁO=3@$fAb"h%[WWGmtp:f}6aי D @+5zq$X?r'j"Du"֕ +S g8@> JdHJ[Q+<: D3q,]bk,d;2{!8?Ds3듀UHXAPAK +},N&-*unH2 _x+lƴEwÆ؃Q7Q9/9}pŀw3Wq>&!?{ԯZ{d>@V#֊ArArUU=,7J$6^Z^%s^[%*7!q+C;Q 8/DN&A-d_Ɠ|Ň-֑{@w. …lٲt[R["WQT;KRgIO{[7c! qe#C1$WLhb- +#G4g _4egy?YH_κs[+▲%kҞ+o.J{IEeW@ܩj$>đ|)֑6UTN-g7G8/yZ\ИNn}%7,ܫQ=V!Jy27ңv[V-@g_Bidg'=6M%sz_e_- ~6K]nt^7 +r 9戞;O?O9$w&8|[ٮ]ٖ2h[ͩ㲦ԷƴwI dgQ@zlZhRjwZOkCf>VEuv$ٳ!}*$\KlWv#Ir8}`ZjMk귚}#ꆵVE}Ƹ|{[)!yDmH@6o<l&} ԭmݣFyN$,P}U.+*wWdS6g4e6d\Kٙ٫NQdsqYUDH$[G dΥ‘2VrG6O]m5n6;^.{vW6g?h䷙6 +[ ++eyU; jks?լ}0RiN0-1VU0.{$mJ l޲T͡ p<߽Vԫ{58xthWflYWf6nIY\#-lTWO0vZn|Z^03 iMqTU?(˷y{)L|28k݃(7x_h {YGՌF6Z +Ě*yeNfSkʦԒ4Sb:ST41L a&.&{S͠|>rǔmݭ%"J};uʍbBf\.1M),,ոLZ^ُĀ>ӐX:)(UƔLV&Bٜ3(CU沧iFuh:'ʿ۝j[W[Ģx=rzSS +nW&./fkIiViqUX٬5X9SY׺-CuyTe4\ѪuMBXEAaIXE@0qWzZD +REAPAܵEܗ#n=3v +cNUԞ,gg|~zy}?ѐf͂1=ŧoA4ӵV+ok2?mW{$QRYk+;.b}˶S"{qIyy%w,>{I@m˶\6E~у*!ݮ3FtmuM原Tյh'ly}OqOj# Ǭ;&a)*>K_X?+w᜜}md}=@V^`O2w  Y٧DN6 u1ֳ.3&sՒ"/jT6慮;TnuÛf=,=sӪo2/ UYeCswFRևD"_IUǧ M%S,\RU\,=㰽CQ>wݩy'G,iY5-yc\vSѬc{SkRNo / Æ/?R>*FGRGCo#zTFtb=tG_]ҡkT%^ 1MmDd+/d/>08g6;>'^:1U>>f6#9(TѰ臝Dw]۽j/qTyÈM{\]ۑފ_q3m,k |VS\1s6zڌ1יӣ vyŴ#>3D]!h`?Utr뮈ӖO}[8:>˼&<ت};hVFByCx]DFvAu:yDgD7#jnfʯӖ"kNkzżr =ZkCO]JOxVcz>Fȵ=U͊t2T8w(C@u752ω.4>/N͈V/y/eTFWfɯfOxdחa3/N׷!oc.܂M |{FD7$/!5Z!Dul+Xvv'_=7-)_3{p~jZxY4C +UClw~d5IJAlbY?hGXaD|K#Q;#JÎ7n:Z(3 +BHc?d`l.ATVK\_0l_Lj*P5˿C)EpVCԿ.4YEjE( "A% #@#r A("HM׫XVG+VWZ]gߝ/g|g]ך$i VcjD0!D +hzG[Cq n@=_\r}As}F} +ns[x +ϫAy9*Φ9|f9DY@DB(KD*׌F!.mz?2a4;Na1vk +ZC狰oR # ~H{/px*ٽ_ +LJjٰb׻ͷ=o:~y_#!|\qw| $|ÃQ>P@)wusW`Qn2#5hyR/ף5n3Q-߇/5uM  +N :!x\$hB6&P(APo8.S3)mOEHd`\iXf6iK'Ed Rtv阽';' :>|$l*@zg!U 4S V, =vS^jR +\g [ͨ.Ǭ="w99)xOHKU|%i t D0^y(ewE&:bh F 0$@@)=Į%Ωs?A şS~+[ovlLqɥgr"2.GRIZYEࡄc|;+#vl6Knsc$SA +j)0@7b-ǮȳCcSSfz3%쥓a㹱.#->J ;,3*o&e=d}06ߐp]PW%n 8r r`d0q-=-@Ѝ}M>*g./.qL'꒮O+IX") ]E7!=*nFgfONTF*=ERώ\>fP陕}z;D/*'Dˡ9a~5i(akRe +-D}/ +=˷Duz|o.5-Bg7߿f6x@ wqo]GSI:mu~nG߶a6޲z1hQoge!̩R^[.*KחkUM/+(L U~P^^Z6j`0pXWwT hu:yMt52-&bEKh}]m[UM6]e_Q*P+K+njQ@ɵgCe"y;B;9S w!!tC}fh@nj ՔUOguUMbW]CVm7ϐNԱu/ D{X[~|pL[V)DBwNc=fh rͲ]5gm[Gn˞YʆܠRzBNQH~T +Ș +Ht@ĖZYpـp{C |i/CC._-+aNn݉[S;mŴݭՌV"0G)js23^;B|3$toL>,u'{RFj+E^O?dr7 N07]X!@*Bw]Ad Bc _ݤt{+k/7ZT_ks76mDna-r[;~cx|D_|J>KˎEћԂEG->v8T)Nв@]n|;)T{s%35q0Ͷm@yW5;dd&GyS-<D6zvc_֍Yco,dYbjmt"\8\ۅHMkD Ds;^ ,4㹼~ocd 8= TxV{ .\;vhH5mL¯.CwC׏ma3>^gsX~G[BQ(e>*  MCraxayFc xGaw$xKp' l`3vog&_$*BM# |Ʉ@CBZ(( *.\,\ xH` X&c ࠇW!fpU3+l?D"\" Hų: Ix +C =q?/8T 籎簝'c??g5|M˾Erb(xS(b +DZDhĒT /j!8K"f5SdZm$=m2] +{ +-HEbfy"z} ];ҏ|!iү 9ꏨbD2wa1xd] ԠkyXzLVG'zB9 q h( F|?b2 ?ɜgfn3~_r +B,#dX,TzGPA}1a4{W#"f2ς友#; @vȨAKH?0q}5HpvE,UO ɯ)cI +n e@t 1W͈1Ҵʀ﫧4OmbEۄ?+[+M:VHiPv}>dj3q]3r57`g0o/iK9XߎM9#sdkQ5nBN y\8 <; ?QB+ y#p!uNxʶ [Ÿ] X&wg<%ݫ:0/<8S6|n:9@틼H뉸Axh|KD~F!ZS4.y} + +|&t3I l}#fr+Ȧ0k4f,9nD$s& J{jUwQ1k n$o<.x:rVȖQF"vIv$5 +Jst0k울 NeNEOU{JX( Z0D] +(ަi0E&pJהFߍyǷ ʣl2v2&%ݵI ť3ɵD K%)^U + +/ +Es +!Bh`/ {o. +c2{WTKEV}9{[I rU:]M/6 %}_7[͖7[|ĒC_dD[ :U7JHu!ܪ5*5LNe莖˜=jС&K<\YH)ʨ+d nQnz 1!Y*bRSv10x{J.7[$5; לvU< uSTbt<%7GEϒ׳dYa$8̯~Lđd"412D +Xp;O눠kXMaщԭq-5ǷUWFRW%TVzeRkYE;')O'̝{/!s[Y)(J"j& pk0hkZ1i8f .ZU*+{H˔Ԥj<|/_|b +.1]$[=gp{W#vVvYB{>bc'ٸQ9jU#'!@jYR.:S%񫚙'+|*'88|"*;R%S"h5[KLqf`34&w3T1Lz-#6-.Y(l5+ȼ&WdC#- n +Va#FpV#ZX+*_ͿE{Wp ``#6ფ!ly +@N{Ss\»JC:՞A=q;mAԣ͈zL(Auy{oq`w0@-vвuq1Q -q/xl#GN *v:s9>Վiq\r@ o/"s;ٿ}52GpsgN kdӻ iWRX0o39jUmW;'2w(tێLݒc} 9. ra ut 4|$@MH3v;b=IQ>as7[MΦ[sf +fjvg:`Kږ:duȎ1{\E+WwA'@?@ίXΟH m!f[Bਞ_l쫏^'1)i}g6Ky+wVn|8x8]Mh_ο-3'pC"HvY(9yѡY&/J9hZru3W/~,=A}ny;P gD.~gЗL{(m# a!: 5px7?ՙSa20 f`FP"JQ,X"q%Uc jtE=.Y{uƵG"%( +!;O}}'~$~0Ofh#v^R+uBW e{; F;m_ x(6Q}اD֍"j)]5GPps`|(|H?-"")bϏ߈5X/v~nH>6J-߳* .C4'DD8?( + + А:H>0ZArCOY +yJLX R`Ev%,M4/q-T{cDAD 38Ӆ㡽.Cw&]mqm{w'♯E^d֬QSzɫly]jyh'P=9]}GK4wV{Ju#qg|&xBSFӉПHD1v( Cjxm#TFtfNLPɮ+( }߆}fDTDDYaVePYM*X&FM0.59Ѵ1ihKs޼[ą3r { ʏ2hnڒ۪1Sb_ǯ*Ҫ=RDna_Y9sMF"",MB0R߯iPQt &VX) wj+\ټwIl徼Tʜl~Yv)(NBQj& +S(Xlaᮔ^;4>#80Pk=uL{Ӽ/xE}ZhBg./c$18%#p0U$MK]O=O>d(NGQb. +w`1JD}P:}'ih`A=hcZU4u kbMeՉV9iҊ~-FX_r'N>++D8E; +QB`4ԃs5ԃz{vH[Cje-ZEM+c-$u))Y$TzU7 Uxm];xs6pk +bJsS 5PH3@/*Ʌ.3rev.+k_ٶ0Ӥ{,wdh9(w辩KpBr_:lEX z.,^.Vô6T~GK5=Z)GvMw[n̳>\Q缮kD{xv;a="zNϤB 4MC rfh a]';m$gxF[bFl6_7 o7䴺)AU輺ɡQA5h8AzvV,Ns!eL83 Gx*NgLбB㐱Um +kpooȱ>^AwP~1?OH1Łi=3LL{յ3OǨޥzZtnT!ACӷyFsh"D3\p-Ds8I?DMy`%6U" lBgE b eJ2L^U++fMOe?Y-k7g]ew+bG)F)O+a5Xs\3 )ς@x+܊f֟btRk(j/˔? 'ODT up~ `$lF򙔱xV2eы,?xO{*PuAo_t?_#?%7j`X~|0^@0WANx絔Ahieޞ`og?hΓ|9g|Ht7B|{`'  zh%hp440ppX%B0H1Bo FʗRQ>= X=Q[LɅCy+)hEˉH #[!`|E~\BAYpS8RB7(ˉ +ro }bL x`B/Hb͇C<hƠ3̕A#z jAM,H`Z&)&5t>2L$U)}~D^ KK0hȠ ]̝ACo l`rI$! 2A%r|INeJvv :2hOZ1[•XB\RJj٨B: Bw,\'u}GEugqSFA"3u +DPAd230 ",BK5ZWcM=hbY-b'su߻}9(zy'V&q_ Nq%]ev^Hihde-r8hQA:'hE"[|}mqBLb?ǖ( zŨ-,rw( e}ow?$kxo%7WCgҋ_w?=߷{'+E;oKQܒ(['e8s21E3fNPxpz]8oW.Z ?Y̬ Y 0/2]7\ +g'\e +/p@w$@/#@oZP/^z~>+]}A&ݙ;U'Eb;w>3_q)0JƧ(:@38]z~@Iw}҆<4{~ެ>;ܛs\Z&Uٳg7'dY>=x5qχ&G<ޚ~f

#z}b!\ C a ZdC_E yN68=qh~y&sL?ݢ?`xOn>A]gwd-MwN6]V@A`Wal-pM9G2p:ҋ},b>H.p ,ݨ?$Ev/6߹r{Z6A[K:K7]`'QkԱO/&f~e%<疈JGT؃q=ѱ{#4=]7nmtۯ6lM%YK#٪w͡hOPc8O7cq>_'d$8,d_۝P=>Ұ;.AԵ$lSlEGtmMֈ6eY˩1sC9z:N(#5hWұ0e7gRYp" S'g67c{g7'upKJFu=1Ŭ-![ܪYĕ6/Yn"UVѩ6̥2+yy]7Li :Ƣ8н}I ڍ0۔)oS1ņ,؛m ;s䬞l/^g\Pu1$U)&uMCR.־:acE|sejkQ)Wjvţ3q$2 +ÍxAe Z!3|gVglnG^[΢ DY f itMuZ<ʾ$ɱHѩII'ܴI7r/Z52ĉȴI0.x82LcTe} +AO)tX6eiʟPj=VٵuZaIBC]U(ReS*,˶I+-K5;w01E]#.BdSc +PFF 9Pg?\Nay4;ʛfq+ Fuj,ĚqҘFYdNʊmLXŠKhLX9:RXU[<^H}ݍkW J8 +(8g6NZ`jNmzN?f`afnMPEESkٺn]6eyZ(*X +)JYYػہΞ;0}'MZB׋ǽ2-c$)nJjG%W?ō'=vpUB`J56<ցYki3d^S`gꪉ~E+߷bz + |NXc.tsȥձK,i)X,1$f=baoy-~KU^)5cFi(ޔmJצJGxiqoMnx$p̆; .X$lhIix^IUDnIcDܵZ"sVIdގ5^u+7r~v'l3`Jy*qEX[Qsl$S}Fna)kֹ9[V̭3ʮ؇-%$}0=5P-gťʁi\&TwWQXJ(W wݣwy2df3]/ӪKR\;-] lI6h )wHp8_\ɞ:P;`yVCNdQ7F׍j)3u{&կro7$1T(c1f`6ɝ.`2Wûùf6hXt$ G<gSFcwAUQ˴2-Z-~ˣQ;"ijro`R?PTY@Ƈ& cO!g|&_$#%;`?;}MCO"h-ݰ} `;+BgDi#3~n`k/b݅ F I'3@9=.ak[,m03Lv^NOй^6Am?tuނvU*3N5?evSO Hflo|oa1:w4;pPA7 -`s̟ɹ2;ك?e[V`'` x@7BdNqL9ćᇡ7\.,P.W/{rg̎ X>̽o,v$'ehB| CG{"$(C iJ0~OzJclr}jO][B 9 <9Sb(T/yf(ў:-TDA@'/R'yN[ߛ3?;nD$_}š-&¸P9U^x<~4^.0#;ߟi%G\ )PaI6Re١Ԫ֏ k괶MM6ѮAbN} :F9UrꧠǕiE`_PKufT :kA+i_ !7!q6Tt-? A$b@k"q$>ǫPZ%vٱDX}ب]ti;֨ڹS+D7Lj:##ݢ{-T3$88t%|t$ˉWӵ ki-Η=>wqڹ\wYsssy6%6{6&]jH`T$>5@| q4Ay@+#Wӝt[ZF⋴dډS5?gcb)+ )yLeKgMi4Hm5M'UvSUX*iIXgk{YjveVc5 Sհ|w cemyUWo5+ o" JbZE( K!@k@E(޸junkn۱vvt;ad?=s9s߰NJbMH k) ^ ك{x s%' 0!n%&,%^JR/5|ϹR3qS։ةPG2{4!xW!s΀e$ kg|¾Ct+J\V卵WI*9}V8=0MTL$[ƒۘI=!CCY=2/.H]r³ זDظTuYc繥ΕAt_fMMtfv<gTF0즎Їyj^]w!S[lϩ mn6gu4Caͤ&s>*Ie#YBCDHYCB>9Ήװ{^.p!g 0e b GP5&0z +ޝ,}`k~ I_Zȭusf털\;')Yh?P[xJ$  |s×jߢ7 A R7 +`LRʢܺKeM + "]`Ȭ3VVs͆v~YQaIH?+)/n(|+)1"4#Ucpу. {F[UQyнŜX[W]_]j6BJj9%m|cqP4*Ht+rޠ5~#0t`aB 8Y0O0{Ͳny\VQS +(2UXEj/-唞ה^dޗd3MD1AJ^W%fA=X4By#45Zѫ ޥ~E@C]S_kͭif!azSz;\Yu:\YHUITf"P _]AxkC?4 +`Cz'f,@w +;kW j0\Ž-nؾ$mˉuY [uMeW/ة)ZxM* u]xpNA{&q38;p;@57h~D@t[ۛ NDn^>pW BCȃz`uP y2cc}8ܻy3itu` cOx>>ޏ;x}~lFຕ@Cq \֥)bJr:ɣP-g< <ܗ\;JܖᦼUp8^E' 霽:'8^vMm -,U)Q٬jifM~/-߿-4˩ŸS۟*p-lQ犓|P:Ma(UOUϰfRn1MPm6MWf7 +l0Ԭ7m\keYb׭Vh %? Z+jslgXgzj~:J[EJ,6PnLW . )lڜk\]n^bԼfy\d\h,7W9aSs\ Nq+H +eu-??;w +WtX1QcJejtȴ* +OY4KTh;7h.?~vP}^P}n#~zБ]N-:3.mKvʺ{:+=TFiXCEqYZX, +SvfU6zY_L.4W:~Frǜ !{vziBЏdO%⹷7ubM7gjHwP,,ΏL떢u͌lsdvq);|a\NwYo _G=97Y#Y.{{3~,K`E=^&W{^VocvJ4yRp }بR=9$A_ٍCf =s c;eH~kZLtNr"}zpppc-4CJbe6%%ppj\&#}YI %)֘ꌉ!;_3T#R4b JIOde7 1P,,.V:,UHA@*`-k1Xb]QQD#UѱrԊ:k+ڙs@wŤ,F/(GFWύ8;jSxTQWc(a>_# }xk+$|dm8IZ%BN(If4-yYrR"!1ba\eLBUt|M,9"V6:p kv + A>0^舶Kgųf] ޹>-)9;r=$eѹ~Ȝ9aّʰ4$Khz: w=}lIV|(fYb.sFx <%!e3˦˂KQ~-'-Vy[M(Yc^IWؒSڎ]*lH!)6=g;ؖm^!I.I}*$BP# `hKWjlҪP3yU UeXxUYRzVnQyTWW+>j +a^c{s2|s@鎭WU[` |7q8P3kH̐ Y I{6+1n2w55w1lmxk:VXX\s;}FZ:K+* <moԪYG]׏[\?Mx,i+q1K6HVȆjdCLN2T+䃶^7τ={tW +MDofm]2 kPO  3CwǀPosc6.C}$NKE%q\[Hv l#z,za ˞u?0 &5M:0h`<c=F`ӒrXBz\U3X>"$d382;s `. 00(лв]:!e +mv0o E2 +N?!kvN}'5) i{M'܋HDrA..iT5/Z\/_\JyC2h/`pB/뭐yO33OW:赦;X_*8kx!v7\[cی@77,]N)KOgͣp4x0mځ=jz/ȏI~"r~T<</qC.נ(++7&F,(,ȲܖEvvrY˂+  ".!xCEh&Fmc6If:i:MSM[vڴ}z<_9y>|e >X6e7pmŕOK\@$ dXqu,xFVe +*U-])[kkݵMp={aj1drrr_w~ko7CfC $r"CkKGmoWkqKp/4 nRZ.GRZpP9E;}VC)g~֬(b}Bq}Lq==WΑHH둄CHW ׇG17r}G͛`!:)3aNi(-)>)wfi^Qg2z{88w}Hca kl!Mw07ߟWЧ>(U Qϊ귙.=CӞOQ[2 $<%b޿{?@ωlsc9ʅ49Lføv33 @fkזs5ތF~OF-L/jOJ[>})iNؕND"BWO_zp}b0L +&tRݱp@Gt>ի/`wg[]6^g@ێ֬@wV?Ӓt3Fݼ^wKZVw#ơ#"$9p7\G߷`=` +ci`@J0C1)Q0󊸞<+ߝ[ВrE 9{NÈaޒWޕ m'2H1D>O1wW9K(D}7 +A) iN3X&{m.,5V4 +ZE5=!8)Ae_HSGD瘃[xqz~\__z_ΒhlViI]lvcI>Yb9Jl5N-,+̃RaYLPZIXn6iH; \>b';(}-ügyQۼxQ}z ?jXxc^.=.vv)jdҐ0@+w(RV, Ư\2ZBm6^V{Nr1糨{{i'҈ߕ>j@k<ɃȣP]S!> kjX?7vy@E}eaOp}P, +(q]ՠƂADET,NPXh{,G$1qu]{Xۏ{@xgygΑڛ%_>`Q2l]f(2C/)멷4y赌A.| b38~Z9P rxë;<+"Q1ír\\p4éUp,2!9V3yLYǻH?RO VF*gS݀cju#`WDak261ZCcIڲ*K%\@]+!=bԝC݉Eݸr6ԯ_ȠAVh6#GdeYPV: S^ jO-Pwm.߃k=?CIl3Yw8ߕF6eل\dikbR5љ&+"CV!V`zmDQ7+|; R@.Wtll]> 7 Lb|II}g'&w!h!y6N(F{;Q׋]# DuOrLhv/C?[7lO 1yI#_ҐWhv<xռmּExD3=桍i<,`!Pqk6@kA? $#dYM6RDJvRK!u/+~xI!쨭PpW;H32$t䐍dur +.2i.'WG ƙ5H?2|B>N"u9RkC:k%2SVo>~CG7A8RWm! +GzjXjMf|tX@Tjds"@# ~I p'4q7F \hK_hZG9&ۇGx}Lԙ0&He%rM8O_ŠS 8tZ%#R9SThgG8A'5qU˲h%|:bN+qJ'98̃UYê +4jpHՀ&|W2cjAxQeNW^/'7~}6}pV7lGX3`?`8nsWu2:AC=84aT9F@YBz7ˈn.yJ\C;N;tQwðԹGT{$aL敃*|Tx{JHfKi +IA3!!Z=k, `;孁Pg} lʎcPR(bdl HVJ TX)Iy'e~LY֐՝FRK03Ov@ol=P4[Gas8OgHy!s!) !!9!5!U!쐣eOKC"#TțY?]8iG,=c~3XP7la(<`G`q8AZc"[eLeʳƕLFEq2ݸS^~EX(\(I< ԝn_>|r8nU =+LXcFie%-7e&2Lt\E)EjZL1S-0FlSϏ8gj1=6 ,Pe s :W|j +{Kھ>XX? +#e&5E\F3+Pydvf>6#hE ()Tm(O|ǧJx bca@OdFwƒ0XiQGdcNR̎LNNγ]mMV71.!Fh*a`+"}ccbuX2qH &̏(͍͎)K#"q4!SR4VhuGEyafav .D&葨((("0 ̌ (qh]\Q0.cMh4rZ=&Ic\kmm&A;8}}yIirjIjI4j{'JxU?3~F[6a>(ѠԦ*CPnH t$=WV^PVOW5MߡYgMYHc֋*^TZRES.qaQؑlZVudD9TfCi*LiPlJN]Y(_Yeƕjq&˸KΘqZqC&#CT ҏ}mf`69x%RuԘTfbK0ʬcQbBA>dbJxyhI%){rs~0AZy(R+‘R9HLT I\E4L6-U]ު^WY>J"r,JB2`y)PK8]LWA߳H^FB@̯}a瞂hĺ0ǝ"ĸ3ndX宖Ns/nO}M><<P{ + ~u@7hYGo ڥŠ$;Fc@G8;#\<өG] + <M hw=n];G;65+P`0^ہN``~ jCp(C!EAeaqC1}C"? 6je6րv1.Ao8]@8B{|a#hB>n~psynu󘈿+27ԝXg&Qs459=@{?0# pZM3lF{p3,?gyٟ!a{(pm>/д.d/`=fC70ԧ'J"H5K\~¿ƍ b^?EnD|B]k4RCIX= +(z%-BR&kOm?rw޸p0>&?62j4hGLAIþxq1GxPR*Ǎ+GsMԝPS20l<@?F-5Aո޸5ZxWXwq+0"<⢤MT8UKƱs qW\ %uW7hZpYӉQ\ňv ¸C8? ΍3n&<ĉIdGoN~:G ӊx0n11W&%atrF&0- _NI~GH) +^?`ST!|:lG0V#ӝ84ߛш3۱j웹 Cv`p>ݳ10v%%U'8V? _LHjȹ{<3&̬)8>'$r&cp{T`: 5cgP'vö~ak?|^ .l +>/څCք|/@܎FcyG92]ұcq6-.Rlw/# û º]bO~qui;X\/=R}F4XLk6c9 b r&G/Ė$W|ٱVW.jձ*]إ[/vI!-;*ޕb$7SjU=c;3Ҙ?ov$/޸ذ, +Xn}+Ra%=W.H Ƅ'NQ?RjjWr^\ Ekp4riӊ 2)I~<'yNGWJVRn0͐/BBl4ԉC6 rUe8T.j* w4eߓ(N*;STu˯lU' j^,^h71nFȘyP"\ֹ-B-΂d,NJ`/( +bAAdHyղ֯dۆ4fi,5L}2dZU%3_S11׫=W̽H;Xx:O#c㳪EpFIB81(rБ-6!Q"ګ{dwY>ey&& MCMZMZr4;ej\A+XEq 挄2r˲S/dSYlN)ݹINuVR55I4)I%)RCm|GiJ%i"ߋk$UNjr!ۥɕ,]]EBLHuW ]򲪣r|ը纯UUT +U+Wg`/*!mMVXE] k#ݳFz}IEDŽdAyZ8Z1~SIOrYSZU!ϸ\R㻤Ž@H55 IFJd$LEb<[ðu ⽉f`ׂX.omBw{P ޻bh'bh*6FU {'Za'|/^@,%#k& jU8"W-EĪdĢn+ºKuG|qXYĖ,$&niTUk_p +"$DԒPJ2UcLUjj:Jϕ:Gr#y<꒕Ȭ g*]FhI#tM#44B3`i M7-a *tfpY Sa*gC~mw@^dQbOE*<7Ps#)7Fay +믐 + +̟j_v;\y)`jcmAv3yf.fN5`={e!/b򥈥Rpq/R?- T@iڔʿ4A~kS>jmVҾU^#_WOjYQx?Vv&gR\)"K/ʥk%O<Xp1Pom$5qQ cXFTޕe) +SM4PIYhx>]B IϕR)51JjIb۶21 ocR P RCk(b Wovm7) + ĚzrjE oTK;$]++>v۽ c~ǏZZ}-ͥbbjW#0Gi%oFɺUh$/5?(G ~ŏc0$~b9EQ:_|F^}I;l 5wKa MchJV0E:\:Ǣt%B{ KuL/gds2y4]!T=AOI.?H+XMXPܥq>gA*KczM#c/v?>>~_zNo:ptp0JSjc &C0&51II1/gה_q0ބ10fXP+` -6ПPOls&\wV6= 0a&~j [Z=W^u_:Rtzme.4+k4xƠF +)O ίu/`@hȉ+f7r}!>w7%,gҹYn!Kktv> KP_ ٤4*3ZzCǪljjm3S/`R _Z- +N!Mhon6\[b6R\wϑc*=Vc=?jCZyF+n{>@NZ5/bF*#r#7i{YQǍԨ+ƌG(HyNd7xg{=Ê6Wvg"7*l.an ZЭ跔=Js'jvLbR53fg̈YaT2c?5b/ScSbM#I̯\%gˌ\}2|))enE1>=*U)@=Da)fn$[IcuhuX&L;by7q3qFzWhD{o͌ qڽ]iVK4+>B =5#>4`%ۆ)6ZSmD{d[1ѶИ`+UXj,m\Fλݳ 1g$b>ã0{ KHe K"I&L2IfLB&$$C!"ITBR, @!(}cVVc] +B_Hg3s9|/>X$E ҐcU8E5IsT@U-wdґ +G@2#Xa:Ŏ;BGYn;[ycq9.YK$_mqg.j]L,kc acSUU +TE<',ݩӣgFsQ3Lw[,q+'+yN+fNj?g8IK+MuJ,Ty]̈Qif3ȝ;KnEFk\mǽvo[Vr_\GF9ƱlMԀxꉧ,'r`fE8;J9SU3GK= qɔϛ\o@^o1Mfg<`9={4cVy+󱕒c}fCV?8+/n-xBRgT7\c_-or}'w*Q?_n0#b&w[I^+Z\xm&}$=o%PF0 7f|>xhA,BeVVQ2#*RzTVj|&)ԥ`- +V(!x lc 4o2cؒbی-͸"ۈ+c/bO~o&j`C5o(]k(FӜUʥWj֪"ͬFnԴnM=ɵ(zۚ\16&gJm<h|Pu<شZՃ4>\3 i7ѴxMmthJcuC2Mjӄ6ii|qkzCz[Qk`mD#hl#Yy&-)tS4s!&E:TKXܗ.S p8.jkaR3нAWe4ހRbc‡/L>e~>g|A`fNmh5@8 +q P`%:X>qBx_]}%~1%ޅ&V#7B%B70vޯեh>g^}~$%zEs`@}xËWbCaADA z,EL +Fe;{v0-[nrt#Lqjh8Чm>GulꖀiEP0'oeX׈?L0?gpjJU^lbPx;w@x#F7b;&"awQ\r㑗#G~-QXM7gQ;O-SQp2"G#q$*q`i9-2 v/kΘV#cak6X.#/a86`Cj~c>11_Cqy,$Ȱ31;VcJlYi$+6%90HAOPKL=PISA&ze?Z#tI %UoW9R2yWP~XaJy;RU496*pz9֧1ڌv d?}ѓݙCM7!Y'KG=2%|'>KL!rl/碗͙s1  ec [Do=9 V8PxWtS9ڕ{QNUy^ g#?¡3m>K,;&Ygɸl`\*cїyŸ_΂j +([ +OaZ p6¥jJ4 ꚰ>ªzB$a-@Sf4(cCO# 1.aV-EWQ|řh/΃D*.m^4aS$E0 u3J$a"?JE>Nśi^t!:Q%,r\pVhЬEv6VZk`n&AaԾ& EQH5咸Oͫz4KI='=駛qfܚ%piQ)CSU6UhԕêӣAgF&}F F@NZOIB[%*%qX'{j}񻋿UZLXj`-P:FC#j -1tBo Ag}Bcr:#w#K V5HA 5Їf$&"p|wHdꓰb | .&7P[M`븪oR#$32R$uHYjA\, iD"*cDAtH8MENLm]'{LwXǿ *pʐ%DqEׁ /BEyjMl`֓&8֪16Mn?H}~~=~_Y⦎%( )Dn(/WS:`ʖ@Φ%r2mKʡ|2LhLcx, W<$Rk3`\r2#s͡jgQ[ ٙek,3ƛvsZ+*Pb[嵅OΗg +S3`VjeSˌ[ۑCh(u:.:.Xn0g<̙+[F_sa +SyH1g`^.@Us$z 4fp'Eg  +m=E'{xK4bX94s퉮j#MCd;srÎ]ر;ر;h(|Ful]pwr߇ {)5՜ ݌>4Ap&B4hΏ{Hc_N`G#I#ůKuX4`;1'-cٮqux-tɞ%CR[1Y~ւ}8694.HbU(Mm™&>v ~fتnc8!;ݪu.4@W 9| -Mywt{>Sӆ#I? {YrU +nGL_M%݁{ց 0=&&OVۃAcYp drXw@0C̄9P eP`~aY̍;ټ' K==⭇܁uޔ_8 l4r9 scxƎi )>s]u ~˯| | \K68ش +/cHgi? ؂.c*Zkl7ң49Y}]ZZ9flAMOŢ:#WϚdDeo{g)Q~hAN^Z0UiEUUnE&herU|w+Wrm]w?<5nk0I!vßWÕ_n/*}cJ;U *4X;<1*J,{T\,POfӌov?)E]C)!*mU2a.mTAE5k)7Vy~7L9ɚ?^3kz7P2VkJ6Ҥ3J &=UjE7%gaz<+Ŗ7fn^ jzM9X=G(eJSF,BW(5x&k\A yOcB+%FXZ(.EQ6XU<+Ė|l%69i!]552{+w >4)l&MPjX&и /SJ +ج%E҈ CE#\ 06C9,{rhaVᮚɑJ쭉}5 5D㢒46jR'ktQ@#bjxFOCcNjH, Q-נ\ZZ#mPGjRRc<5>_b5&.R)qo%jd%ŧix|4,ޤ5^JأNh`'P-?<*?we1 $n "" 2,0QNHAA(MqZ5q4զM6mzĸ&ƚXa9}"ΡlX?m _fK1SU@Y(/ir'+; ,E&C2 2UZJRSdHPR>%RBNJO %$HrT#,g= 3 +boeȜ6RpeE+#=ItsjLJ26(\MG'qA;Nw(4bS:F @QU5IVcwU^56=VS5Y!r>><ekzP +)iluOy-P0yڇ>+7{4>]5o_pS$l7SO7=ϡ~z&j"9Ff3A(h ܚ4K}i~i<[dZ8ZL-P kygຈmlyh*^/|3Xs"kĚC 7IÚ%%m,1ϵxXE# C N01ҾCP"p8iFjz͚ 5Jc{Jj}?@?6f p뤰;YT':ppzybFcI7xZZ+ow^BmxBP\wFzw>{pbGs֏ ŜC9VM(gU8@xuq?Nx;AEquO/Nj[9WuqN ?%wŗ̺75f/NLN>V 1,vb{%Ө;[|;xR>prWJU}s_DщTMNΨ@Ə7𣋼:~ŏZu[8}D|E Bm'|.85go-/(t"шZ:s_lخ|l6bsll29=قldsۮ"G'#$:D b]Pr\l.`w,$ +ϓTVWUD̮r]9 ];A1B9 (hr4*Ѩf,Ry ZDd+G#r"pvrԾѿ+`ܵ^ Gk4:ıT-TiL\Yn0˰/2,3,31 $vcxKʭk7V괪*RRU~V.Q*Jc;R{;G: rq+YȦcn:JFd)ﱰG}VuWj폴~UeZr6f_T=/F|Tg"S8%S[K8]ͱlsrx[}嘽,Lr fÄce.vLg2=&> 1,wvi9Tk%?k5t2Y$Dq"nG9orj8`!E8\IL&1B(iK{SH9#3jJCq'_vDSyʝi%SK,'r %pj6iLU1݌2ьQfL4-0`tݙ2y_ d2LG_d}>'.zi{XdU˜jɌf*3Y&w/4i'p y-0ws_c=om)]Ɲo6t=&ezX✖.kߜ,ȔjٯZ͛ٗs J*fwa=V|En+x O=ūt?*%o^ΒVGaֺ"tQޓDY3%R=V +=xz1{GN]a92k=c`~53tRLrH[(m $`H#Ϸ\_!9 +}ue1ӿH4)$(~I$ =5XE_Z#_t ^}Wt,RT$k$S @:;I Th$9")Obp/ yvOL\Mb&&+#rrC|ǥĠp!ҮZjBVCq$Y!6BLaCSl aTdo1'"lgqHLݢէ9(Ji+"J_1uBp:ع DSbsMa}aܰnBywx fkf?T#VJ٭aH=Aa+\89JI_4)ҟMDZYXI׃(ORS_US[Ƕ\[U\=%=@vP5,O8"Y=%]6mzI0H_)K0l>.wR )ZL-vj5!/Cp'V54Xք,(z۩g C|D' z "9&5xZpT% -vz'57` BcㆎS}&Tyi0(:5 : HtRwKc)j<)^xrS긭Mz[95YiGcݲ9S OkI7e.5ӍB 2{2ceey(Kk]XXXv]`9DPEEE-}3Ѫ68ƨǚ&5UcըʹMG϶&iLL9l?qg~e}yG㣍 Y&FaV[O?r&4ݑ Cƹߢԩ~?pҪ 'Ki.g]l穋 LhݷS c)+C7`?vj $ur.{gxhV.37kznP7I7M;*D2f;y6U+6S|}.UXzM|;]jsrE5zH]< t9}" v@ Z3a,tS|=t}M>|\sOzO BVȆB}24FQG@Ǘ9 3ЕbA\Ru!u>}p?^0zݣ׽C.RC('~n>_~fb/%||% +x6Otk?Sn)qG>H^WBԟqsϨسu8Mhl6uF*ާVc%>V2e e摍ϯilJfSQM49αͷhf x%{Z1p"ơ4-6o,P +4jИTmnq_x y-5+8{wn}W0zh%KdhVWfvWc!޽LӺR8MI~Tc&X[Us<1=/gjjb(Gˋla5øph?YCif5iJ_&U}M (Q]HѸ8C5 TFU[UWo<=ߏ2pFqZ#-93#gjҔ>(BlQmp֘~+~e_UC,dlְڪ!T~q >O ИUEktI"2¡9*PJ4@);҃i Vgd(͑TG9du(9YgdrF wAF2:)SB}ځγ$:P^ ,g3_Yٲ5(ۢt%ggWk̮*\Jp5fuoQeEຬ(]EgS WgђL1P%PR]e`Yr#+sY<9Sg<);S2Ez7+;y*sIaSDn[X,4&rP ^pV,o4 P!2WdU薡PE#Q4NE +-ZE'̃>8dY]p9dj FEvǮ"!fRzD1j56$HӚ1ZsL5Gڴ4uSv~LLJ=}}}J,}Zҗe-=/kMي\!iZP[OhgJ(~ԏ0h.CM& lXoӈ`]~񣇋5顸{ ٽ ]k4N>brK $B])f:[`ki8`ogg~rr9H};¥{Ev$9P,z)YJ\BcU?t-=7L0cQq-)8ť|?ct$`]9sMxB@w~DŽ q` +a2B5XXQfezE|^&WT_?xNDH x&@QGՠoLNי1]e +?>Ǐ?Y>c2D|oI9d 88>//w@<)3̤NL ?>ď0՝?{wgROyN9%x%cd5^ \{%e3)/&.lخlln应wEVوvϓ:^<@G!.b(?hDcy2ĶuDڄ]?Sm+_qх*?J&v%} (nC +D:\fkmt*t3zs7]/Rk3ɰZ嶥jm\Lʤ"iʒUTZM8K[T`T}wj9ME$QnrvJˤ3i ƗR-gE)v8T:Lũ#5-u&0PiєA^MԬI_ ەO_ kx +G҂Ҋ. `+ܔ9"T0k#Qi*7eyG(AuY`w]`e]]6xM0xD⠉hhԦ:M4=$ΤvI۴;^37{y{wiJ>SMM,)O"t]-)n~]6pDo}=׿%؃ +M|!.oNP9M1#U3&_,UVSSE嶶i] u.XwzHb=xpgيlAS!|(^UEUY\QYM29m^a,-<ٗоY.e|9)-0pvӍ*-M0 &]*pĪ̑,Wi*-5,TRŮ:&5UW27j{/h*u]9rFc3e.KFB|P e;GYli*.RQyVe(S^&OF{f)ӡQ]FV>L+y>FG*^3T͑[|oF׸[SQ5SӨ|3kWo2|ەۯ4 \UZ FoTQ=Fh.& B +}/P06Fk[yoHCY2uLRz` XmJ-ocB2)f(= &rkxȧPPɡf%*!BCC݊S\bo+6znڌ5]0Pp]W>mĤX6&*%p¹J[4,p(.ܨ0/6&|f,4b96Dx5ƌ@=|mA{D'Rb45AC[R@pDT#EMaP<0iBSBca<}P{{$7eh6ugrј?v6ʜMncښ 0mx9c8GXfH⽓1[s)V)m)nql( ".ɣ=åM$wc:<_O&(ӧ &⩒iX tSK(kRˆpp [eg%yt2'9drcN/8&s-[ֳji'7UjCm^0}ƛnr ]"W4y&걙ztG7B=V6,Ԣ\1ovaM]QD:Ro ig3tt:~͍[`+<(f"$#I̯e'{5N1bhof=Cc@~ Wad 0*r޸ΞqM&:$fϼɀ$`8dA>ؠAd,-=qB~#M][}wuO|ʯ~g ryAXzEa N +n2.SY4yy]C4b9eh'{̻Ja,#tZ\S Z!}5}L>U3 xG;h^ms{V3]8 +Je|INS4hTO[}?#ĞIybZg)W*7eƻjArz}}Fwㄧ ShGV4\ԭ~b&Tb n_}ث ѫmM-v,ϵ'`| />g,ƒ8B-^T*G_L|7{٢mӉ9:w [iɨ Fܤ`< W;k,ExNT2yg?fۈ_FtA7 +Z9#9NZ֓I:Y' +\9yv2È?#KBh&t0UjgBF5׏p6XfƱZtR'e]o;v.p8qNlp9&MNv-mvJWrT+[v h5[@QZXA\1& +  +!:'}<_+Qˌ7ъFQ4$M,c]OxaYEVW^eN{{J;Q>!ctM:^FݏNtf6R;Iha:fmMEQڣ^C")RQXs< +uM!}*FjT tj"W5=dƲ7k 7,jpV7PE,+s_ܴb%4J{JCvJ.Ym\)Weʘ&+W*ߩd~ +Z4ZHAD˜*@#S4hтk"6P:MAZ]ƴwRIJfa X<1ٔ0974dnҀ9~sb}kIieF˜, WrFAeY*]YzJ9ZM `<ĉeȖ" X-V(b ֣.:c +7(hߡ} +Skj.7-}G\ܓ<:B %CYXc)O/;Qb-SOYrʫYVI6+^UrD~ǤZ[ث&xFNjr;^Ɋphƒ8$:j0.kQmRD5jq*P mZjj9Ffy|Bu|A5WU| qOPٍQ4` z=^0>Eü^P.Z\jvW]/ۧv5GT_?(g\.&9=A6Á23|43 #7964U_.4&ab1۸zsVW6t-ribAL"c+ǶDObIcN9TYPs46LJs;0c`w^@nwUf 5V1!a5&9f6Ԍn&لnތc+Z$_-xIL|1yyuz8c}:`?GgisyǼO& ٷ=0ۃ>9g4OdNi8)<|.[O+q8O^aX\ūÚRZ#u}g\"ӿ30+FHaW MqM7-:uqSu_qp?a`ә>^h^; s͌I.1_^ }C~w=ue|>r,!݆!ytVLX1K/W[e2c̦Z^ً@'~yy_=ͫ O8v?;NDZ%n;7zImvݺ6[E֪] Bҁ( ʠ*kT.T`@`m2sQS>w{y+8!hn X_8wp@7)82}]c^e?̫ +<߅o79|NFb-COoc\#Wp9/|^u¹|<~KhM^#80lO1|e.c_ރw&2؉_3/^P'=C%i/pZO~|1!} +"zARBLy,|>Osyx4c$csyy0;G{ W=hϳ<*wnY6e6NY]adZyN8K΋eT/·df }?edNaA{)tg"֣=Sqy9 ܯ3 +OTnawj~ m+'`6@;vahO0y$>f{;{n2ŵSϰހa<_֜B~c7EE]TK2/{]B?J5hgI8Zrs̜y)u&x"<参 ǃ-hQt1"Eo2KnB>@6X=GRff}6CKc@ ZbKI~hyYE6VhF~ , )Y}E SQiT]ILkiS;,>Dj+>V%%9ib"6N&!ˀXf2ez˪cU99Ty:;QޣeJZV2V˼jQAE-\RrU!u9Eqs mohn0*]7t ԵTiU)CjꔴXSҤZnicƄYEyj0*h|JTgX>E:'?'n݅=XK۳|ý49u_;-s)(WaQV+TѦhEJgάkpnr*[yZsrW^Ru pSngN5pwoc-u@[>C )VB.1WljtU(r+RW:긂 +ܫuonkUsJ5_#9ϫ}*s:Ļv|OA?tbqo&FxL +y,j+P[ZޠMyu7)6U>(g9|'e="|Ruޜp-ĺV|e:^$Z"s~|KwF@܁rҪ d%"#O Y_%xQgTxSJ}NBw3h&hڡ{Pa\a.UF|rFBt-:'kt,=2GWY!D.5Wi8{ 5سly Cc~;7zUSr cN1d5OQy|Lj78SEc*hct U +9?ހڣس^V>7CPǵIrag+Z +eʖʚpȒp1xiE%ɔL%I$1ILY( IpB'Po+h{$qh~\r߅uc H^"sʢ!Sʩ%) +S jV `V4NaRRRl֝Iّ]hϠņd6h3//LH/S/9t5Hu i࿏{vw #A<0sqsc,1|rl7mF1f#+>i<>]s 4y%lH*P_rsN0+8t&ܧH()^b)e`.ɐц?:񣛜M'х.;q+\̎ ')'/aS} 0Pc7!g y?QK9d% .5u!}0klVO)^ތ6)`{`5=0XI}ƏuaK}u\kWr@nzcyGY<D^%-ći 5M7a&X90Os6&j>괟d+V곟Xl!y}K؟6Sϟ!s=U|R</hr뭁H(!0 XBqaC*5?+8plI>| L}_cuM;9`ͅ9x7Z}k -Ǹ(dD\,FN?#'')3q˥|xCulb3׻Z>W]yD&Qp$ U\0!Vs%q@ϓs ,QTg~)!ĻeW9IнFsƺFA}pC&k@&0@>r0u-ys% kTmr YWIe{1܏-S׀CX5ȵG6(пјwUH}r:~\eM! s?ΣijOZ{$U1#1J ]v[>_mpmu })'hЗQ* 8fy +>=w$) t9Ïa|$љY;6f_)b 5خǶ&b{gbx O)5dt;mG/Q'*;)p XUf{&wѺИPn.NVjd ~E=Kx:\?דDtO`X >-`U2K@ +\gQQH/5?z ORz^Nl߰Ǩc~g;h$i= lYnl WP:l7`{'!n-n_%sŃtAzDwm_P|ت]>`tdJa7#u:IDQR-4,MGZYmbÛV͵ǐy,G1C,E'9 'F;5:KQL䥅L>f2H6lq~+93=\ssAOǾٚ5E^8BpDJ8jnV_D*P#ĸc7|8V3pw1wG6Q)pd‘GnRx੅M؟Ld4HR1è:g(UW^1DwAýxK#>6s13:mԐ`ˀ)𔰓U W\ᚈxC v~nw]Al}`hi`, Y̹ßI)&;U^U'4$yRTRLPij݊.V8uS_T(u)G9%RQ}_ι_m>@xV˻JP=Eՙa2åL2TYrEm5WEA{kߢ^y䶝UrF8Xʸ HjFJޗO4:Vđ,Y**U" 3X|WF\~96>>`b:ɧ20ہZyVJ)7WJI*vf*RRY N@9U*!k]S˵HNZe^+쮳9ALk=YHI;cQ5WR> BK?/M< +*ϗ'';A׃AA?L pew^g;n ,$$\ T +D8V^Bq2ZN6#2Ң >q;9oyn'[鐫%g+{ ]Il% +e VP!d"Z "8<<]LpUq-@ԉhܛ_! +c> ) $Uc֥ &Sa +(Hw#)<as29C>q-JFP .~1͵~L{ MHi 4 -JG ll+@5c`*o >40E70cۭ +W/pdK,1!a7fF3bll m B&xjG؄;@ |Ro.<)> ?:cm9&'4^6O/3JκsܺbCg\o3@jiy\g6^g8 9@/}o1DNQCbwD&AzkN# -:Ncnx_`='d62!'#FW?r&eRR;㚅ͬU[uv ~&v6IZFPI`%XEnE㮥>yl>7 ,f=F5\3KTh\5!%>擤!s`1kD- ^[csX|0>CMlFY} s$A n–Z5d||X`5?b ߝ%b&&ϰo_`aM<~H{xy71RX:8{WYIň%@#_&A%WL$u8xWXQ>8B>0uUJ &^pKd|G|FwUV3]6KD_PLpoFp*%U~/N )ڇGNvSO8jQv85mjd+~Ɵ9D!Mǧ);Lr+jOU,U*.V_ZUbRmP*Q!y7^'q~&>@^gUcS;Y))*wzT0TjĞb{*tT(Ѭj-JsHOU/Zl( "Tr O%*HV^SSSI++5W0*7BMJ3:eK1VmlxRS4Na\ɑJb1ǐ' A9J@!%7=A9$e(ϗP&#}cr?8ʫ +o6$,fwI6l~vIHBH&@J$ +$AkJJJRZjŢXZdZQt:0VvږaV;0/۽=s}o +|ӷCyd}Ke+{y3݌slP⼫`M2|ey*(!Uh+ت`>9ò7RN-F 6`|KZi +|A|lr :)wr(4KP +Q~RpBpNˆ/B׏܆hDѲ!|PNc%|a#hpJF0ߕKżbxLq㤸Sn~ǐ Ѐ (%]%\a8g|JHlHOq4di X65|ՆoexhE0W!Д./n{y೎Y|< scZlŏv0 :rEE0&u٦0k@3nIk%e o!ya|HsvB!'KA#KYd>`]*Y Ճr\tuL-1GlkKx_ o8I/9kA!h.\c 2ꄯMS~w9Xeqrđ&fNjn q/X6,ao=puV?&kyGC&g3dL(9!Qjgky?ۇG>-})wžk) +!#6ko,c\ɊA(fC~yCv&ړ{OK߹F*JyW=烀% qe#3pH\΀j<9y{@&/|N:gT "bc|'ku4Jg-_-__߃?[mrrz{ҿrGQ +-@t%"}v̨N|StLF8$P3\PEM/3y^b}"3ɹ#LV92l+C +3l3ԑ)eX%x?<>j* + +-tL4&qXsh^x_xONjqJtR{L(P&˽v+p^Z!3Ne8qY Squ sa(C2M~] +{mf{Lm5:'`6?)=|w|_APŎL籟.Li$_y=Bz?"kzDZ}p_!B%}'] J)(<5kn tb#BŅ9!:NwpCȎn$|_)nSV"xfO*xlyxH%k7xxSspd;I쯇o9r8+[@ +ԁ8cҕhC|E\ +;{Tn6ٻ4wX܍*ɝyyrgEo/(3?do%3$$`BH@ Ud(Q"EED +TPM(Ȗ-Z""Kw;=4s3_sg}ߖ6(M@rAk&Ь%vJ^ ; KgM@ úZ|u9I<9v,}l+팸 O8:C_ mk<b$J.!)A-A&.~OHtOHZsѴѪŭ$NVi%M["VxsRܢx:{u>4 gqYBzt}N}.ѽzDEģgq%+ġ~ŢNy}d8/aKbrg*bNE} +A3A "M~K[4[<~M [[%VA[rNj?]༆ey|1G@(h`*]S@K!M>b Gs)4 N_(| SC,u%7$ђ4ų `6уv-dwCaآļb1a11NSaȤϋ8!5F -ESw':{U!<\>y0?*>⎤3&C̙",\&57K?GӚ +4JC96g! -dSCI23!rm3A{Z"%I cfqdZ$-*<|6xcw!^"0Å("qkNƤ5!96"M%3 Cso#:24s4/%RLZJkM[f +ESjhrٓ\gRGB %xPEWjI],-VI^T0 GFZќ^IRkA#VN,c.'ZϕW:g/\hL1$iRUkkuRG[bNڱEAΚh˺نTIn}Rɻ@S3$( 4[f\" h /\4DSGwΆ݊+yލCF3gDv6gTT a[>u 4UFhF4B@?hI| baX_MbHДt%0>BS .z$f*|ըj@8:FF0'YPyH`pΪ4M LH9:KFf T{|jHh#OS4puddq'qm*i~RRB7 ೛%ljۛ ZoIq@>CRM}jP~D&%x8(D笚|9*Ŭvh֘Ws/wQqN2,AI5F(SB)RV$M׍luxUyd./(ǘn+ДЬB݆j>׍l[ {T38؂r99<cBvOUdN[`(Y9y +6izEqe-Z^Yqխ暶U_WݱSv7٫w8vC 1r17~¤Snco5{gκos~?.x?.|EO<䩥˖xz3ϮZ k^Z~Ɨ7ymn߱s[{o{>Og𑯎~}Ϝ=ϟ.\JJ]IYWQdg+/RKrR+kAݔ7) nƃe-ʅpa2b"NLUV܉w+3~ܘP~< y G+K<Ô+/b:&e+8fMy[sP>| T}<:I?().^J>\ͻ%~__b2lvǣaO G8#1<\|LҚ7?3' t뮶;f[mq&O6}ƽfϝ7 [xe+.j[ȤƟILiLT*Nhj~o'G~83gϞ;w?]pƶehbm֮-;zW_5a3Жj꩛sӲZdOG. 54PCC 54PCC w +u%^]/9 _ԏ-~kwe ܝVOѢ'~HPG VFծ=Ͽ1}C&|ww>/n{y /Mٵzo.Ѳ{_d'װ6Rk]/޳̾{ttp|gvzffgi;fiNд2/AoF)TLP. E["-)'-߶g/yޘᎀN"_ +)Uka"a>W~ՓĢ ?J!&vezzc-̣>$CkSFkCe\ )j3J-)|ʉ鱶d(;nZs>w'C71}fDmX4 >J6 3O;F.^hW}F]υ +{E"f(/c`4Ѭ7h^!}w>85KhʙHAΡ 5.-F\ |{Gq{im=/ZtUppdK*8+#KD0 +3{717@AoPa.57d0~DK2qH9yBCOmHLU1tՔl2"8dX2, K%e( %6@du= +םj^A\ˎ*$,!2.KGv[=ZP +$A=]+#zw^ XaF*bZ*SRD &^\4h`C͏@v~'x<\վAGi]8^@(WI<}IXA-edYÍDVa( e Zg:8QCHz,I^PQ%xI-02,탡2Ad jk.s[g-HQ$Xi}yJ&E|Ne2@ZFO AF# zw/؄9Ќވ0RYeJ($9J;C`M􂜇}0 P/69&Il됼:y*LYT~?W@lͥt%SYBfaC*Pn;ӑW_ހ}]M*'(bN)%O2qbzȅ)}^KgX $'mo N_u_q y[r=P"fUdVp=!:qܴ.K``ZJ s^9z5-&i *ઑ9u(I#ObDQHnƖP VKE2jVwn '\G&ǼԲ֠m0NJ\ɰuUH Z %4Y@" 5Pog1ip`䉳ߦq/g(MEɱZ,T"V $KM2TjA})Ï9;g/(Ė>Ȝf+Z5b m @92v~ jl̆q'G%7B#~̇ސt& n磛#XB. xю?S]1a^‹w>LpP8:H"Ol@H4@D E> Eߧh x 3{ =p~@bIb)y`o%65~) +}OztGr( yĆ_ x {L|@mT+5s7*Nȁ3GR]xڅ)|9x^d\ \dyb.pPdmkkm_"8'q*)c{&B?P|5 +b} \hXL35j1|%/h`?b!4У( ^@9 Sa6r%'Pb 5A(=)|FIS|F!'AcIn#V4jBkn    {C.bE aԞ=ag*"tVP*GhHLf)sUQ͚H%PY~5[y6V!zgkhpwK +Ly}\DM3 3]WdkijJ$#d=U$yA +7B-P%P_6`ׅ3$}N+5AIL62U`#%yWFSE E[V\Ks2[nh`ԱCbx. 蕽|Đ +Cű-NV>ߊ=jVy& ޠe=ή0ۯk@G +*h\̰O^LA m(U42fwO'pxa0|YPa47(t%1 Ο;\0^vwvgԟg oB l;e^cdUd ~Pb07(PfG?^;87rzĸ~_|)8Wх5SSrITdC!b@ As/=s߼tD[gnyQAA$LN'3 c8FBm}.)u#=g4b4~noUc[Q8ܾMYBy͇fBHOI8t8:K + |H{ȠLdT}ūoݸ\7gMӫ[e`Gp=ϡnO"@EdYs@\4yjlflV/o.=ٴBj:*n%}lNmg[SeJKn/T^P@QQQ@@PA/],YinmyRؽ +e[ +C>yE@)H;a#ssEfKϖ?,?_V3|~lEfAx8䌃XH?Br_({Jh3[^^0_S 3`p^AkOot7$磐dmÐА +P+6/ +f^ Gp1~)$T1|RB.玦TMI千.YoA777SCkCɦC ?#4wPO?Nfo0qZbNYLn~(VbOKmkZeu8MB ̵Օ??#Ȏ,kNDs:#:'>V\9Oe t̚R2'L掞8Nhmנ镡1!?mb#~GPqEfV 7UO$K.R+ \f9\cLu%uMXyߪoNhkGWF 5Ak(9ԁZ$)93Ε4RfiNb]6*MZInAӉW2v -&Ġڷ6[ɐiuL Ye>3YK@e6rU/"4 SjbMCb"5b@ ЇIUBEI*w:SW.+Է[i>9Eߔ+UKr7Se@p^*6A3x!Y!,!*y-vANEM&ACӫ cuԆnvC$e^X_/.bm[rĠyb g \)ƴ&} IQRVmz;hgyn46,bhغ ;WB;b>tv/KWt:A`jNmg\}CEŴ6NΠ7Ҥ}4E111t"/,1AaO\4FٴC AJd2ȫ(8Um3R HaD ذ$[n+A? + cSΙ# ͺvUD֜Zא )F/ +(F;Lj! +14! +rfס^w Y]1|6QHUU5gvŹ=utsԚSͳe׈2xRKFEMP81H|ZOgk15zq4`.dzXFPV(3Kd&Z/asbP+KVPBCǎOf{~4]=|RPIZ-` I-|M)z圾ЂxME os?߻IocA?c)ґ]쉗RtIZbAe򺣕EHE)B)2*AW8/1/o\#=s#ǒF#l{t%/NՓ % ʸtM~aB4|}MG 5 qtl^44ra8((>' ) 1tIDIz*5+ @};XpgӻG\^km'#!_ٴ_DTXrR,-s4A8K`qqY9UX[~M6®QUA۠]tw \ԮUGg<6`**9{".#u 7 '8́j');m{k&h ho''DX_A!NW1K)LY[FfZy on: L㆚ P 5ۗ@+@t =  򆶤YIVS~AƷST*e\W;^^'cF:/n΢wt@s[\d FPEt$H3>eOsJ0)/(kh@>Ӭn fvhN1{vgo'h9_ >u6EgZcin=aqWu7h4(N~ ="l'h0SFI721MGMl/ 4d`B mȠ84'<@sgV;5Q9Ts ny*rQ(FRiھ,&#{ZsJgK|ݶ ۷6@|ftgB&'=TeH[H}U{˚6˪Zs}I/S9K 'h߷ +T7P1!O I=;scPcƪQm%WY.(IM7ـ Ad|LgGX"nJVx+9J%rS}Zd5LV%THdHm/6%^AfdP] ={}-*[[|SJј*9(#6a"[R)|Υt9Xe*\of{{8 o@eЅ փos{Ȑ選 WtEi2ȕMe*icAfa<&ZOki*QCP:gZd`"/zn߽ʯ'mytSqф̚t^s4{g%wQ5g,lmEڬJgd୛ m?gz݋NP*|3I;! RʼnC䖸 5mkey_goMi#֊NǺ_ъbZԊ"( D K! ـ!!@BB "ua(nXQHU^h?ܿʪ@-g{~o٦w7iaݯ'^ EQG TŶȟEa|1Hx]&]-E"͚`^?eܡaWtLmqu~)~?;I _)OԄi_hY=A.3+ݑq+rnW-n/^2禰gl}'=$qϛ2 &[ftC2.L?+N +z*)ShSes s +)[+,vU%8Zyps T z;v6ُ.3 -#0l&. . x D ꞏ|ces`"5^Y{JOD'"E5 2p!8 ;Bq(7n\v{>F+,Uyv.5ก +.I- +vA@Dl 8p}!:.uXb,15(`ռbYȅK2Uw ׇ _ yC7^R@qX;o;w]8|6s\FV[a4,/Aqp[k=;\ȯ f+7@!H26:C6 pm mlO +8{q\ׁD!P@rԣag +BdIR&ԉqMYϢhc.ƓޜG{a87Nso5dX݋`J#o;A ccx⇿LNHVvL7(I sU g F3LcL.SITS󞞹's1{.bXܛ|mz^y3-9D^鮒d L4T ~m8d{嘳@_h[;V'(PJIki)%F'\WTonuwWIeU'z+fjol/c}I6K m+ΨU\f\VnFeoÅwE*I> fh:֥ݰ˧֚.n&(袔[1Z(>D$h $k+{*%KGuS[o{d<5mq|셽qj??gpzB9(RF/oeV[׃ZE-M]5rI@.i' 7crk]:_Szp؜q봋sd 2hD Ӌ>n_ҧʫW\[1(\Ax*P& e~Qaўw5rr,` )||dh2e"1!>LpW1CBzmM><\( WyPzѿdf--hxomP1^R#g¦iIIVD6)/D~R:.rЬ,N/TV ֭],[y +)u߃'/RBHoƒHgyQ0 +L=ED] +DI(>݂]+Q[W_M[f1-cC\ÿDa)5:6`5\,+E$Eq$rV7z߂jZ'W ۄpN%4X`E3@D߅P Y &( Nv /Wm FI,ˣF9"/*J~ ?*\8 'C| X d}51RL܁i k|s'Z8B$1"۳ uod8:;r8 8DC+D8CN@;)/S~l ZCDݑA5"*{&#Ud8p@>3Nl ]80 {`ma CVsX@s`5Qd3c&?.n)TC*בֿ$\)/]N`,w[V6/SW1F@g JUTC4$"1 Bg $*AHP ' `jAj9H7Z $d;A, Q^jC>Ak6*8$l(|g<59jCo_j@nEDioK 0W, `{kX3_*yBJZJEZ n $/F.D>y;5?5HoCIH>,1Sd{jC<, 5ujS h5<:y)!j@Ky4@ݿ4$ig>3MM$" q:y;*CaӇ,.1ҽ?'qL.\|Q&$NzEseP ONM%O_P@<Ґֻ<eh@!Z jYu&o5C\D.S^GU$ͅ`̐n1p=pS4\:9x Va dYˤ~Hg/$'gK'd= iN%  t=n?e5&S74!i HCJ9@ї^\Z;=z4C1O# + FI%>aOЀ~9x,&i<4А͛lG68`H7K +ANmtaLs)JM + + +.QY2%Y")u"bb] +q@$8@50Eڿp0̿bv9YCu7DrV,8dI6Rr<ĵH i(ߴ׵G>trÛV/,أO[C0L]5SI =V E fKt XBkUSjOL~Wi_  鶅 ^9k>=퓝#ۃ͑QqMzZA(VIXb>Yʙ,uIr- RzV]@j +齒B  dW'`#g! ƽßo=UǹC;|{Z#"[o]MIjRE6') oTWV(VX5֝U[++h(\Aj|l>m/^7K>fs,ؐ'NYJdXʮK2_f dzh F<ߪ!zA=P4;A%r@Esw]kЙM? _p8#,-:Ym+jQYņ<YK G*hez}I$jp^ixo\GJ9t[ivO=W{y{7QUmqYd +݄/4s +b)R$Ī8V}pKsةUu_8t#Tov4t_6=sꋈw]`X ҊsdU4a|S$$E#LMaT! LdN)σM~kcK_o}vvo8~,x8<⻘4j̒byƉ_Qy"Z4`k0mz{i4hހ&ǁqܵy 9O"n|@F 'gR> ݈6fYM\d2m&Vp73pp,gnWA8vx2 5c/OOp>D962{"1>m"S^gEYQϸĐ҂z6 +v|yl@jGr j`bCo+ o=]ޜ3a93WgC3"㧉1ԸkxI!/)uJTm sE7Cj?EXzf?l^s_);xًٳa'fKf`cfKʂCgy!$a~W}g{e(]P;# Q7la +8 +` xd( yBr&gp>;~`}juBR*G!lu))6<קix A;/CԞPH i =H1= bPz\Qoh<-^(eCUM-tZ':-"%,X8.λی-~^m灴\qJw֮ udO~q|2PG( ac>lpNj2[Ke8vGEłH "BH)$${$!H*(( X.l"(3{9W?p.Y{ofF0  dI_}Rb/Wx"xW]^ <|s8ųq0}<Nb8!cVx} sw[1,b]YHLelQuҬ`ZdY-IVQ¾guDY@< ␋ +_x:[9pˣ!5Q-e'& +㤞-Pq$FDk +(ܚ|9ǻenkxn1P` #|"Ȝ̍j]w{MEP[[L('1F:רgKjJPER+.4ŧ3M7XN-Kt_>kDP"ga^c'qqK>˞^=SgsוGŜ*OJ)*JS9ZSXW +tr]:ǐ,ȣ+*,4EC>UuӜХKe"[q`/j, +IgMk@76޺|tŦڳ1ѥ|~y +M_La˭LQM-àͥXL$}9UBȹn&;t$=)Y-0epD`anj{9vZkgoaGQudC g Kv1[F?!RS +zdH4%Y0aN8u)H d9s8g[lIJŴ\u]I㚚G1hhjsP+]ռ\}xn~sDr^G{TAPI =uz:ڬ5>tk7ͤ﾿Mw/uk zDs7u#)y)6YAO9e;푷T֦P{@!AsSwZCRs?U O>Rj&;ߨ}M[Z +W}^w76MUK,Ց=8RAbyڰsԁ ֫ uTqZV"D '(`A^Iyݿ20duQ琯UPi5w["I^OjfƵ<ɕawY9*y;zZ]k^wiT4لݔxwg 10dBVI۰ՙ!NG|=xa~iw\p7?W^)m,m*m+w4XƋk/ TA!GRpn .q.qst [q3c>VFn=RRL{ e"Ibw:C/8hΎCBh$3b\PpJx֮CyK2c~q_vdrT]ptInpF"Sp},t66!l"FMl I3Ff9X!AN{H+RƍQgSwy*wlHڨTG= cpsdX"[,G\Z $7@t6KH  +/im>MKH{ +D6XkBA2]d (["O@~bN{@i 9Z F?x9 ϙaciǩF9ݬۜ{1HH@?!i&Ri#g.Qi@sTnBz!<y1v> eJ ?Vެ#Cbhw/e=(}z,~L:%|HŞcdA@6}GnRŨj=˱j*n_J2}rcf32gҎ$MIٔqQ~7לG᜻ vfOJsE]Y*HPkPNaZnZweCI~T~%c"7*kHNT$Kc͢ܧEw/ sGxvt'g@B6$7ϰ&5oT#G:i)E edY$oH I؄ld)C@+R>}/Ç}07H^0iƟRO~O$,i,K0)QN|BȢ`z@`/A\$%%!5v_k]7t 7S.lt9nF f=ް|܁Uǵ6[B!ڐgiznT[$߮sڀxoʐ8dgWos0f3iApZ@bڢ2Mq? n.a~DX+"UP"  "d&R0 w~T]sJ/)h +k0x QbF-&*E jQQDkbaĠ8?R9Q_3kỵ@` ܦO_,Z_t86]aɿe?'#a dëcV[L:@?}b#o$`W{tC +5@; A_m@%kPkj~CfeK0Jjn@A((g4:I?|kXyI*x $%Rtfffjj3Q*jS$bZ\uab'q(\} Tp0zSs( 2A hBmT‰c4탱!]~^qD:M"!#M)Xag +'d&n,D#fa$ȋO0K!G>(B'j m6s+.\I9MD*9N` (7Fx!$fツ^kx]2_K,GT-t@B{,Z_]$$)\Na8XE= Ìzs\2Nl숄^ RMVBd2ePڠfV*`u}P\\cB瀿<JmQۂG0ց~Ӯ^ 7Pz<^O$B°7yi}>Ǎhc'|>B':8<WC𼍑2M0,؀oNXׂ䣮wvkʯHH|;čWH^: 4.x#=h1, -GrR:" `q'yq~=@$= &j ڐw c!o& 0 *r4bY0CFsȒ,!M[t=NU")3`^D`0~폰I𱤡-YI|89H  #D:#eDN3afȎ\E%+!_q U7xw܎ pN}!kH) +'c-uh&W؁/1("B`p7Yke9⬐˶ETxATGLroc?KO~K RSS?{i_c#:u6ᐼJUOjoSp +'r"Rqΐ1QcM#)'XkF/%mG{~B?d%KD.vX5u3Qi`slBE|q볢0H+z/}+K~?Hcd`v1n O ?dh=L-6kq=NƙLR +=d,GJfb *`[%ƶh>U^ذl`=>ԧٝG0odg>$nޤ__I\2s)pFn[lu4v?5c5vwֿ) eG+ ˙%5oDH:2p~LξɹΧ}⏰O2t.KC 7:y, TzdVG[ʾ=VF9Pis.)/w"`8P#~}bC:1J"n!ȼ=sSbMsF])c~.SPnrn(W%3ʓNcžQ[=T ,BBxyɮht9e5hp[Ԋ˓vja̭J9jsT}vi.|oC#$ +$Z-2dAC.q {'i:&C D,{ږ^;2(+r9gJ' +*GUYs[eu-FvAdOse}N6V i(&A;}_;c䰛p­s}Vt*YIVe˯W6嵨~[TsdJiujejekq@H[2YD,%!iAGF>s:jh[i~W#J:Q#gW *J-eٍŻuMj*UgirYB?uz@Q5B];sk:~#-4)A)ԡZ I - +*HDP]@?8*~Yѳ}ssv: {:,{~'ŠBzjZƲԨ3Y i%9ՙp0W(D/D)췉y@4!M?a{g6-—KR.~4qj4h^\:Y]_^+(.*N/gd)ŒԌ 񟱒@:mCySn~c+ǯx`q_8ΩZAd +ёTaiEfFajŜ¾#E%/KiG $I;8-88 w>\/~e*=3rpAO^?۶[cK8!)LjFU^Y\Q/?//[>_LRZbٛ$8I rԫ⾶oý؁{q{nvh䘽a^k]gOhV0qјĴdL^M0TWõO5Ki1oxU+q@6\ET)I}QFˣ{*޴!ݖ17ݶa LjiO$3#>$Mr,ȅ#q)MU2Cu6d7m\N ;~8I jTDfl\o,jo: {FeDzS{“zbb#; WקjHjNgv̦_ -8$t%diF4;$ݑFSh䑎T^Ŗ86_p& ׄ!q쁊D$߁!c`V761=/{5JqP)^^ >;JBf6gdtmB᱃F՜ACƾ,ǴPOhޝ6wBš(whñԉ9mb%~cPI _}8-ۤН /οQKrk{5.T@%uR=w1щXE_R^K>KC  />/iE%FoZgaAլ HkU-ɫV"WCW9FHՔ}B[Z~Z/9})gOrveNfB82GuRbE| |#5lYwT [`wi} ӣ}x={ɏPcMeC0cy^a[I2ކP_B-7:=P&\hΆ80dWPh' bpN't/}hc{6m@]Ĭ Pet7||ϔA$י T%OX黀 >]4.#`\5ƨ LϬ_9,P-R ,?S@5"Ib-adVp'EBP>0O]QM^[TzYuQ Ɛ9! I@ @ A@(rUZPE +*Ȱw;9]笇ظm@X  o#D/a$vla,|Fk~`We0;xۜ{!p .B i+n hkrx[6?nǹQ'q-[FÖ8āh=н0 D Aq1O#pR=%~h@m 3@ ҵ@ez$|e[IZ؀ ws*CfV=zG%v?&W0e 'waO"w6x   Æ9~/ϸnl$;C8 T7[ځ|فa䮛 N!F#{4i!U!_ٔ>oA%W;9-<þ$`ODfhl<%n|TQG wN::>r~u.;Zm`.W&<AȍԄȾD WA3JJb;D|IoKIyO%^H>J3*dS +4p1:?,y7s_pyP]yW~1GyFԦЎ'XGE6&Z,L( %;Hi{I 2+F,,jB&)&:Wn*J.eW{;i4IsȒVIT|(0g-$Z.UíN2 +TU% iC +nE>rSiT՟՟y z ߾C7u27ۉZ5/[|ٲ[WjʙN[QM*jmU-M-4cR<7U>42_%di> +35LA,ty ]lrxOgwۂ_;CO=aCAֶ2fS<֨ThX%B}0/D=$קUR:U)?RHӎ1thkuNf Gkf,ںkyWS:s-=hUR*S Y#0deIU+*"0$N%ǘq5@:g6t1f_Km^t?p#`:Ἇ7R4ԲwVW e2raS(hr+F$!ˬeHP<3Sd[X15@ cbfq݉Ř]K0W4t QrFVXY_aS֗pRK qb\&-O+=JA]4_8̗-,qi O +1P= f<^g̍Kv;φڻp;iSe #ݓ &ZJMr`:/2O_^*yNi7.*a^\W<ƴH=;af~.al̽s0W0}Wu8/l_t.ҳWl:j~IH (" ;BBB@aG(Vԩ#.uSw +,0EtVEq=c= bʎϼO;~|}&GPnj'Stbo~~́ՍҴ껥? eUe>6 S9Gg?2ɃVEnvK7rk. ^H +/usYq[[ 7sbMFuaӶ9Y k +U E┆u9&NMit tIn3 .3^9w^SǰVՑ|פЭ37\X%XQ"L{~:ܮԶʬymdmC9TeZl7$chI-if+ qA3$MScCV{n Э _}#/zq|εIJŕJ*-A#HOr{kJxBrA7좑ܭt~NZn2I##rߒwYQ۞7<{7ú{cDfknNS2KR2LH.$ &zrX艨Y? +^3C \?bY>.Ԉd#hݐky˰qooLlqd)jMlp-:2{-O)zIH8!J"HX>--t?x9g#0 ee:@i5 !e96̰p\C8hՇ" `Bʂ,R)!*Bk ;[s@\#/x7){4<ǃ.fqq!cBE1"ST,B%W"=U^jo3v+w)n࿡) +>HmW] f{!և‡ T\cMPCj1de6C!>Q DHhu«)5QʤL @JM 0&jTًH CָCR6 Qrq Zلq鄏 gLQغ|AACil2} fl)2HϠY_8!e+<8!vCKľāIp1\h"G$wH +.HpAFڕLw8(XahS-^dltf',rw6&`FQ4%oL::!Az;׈Qɛo%Cҹ7I{-GK+ D4ȝP*yLa5%B )mP1oL6Ɍ=~iޫԆ&7rGQo1IyCWW/dclLg)BCBt!ő,:飔c}!"LPƷ:̚ bϱMr6s_`kcN8MEqkKXܪ {H @ b B-@"D@D +A^VPֶ^u9ߞ3)1 ŌyD>$ < {>p}n0 1[ n32+$lw} b:XۯQ)GrU`0kq&LxO1 Q f#@O[ a#O}kTm=0}ډ}Bs"oףX}i$6hWѰV0+ +s~1e9XET2K^Q9A~E6fLH@S@V@((C^ +d!o5n3aNKǪ]/wt9Q~uqXN-Q1J8yj^NB03S?*?g$z$ {s羚P?llew]O~{GI=VkȉŔe&tir:NfQJ8Y9$Q)JRR^y:m<$HX|\^ԯsv-K.O}ݪ7rV>VANfgf1ӋjMOu^>/NPJԷ$?IIeH\@\k X +:G.5yionm>KWg(Kɔ4m#%']ƍϬfeiƴ$:7<-3.#%. lb$ zob0[=\&:7;/j;E W_v_U*є(ɧB-K^P•Djω^H;)ʋ*|˔|J d!"5.7 Eg0ri={vUM-ݥ :gv_cĄr5-4uFxb$[ܒ\A?LQGl2d=iv'poٻǩѕ7w6qiD>YP|]>&Q*4qw mWB-PA;?k#t{h5h0phUw-uHy^/;,1 +0idҌ,M6ɍOhoht#$1a-0 pF;0r]m3`fouw)^lw+{/J#E] J ˒B'Q:*(v#-3>xJ÷!a m̝`,߷A ,hrO-i~%s0ɇv9-t9(ax@!p`9 l ,n0aߌ@v;(ݎ[G%];1MοÞOʾ\O%(wƁfdlfGmrޟ~n^BL Ѿ"4 I\dLCpfbc!Ń5RlOh0P¡Ej9Nh8b#MN dBBgCbrDd9CVI;hdFo۸O@p꣞Sc>k ᳐ENCP@^ᆌE gސlB@|<:S!RԨ/Do/G [1|l hf;U:A=*$(j='os背f2N/d~~C]'^OaM)^Rq|m$ y$ rȋACrr]3CS2.TkyP~@ȏA~6dJ +|:a9z[ gBƄ>c8i80 :W=79>Эvc4ۂnAPAu,lȗQ!ѿ)^E*T'* d#d@G4LX( aaV4D{%1K튢|O"Ə y%~Gnwv?DsdڐT ߳`F5}E=z&L`dcn= +'\y0.+\2lZb憘gMOsN=ɪHӞK{*+y&O\0TAtLi/vNuĂ 7ucżsJ>?.\0s}Իym9,?-wnog\?]}oD|$u0R.`ḁS.͇=/4[/[$ɿ(*n)1wƎKNw=Rv<[7E)F$z".5,uL,Xo?T48˽oҐ17*fhiHRRF酒EMs-3ԧL4'L]c;ڣϳۋd)!J~r}EoY{|_y"űo2ksk._YB|Ʋ.͊c/5K9P|>wϹ%VKedZ n)J{4/#/x +b}_`߻FܽR|~vLU k,WTy|zߜ_);qc2i@Vs%dM}Q ỐOsڷYVp3? c> tF}i1\Ci`mrkU{*7iw<狹_(o3~n9h2m:oHXնf>L0?I8XUA)ғ`B(@( =jjA@P((2눸zQ 3{f{vV|>_NnMF*1&8xxot~ |NΌъXQuTY٭9.}|gWF>UVJoO&51/'&Tſ +NZ 4D#/C ++2TVkrRtLgve뢰%1Gz ;ryr)R~1)ܿ>YƪLa&KEļus->TC"{٘p#W7 ưnA:hO6zIw VzE':J 9U*%IeQ'Nt=h/L@ +TP![ ד`]tk 5]Rwҗ]&ok7BۣKq-IM79'LWBȎr0yL, +M1e?0Y~rD#CdUV&z 0_@]=hxVr⸁pD0`ƿޟ:esZdjJh*dAC1b)VO(P T{kn~x{oeFgC5='ݼios~)wC,D쏹k5t$9ǐ27zO17ml36E|blՋ6<ȕ~WNP0- 7HP5 #(^C}lgIqLO΅sd?8{ &`V`ǘ9f32g̠촋#:JR%n+Wq gC5(~/r!Z Ɯ% Ygf~,"/|&x6dtmGUnߣCnO6p`sY9P@ -HUY.B )RyLR7*71[hP),SOeNwen6sew,~^p\O;Cde.|-{2!aYb3V]5+ꊟJJMWӌV}(>o;6kb6ە/a+~*p<@k:> }Kې_|4kC:(r:k!T +5C^pZ>}w <H[_Hh \~:L:IvMQ" +ְD{P9Jڍrw2Iu|u &9+m8)@ g)kHE vȜ` dYTg;Av5&@ $$$6!)67,E*n8RA[EQ}k=ťӊ֭Uq3_ۙx;}srpig0 bɴA$ +ZH2E1ʴ JYec'6PT9I~(“Fp [83ؘǰ' hiCzu%icj&v&ON߃Ѓ`O B Jπ_.xzǂ6p0~b8A\4uxg3O>C|x\-,@0Yï {M;H3)W;=%wÔ/x0ȃ&|<BDd,H:τ(} Xict `)$- ?&^[?i >Th\H>D,Ku YB !2m@½V"i EknٓWB_ a5W\R'H#ݘZXc!F](#,2S֛CMʆd͔dpG#vg&W߉ڏux!px.S lH`8G!ք`gr{Qv4bgمD)t01&*4 _c3fE;v7{^u~%;4 sI\I>{7s~c +RV$4ePͦ24/-!E: >&ϵ|3So"j9O=w60G=/xߑI;vM +3 " D[1`@*&D3>+ߤL_$~YT|?V.z}nFs#b{=bwUywTyߥ7 Q> v&c a$7d;3,!7#ўL {g c NrPչ_Khȹ&v߅s1D <}Ip"Xˀ|ăs8Ép'4!ιtl2K %dsobɬ&?$3K/w)|*Ι=G :Pui㟈&LUw( dx CIb̀B R2 +{ƛ*WI5GneЌeJѢDNgN˽^w05@rp_Rhhɠj_Ȁ꘴?lww}Kop[b RH~6[EFVQlƯuNV+.Y*Ns:v(@Vo?,r=K%};;RC ˷W$VCؓ/M7&wУ(#Qo̩G06NX'3ZȖgaks&%C>_GT䷫I+&gRVRZfQ6Qmv>-"{9צU[^RZ*^Q$ސA.o9wGxS#VD5\j}\?!m,DPSO;!oQzR[3~:7SohUڻR]\Qo+/]%n.Y'k*ڤXUMYW0Y?U)aDm{gՕAP_&(TLf ֦CnAlMU``|wBmMIs2<;?n-_[])XSY/^],+oWԖ~*鏬(9]VrUQ.rՕT iiQohjl5M]_M:4:-p|澮PѶ[ZT.kzlXпBаliTW}" aQ(B @ؑm( ""PYdY(.Pjg: eLm 8ȢTEgǙ3=a>~s>9 +f?pfތ=!)B3&w7- :íT~!3߷1 ײ~\btqjZVWdx,ҬdX]~at,^}w:}.();x{Br%FeTA:']Hx uE:L8˄M|j2$Z%&EŹ;itK+L)(I:Z㟘75Qp|o~ ^BD&}8jh]π4\nAG byэWYoP|&lmM95qU;U.puVnTUy?? Ȫ=us5:r%j8Of.-lHa^ttz/Z}=b]Zfx;:ƞ͒G7(=:}B|BF:V7^:{Nx +۵W:?yO^T]ׇ^+F5);ǃѽAOﺴ4BU\ۘ{>ȔF|rT^^v=#}#mJ6'jEVH]r.;hHO2pl`)0?cWh-KjэcǚD&Zn*Q<ZG+2[2Q)'9O7^F;uߑ.> g_E̟d+?Āp{߆L3Npp~; ơwRL2,X +kmb>E !T*ք!>8^LI dlT,q*+N׶>~LW4Ӡg3s'|:Dx ꩻDa5`ɿ | 9_!(_SW"y֑vuc8aڽ԰ye=c\\tm2YYpO'-Ba -|P&(Pq%HђBW=iS `0F3 1 +Ә+{XY2kY|uS}.?@O߁2``Aa1 +5ZJTP+Л^4#h=up,08XKt0Ļ75LU$;x #0%uj}4d/K P@領F)AWJ) (t" EƖF;R!"Jh`8 AhyǵHsq'*.Zoω7r,ɖXD8(g?E,A660G \ QJ\ Y ?ψrȝ/j:YB(>\E t1QB0MƲ!Y 2Pͺ(EQK  gijoĨ;Kx,(RfBҜ0SD% ݂5%;_t߸Jkx(i ZG>b9 z }z3u< +qz:O|I~`V=.h` t "7N qQTM ֆAH$2Ī3l5c ~[>`-c5Sfe~ #Ɯ}Ƃٽ0L ƋBF cJjH}1@LIJQz#r߇zVM#ٳn'AF}xiۻnzЂL0X^W6!``U8ߐ4|3-5.!q1GQkG,7[޸VNa{rq&ՐΗB;_ y4F=֧#TX`̿6M{W"H7Bd]沼5_g.}ʎ{fk"f|*k1vWZ~޴b.#" t?>1>Kg O.Qx,ŀ^ `38xػ,|+>Iq峜DKm%8opks=}2f43J>}pIʡ^~3G 4@x{;W`2@_VBkcڝ"_!y٦9zw,;XýȒp>IdY>--\!BEݔjoBWhN(Ԏ}ɂWD+,z*2m;xBa"4hR~/C);ªțfc?]Y뫊]H[@Y1BVaߩSGB:j&Z4y/#g$H;$l61ױTW*H}$B%M\(/, + nOY xb - ;jp:DUʎ0\2ckY,ͦ&k\wUEbʊ:NFQ _r*(VP~[|(B0l5g>BU t]*щvutc%߱0Nkc,l 3R5n^Ԑb]P+uHd|&3e#30x=KvHU=ki;m_0ptn.>'n_Zm}W +>H[4@oƤ`GLspf=1Ze_LRs`6`a(nQ5 S≧3JӾU_zk;qolcoLc9a91 5Rk)C:{PWX\(nvW(hdDzs۵ DQ:8[3.O08ĵ}ݶYٶG1ֻ5]ƶD\"ΡKԼ +*/= 0"&\Bֿl!:!#ԑufq:': ;#;?:kXݵ&$F$W1h|~z=}?o ? n3b{˜XFӛ̊VsBs>)Kk ~ׅBy yV?Kv@x D? ŸBG0qLd0%c Mc{ xgu7v+{u+}u+5=Jp_A_F9\w`l7@0JttTa4F1ned8 Y8ebIeI 52@cs'?25P@` EԔP\ 1l1 l01LF>ba c/jwJRC,Hn!? ۞ Fz0EYf&\TOal>/r* QD('UDE +尢O\\DEM‘0Qn ƹ28_BX=&P3] ^"°O,ߨ[VeJڤRUUG/Tgs⧪+⇪n}Sq[{jVwF@/eP`}\zi=u\Ԏc|p<˘VtS~U*~QV@do}v5uv^ͥQw5y2FkHWɕ(az{tGh.R0#3{g$inuD;nݽov%n=N7coK;bOIǶˮޖ]}$7,5ƣSk<:OQ0-mH8&dհd'dXdYIgs3e]~õ5NW7HL4\rA׭][ަm}^9U3~fݐ{S"6&d2:HF'6Q7t̓МЏyTbq~t[]͙i{iBέ\ΥM8t2&}w }q_GRJEϺ4tKGtfmL,+zwNq›NxLdnG*/ZN~I[rMuG5}qIK@H &8L 5! !!!!B-D~AumγMzvqwHEӒԫ|90;Fzx5OռQQBgC$kP|sKMgZ;> .=w$e@q<;eb6tU!ŕFQ=.Q#U"tGr VMN|D#2fo+) ;i Dokvpa2v\wz`Ys:P{qG2ˬ6d:jH343!ZHXi\:!$;D0ut [8?^|WA ,9ai;d8У;^rji&F7Q*Vnbh +CJdCJ,K!).R.>H_RT +DQ!5({AW ie$J/wwT_ZIqae-Q(w=|kXhރk}twKfWvzoUk%ƜyTe7J| EueTam5-hftd֌W RUXz͏eDL5;hϴ`!@[+{} =L۪_9w^ܧHr+pڸVwU9)ECi6P3&4l6m&lbB&fBdk*=[\?ޅ;`@Iv0ʾd Qџ\ЛvPԓ}-bnV>h0-<m[8u{\r#?Z_#3M/eȐoewbp8S-]YrNaUy,"_M|Tn'UԐZ\&MaSހׯT%=Oz{U z9gIO1!E41C׹z. 銌hԯ-iw {=k aC,CRDNئC +GgsYg./1n_nߘ7wϰ_d8"i46[4X\3 嵄 37%_A_Kn^ ,Pisc ?\tN B`hDSEoOu̐&ʡ'Q <8H1&FTȅ?G|&^(=7ت.Dv6ltvS!{lOVԆ!aP~`*ZpӄqtL:R͠LCsR|I_EuqӱKO,^&?u-Ñ#w6N/►*♺2jw*vEME4ʈhn +ҵПƃL##Z3p'S2'2h,ď,Q ;mu\ݾU{w+igaˣlnsۧ.eqhWD>F` }lAmstl6+Bx4sPzd\yʔŊBb5e Λ]7w+w_cmBKI"KPUvv4 t6L睦y 4,B8,pc7p5aFrD{̔=jG|Ŗ6\!uSiz)kN>*ve]]q+aMLtX*b72):F[\B:qP?Y@PU/bT5?F37Y-gUYv|cVtbYk25X2}ۗiӾ-K;4NҌA^6 ru КHW?w|98/#j8g> ̛fM -KeKr?R|Z9E5.fo/u$F!@n ulJA@5@XYE#.`ǕxZjUlF2Z;sng.8g>>&u)1$~*2~DV]Y$ILLl'bopk9@[D;W"!+H^૫QMmG3ӭ>ȵNSWV:u.NLVH:.K$Mr"91{b7P.8EC`{Jm]inTśXVʳmʲ Y咢LSAFK^z:kQ;kiZ2E]\PUnZV=CU`QJV$YNM.)g')v'(ds8]ٚ&3&I*`Fga4g˨}=@W:Eh[+WV(DVerی"ԒJiRqì5Mh'*o{DZŜb'z|K}jpvAH{WALl:O^UniCan4:vfGɖiY6I55تzv++ETuQOL9DU0DR/i?WS (l BԶ۠rW~>oJn +㬖u1D mRUjNaug}Pw5n|5s U3b7%zCt}v=7[*J5PjfqoEz S:BL6ψiO3ڐk6V*Y%]ֺ)s`7΁-Zòf&^l'~L !߽PvK'^e.=ӑ#Af'OЏl=R-4+Y֕mYdbkufM_Osak%[F~mf6zP(hU((H"y5E/_fm7A|oi=3zj,}{=e{g7>=f>yz LwoTy#@D rH!O.tȇe|5r B<x GhfL{'0yZLA8 c< +0~2$o򏁜a?O@ ([@z0F=7 30z ׋z9cQ- 7ö́1j5򄌑+)?W $ïK(ۍ(0` +2=1 |f Lmo08qLJ8 ƍcGg 0H YG6.Yc \#'+q/?dyTSWK¾!/@ Z*,ʾHHXHԸТH݊8mک^ENw~NrOqw¢)^/  (sHlCbh&M+_<8 xKKO>Nctf' HbGZdAC6=|Gwѽ8}|K ߑgcr?F>c!SMA\=iOcOg#SbH5|'.5ԘhZz%BSE]3QDtNSEWG-M1fO u?Ax}aM>nۓO_)S 'zRC*}I d+d[}̛~?$'7$XW<.z60s;pv*f} τp-#k +,IK`btV`Y.u˻w52U&߽6]n|ѳMF<My~ozIfC޿Ʀ76# uAmaG-Ƽ\%9Zy%FjM0=favo}OOՀ)c>׬>~?l\Ȃ aha߿~}'l_o0'([wb+`50@hlFcYqeF9 3Йۨ(֑p< u}ֽK{BVq +nn ++ogY^G-=w[k [?0^c_t-ě:aqFbe=-V؝՜vkNo o ;(61'ǖg;͑ض9 +|/=7SЅt>LCO!l/5ѓc;)մ31bGں=[n[cm\L_&X'\=* 1X쁭! Bwa0$Ѱѡ 1&T,ҨCh-Mfٚޔ$7'V94%6ҫVovZC,nKCQQ}܈.K]¸c]"0Iiq' AR :Jm(sEM^ğPи(Ƭ Ų\+gjm܂RZW#P BUQVW-Su=#*x!Tc' jLޤQ8' •\CT" RFM.P1ha, 1(6-+Id,[MQPSV +;ej׻ȵe=nRq4ew8],X\iP%28Z2 XNvQSK髂X& Z:\Q-Qg9(J+FuiWIcn(YS üIwypB{a4ܷ 7XFU7(oE42 ÍbrkS,klEV^UM*U.$W4 *\ݢXq04k 3!A4(ADqpU֩Z +X+ +8"8KlUk+.D:Zu}_Z?y}r?hL1+'Ǫ$;LZ_3~Pec^:A?iÖ8g~&h;+Wƒ&^I>7AR9{u{d*`}¬4=f15x/j\jѫ;|v G X{EwϔLmn5l%$ ݓWoy?8lJeҁ529ega:__qڋQq=C89NwnXۚ]2xuj8QgCls4و<+al܃?/ b, q=0DGcr504/"~}Ts{re.r,EvܜGD7H}zQI;q-ri9Ѩ }>mmV ⭱5^tWtSYNq̟Xbߢm_6*m管;k莿+gs' v}8 .B- 8Dz 6PF mmmmdۤ}hͮnyc!xP:շn+9 +d ;H΢l@@ѺEA0[TV%=вdKƠE4++JDuIU>%Kſ+ +T Oﳿ&3{_3[_ wE .R.uCKɗ"ۡrAWY E ] ombj/e?fSXhf? rh^U?mwfpػ>pbP٭P؋!vI/3xG@S` +j'hjXU5@¨#񥤆5kxk ^]zB/Hf,d~Љٖ@ˀO&|P:t^;5o +@] a\:$dwXNR]% +RJ:RpUu~ߜ%Hx]/dϦ{̽j  ~O9^D.Ue纍.O<Otc BTPwk`w%襸MtlVGKf#d<3#Kwa5,Ն!]jr}va2v7Ἰ}[S-.R\ +@!nӀ\!Cu~a/ZlEY`<7"{n\$n q͸Ah?J ŀ2EyuŹf)4S6b*B:Ul| 2ۚ0#Zŭ i4UT$wT9Si̴MuڴWUb*PԅJc~ 2W :b\Qq}nE%󖱢2YQjPYl:e^Ɯ>iNs8ar8.hvO820|aj|tmGF8BF"xY;ը&(n1PO|3Bq"zQt8/ǃKGhE2 jĪ}Eb'{c\jl!B!$K@$6Ibر@ 8X$vl'Y&vL=i&I:Mm433{y9^+b?uUL$L(8/~?b.JϤTJ> FI l +|,Ki #ޖ_LAYB e"dDG_ŞvQe sIZOKB/yȝK3kFJ0}n3уL̽{T +rr\9fW 9eAEEr5 z!֜l=+;ŝ\2S cr0GY)kXP!JEBlkdJ'+RRD.0ԓy 5LG aŸ!5Gh@h@DЯ$a!0\̜/񨻍(#AḦ́˚Ͱy 4iӥr)uQL6WlzUDQs=\,+ {xw/\: >ulG<>G~=<𞍄r98 z1iVIEזƌ3SZPJ\ܞx"Y|RԡZoS'&>Ij){|K !hQ< 0*A-3^d hE0cJ!MaCqG_NU{ʭ.m#۩mv4BfFԤYJh,]KNi~ɦ[ڴ߮%'7؇1wޭF0w]żcX[kN&U&VfG TF4nQZjFn5r]FЮk/'Yt6~5F_EO,g50_.|\}DW1y+Zu/iВFEtUG9*=QYhc5T4sm&Z@bbR&# +ӏJ!@xU&K>zpu6͘79o=Flc 61]ASF4[˩ +ʪnX;恸Jqʟp|&]ՇȗIz"CG/_p3u8mx 8لǚyRHG"^mQlFY]gTֵL}qq:46ZGHX#*qe_k%xa>}g6ּ::1wvw ҠMζm֖Ljn=LnhG; +-Zeijg[nAYè>_b9Qe5^Rs|^b;Gxa}x&ּ+?1s [ܮhhw~{I6W*֕IvFVvǘ:˩ +zy{-ns[ +[gDdZ$E,,siJg|XHCBr<(ds r뀯hf'07!_R:WƊ2B_}(VM* 6U M Me0?;ϋgnse@@Ӏs%`-TMP^q7W;AT(ĉff>XxkU@c^_ c?\p/0Qz:Ue@+ n:ԤnZpC͐7݀3!/o)ca؉?DZڏCKswُM>0U﵀&Ѓ)yocܤQ}E.>o9G윸x~Q`:ϞWXx}ͼ{~⦆5i`M󞬉"CFQl`.~ <_ @]Q }Fi +ͦIٴ66*TL';1E;w<;A&W E8>UQ1=H?y,NxdJ<2uQ-R.iOeEBvWjz/+/ x=K{+~rK NX2Z*L-!Kel%]ϒ%#/X +|* +})v\UlSl}Mbc#?4esZ 4tU\q/Q]}IEcdOΔﰦ)[+ZW(7[sUͪ #s5oPtU]*60>kt&T Q?wQ=F*Nm %4N)h"/_WfWdkr6hvج o"nYo̠6ABmАc̿B$Q~<)p0EaWHiCxڰܰъ_({NV ^ +]dLk$d>=H(aAha^S}ZO#=vn4ݛjfWpj/s'Ϡ?FJ׀7GbCdr#H91Pf蛤^'Ygi3lz2 h8;8R}J_#6{܎~f췏l:lvژȉ醕1aRVtYFtbaʅ&-jiّ" )+G7Niq4%CrcG ;ғ=FYcP'pFnXoEF|O v"-6Q͠hfLΈIM=ߐe41zWCR[c@a [5{砚}>)8 +|`BV `)-,5!Z>ʔULM7]?1nݗbWq\>r{c ;ғm|/#Y.h=?goÌX<5/e GAkТ!#@ Az@TBt]OZa]-3umn~L _|?~i扫t$))2k89ǹ0ՒJT2k7gk[=LڃYSL^&3iH$%QS{ Krٻ>5`:d1UKkR$iAzc~97⚣[XVu'4i^ԛ4#uNpK J?sYIjeC?14LӱظP\!?kԜsr2\ VAZwmꔌ5I^Z Iz-Y/(bkی8(bq1;¬Ay¤c> xc&;b|G:1SYQ1#:As9|ҩw X=|}鄓2v q~ x́GO4=ˠ5½ +PBEE(z<(O=޷z]ɸ-w "N! t;< Ji7N}7PHI2$9CԿp;7qBƝIS0"@!tIeKo4pe" WX0/#tpL.#?o05w1cbzx;~~ 3 'MJpT,=/^`Q|9Y0y\t$o>r|O~|F!Dϵg/PdcE]cAnArKĂܑlX Y,?`/G|b‡hEE>{F)[6SDϣ̘.c x6o>&w -C}1<%ă=&YEyCp m49q42,&$ Ud=LZțNr qO?/ +z%qx:)$D-"d% d+APg?u1q +xk%w~AE?4tN"|G҉Xy8&>y;uvQ ?uR8ۃo>?pnA+r7Fx@qnT\9C41$[1jlf4h:Ӆ/u<;HT}Pem:X5$p 1$$"B"QmCToB +~ZC j]FҊ6\lU~\_qQBYOU"1J F* !zR}/&4w|kuWa\QƗ#.hVs|يs=1|Nw'#k"uqb  $?-2zp۸%Wb7;>ŹU8ӽz4Þ8ٳ'z^m8k:CO`kO]"_ǘ٧1-O$.E&꟏Q8ÑEOg`f_BfOr2lav lpxixm71Fd7w_AB> ' ]8\Q|L|4h9'6{6`ٮf:S-ڙLv.Yݤ]nnbkwrܺ!g5CV_>T-ÈG<&w銿6ZY=[|0,Ga_pҍ6 [tyجs0t%zmu:vMl*[/m[bJ,ѝ.ݒ6x,m!J? +O?$[FM|@380J]b^q!ވ,fM\2]WʶUqKiB}YHҤ_%o5OW̸񢔐O%RkL!jy{Io$('ClH&$%IfQmNpM$2BZ +P )Ҟs=n#ڌ2tŪh1hNMaf3sRNaC1,36 +K5e0j*` +G11E٫`Sg~+Ofz^b)K29sG1sӐc 7_k*ԘҐi:A/OL_LoWUPQ*L,Ch>rp:>iBzeE6l r1M4侍>'d[PJYҪ2 ܤW(6uy8ƓuE^W(6ҜN`g!XK- 5?OY=1#?ov` UyvΟ-R%(ZBe“LUQݭqZ>8,;9,?y™'ʝQxɷTd8GڳX@~*P`ڢQ3a6=$fb+ +rٲWZPėX}5 + .ka][׫m]NVM_jUTXE gܤ:![G-^]4:u&rDiי; ^Q%k}j_ooUwj,\ub3^wY Gr`C3}Qye1LȸfnowKlE~F/zGn)\)\*ܮ6,x2Js KtNRS*4~$'j+텒x|Q䋃7q2 t7畖Kr!Yw]Q{;TiޣTďQV"_ <3:S P4vNO~%npUFQ9FXҘlRir* J$?IRF*ErVe*IXPT!*E9!{:;)`Tҝui />aB0H1șldBLf(5\ZO N$I2Cp0]<^PU T$ +QSo&7h"i4L#UOs: {\?a0G!=p:c 066)a ~nL>\yTƟ3, +ʦ0 '-Dk$F5O465"eE 8Hpj%&*.TӨ(1> +&y{E +9^٬IθI&9]hBm^]u KY+ǢVwdX'!-'Y00g#YT:Gaf)r +/lV&TƜҘXe\*T%R=PC_7f1&yeVr dia=H>}BR8Ο,$}oɽX{c?&ؾc~RĬvywR@Դ`5GQk׋WI%0PCi4K+MA/@t Cc4b嘆HG;rX/usRغv)XHk}/q ;z8x@Mi3_pz"©G3*ViDhe +B*"r8*Ǣk$T͆U[U}VRS0\$1θلyY&7Vlc<.=c6$z =08WO] Թԩy$&ߓBwp_F;~v[.vB-ӎxJd"%"SB ԩN 5j{q|˿C?N?D_/b"Od +fRg>u p6Q)\s;SU[whWp}+\D ZBӅ9 H^!M?Ө3m&SǎXC56sjnݸX|8%:Uj- @oX ^zXHo2L77Z3X Ȧ +󸮥F5*phf,Nc'Y@*o1zuAS;hvcGbl ^;CQ T6`sQl +n?Jp!! "',Y<8}hHBmcj"G:rĦ lZDB4zT픊51n(T{GUHOic{WT^o}kd4hg7Pih2X8 PbxņiuBT#'Ib9/a2a"axFq-ENcEv:Y=k=ן@|U߶^pĦXcBIXcզQ74QZek!0}$-3-rPe*S,1mU,65*N*$Pf)盅"JCơqs5>}{`%v,iȵ2j/e[&IK-Ŗ兖 y%[a)-%yjťeyޙ{D K] qDpFf`fD +5.Kq-5zXTkĜ4mz5m<96ij4Iۓd1w= |zemA6G#ulI1kLslJFɄU&3-X,VUZMI[a(wcm<+1Vl y+6"SH"?7wg:xuH?6#<MXmE%4X2EZ +S,7{2 +ۼZ[b~^*6o]BeKa?LK^Ze}%s4kahEI٦*t۲mPj+KlbͫqֵRul:lsm/ԬkCzu]˸9Dq-빮l-#QW +eʔ$#JLHY"8Xr]+~)W$/U~Q)ʅpEy'<[!܃Yż1t7|ۊQBRu&T@j:\L5IRԀXݭRYVxO^YՐLܢߗuJ@o/K} J#Pdc:9pHG#KPX&.q5َ,Gjo2;uq.,q3l>P/^0GO4l^\NGV G3 +w><\$丌X]9bCJLWcqҦ6H&gltҥ^եOuo4gH꣰+y|'{X[rzTB^i$1qO➉ŞdyRaX,|!S$.TFO&ͽNkpoRrFIII>KB^ޠgS@-H zdW BVHX+' ; <)XTeʆUVU(ebNL,n{OKqޫ)ڸʐ6'.S8\>84ʕ] \n ~OFo }HYSs >Ź͚پSX[hbBڟ8tf`5 |?` 4HnX< S1?$0o.f0fi8Ycc 1Qu@fύC PD3I&s[1efƌhLoiqڪ3fL ((@Lс<؈ =x*)`|W ~KwQ{s+=o^[6 Q1LLjۢ0m,&MSX<`*30`1FkZن;aX"FԎG=a֐Qe۩BFT'%`^ v>ۣ0} ڣ1}t'i;w,ǠF ؂ h?[?CAzdݛX'$b_f1G Dqrº+RW,] Lz?]  |d8paD8vs 0CK77[7E. ̹3_oI}^3vi=EWGA a:-Dr:0 3G_l]BG>Z{#=`7ԧ__ DQԾI@!j{r aCя =aOpaȞߓ{G{]E Ybj٬5{#|Dc1=GO>g`|C x/y=dO4 rjbE 20*;o!"\>'ug_KH2kDT} ** EZnnhYDQA@B"2bM01rRV&NRV8ff\*5qܢo~T{=缤O~ld!Hu'3enDٍ^ӉYDdd"d3AvtS"oq?xW?" ~ 1 1tKlF3`'5ڨqssg#>mj O9z<&ȿ?eg7N&qdOT@EꬤF5j8s#5P{8g;V!}i_2:2G;C5ķQĝL%_AԌ3sӨCBjF%5jH-_'QB//} Moq~$7 /DÁc 9}r]*|=c\| urQDUԨF-5>V9wd4o鋫˴wi0Z"6;ٙ0eG'\;kBq5JN&gͣp y]U +Dh9YВSG|kwqlCyeÆo$O^17x Ұ,\p9bu,ǙU85|z6S 9G#qGF^Qߠ1] sh!ȓx吻|!+ȍpy~.)DpM1lt-C[ :jtmD6toO$xm}qoc<6WL7OfRߛ70L.Ot%wW􎝆|=^ }`M.Ůk:-ScJ O9Sylv M=D+4xB y4O3 : +]&s6L*gsf2ϴaR4{bW*UY[Q?kP7S+}]s_\uS^})ZO.;v{{bs%}4h1' >VlDoj|P[*BoηUX3P>G\=X6rޏb|Y,yP<\{-]~tS\ `*aRJ=ʔXLAҎ"eBY$,W ˔br+-]--YtI#e?!,CG߈.10vƲ1-Zָ. Uc6C}PUT:(PLy!E_H^X +1cx@k[Hb[fB+:q#1&.헥{Rh2q<3I+s#kvxa>Y=DlvBP&-~,"d%ĞXVjI 5bԴc1ZiCvZ3\o1\r{y{lb>Kz 4&Vq.]#4"!RhX0&>'dӀ~M}̽5G%]3G%>4G%VhdeT>` + 38E<gTJ&;iHbR48%LSh@jT6Q}Ҧ+:mҲ+3m),)tUShShdArCc#˰ Jsz2gکOzguStV_ٱ +ώS +˙МSPE9kS+c͹,2L/RXݲ|އB}0 f8*]A +, V@a Zƨe|,3mIU7"ue<-\GacFgWA+%r:!-;klql}Q3dcMW2UP +#[yL@^RE7_W?7Hq؃R)`+5okTg/S |!adg,@PՑXuw\ xº2s/)kS +܍>iޖloaHa1~R=Ci}_CP o,^Ç<OXI-A GhFoz<^ÒsdwT2GvNI8Eag0?:Ǚg +hrM@-H| -/:'֣?<ŕldllj֟%hMFg&9GEq\#dG(+t|+e`؛=vEHrsh@:st4CjQNFi-9c֋]DNg:ЙCGaoA:N:K(gJm5b>i-mP՝ U|ǴUl';cWC(NzM=~WO2|u{7W ?w1ԄZY?T}40VEq*  zM f*7h+;8WYEYy!GsC+-)%)a_ڸŵ7+x(0fl#Yik͊P- %,@=# ^+eOiJWZxR#2Q>_ +h- ZE%Hy!@$ $BТmN!Zҭ͵{3nu;֞vNZ!~>Ͻ`͊O= S&',V iw$uLs0^5K>[R)G{Z +6g-=Xaڌ +pŸQ ?|mX +o^:"YDX\f!U<ຒX`d?|lΞH)EkӰ:;9:rLh)GCN9u]Q-\ʰQjIY̡TP/*IT80Tf?گ>8b팣E5yhV-O j Q`e<y [v&*w _4#2]Y&H4cO79rZM;렂Ʊ _39j&c6.N:tpQæ_/'EYQZ' ̆wd%["G+ ?Xu ;i& }60(Ӱ9lT4 +a+,ƕ(5`1h(.z^ɊLC2iTVh#HEc[LyB~'Z$[s8ܦIpf +bLa5eXX0QRBq*[`4(0zOd:yc/"ɴfIJG=L+s3Y&Pa0JR si:K0PTf̊ʽЗ?]yX}"z\loTBe(me-rA/{"z`-]c,Mb{,KQhO|+UA[YJ*WC][:l1pYUD+~g9 ۀ}M.G}\fN*KqC0TGB_]"hj!&y5*P9P:+ZlW3 tu WH=*gDjUO!wIBFs/QwZǀ'Ɇ5y0(Ȑ_{8CAGL V;V߈Vx2oR/#{Z$y HDGqKU(=C$ s[*e^ Oo*2}QHGZ"țRڔM*,o6`YUHj"ѿK['?m$4CB$!s;ڹ'Zg[#cR3 Hi@R$bi,i]G[Xܪ ;u Fl 11man% ¼"EB̺1q}~ux@s `3]9 ;v#%L-[Jpmcr60%&^JI$"|HL8x˥^ȩI @@ \*""^b2T@W=j>gmt]36v[NvݦsT|?D~;K NH#H3i#ϑm%1|I1G,Cy|G3y~g_2)ѐ,O"ƯgFCldbOajWL#>[_0o69aOƒ #5 &$dP/:jTι_72~w1N.~vp:kߤ0ڍ>$%qαRgrragaoj^ԓ24jZ}\ q>)tvpgp//^_ğYopjG708=]O͙xԓ3I<87+]Jjbf@FRcn)C\vV{k4Wy? C~9wyD)B8%3/ DQU^jM]c:ut='ye&I-`SGch"x^Qy1H}^Y:9?"56qj66LubTZGKB<kW)hVub]X1eG;Kf ?6I:E1g ~s7ڧmFeV +5f4`Up>V.X6!QҌ%!X50<_EugxG|Lw +d*g> Iǚl)X>#"BTGP\,SEsajTϭCFTmCyTG@Y̋ Qo +O}؂ձ!|u iKd煕Q~X=u1cQl2jPkDe qN̏,Q⟠Hn (D +•>.SL >{Hh%kS'F$ $Ơ\*C4 z$d(OB܉(L\|2dp:F87`O9Ia0x'29gIigk譞>'B>e`H![BIFlp&9H*F^r%K))w"KyUȢ(S`n:ظv``볎>VG-}+Ǣ$t(#R#O +J٪\Rݰ#+F¤QsDyUd _Ads6x:ْ>(}T"O +:X5)hĄLm6KaLAn6tۑ? HcNAF?V'.w/Zd=F.V}0,9ԋa+`ԧ!Ð +}Bk\q=LH5|Q4@A4 " F'Aj?xK1#MQ2gLdL3a Yt +ZL ԙyH!RU2d"9k^>d{|~y0Bc{?wp$(^ J5ři h!Pۢf"Ֆ UlRHqCSyRHoԾsGBl$va3#{/u+9Tq/𹼜<\z1:EPyCYH΋D# +rGd $:m:!qAEk-b]g|A#% 9i?wQ{">9*VK!G%=B$A ;y @TQ `NQ#"7#xŠO!m9B!H@+9Κ~/;9_ +4s]QQXWeueߑE=-fQ(̸ `T 0q8QU bզAlVMM`L6{bCRc4how{ xmcb-fJM`PW`ŘՔhSE(4\ldZR[_yE`oجloCkiYΧ6B}3UXO|)uF(6VvЫ +dά<Ȇ3D$ͭlJabWS2mzAWڄf_0'xni]' )vba'luPC!d|R[Yp156v)40wIwvjQ:jXG .@Z.Z}-Kbna14,ttN_tb\KK34@ o/uahj!j6pENc$\bq'-%r?= kgY,zA&Z@q.IX4iÁ=9]lix3o'3#MF{- ~FK.wuNĐv>Q@$M1p2 u1(}\4׸7qț|m‘3}ldIƿ>_{[4Ү)yWP(]%| [6]?>FC#c61qF./l~ `0)`(bJzآ~d|isY;}/\pedZ AwH0Ŵ}k1˰_}- :55u]|gu N|OCx̹7T} c ضa{.0.S0I v͏C8 Zנ"ZIJa/`߈"ih~1/Ƕ \M?Ч<~b*-a8k7刦NƠABc")}gcfcߪ^N*ȎSD2P-T+nKK_ϡ1L4ʓIg#?EhXrc;YvO^Ö}51%;JUhi#:cFg1v՜\; keҧ.]:6k 8qW:Dy{+ePvw9] ƧimZqGiV9hsV8s\ +eJ]*TNuA2_T=z6k\FXᷔaw͆SUnZ=̣U9R%3EiI *4,\JhX|~C9>5fSvVfspN_FъpuQ7N :sh@ h;3bʹvK| ]9ʎ UVd21fF ֌=Vi)=MSf)kRb5)\c7+9Zh|qݚy};`sآ#;EXojz\kj|MV*%~&unS5Qr5.at_7W=hTbF&6jdѳm/uT@T@S2 0 ]`H䲨1 `y ^K$Zf*hY)=Zֶɶv:k%ִܓ?>y}}˚ƎL}%q4bb\9\0 -_EUG$+7ª\eGڔYQ5ʌ5EJTjl,5?NܛEra #NJ + q-z +)?zrX͎1*#&U,*-ήԸjYR)JNإ2%Șx~)S'FNm[q88GE9^2LTaJ3D)Ր KB JI,Pr\%ͪiV'4˸Q2ː.;?^b911AaaV٦0QG%#dɔ$cRf%*1D ɏȐRfřE[*| w)<@75؇~gא2jSHdd8̓d4*yS~NC@SKoޖt/*zXlȤ,bI&XP,cR4QE +*(M+NTV) +M-Ճ%4CJɧ䔼K>yC6&35‹JzYQ΅Zz-X҉oya+>J+)5I0=hD{&3SV$_VqOjlyʳ<˳:8e ,\~Zʹ4\SHl2y1!P&JOոJ? HyU%ʳ*UcQe{"n[FVKիUF.wZVmhȠF΅ǩzr@LI1Z(7T:B(GFe遺 : ;лX_mQg?ߎI~%g#=Rb|J cʥUÛйM\\k1>$mIgiໝSQ;vMG'$]0P`C@uQN w+ +}|7[ًO +FwJ]#y‘PRa#> eԥ8 t4v71qzjiW|?-/҃ +܏WO1xNA^SIAN$'gR,Yhmy׵u/`ͅ35b%Ұ>Z ҅\Opn!p8>c"5ec,ýKKf+ų`ߐoO!|z-Kp\uCѫ 7RnWosܦHv;; PeP hfh(MEyEևb7:󺮢gKp>5HCax$q`\,?Yu !yaMZ`{!`{9)E h̏Qh;:.iofp^'Ѻ7/}J3G~1`9U~ YKm@k6Ӣ?ڵzGOѺѩlS$8AQn<r_ w_pYX;|r"𓈏4-"el +ֱc X:V;؎t^*ׅ5h 9$ V,a߆};plՐZ| -]ɳ|kyF;lݘ؀m@an_L b -M&kk^5SWUv6ҤjTiViӤݴnUNC}>}}.Wy%z"Y/_{Ob> +ۻ3>wiJ>EOOUE79𓣛}!\+q~F6e;K 0"WҽMyޑ`HRsxx/Yڱ8]c~9Xze TtOҢQB|c29wxz8-RLSγhqyi'Ooi=lff1s c`4!F?јop4Vc:Wy,=|`oŔ>1 D`1*u`6ƎjLza"ΏnhF0pC LÒ{_CI"%M{MlbdK II%LTc,QcI%:0,APڀ!i H;0 EldcdsI^EwUtmDG{+3wLYfV 37C;1"##) /ՆCГք6tw`z?:GϘ2іyYwz ^ω?9B x6`uKlfiq'L) (R‚@v9NgѦUGޜ!4LE4?-xo s@Ïy uQD\, Nݿ{xmtMc[:oCxhdj2q@FV Z' +ܨ-ZKg1TΡRav+(7~@N<_&-7p%~X Rud h,LGz}jTpp2Ԣ؄ +c;E즣(3@y6uX-/>K%"Y=r`wps:T:&9&*Mp a7Qn.CŅRKlm$iXga]GQ"}opKcm*q-$ RG7u2VP֊&E&.wm  li&IX9㡭BS5uv۠T!ӆ^(Fp +Ho"!R䳈=%.p$[;xuwIE덂99r(ݬ«CׂL:|Hu!7 yI$lBr ҖHlI-_Y̷۴?77s, ijڥZ Qn Y8H!ůܟd2pAф;! !3 OqF_|g|AfY㼓#VA}FK=J} io{eD$ + B + +D !L`0!J{e7#bɽ6ɼ0Xa,L|qzJ] PSSm$;8D'!b8 +-,FI> d0 1y7ȹf{5"Iq[\9 N98|_%~ / .) ._\Z!,8 ]u'0B(5wN FO3朜>dPg\Ҥ}jCtrt\\ȯkK8D??8{=<<wrx\O &5y vh}q- t=! P Fj0ؔf/TdV [=v]Ku_}K7펝ץc+ XASZQvg+tB-l7?ckncgX>Ntho+|+{n* ^k踂?t\B{lum29wtt"w71pyG\Vx塿ۏa +]x: k %^i optDoq>!;p(cv;i w|-88,~>^rlWaد@Z=ZAXf8Z_m&:-D`kwp~ >szK?"'f)X~vcN^F[4Eт&tl2!'*,42"^q6Q{rר_\1a#bP Gcᨆc2pӜ.E(>;Fvf|¤n 3a#<H#8 +-F"t)rkKwմZ)eZTmjKU}*{lVEσF]W=x2undy>уnOun5W&h{j3T힫qCU1Bc=U9^= y.RJxh~Km**qtS>TgYB*ݨ|V {Sy+0w^s6|;:rT +?Oj_J#5ߤb*ꛪa}sTw+?\Co50hv++2*3䞲B#u jv}L$7TA* 2 (F588CB)7P9!_) t21RJq%ڕP +xwۜC^_IqD7g C"De(#<[JԈ +DNRRl٣Zw}L֘Kp(щCp`<9k6d>FBr<̨~J2(-*F)QJ+):C ׀r%j"ǭٴ]&gzWq2}61dZʧyo":*1CБTCd3F*'k\T%b.TLje΁kJJ%QC|`jK0~a||}XzfXd/,`0oJfJj_5 TE +WQ%+@3T.¤Vބ;@_Kڕ|VKH F7D`aLr_hvȣ<ȣ<iFF6wh es-**12eXI3b3Ism2Q"@zcn^NVN$)I&O/\T ypײ ~ h +x Nw 8 ^o7h:9ϚQL3xm\|pZ+>V4X9np 9 +%pb]79E|Fk.=tqߣp_ ~ @z! 8d +%8b&qO, 7G;[s}F7}#8>oDX׏xobE.!}F'W\G8?#} +y 7{//x8xB/?xxd!]ʥ?8 +Jqq`2ϓ9cʚv鷈uXi<^^G~_['228}@-1/i z]@"b#v91::f)d̲%8 )=`A}`7x#vL*%x[fEA>Nlb=Ӊe2į~xVav];aA-63ڧamFnf:iyZG1cW6!~>gbE,C %F3QVXn8ױwl=>t 3mIB6wh=X)p1b8{V e5YЕ(އq#%Y/>`ݍ.F($ p< +G + 68jȣZӴ<G UJ\ #J7á{6h^b{?v[!{8v +!J$D @2-Dʂ xPW`k,@9GY?[ԟ0G^m8rК.5~a_\0A O:YT W*N.gd m$VM{Mn+rޓ+}GXo|/DA]U9fy;kfTW5-hr,lSNCݚ;d\%X mh#aǕ~Iww[~8:ZڲE7*HFyb=41\ T3f(8NYɲGNWfd2"+Y&YMj:.,/>R+цhkknтҖQ|k9T(ƛm,S/My2̣d3[n\F)%fĬШW#^wh 8ӂ%mhY y>̠NSikTF.+_l# 0 3ΰl +(0.D4Dwq;hc9&٬i&VLlkXSi&=iZcܲUt=}kPqQE! 0ԩ,+7lFSNx1WUJ3nUK)rF7r+%.^nrn-d߂Y?=N#_<&0ҧzs+&OQA1#RVg&),3]Y +*հI2dPp<(0C9?(8/<39AM֪lTi&Sy?;pMgq$*rkPHnȐP`~˿̖qHA>+#C *B ܼg9G0s%\*(EYX'btTP%b_qq-OI,WWҍ1 %gحNՠ:iV4x i|U<}/!㤀A+ Р2|ˌ)h`yr\rYX +0嘵rCƠSW.jB豉4/Ɩd%ӛ BM +0wE=\.BD."c'1!Mdb61;-s8KpG`O+yɇK*a@ȡ3$x \ \5\t5\@5д!`u+-M_M;"88Lum6{&P\ U jbibh[6ҋP@/DG=lyC2D-\X:` +XX G} 35ã9p5XᲈXĢ.$ml||<[\ +nm 5ʡ]ֱ@!H]/Y@ & +VxҏVx£%RZq.|j&UL+q4+ZOX9HfF$|6K[w+(݋ < d۹xvzю(8r965]@:r;zgAK2>Ab{婋t} A===uh $߽V3u"o%9KɓFbvI9V#= u̐ǜc@E?eb(Ea.^zCU>_Z>QA\%!Կ_p55AGy1~ [/ g?>q&8Ǣ%Yzq]9@"g 57<Ǽ=f/΀w9Q|P5Xr*.S 8yP  q-M\׸p@E~_).: x~B>G"QUmpA0ҷx̯5c=U K+<.$;?1?R>@k?eέx +^?ni 53|5ezqA#_L +^.{8 3w𗿂8#=C=:n$2y?t,Y?8VrEr?أ8G:rXD^]M2m~A馲.= ݠ&救GZq+YȑLLV8DDRKX%_"6cvv'iP6Դl_+u:~G-rE.9ϢB1į DWc Ğ2 YNy: ߰Z_j%yWx=19v-{E'{Cf$Ilq1 BjrԑdkL76`0`n&&`CbH'@B(HB[Fi.K@%Ye (mfi6AZN]5mӺ}m6MӦM۪}ؤjڥ4G.S =z?y99『w f 8$7el{W('ߡܿ$xqÖ8 1Ua#f<ߦg3q;cX5#Df= MSw)h5졅p$v1iL.x +8K)gYBDim` $]v>NK<n'2LY%u )tY='e*\v/q~J M5+ɢmIښQ{rڒ˵9%M)aES՜USj61m"Z~D XR(j ?R/1~ +b:m:r"8+GS IږVQQU6`(VBZ7֫޸Qu6Mݪ5Ri3)yNU +VUX>T3SKH'bCطEȓ&K"L3TgU\Z_5ZjUm(hک_Qgͪ,mUb{Sg;>S#{Lo&Yg{(C$;I!Qk,ekͭ*[*m媰W^2GJ[SI39OQsWޜw6 %33IcuKZ~vlF9{IW3SNʜ.*8'"WH>涩 Gyv?ʬQ5` Q)-[J&RVj0vƟ^Dw;X҃][K> 'dMSfI,kr@ ʨVz(PRB=J +)1N0uR;HfbM ~f/w_ዾKax e"'q!a$|:xĞqbMG#a{i{sp mx AY2`͐ѐb: }0q8k]A(nbL4n"LvLavL"&i0bK4A<&?åC){1ǎJw ցJ9>c;cܘɋ9.?7FҳB_Hx| +:;_ U:G;0\|Hv,bb,R(2 $y{8G^~;?oسEi㗩WH*_%p p Ǎ' 67%X,e +2X&8ҫ>_{Ŵna"r܄*_a |n]M>gVcB~PW +Iʊt9c/ggTW6\ۏ_ݛ¸oo=^I/G!R6\{tƟ6%inmzK4IIKKEZ.E\1AAȠ ás)`e2q2&sӝYiOs~/<Yz,GG>ۇ;h +{mf5*c?,ks51#ꋚ b԰>_8?@}^Gnx7u6v̀/b@2(CAw6ڦq-gҿu7g8?R<7{{BGeER?.jK?wvT=:uч踂89,C%tz gz@{཮kz _>/߈M_p귪һܷtɜGG8qyqa6WqR6K'Hz0v]_p|ܟ>ݛ,::)tGsc88#8Zܬ}d/ _R@m!B#_y \b3e'"֯MzGek=:Bt5JR=pt±nѽ(\Sݰt*O.r?b̘C"f'Q~mmIG<4vPAo ɠy#ynsmEo + 8,OUB$P]*,Od_ 2\G{?vX-s^tSsd+\x +)c:h_P +~/k$?fOyF>OqmrѺ!.sSc>;\䱧"p᪇pMdptvZf^w@dG\ȝ +-a4uAL&cjHָA9ʂ͞*P}LHuª4Z59_'`K0\RE-U$Fp+mw_ղqlI&&cqjHNQ8:CjU`b+4$JUI +$5ȗ4VH%oUqOxBwU`BSDEOƮGm%#P1i(bPɨ!Ft94y4T*Rjܤbs +*HW5r[)\ʱ\zD $#F#ϯw泥8!7#kȍߚ +YJ-*RBK +UX):Jn[rm3/T}RcxGi3-»[1nŌsJnFS'R*U`cO۞<{r%r9|I );AY㕙>MNgҝ+*{^2^5MlkH=Sl-~@ Fy24+iSө̌\P +93*=+4L={l]< K7#L_O̔zvx75RxeXՅ|vꤖz P#6(e3Ǣ49\#L*Yek.{LddHO*sLIs#>|o #c`;3 mcHrSCn|Ĥ* Y|vY +ke,K)EmJ.+x U\Qy|;rȻ chiCG3#t27^RL%VJe,u) % VRYH 2*ۡXxK^n"/˴2K-pg]9]m jF_-CF2֓b$&@>*-JLx_b}^ SH~gCcc ~cUEp>4q*=NsaXFh11+)`bA MhPi`0MA C?Vj)x6{LzӐأVBV7q7 $K%l\xa0t\x ǸcBHuhcC걓zCON0yy@0"dF\1RkRivHMdM4pġӄ&45GoLLk.Khhh k\ni)![ 9<h#;?;: 6+Xy#tp 30hs1 ; 9tG7&4nrхU]Gy,AUEpܳ:^J<a<2h6ƺ gGI'M/uE賏FG.Y'ṿ; 1pa0p{Lߐ {%W@Ca!WқO c *r1@_RqpfLtLRl`ut^o$6hVӐq -8.sfp>rFqخR+_W.0Y āt0Rοgjs;pH}A#GGs"^@ aG>|Tp!X4T |pƲ~kg88K8G<N]zS'u/ >z:=E;N*ңn<7U#` :._ORܠԍp/h=k!G!^7YJgz\hDt*bn 6^ 489x,؋h2GM>:p6Nv4#ԥY EfUR0we mXu8# teDt2!Ue/Z"\B.j(fmV]O{ jȭ7\~t \χc9)2xYŮC-Z@泳R\ ,F}9(48ĵ5xW:EiU5YJϨ.&j$ +n1 BxS(fYjC(i>'{ogG;k}+l$n9C5rxxK;\p%'/\p k4\5hr#{#PN. +idgqedY1@3zMaL$?r2C&X5>ȡ1A.%jTPFgiD a!w+'tCV:7)5C)O( 1|!OwDt.Xm)1PANO!ǁ紆*dT^Ur .eGxGRZySbdSd{< =ZQ1]!2YQ,jLN\r,rNi 9~LSeLȄ*W*,qB=9  +NUHO]pwL,Xߕ|VLl)f9#'CNPEyLxl2{2yeLJUD0(-U3Ui0v|:ɮL1v +ͥB+tr)D]᥊y +ݸ~0)\*ָɽû{Xfmհ2V|ߵ=růĔTMT۩jEZWj^vqq*B˄ΆKZ[µo5c[_U`8,G bK^2ٓ:hh5i|1/jZVXA>ך_,N7Ѧ _\[=_iu`xD@yy_2%ʹx>r؏{Թr`jf>+Te$9 `cU: I ~%ٱ/袁/h _s)qqlK3[j ML_>7\;ֲc4QkTT((kx[w +ሕKk4U@{.J1P╢4 ŗqE`ƎUn\ɼEi]l'${.yǵ1Ja} !Ϛ:mfG3m4I3]4E35q^'$;i츎[u r@ +1T<ȸѹm a-߉MKvǀz(j-|BL9~3p.Q3 xԭGn߶dN;|ܛ}6'Ѷ$3'qR<%&4S|qJ~DzR>ދx/9f |ʸ'yj= kâٱ ]0!,ڣp~ӳq0rN<Qٗc;ޥ`|<\^\e>PF<?WOcq|xiorM_a{ u| =&RK忚6W$dv}*1?X߶i{#_\Y3Nmc} 6>|d)];__/9Գ +3%OlOI' 3d,mB=E;bW8{; +,g_^U*IltBtl x( $/g :{'iv6l`gv;8hûCQO)͠s'I=. \x)9)#+yJ9ۉxs'5ۆ Tx>)3tSI/ WB)t~-vk~ƻFvNZMsEp]z>Dk;ddI8,ybi|ENbWVf{crVրco5(Xe1/sSG j+GYvꎣ7b%8pTȊ*J3LJY–ٲ_h9 +ukTz.?.7i<%oD,!`R8\)`. .jȥHB@H1%폎@TXb/&f:.cK4#1wsb=8|LfҖxxCCxt $2N(mt 5&j0T?CpmG2aEh9K(U/0q&{@AkX = =Y&zfͺ uЭ>HV^iPfPwމЋlxH9,4ٲ5f` ,x808!qM٠)]I l"10BTI##P$Ccba܍2Sc5#&F&G;Τ-gҖH#D >[3F5b( Ab${izз9&l^}p"F;b2!{asE +D&x#8j$,byb!p,dLY]ّ!1CHlp\q .U%NLH-Rdch +^@D3Hvgxq|Dp*жhcHu}67jʌ +?R#3I3< PS,> ؞Eq\=-R'6;9IAzɆٜI6|XdA,@W־+Y?[ړC iBF-(ӊ -A[(oq@j ȡ^s8j$,AE$h~?Xhڊ>ǁ-•a0|!St+R)5D@*zmahCFnlV7qm͐pnyQњ+{O#Ok R>5y]Nbs0 ;P^84~EJcil)%dtUY#Wq€rFtGz](9dj_8`]భKJ7HKwsؗ1TT..(rۮѵ}4f>z{ϟࣵLAϻsƌzfzkfL(քC ~h?j}CJ3E%/c_TVJ*pT_xEy\_^Hڨ;Wi YA"ҭ[l!Iv^يR9$Vd2nqy>=/<y;s+Nw $ ӟmWy0\*c<0gלuN@B! +G[Yu?R|^rrH/坑,~$K]Kn`l=Z5[7q|gUnr"~F8ߛ-cY đ\ೖ-K1Es)`[>zyH]PF(볫ܤ;dqFV Lk-zPߔJK{wWy~P'C8d,ߴ. :J@7 dzqF@` V" 6X ##  ZeWŔԃN~a~qfu#E".lйy.?Xϊ ;m HK=`(tu4G!gn_:^!B@zhCLZ8l$@ ++ @ e!OAx C8~ⷎNs]=/I֣3ѡM*{q6ljK~!}9Ym!!_7Hlް(Qppj`0GXs,D`+/xGF@ҚSШ +s=t##URuMT?|zq+[:sMnִ䂹33o\P7.B *OEtO1o,N4GO\ٞ~pc݌)GR0XQAl(f4 M)h@<׹L"]NJYsr,'%hݹv + ݆/U)|JnPW +x kFEQ`0|=t[ 1x}fpc3A&ŽpJ ~ 7%1,۰PRND,^HU0uf>7웻ñ]zQZVq6 S d`0XA#GVJ[(9 +RWvHo^0x3 bx +p`+gQ(^1ױ>9ږ騬*^x#qb ,Y2aHwcVMOb/f=-ȁ/} - `=瀾}k) +4`" C!)p3:mu@XoQv ngn3w:s+*qBV- M$NreO{}v R` 83JyMO4)XZGyQj{DM {_πY ̸Ӻ|)weUefᨈ.A]]dciI~\w<8/t Pg+e >*7E`S# 3\GHpχHn aKS[K 5uk;mɶcVރ iEHD_+߾U\'9GVXJ¬9M<~̨փI+qijL9%A0pcF"((`77Q#'q h[:-H,n#*Z_YXO +=Vy!pLYzY*K;x2}{"w7er"Iw:GSy\V[<6'Rչn%:溬'5mDtbZL\&$ +ܾ~vן{}߻<%E&gINDHJ"NƄdD] Q!c@ +d *>7 8PW% \ h`3^l:93cM|;egA :܂8XJ[7XI|0|N7w[{EkvcJȬi%J-Q#u|FBѵ<~ԠVTw|_JvV{J,͓ɯ)l/` R|Vxfm 96pL1c3Y0ߜ,/NP[@Qt+eKTe9ۏ-p +Ȯ|BpW$ %IHO޿y:~0?_(gD,rE}KcШ+)J_*=I,?!4l=Å[Pծ=Ğ [ }g OZO$o!xL=5dbBC) Oմ>RIr\r"#;@V2[kclzi5a#*Xm?;62.#:ĉ֙Li_8L+ endstream endobj 104 0 obj <> endobj 112 0 obj <> endobj 113 0 obj <> endobj 103 0 obj <> endobj 114 0 obj <> endobj 90 0 obj <> endobj 115 0 obj [/View/Design] endobj 116 0 obj <>>> endobj 96 0 obj <> endobj 93 0 obj <> endobj 117 0 obj <> endobj 118 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 16.0 %%AI8_CreatorVersion: 16.0.0 %%For: (Lennart van Zanten) () %%Title: (OPNsense_Logo naam + beeldmerk_FC.ai) %%CreationDate: 17-12-14 10:21 %%Canvassize: 16383 %%BoundingBox: 166 -466 1032 -292 %%HiResBoundingBox: 166.6621 -465.1621 1031.0273 -292.1592 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 12.0 %AI12_BuildNumber: 682 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBCustomColor: 0.886428 0.26404 0.004576 (PANTONE 1665 C) %%CMYKProcessColor: 1 1 1 1 ([Registration]) %AI3_Cropmarks: 0 -841.8896 1190.5498 0 %AI3_TemplateBox: 595.5 -421.5 595.5 -421.5 %AI3_TileBox: 192.2749 -700.4453 975.2754 -141.4448 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 1 %AI9_ColorModel: 2 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: -2168.457 1082.3311 0.3333 1869 1054 18 0 0 6 133 0 0 0 1 1 0 1 1 0 1 %AI5_OpenViewLayers: 7 %%PageOrigin:289 -817 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 119 0 obj <>stream +%%BoundingBox: 166 -466 1032 -292 %%HiResBoundingBox: 166.6621 -465.1621 1031.0273 -292.1592 %AI7_Thumbnail: 128 28 8 %%BeginData: 5990 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FFFD187DFD67FF7D7D527D527D537D527D537D527D537D527D537D %527D537D52FD07FFFD0CA87EA8FD04FFFD0DA8FD05FFFD0DA8FD2FFF5252 %A8FFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FF537DFD07FF7D527D52 %52527D5252527D52527DFFFFFFA87D5252527D5252527D525952A8FFFFFF %A87D7D527D527D527D527D527D52A8FD2FFF5259FD15FF7D7DFD06FF7D52 %7D597D7D7D537D7D7D537D527DFFFFA87D527D7D7D537D7D7D537D52527D %FFFFFF5253527D527D7D7D527D7D7D5253A8FD2FFFA87DFFA852527D5259 %527D5259527D5259527D5253A8AF7DA8FD06FF7D7DA8FD09FFA87D7DFFFF %FF527DFD09FFA852A8FFFFA87D7DFD0AFFA852A8FD2FFFA87D7D7D2827F8 %27F827F827F827F827F827F827527D7D84A8FD05FFA87D52FD0BFF527DFF %FFA8527DFD09FFA8527DFFFFA8527DFD0AFF7D52A8FD30FFA9A87D7D527D %7DA87DA87DA87DA87DA87D7D527D7DA8A8FD07FF527DA8FD09FFA87D7DFF %FFFF527DFD09FFA852A8FFFFA8597DFD0AFFA852A8FD32FFA87D7D7DA8FD %08FFA8A8527D7DFD09FFAF7D52FD0AFFA8527DFFFFA8537DFD09FF7E527D %FFFFA8527DFD0AFF7D527EFD31FFA87D7D527D527DA8FD05FFA859527D52 %7D7DA8FD08FF537DAFFD09FFA87D7DFFFFFF527EFD09FFA852A8FFFFA87D %7DFD0AFFA852A8FD31FF274B4B27275227A8FD05FF7D2752F8274B4B27FD %08FF7D52FD0AFFA8527DFFFFA87D7DFD09FFA8527DFFFFA8527DFD0AFF7D %52A8FD2BFFA8A87DA8FFFFA87CB5757D527DA8FD05FFA87D527C75B57DA8 %FD08FF7D7DA8FD09FFA87D7DFFFFFF5284FD09FFA852A8FFFFA87D7DFD0A %FFA852A8FD2BFFA87DA87EFFFFFFCF938D93C3FFFFCAFFFFFFCAFFFFC393 %8D93FD09FFA87D52FD0AFFA8527DFFFFA8527DFD09FFA8527DFFFFA8527D %FD0AFF7D52A8FD2BFFA8A87DA8C9C3C9C9C293B593BCCAFD05FFCABC93B5 %93C3C3C9C3C9FD06FF7D7DA8FD09FFA87D7DFFFFFF52A8FD09FFA852A8FF %FFA87D7DFD0AFFA852A8FD04FFC9CACAFD05FFCACACAFD05FFCFFFFFFFCA %CFFD04FFCACAC9FD06FFCFC9CFFFFFA8A8A88D938DB5939393B58DC3FD05 %FFC98D9393BB93938D9393FD05FFA87D52FD0AFFAF527DFFFFA8527DFFFF %FFA8FFA8FFA8FF7D527DFFFFA8527DFD0AFF7D52A8FFCAC2939393BBA0FF %FFFF9A9393B593C9FFFF999993C2999393C3FFCF99BB939393C3FFFFCAC2 %939393BBA1FFFFFFBC99BB99BC93B593B5C9FD05FFA1B593B593BC99BB93 %BCFD06FF527DA8FD09FFA87D7DFFFFFF527D527D7D7D527D7D7D527D52A8 %FFFFA8597DFD0AFFA852A8FFC38DB593B593B5C3FF9AB593B593B593CAFF %BB93B593B593B593FFA0B093B593B58DCAFFBC8DB593B58DB5CAFFFFA8FF %CFCF99938D99A0FD07FFA0BB8D939AFFCAFFA8FD05FFAF7D52FD0AFFA852 %7DFFFFA87D5253527D5253527D525352A8FFFFFFA8527DFD0AFF7D527EFF %99938CC29A938CBCCA939293A09A8C9399FF9393939A9A939393A1BC9393 %9AC28D8D9ACF939392C399938CC2FD05FFC9B593A0A8FD07FFA8FFA8A093 %B5CAFD09FF537DAFFD09FFA87D7DFFFFFF527DA8FFAFFFA8FFAFFFA8FD05 %FFA87D7DFD0AFFA852A8FFC293B5C3CA93BBA0CA93BB93CAA0B593BCCFBC %93B5A0CA93B593CA99B58DC9C3BB93C9C9B593BBCAC293B599FD04FF5276 %6F52275227A8FD05FFA8275227526F7652FD08FF7D52FD0AFFA8527DFFFF %A87D7DFD0EFFA8527DFD0AFF7D52A8FF999393BBA0CACAFFC99393B59ABC %93B593CF93B58DC2A1B59393A7BC939393C3CACFCFC9939393C2999393BB %FFFFFFA8525252275252527DFD05FF7D52525227522752FD08FF7D7DA8FD %09FFA87D7DFFFFFF5284FD0EFFA87D7DFD0AFFA852A8FFC98DB593B59ACF %FFCA93B593B58DB58DBBCABB93B5C2CA93BB93CAA1B593B593C2CAFFA1B5 %93BB8DB593B599FD04FFA8A87D7D527D7DFD07FF7D52527D7DA8A8FD07FF %A87D52FD0AFFA8527DFFFFA8527DFD0EFFA8527DFD0AFF7D52A8FFFFC393 %93929393C9A793939399C2A0C2A0FF93938CC3A1939293A7FFA0938D938C %93A8C98C93939A9AC29AC3CAFD04FFA87E7D7DA8FD09FFA87D7D7DA8FD09 %FF7D7DA8FD09FFA87D7DFFFFFF52A8FD0EFFA87D7DFD0AFFA852A8FFFFFF %CA99B593B599CA93B593CACAC29AC3CFBB93B5C2CA93BB93CAFFFFC9BC93 %BB8DC2C3B593B5CACA9AC2A0FFFFA9A87D7DFD0E522852527D7DA8FD06FF %A87D52FD0BFF527DFFFFA8527DFD0EFFA8527DFD0AFF7D52A8FF9ABB99C9 %A0B59399A1B59393A7C98D9393FF93938DC3A19393B5A7C299BCA7C28DB5 %99C393B593CA9A8D8D99CFFFA87DA87D522727F8272727F8272727F82727 %2720527DA87DA8FD06FF527DFD0AFFA87D7DFFFFFF527DFD0EFFA8597DFD %0AFFA852A8FFC28DB5C3CA8DB599CA93BB93CAA1B593BBCABB93B5A0CA93 %B593CA99B58DCAC9B593C2C9B593B5CAC38DB599FFFF7D7DA8FF7DA87D7E %7DA87D7E7DA87D7E7DA87D7D7DFFA87D7DFD05FFAF7D527E7D847DA87D84 %7DA87D7D52A8FFFFA8537DFD0EFFA8527DFD06FFA8A87DA85252A8FFA08D %92BB99938CBBCA998C93999992939AFF93938DC2A1939393A7C28D9399BC %939399FF939392BC93938CC3FFFF7D52FD15FF527DFD06FF527D527D527D %527D527D527D527DA8FFFFFF527DFD0EFFA8527DFD06FFA8527D527D7DFF %FFCF93B58DB593B5C3FFC3B593B58DB593FFFFBB8DB0A0CA8DB58DCFCAB5 %8DB58DB58DC9FFC98DB58DB58DBCCFFFFF527D7DA87DA87DA87DA87DA87D %A87DA87DA87DA87DA87D5252FD06FF7D7D7E7D7D7D7E7D7D7D7E7D7EA8FF %FFFFA8A8A8FD0FFF7DA8FD06FFA8FD047DFD04FFCA9ABC99BCA1FFFFFFA1 %C299999ACAFFFFA0C29AC9A8C2A0C2A8FFC9C299BC99C9FFFFFFC999BC99 %C2A8FFFFFF7D527D527D527D527D527D527D527D527D527D527D527D7DFD %68FF7DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DAFFD67FFFF %%EndData endstream endobj 120 0 obj <>stream +uĶ}]?ʘJZ?& +X0^b:5w 75p% zΒX'͟^4Nxy)æSA$דӇ֮/. ~@f; G@H ֵw$@\cZNU|鋩}c u@m%%G|-RM$U˩m>n0OT}zFL;56)6M‡[7=Ѝ*~m OK8Y#PJCvޙTq4FptJy +FH!Ȭ:d[ܖzk2((~T~Vy=?DZ`9\+YW%.f} +e-zc +$f2hؙ9=[dWiC+dرoͭ6Y^.\{~?r6gTKh&qZ ڐáiՔ^YЏD{laDJ幺X|X}O`knYbxY +ܫ@I *M~֟%iǺ32IY&8vcnD,E >mc N$0|+~zfxɯ'[Ojbt^5ҋ tTz6´L8I<qG*v՘:ek3&=Bmb(su;}hC3ؘ6t_ER a͖Wo^߽|=FQc%x`GuZz@N6K#;GT6z_4Djc*>4d?jKkbt@Ŀ$ڀƎL2U$w˄!tywҺQLY? +lKBZw}RhݸyנZs*A|\'hw +-qYntS:?N* W\@#?or\j"Vmk=}G`'xmjoѸkxVJT/JnuqlHtHWNR=jw@Ԇ.-!`vgFzn[9s~XOorB^$i6F]oط͍YMNujDO<ۦz峌KOQIhvR^A:`eFNIN¼%'$DoB{>Jѹ^lAݶ6ZuS~wI&#NL(w?tA%rN~"q{6IK +u[J{_FXE1xgDf(꿬v>OTbr뫌uԣ1`Ǵ[-n8';=8ڃVuuLV97Gmؒb'ndbX[zm][V~Mh[5Be~ fa{Ol@0剿\';ۼ\ΡT4jq4V.{`Fnd>zAJ +ˡ\mAYKq{ +/j$oE?}mHeOGg}K-7& >6K+,Ӆ:{߶6cUQǍ^ҕ )WБz\iIb<a>ZϞs +Q.Tz}݊znvEidE +_b{&U.q0᧮xO(t;-_MޢiS~ڱ,ң6;iUWL=ҩjz4jwjjZJJ)#ZwM/JPܘi+c2 !UEǾRou'29"Һ_Ńwd~hFsצgɫz8|)bt=Ub/AdMlEyc:RB2.㥾Ny5G,~ll`Lƥwک5Y8T fZ z]dvBl7xGfKvWo5V7ZBRJ,A҂)I_5MRjqk1VsemJaqz[Jϻ]9-}N䦴QI(Eb ,(}~")WP1g3Yx\"r"prWJG8ȕv5qsiN:}1#XgȢ?SQbe̔fqA9*“ OB$=фa2_[]?QFPMc?) me1 5(~(*@u}5HHB *E"^=fQʆV do4CA%gj7ؤ˞ʿ27'o;PhCtmBTdU9?PH/AMys $"y*Dh;ok/hU~@*s oO:uC@e +P~Q5huq_@"2`] nV;Kb4e"QX!)%]_:^[ҡ KՎ %I輸b\Z9JSyf@1lJ8l%@"S!NlۧKy޺Ot⋪рi<*++sRjoOv<:숼!&+`b]߄= +QPh:5@) qM2ϣeTh a*uپ<> +(k(ͨ}nC ]Wzi}mpZ4" з&[U׵WP0/ZѧSz?18.U*䣚oUo;ׂWvF(\Q^`r +06B%Tpw'WdwޯM>cY7|\΍l2xToWޝ%͢M}$s]R%( A: {pl+2?pT7~:.b * uχgǏG9?IF-հQ6]|<3 [\h JG̺$kfG,F}N_ [y w ^ǀd[ ]"ۊ>)dP ޱq#wo?l/V.M#ۍg*iD7 C;Ou&: ;ߵwwô' ) (iΗ +2ecH[\*!kF%,n ߂vwʃu/|k VlKyqqR5lYb݃쯀.k.F;6TiɖzgKTU+{[kյڊ;_K>v輻 +?o +K-tğ_i +$}@Կ;#ܫ$b#魨wys دՖ:_uO/ɾR˅:AFwtݣynvLYֱ첝{ZD)T+zfx,@<4gB'wg7(tݑr04oRk{!7>r]zp r:.Pyyώ%:55 bΈcHǯijxvqEp{rІ$(C1HI>dU_t|Ԣ*z:\fv.ǹZS׌)y?!egaefY ]"=*[+$o@Vk 8*3Ja#Bc\ߓ) =?ȜR+˙!,& gS|nuR0OΙ5^cg}`39oyĿ{.tH=Nq T@Jm{,@kТsM +_n5v cʟQumLSΘ i;fa^sߨD}%C}~?5t3jW[24j@/ Q?_p"-HC@q(s)G~uOI8m!j:.p&`5"fhgFu{)3QwEe_>Γ=j.I>^BcnP +>bl,}_Q9~\ + +TR˭ɹ!j5b(EoL75xIWsͷ6Jl{$=IS&W"Շ'E{{^(?{H[5hCNfy|zx#|þJ`8^2ibkߘ]sou [S r7{!9K1|vxlQΜOa!d4&->=lO}w?me~6K7G8Ye[Vm5۳nmYu z[.tE~{6Eb[.|a<"^XP_CSw.tٝlaE[ǖe>/2\354jQŘb/X A#ٹPJӞbT@IgxyFlR:IwQjҌm\gZ~WVid{i E4,`Jrfʙf^jPMyXZ4 8ʔ1`I (ȠYf-uZgˌ k Ya tHF[s' +k +r  d ĊxAQAh s:"A?_WE:kPBUa +?7dȞ*N?=5;c #o]x  +qɁ,TYs ",æ ?2_+W#j~y?$chTW@5m^+{dWda|JWXAV%߫d5"p~Hgy8z"Wġ̣.DBohqI , 2 {}9@ y񛰟eA60 (dߦedDOPN'ؙrĩ\|^:6:W޹gWl'aDY]^}@grhya4^Xd5~dr + %H5 $y ' Sjؘ r]qm," Nj5M>} `bxlBg _C+oltB ҋg?EŌ>D5ǟMGh/몽_;7΄{9؝+C&kWCUzM9IBriġ%qig߭ y })z\-j8JN^磷NW@o=ĂA& |sY`@%e 88p6Q3Ty!/øBӨ7ܢ|8~+jEr1jIˉӏUq\/̾;odwR]O0T~o[>'BSNUP 1XD}jϒi?vs]|o'kIp">ȭ궵CE%h49Oօb?_q3[BWvO}`~nPfWdR zQ=*ɑTv5\|&zew9sa% d=oJyu eκz|`?S{JE o<}c?PL: Fw9 ~ uq9dVB[`Y>oX_?\^? ͛re)C.vi.m'mwG!CKU×KLw/.J&9fH PMOG5Ѱ_X/f\ U{1ˊ^샐yFEDEAePEPY몮z\ݴ|H!3Zqi_OqݴgCREIEm5YBomƽfP~ҹMd\`LAWg,v@.ED?ou]2`3ʕp?ghoFKy +EǙU3S]0Z+T{׼$;_';SCCu{fV/- "ꑇmn*'Mkѓ  'w 7yD/ƎCxvwwހ ƩuT*NhLjkr7O7ׂ*KMyZwMx?;sW^\G +hGV]Bjk6z}3N~\ k7T*U1Rg{c?$7[sYI5`ꔜsF,Y2rs/#ƜD%Q>\t^7+F-Mj<0';Z*{qdst#DVF^dWRᾷq${lJw2dFS%dV4G1u_vjj2\u# + dbYT?8ER؎K }JIXaڦBR3ZgZGCp_Zlbhg%:;V)ph﫞ջ<95&=r[wNΆ(N芹#/Mm"7|ѻ] Vrq2wNVTN-Sej`{r=nq˻iLD"9sU'C;lcPM~n]ŠTΕLif^ δtYŇy資 k2\\kvl>yd2o}~= |C[LU|,5xѨ6K9's vU52 i` mڕN tl?3} '?d-eS,Zt_Vp)$mͬʼd{G8Qqf/Ny"4D9\ke{ +QǻVUW"Ptzi.K/uV_PhYi w4[zo&j_y\ߥx6\vYNyIPs֋<@{KkȬY;Tۉ~Пe,ҨveXnSt/L4%63̘ؾ)]SpSpXBa7i rNWk3WMJeccu`?: x%#|zKaq{ôfg +S ]naJMnK=eʎ( ++` lsZfu=[41́2^@dT^ApC3),y1pt*FG`<ߔ8j(m×BZMYzTo5u$fѴ spwy +b}2cq"_Ge逸i ^G3mnY٨19j3^e>UVnjlϸ• +~V|Dm Zop.ޏMmPc'n{ine'}#[ʹ@ә8j*h}ڨFQJ⇪#/wN*ĵ3OTsߥҫ2 +RSxW` +R zx+JrE-xجN!blC? +VF*Ө%^T?k* f&aJ*|irJYԾk񑣋Y"z֚^lR38F?]T( #8#7s^ec5-}.u<4yV?]qk O?[sC+SP\7La0 +(WgZ ]PA-Zo!@w7hP|\hzds9q͜7:_7&zG2Y#0%x%7A~PG!@^I F7.9@lV @ !b^zyE?2ls +࣡KAph>:-`LvuB"ew!|ߕ!EbSK\s{|^>xzk*\|q =kTey']9G7%3ƣ pe/^xm!ZBo5s+gA^3G2n /rJ_toXR8҆B}D@`qʻ؎΀ 2qV|l[8¼z)/grDQ~TI>${=]n0>OD#Wߏ>u6>P(7QA`cD=pdPdc17֌u%w.˜W/;eq.=NPw(;qZ`)*aoFS2 (susF;{^\˗{Gߞ䐿Zҽ>g Xi4/a%'Ǔ!Jw)͓@vE?^ez`t;d7~٬{]@^E߷s!HULΛꜭgM!R6YM@l(|uLvzƶRգN7ښd٭} ~M0oP&@N; C|ߡב_i'=M{=|e퀭G䝏dg I-cmn7QkŜDl^}ݕW^%q~l h@~>H'w/Ndm/h=NiEfk(]e-`;^Dj1o1c0F^L,@,[ϊS/}2Tn"Vx{38XŗymɊ +.k`O vߢU(VhK +ń,県wL_ dRN{/J1?X@ <ϯ 0.ݹlɏu$'d}q=❹{c.+1E۴>8-Мb!fk+ J-yic3Ϲ3Oh`͹ +s` a}^암K̹#G!IZz;yWJ{:kꄬvw*m?AiI}} 9}g5-i1(1C]yfI5?r]\/ekSu +ݱ]Sj31M:4Υٲ.9!}uQ'P.fP66ؘ 5Eîr }RQo$j4c2 1=uxfPg_h[}v s־E?c,F$T=7,ӥY6<0IlrG2䄡#}HWLn/]y5WM9yo6mrnHg֏ +þ uĻ*ottsLNieR3]|]Es T =W#9C{ÆDydِzGI֔5=@Je(tkeY- G~Rg{s*9,יU>gО)l-BOs|laYv|e#Go؎ V!veClD9S;eM緙eO<ZC3SRݴdrG2 ,Pcr;)=>> +}ACzL܉\b¡}ϟ .}8L;Q;'27 x/+ͺ_=˭/D16)+F#5_/#yS-wQW#WCjn~tK?x7N֫̕;tRL1k!xYfhNi%ߧmL~yrfi[u֛ YG7}a:o&SDe;*`,[o9[~?Mn ywjψdsߦS=FhAOw1~ '-LEh +Y?јn1;w`>pYK[wb))ё3b5aA7+]efƹqЙZg%_mF q+eK-϶ˆ6Gh˟o?F>7?N0qOϧ``9?O^nɼuVޡyB!c/W3Kx#o9$W^<{6^7LNF6t\[wJSنVT4 +xe2g4]e>qO~6躯>V= g"Qgp?NѝzcF +Kamv ͛jqOfbGO֊j2-sOUWMA|Ze)eaVurO<]K j\qKiYof؊|jk~cҬSR뷠}jT]vRYY%]B9MݍK{|Q**+޸$:on(|~̥7uoF>Դ#c?nt:nbL͵Gcƌ\kG ]a3Ϻ_e {!4Puy:rH. ja-}Ѳ^8KWz.~^NK,rU32jE^Oev4`lzhvP6R]tvNu$Qi!^ QzFSb.ch@ۄ~4|\zGLg?88S)KkNcUKuš:1?C߿ THP-:4`D/]?wn)UPdRR! w2(H9Hs]Y7B`DBst h''4+j  \?Һr rt&*H|M R .qekxz.(^2X8,T8.}sEhBc~НoTLZ\0@ nVi@h B.`MW 0b=ٰ5+{!zrn|P(xl\*ʽg|%z5yp̓ڨ{)kYZ,&9 b;FLs?~z >ʷ{uwnJ?-{ ܪp*%Lb@|$4J$ޫFJw)OuΎ\<{ TfeiKzx8/UU`>{<Wv^p ޷W#nP=;F['/XGa8NP *< +]}N.h$&uy y-ʽv{Ou x慭zΘG1OF\S'-p J +oVڃدkcd䙿+eYۻw m2ԳFw*^Wf_NՉ=at9k{r ž{ٿUv9?vw9oF9{˩{2P Q@:;Z&~ho3屿I/`J ?PY nl"d'Tovg;|o!c$oK=ص!'vSg<*p:DyR/CЎ*i-ʕM>޸N$sA7#`]ȖO镎o֭a3k#̝F>l;/6e'hkGȢ%$) /~eh9E(TY@R+IPySvKhu~oM+d]֭*?JzܔQz@JE:}\}#.d l(jBɷf<*f=ꙵjzlքlܪuѸ1m7.Wyn?Xyx*WT_-uȝKzI I˟ +p/֓^'gdh\7|ԬmiJPc-hiO +U$<9k91Cޖ[emVk3A&ilRԢ2 >FٮjvD16\- 8G=ɡS1-Q;gz9լ#`ȮTSqӳk6V[VNbhlUCN=Ԛ}r9j P3,'fpka~}~NW/zoDf}7̩D +7Oɟew|f,k1mQyҲ;޾r[ڽ}JFd+̉ٚO E+3̫rǃ_Zׄ E甎'e !)?vwm %3]U/-46G,hטϘV:#H!X{u]IZ45lr3je)F^ʟ|#m G$M8u ?{5~QmWFouN}61\{pKp_-w.m VzzTxgtfo'5A6܋DIq*u0A`n +BUăGL+^Twk4&nu|qoHĠ\ h pNscSwҹGf;[ME0,l)>.Ki>W Ŋ?Fu½>nnvȰTg4) 蔞l%4Q X?hS=[MAoT޽܇UͽVrBm{#x1QW(J]0iBZŭnߟ/nDI'2sNgjw[iR~fzdj/̚o>俪쬳Ux_F>꜒jՉtz|Jty5th*-H;P;ne)-[LZzv d]g#@S~\Sm<-Jpv4BGi}/.F!ܶFoc][wAvr7l*UFei̿);Ḱ2M*}m yhIbNxLl=^ɹx60;624YZ!ÇB=rḬ';sFUwæGoAOCLCjR5mq_cXCf w|e9p+[NriT4ތ-_Vi~ s-yeje4|]=GN^W.?߲Ɍ}W كޤev+5iF|n{zaW3/E=O60М)N`U>Ֆtzд9rOl"WA!B +? ? $^eMy[wEwѭ M cw1Ԍ1v+[Px4ӂʎu9sH_gzP3!!;~$L${4O%!e;աGTw!*0i7 xtsVAsJjPyF^3&|ֆ7$k&,J_Tx˫5hk#[:TŃ ,čNu괈5FS/| u41PG $ Q@MuA*mL>N3H>~xcGffl0V T "XgC3f!u;<} eb e%(S)L4)|> RuB$[J>wG +,xA +;@ +/e9 ,StQRU&^7 @~].o@@jW eM ̲,DO0XyƆ 4 aAJϱ /2bKzi7k_1(/Ot@Q®YYY=dg|o 1&TcP4{9܎0<'ßGk`tm%ᅉzg'GR!26:Pk}j}E|)sSb pc~>w7/HG#o˅e[tCl:lmv2/h~_W9B@zߙ_>6;igG9y@wbBXH,l1>zu b1^SHTو ~_.OYS{Î'2m6*^2De73a~M_9Ν8h+3z'^ǙҎJӪ>H0c/+R܊{;_m2;ټF 6uubiV =6bmٜՆ8*m(OӕY]mMĂ)ܛwI&8а5H +KmGoܩ|kcXq±e|ܳ'83廞޿rԘE/4ob|QP!YmJPa &}NECKc{<{o/7w1皿h&+<KGePZC7cagi %)$QMk4٭#>. pEb$IW>k0]"ަh"v\en}uawn'kţgegpY7?!㈡Muiy#63f.ܓKWP!E6nm6q@ڠ_Y98?ev&{>÷WyNƽXćb,Nf3tiꋶxi)A[3 n#JsznXuZjiI(h>i('\ݏz >t s+d9t|.hof\4ʟ{8۳*itII9rJ7ƍr7 9 2#~i|E)9 9X"sh&Pc'd zEv {BEk/L>:߬LhA;eG[Xcc{L22ﱾH*қYMEB/! 0]Z(-EY9f8i+e'bT8X+,fh2jVAk:ê9.>2_'y)On-Ѧ.p=j|Rޅ1_>ĭ*b.?zYA$M='x$t{FJh%n23U؞ʛS%c*ND.ؤlÍ `Iq{L3<%%JŞ%ZD80?!7d #_WD0 r-^գsk`yҘiP$۩uqki9EyL-UNC-HRWZP{` [1Z Fy>>.s_d ^}:z,Xwpkk<%5H.Ý Y.Bӊ1e=s2xV8|=O%DDWc{5R9,?x;>h:$g39ɶƊ@9}߼cp5 +lFsj杅w\êvlt-ө/*Ր޵+q*ҳ,L>??W>nJ#57ݩDQz#W%鳭L/|~Nc{=q.a~ۥǶaʖƵ`ʏixg$cĀqñBNx2݇m̠_۟nZY1НC8`Gcg c 3??HP"zT=XL?i>K67u\->H$EU[B|ϲ6=9-Y_YfƹI$3f70'j[fP&NKNs_ Lvr>/7t_׳R=@s+7CySj>G{쁉Ůdahs+iY(;Ad Fz)g1mij4hZ/J-PB<FWIA4ލ/N-"gЭ>3VSdNZDܦ$,xĖau4L,rm'NwD<;.N君3]~t{[yX57زo+bk;4^?8m;yNkG '{m5KcכcwQ ))+Np*)/T 'ϝےV'{規۩}`n'\?|$c]8RYĥz{ꝭ: +=//_9M#D³ƋZC.%KE^˵j3}f\]LmV2ڌPp\ci9^F`؛$֔*4ڨAOs̃nOxN;aQOasM!iM3ILV?xևIj+*V)W]aG cI9?tyU_Gh3L’^ pApVMTvmf!7͐gzp%^.tƚbe2^Ks-N[m)}qeQ,&_YrZ4B 3˛6-W9%s:;g(kUfπW麂.p)L9SB)sRNsV + JW Kf9mya 5Rn%,ydǮ7l-tn19GlsKOYNY]nzy0%r9 +cn]yPtse@!BTBBJD!Xl˯Z-ri_»t$÷"'D`wL97,0P)0M3* . \I-Qdy.Xo`MQrusT OwBTfr|6xUJ;bAt!-lɟ|!Ϗ&|cn U}=׮> +٧7òkqͮWE0~:TzLqws +]$# ;]5tЩ.LfB"ل&ݹk{烱W!MX|8EUm'3h$-n} !b !`l|)zx]D-b&ôCC4 +B6kEe,"SS( $#*G!8}'%?6Š;5l1}jn_"ie,V.auvq=A'M2? VuL2'&H j ho> Z{WTGo#/br{z=$o C(5Z x=ן5|d?u>N _ޟ$3$K`IFIfv1 Z': yOf7h(xx9+d8/ khl`/<0>Wjw7j@M/Lzz'Yg\߬|(Or d}EH}w+r5 km>Cn=S>cO={j#T}fzo8K>㗋$:uƥrz{? ȓ:!Ψ|ób5a5f=b~( q1^9Qe^b&sC(apY堹!a_qvIՏ2>U;W~`:z )95e=崠Դbh]yW$W+0/Dx8ɚPPZ=eVKe6xX񮼷&lbX470{ZOD OHGqJ%vr@n #'In31_2In4ԞDYLv_BQkpϲ*iVsN|b' O[z:tqCRNG{09ɡ25`vn2WU>V3_^/("POn{: /QyKjY'sѵT($Mp;^`ܳ[ /'wr=¶#6T[KGIGH7/4(>w]7p#Ś;gfθrwJ>&*6NK>l r3{7ju唬6zN歓gOwFcԶ}Kک5^+SK]V*4d^wkWgQ=*^O:W'&擵%s~Oqz٣ar4Nvm[}KZg (הS':- _Un)=]r_nfXz8L55t:)q_L?076ї_$-=7/'^#b[Ob u<=0w|ߢ +L"rKxKMfo0&ýp≂'k?[%Qlo~|eNl'EGC+\;Nq$ŭJIA) +ݽQv]Y( +XԂtm!j#~4ްτ)oYGͼxBF>=i߯enz/(7nN~33@ߖUR݃1,6Gc$vWN.Q0SluڗI1&#t߽ɪ|b]~/h#F';ΐ=L]/#p}j+r'q>->[0 U=?>o[oP)t~}|@X)(4_2]X.:`6]S$ >*ްZÇDevz~ =ЧF [Q#%uEH [Zr Zڮ]Fmɑgԭ. ӱrkpUg:"e<LdTܰFpgﵨl-a +3MhW`W%Fo3ϺY橣PBM< ۔TVyi'bJŸ 2[*(OCv]n%Y +;stXgҩfY?:x[юJj!Fj-t/aF?,+6!ErΨuZ'QHكdS׌PYRXٽtnU124Z Zdɭ3[5 UьrF_[9um;ʍͧ NJmG.IFJe7gCϑV:^w>xDO3).bdJ&^qWhdSqcG/~߅~6U ZqIOr"2oJ ͏ٕv7ڭ-BZ.74k41zkB54HY~mc_}:˿ժmժ[6Uӯ,W/`ioӊK:,cs]09H|3=4DŊud(UQ%A^PώRh[i>QY%e馷J!'Kۏ$K)j|t.;~ ٶMIO'A2zCouڗ[5sʕm*_~vQLH¢.22 ɹm`lQ_m[ʢSn6`ᙷ+pp +_͕xZv|/s+bql7ZRkP~ZK?EX2^v9.Z eT\̣ڗ:ʕ&Y)sg_U /Hˉ#]ss"#/(:P": 0E4 +HR 57@T "0dxܱgw5fs[]wn,Lk+2}fSK"Fr§tỗ6 ^2V 7l%wm_ 98 0l,_r}"Sx3a0Vfㄈ84Hq2$.8f>`8h?2VQE>Nijp8o 8 l}{ q#5pS*}<>7,Vray_-\INjI$;k9")2ǠӦgO]%'OZܡcLxQlRvuϯ:3`c+(3nI&e@p loK$W}p_N~73u IiчCz! ʯzmA"dVt9h[d238OtzOޝ  =L?UA67u&9-E\E!I/lVުyaxy}Gs/"K8ݛt0׳FUxpH,EE%9O̩{voKwU嶫\I.炢\{nh8X >eI2)uqlQojB}]F4aH+!q8."ܞ#BYNl6ٷ7~~E͛w?=WYv!#HF^(~i۫Oy('80|rZhi2nBӦx=i }UR}K ;j + +7Ѥh./?$LOmmx|V.ǕN}.L/OψՃ>Bt`[:Y"?bmr_p<^lQˮ;[!2uFìݡ0#{7.B}__l>K?Sԇݵ_ cDpUN̬nS ҉=|켷' ,#0jy eET~ga/Zs.QnvhOّ49{L&'zlD;+k^0>.SeŽ;+l"{Rn?Ȯ +|$褾o]jB5jY٠x;Y}<"Ȗಁ*p qasm}1f'3;Ppܘuqz-.#Ŭ#<dR6Zam5Yf\e`B%mܘ.lwWM%K.S8sX;k,k`R,qlIY6^Z45_NuחkYF$n?.B۫h+԰9ܻꑔ%imމ$31Zt]El{yFJsvЩ!;iؒmY6'9:BeeO9y?fus"l/?s|[gMWJfg43ܵăd=r[s(+rրusg7$ 7~pi0gh]ُNyoHQPxD)> e/?Skv)}_:QO 0igRFE@|(39;MKU 'ׇs~ 21S;$< GtWuқDhK-iqv^`tp?g65A.)e$:xpp!bstf)6ffLecǚtԥmAa{<,Yr㋣ 7H`2Y6TxcԱTH1-1S[`wCNqެ;6#v壡{o[nTB@Wt]Ccuk(4֙軃W50>_/nWU44Zov]d7+.eo\v5{NzBҵ[\^|zWJpDsЫ N(1FqQ\UgֽwYdshr`s~ߓUw{/[<R1<2Bq07&T𩂁A s1dNPe9M v*&^ vcܣ5qѵa-]s)%rs(컥~93(E rcby&s65Ӥs0ty>EWXyM +{]e>V 4ՋtTJcC2g;4<|vü\ꀙng[8e;א6aރٶ0~&hr 9^) L~s?sfFs3F5x6bIA_E|Tyz0?fo9r=--=Q !maqH+0({.gZM׀āj.~dKf9z:fc &M^C /i~5yꌬ j1ޮjublxi0pr 2sCxvhԭXmslZw5gO{b`ǟRՌui6dq8$qpCx .x,/`qL +8=8J0* kD` >a(~ws*Vr Pbɾ >IѨ9jTSq|8s;Nw+c({, lzq,t(} b$g$ˆF(;ʧ>CEP1k4@=#Nĺil 8 89x4NV5QㄫEJp0&bbZ`cUn;wHI@kmAz-!q:'ZqqZ8m6=g*=^7f +E"v˨3|x46̜\{ᛃ=V֧Zm}70 +D&b9L]l!E%^F|V+ϊVy7X.ģgW֕;{w~)nVd]9ۼ-]qzi.dʾd:W`0?$O&k}EA]N#, ]y4ai'Փ ͲTb+?rb\O\8SVmbw8[V#ӨlV-șH2D P;<%Y,ʪP8s٠3YU|Tn{H1\/7rd~jaYoNe+ +|3S8dT5'SоQa}Ԝ)Yu"<*7dAd ͎Tz ^KO{yh\]I/ݎ;oPu: ~ID(F·'S3XL{֭YuZ)G}W8/s_;Rdu3 +-FfAw%^H%nxκ9ذ?^YȊ +9UC[ӮBEu<4Yɮ/C~ߎgX.\|N[_}?V$ʶSdwc4|NV}q寷l8uv0&ި>ri& 1Yj#>!JN*?vݥ0x{?oRnP*Ce۬g52@(нD\-r; Kdo##ɏWK'=c'ӺqJdrz[2kf[JN_mn6C=Z(ANj\-Zm'͸UYNg_dl"U%uT_3rE*fNwXWqܜ +%]ۇ6K+\|*(' à:5hvn=߇˩Lڼw\xuhrR帚wv _O>|ѫ ͙@U*UǺ N:~V`M}ZȭWv >Tώ4rފ@dA/W?+~fcu7ϻ|w26o. }=gmHŬ'U}}.l[}jdE2B}~tTlTv3XVzc+Rp^VKh=xp/Pqqje-uN"wa5rǻEx}Qw{Lu~%xOkk?؆e&v}H[n;ƕ򣮳໴".w`~bjZݙGzJ/4cLuIJLCGc))=|t.—9!ehT \*l|um_ 6o{rxj=gF"3?TW;kQ`)?xO4*N =hȔYpg\Dpep?Dbw!SSfjAsRhI ae^#ڙ4:d:4ua҆[ +>u6H/Q~nEn5ߞuv4_nu>?p&7F874pդ~|O펚c/TdRr4)3j`X82eHOzѷaNj{M 6x`=h>޳A᱃5h +?9TVQJIN6YkakΏG^8-wF8t?Յ/УvO+ΑCFuwV˴IpfVc302;rW`@| [aQfW:oHqTl+5Gg[%j5!DbqF8[m4IJ#ѓ! f{%s{;74[j8.#GcQm5TzwK4ur$iokL'ofsL 1ܺY_d>uhu7b߽:~/4"sN67kD~T.wa=t rC* QZ3n}J=FG]']NvtNԹ鼽 +R)0W7AWJ2H 7k4,y;Qר Ps'?F]>:\yk'(ruuۭm[so Zْuu2zkHTV&R2+fjoo|T^^ʭƓ(=$I̪`_ȭN$H ? 7piSh. += !ACz\" /X6qA|~93un5<T 5oa~NjWa{ <"*e' "?sܛ@=N A;3xC75N!N{3;m8yxq<:K$NcbSE 0$it p 6 #7˴P}@OfV" -N?w4dKqdv ¦О Zi!@N +^f.E <[-/{#1FݰC<؂`նqO$PMnzL;]NokP)ĕW ]?,s.+k\Z-:bEVUُ`9O{;ϖN{=Nm fE_P~K)*TfXjZ/YAc}Rd0z+YCƅu3V- wX:gi@{q:88S"ð;L9 {lc4Ṛ֏vݣWξch+@Ͱr9؆؝\Oq^@g{u{jȿ$М8`j58(o0 +eeOˎ-1jn7S:N`x^\@U)$9hqՌX2QǠ$ O)JGڠM$iX9#Kfk V }wVZHq&+=ZveLpRQ$c7bw}2 +Yݞwr^ϵc^ .g z^95CL[mƤSuWcwGlYJZc_P&S_MŮ2O~ }Ĕz3N$/u:!oxVS=-7&-k]~WN4ʨ[)*o.̒9'GUoEO;^vmk0E7ra6_o]_e$Iv9>ܳk,BvQZ(wѯ9=\4[rA_ڢ}>v|u@bok:,G(I^]Z̲A>‰~a7ƗG{z} [U3KruֱCLB;߮r &:ztHTSxEVUz"}K;͖%' +Օ\^,"h=/nH7x8oMv%UWU]8RcJ,x v^RntpIs𖶩f7U_4`"k,0&l3 >zjY~<6'<6 /ԗ«ELM{y67=Tu#@@%gɈ" +Pso?PX]lO=A@g~@_a\[ cgv`%4x/a4J{Њ.<F{n6FI#Vpk(a>V5V@S]s\|q;ѱhUkʊy>B?0riܙ bslXQ%cFUb6Uuj80=q/FT_WYڈpdjڔ%b:+vnӝ++~;}uSѢ&OywΗpW/r˽|6Mw/AWd\55VrT6JLJ~]!{Q}9 tJpAWUɋp1f/.nj,d«PtJvQZ +OgeUyjKNoFrZU:oʲ8zZљ]uQw}NpDabr| /rɵBiCGQ(:o<u)%7C9V)gG]T˫5a. Ѱ.ą'!ŽV[r,m*l8Lf>RLmNhopy# ${I@ G FB @ 6#yl/lg$xu$f 4W?~׉iRq;Eecxmz[)|WLEov3=T)<4I+ yqCq2P1Dy !+&1(B6fCkת6A^w'\.[nZ8rsRh^lf6 K֍H1 ? f(68(<4eb dܜxPY 7@%?Rv)ö}a[]cF/BS&};m}c_4Or~$`@9\{A ꍤs 4(] lkr4W\BcTh< AU:PI=odrzCu)XkLG/QsIL~wQ eiL.VMT7 ynM+~A1hD5kB鍀FfwTsR&nJZfU5vU+B?+CpAoy0.]٪;c*YnԼxASޏmnQ[ܩ&޳VJz\hT5ߩ춱_>MoߥK܃~3%NKh+W,@+ƃ^uŨ@êuFr,Em H5ؒX![;<)O.afeT|dT] d +A-d+_4+6/QJ(9pF1pvIpF/~oY.k%b + YlFq} ƌZe\mIq +ohk[h~0i4W>ٝ _]\yY(d +b(eZ\vp @I @K-e Dxҿp +=k3\jdc|a:駳%uV yPꮠ78jk~ +#00}~q `1`gNq\إ+v  U3EE"%COScj#QBZ7#8'/SBI~='"?߅5J{Ԑp|uE kmO75nU_km!U}iR$15SSB>?*X;ukvj? ZJ7>O ifd88sol_re\] +^ZlGډѷ}{3v; +FsuV`,8h,i y6sSM[Rךf:.'5x:Wp{sk4TӑC{nsf?;7pZ[_]9vqyƒd9g1yEx|fnLD*F-NƺN{<d>Д>?3vnjgGV3Eg?x~1KalDiy0,[}Vj>Z:QDŽИXiӹ&ԡNm}cCY=o>W?Ȯ/?}%SAt=u&|&VDm7ݺhK-}ږȚɜEia-lp:u,W^oO( q8ިsRvC9K^qwk~jAA["g&S=3Vھ13 !`s4\ޏPy^!'c.,zZ#Qyۣݴ^ZHXA-n ό";SO緩|\^fjf>{.i,#gWf4]juz)I6ۧp`8@q~Oy D?ľ`TJ̺fQ3B~tw] WͨM1VϑJR1JѾ9zgt>zg{E`TogiۖO/-뽩xWOTkxۓksT/SG6;ȤqFVetε 6&irܪEP qV#3AJSdGcNZG:wn߸Cif34uʶ7p{Hě誣5yפiHV%3Q[%Vr2~m?, +Ga0h:I1hU<ȬvŸ/QQŘYoLƏT}0X>F6#yg*eʴW+ EkʅGVJzH6Y77\ۙK"j+8xGO>_<; i/3gګDL`ilM`C'hՃx%A]4[,@ZUTO:eĺ]wXNge},p3 /6>W_UqH3Ƌ<8M쬃6K~yq<ky h}lW%K 3Efh{sXB1wY0# +_N4 h9dv9{Dlv?831 ٤Ii[/i3LkT/ cC4R.D;u[ng̲z Ks%iE&W:GPT ).9 g)`Hl DDK %9$eMA/~-6չsU izv.;drrSfj/m,p(8u,R'FkFRadf3=@sX4!IJX,\yF\'a5lRAygpN2>:͖\bh/=9wm`tp .A2Y_lXC,hR5F\0R] $B2)S->qÖ3g@h T0PtɊKn(c̺laPoPpxLG22/8GWەY2]yP} v=؆KtSV@a~iQvh)^gp3b얢_wk <WHgm^nК6ՙԮV73\Rwv>d}b:E1A1̨>ͶuyA fSTiVTUkrRv܊J>f?nH. X:|t~;\*Yuɚ%ZEzNsCRvc:Ne rAHF ʽ#M)]d=1\o@a {2 ~ ,NA_OH'φ:l>ڥ|s_Bm֔w6F+9I$gm/yS3K$5~m;j +2L-G `wW'ew{cJqi8J~ $/4&xI]5QzJP/q\X(fS1)nGV݋wawt%ԸVZD#].Ͱ:;M,5Uvc͎S&G2/ȴO;Ug!%I?S U[hۺnՁT6FB{KI)m㘨uvs0}>,yxٮ⦱uRY׺(%/uΤ#s'3d$=ނ=Cÿ6cx0)c"ׯ{eY-eu&fZF4˜Y]B҃ +Å *. сqEVuݬw*Skqy6vpȥ&GhJx:G8خ#tbKZ=6?\>³ƣ+䣲]BYcb9w,gH0`6ELH޽4exG{[KC?q>4 /+KJ9X3Q-rW]FهL95NnrnL*v \MXȪQ>A[Bs|fDoP=' ݫlR{m}WKrBUN[*OipI)7SN-(!ww )0\Tt51^u;mwֹh՚߳_<~1WARYv9h>se򪏁bsHu8ƻAkOG3_]+sp1LSn~7s^!Kx%Q=Y%lXX U>_ikB3hܳ.lT5:J`ýaZ/XL0 {͋Ÿ'uҽQ-9|6zS>-elx ~볊tbyfxѱ|qco}@ioP{ٗREۉL7N^I_fu434/@#rI{QPT&8(JWSojIbp5O~$+g2_\޽^0F6-8H]#UxR4"dU,R+Ij܁AZL3I͇$Td2_\ E\w1ZN{Js/d y?`Ѐ"sn@Fs ڝk(Muձ+Shs\_7$cݓɀ?3wen8>x?f^_ <+2 0tt/`´*_]#ʹ2@0 +ICR6lFօX y`! CO]c{pqP9 +`5b3zfƞ͸A^/eŜS0qvî<^:ZQ +8頪Lbw1n\xb`8ffadBH}!(eOܫ KIC^YFܑ;ӯMbJkz6Al6L$y&Ъ\fASZ=V]1 W5]̈́*gE/AyF4_G/VPrR}_py[r1a:WԥZmF0&޸bvmhDK&{"2 (m*S5$.AJhq>̫!JE̻Ypœv.ݫ|J@ƅDy9z2[j,{;JoF'v9>H+ = +%¢j :A16'=\tI'rȴK^[ o/ƅ[}juCتMٕ|\%o.t9F+mWF|[Í8~x?7ڈ/I]N{eFε0O=8I4 d)։:eP. Jdks;-yjWmL4ys  NA^5ix_ցGkS߃j<:5w5>k]` gyc!pQ#D<{. b{N +1ԇ""5F`6($_!CpSgIRϦU-\mK5A=U%s߯.謢:{ymҳ%-o- +sIu3;WQ6Ds=)YY{WT&ZǫraZ^E Q&Qywvː̖[Vj[x0/W +0 Z<M% Т+oyv3^T؉Xt0W)b|FkD8)~*|F).?1 O WWGR jѢ1n2I@ݟ$e=;|L?z2^gmm#No+@0  V ^O"H&@.@.@&@ + lBBOL>PVbNkuKq4<~8_m+vۿw= +j#CԴ_eBh~mm"y$!IH$,8JvIĿA/sto. +$)=oJ}5`:_O/v'ΚytnzV^m8,Lh4G:jEk:́9韇Npe0@t|>c;cvύU9z(-Ǭ[WPH3uyAv!~*Ϝ[Bxl6^LMNڝ^5,5&]lj9Gf UoXmު +ʴt ; zm9* +F~e%gQz뻤/&Q:2%0 4O77{cs. +W^200`lgD!g94l|rQ0U^]n0gJck;dоJ^YQ+Om.ޘ/nJslz+aN}sebsS_?ͧvV}$nQhӠ!ͯH*aJ7*J]t: /<}! P/`~Mu{d.wX<_M;- ys|~m[0P}PECٌ.ĵEYӅ{Rq>XB-NVnpk4u4G.sޡZu.p+.6sW_gJIG^XW8)?us"-R*^g{Tp +BKkrDx;a#,oq#fڼRvQ:ng /auWTzpnԟ53 Ls-wRX*{]S ѰWvԁǥ`5.;ڏ1Zɺ%rU`|Pf)쮫lͻGk2@e~Luw[lJµL47inլ>yxf^ž>"Dۖ/5Πԇa9+ׯ +Ç՝ׂ*U4WmQG!WS{y-9l{ລ\*Vᓦ~栳6 ^[@ٸt㦸ƍ͡vIa=_LQ[Gb A[X^^jS?-3ĥMwd|[brkڝ*tF՛ iǬýh7=twl#FFnL}":ڛI]kAj1ߦ·/k{y_|׹O-B>xPnmqq/@ +9n 8G7/6vJcR |Yp\$1P1JuqjAxeTUV)k@RNJ.*2/RK˞A}b1HL+:XEg7A ު*W)YZի]wZReRvQy[AxEd^^YR/pcFxVUg6rQSV^7,i!%R3=)-рNV#j ,v*T+nb !E`Ed9 r*4*;mO%lzM{ :9YRj+^|{g?l皪L{}% E(x|[鄒P<5Qm*M62G *\ +cS>^~jogtu8R-D*Rn9p0OtKX=Uv`;{3Ke cx&{-n;n\^oTj=6_ƃ<:a&f/j'+-:<7Bjҏ̥%pJ8VXum>>t |t@m nI-R@E@JTH%U$k1t$Rmh^8L$!''9$ +61U`%$RTB{@v@N3@rzgnmuq+?7b XSG{4]S&`|m?6q&RwHt'kO WD%-B1΃0[9`U]sgoGK&G67DxF?%7(ch/!1)WjBߵ}ƚ(>_>)} mo[sb$\v|i>SsTJ$뱕7k_ +iᓫlsvg,̐1BVƨOvhנCCum6L|Zؾ'v8>mtj`55Kc˛ ؅__J+3dBoMו3EgAd^f{m.9}CfYQx!|LJVK}.0#풿ʣ˗iw{" #1Aȣ! ٗ: P #utd0zmHs/ع+?e3t'5>l\r6di6'haQu8"%!7ݿ +04FTˇ>b;+=OYyaɠdE;d]SxIw{]7mHst +M<ȿJ :WVo[>ژbz_KW VY/V+8 qhə>;fvڨ3 +;*^igj5͵i_yhя^n?_̻5~ _CP/}PMqݘNS|hd>p[̫ 9E&q\ɶ6L| nJWֲQvQǵZ0مkJίv簞?:k^ =ğ*Azh[&`맢r<ڙX#OLkNeU Fg_ E6ĢʠP"**nP^=npV\<. S:~)SWm̻kd%_7ZX.U[;Ox!*[cId]W8)hV?Z-Ōt1 |Nzte?!yhd';աZ4Oנ^Qۃ,]\ U7}Vn+-+^.W.wU|QP;[*RhR%qx Z˙'/FDZ\+/G?ᄆzޅתr?}z~)4ɚC/)[uׅJ/*"ITvuJu*3._R)gŭK5Hl)>ZO|{-{܋o P2/5ҐJ|ޙgsR|=B֨]IX;۰ꮌ|ۙY_X-WZ9ZjpKn֗ ?Nh@N)$bJ"qMفыp^`n~'/ =3-L{I|E{Mx&[a9Ȍʽٔ2pyRGbK:.eG0oRC]y_kLGJ$i>[N0<[LLr#D'npnp#c Ay2iACy9hrtt-} nxڬkQFӫ !TaN. Bj/a*jd[h +'tg0*aW}Tcs`SVF3aȦ+-Orcũ@[=a"ge@5^lw0by9 \Fp_;[ E=ʀQ,mxJE~L1Z15picBlicZ,FHY_>= /xz +?H]:uyB|b&ڮFPZuO@O _D䆷 +^Ga?E 2r}rh7s D/$йAPkTн%w㒴%BFGJ&M.l_39.o-84~8ԉcqHo?-\߸R}Asf+½Ȅ4T˴dR^l]k:?}jbTlD>5D)LDN_^ݻA +FzG]Pk&ZvԇWz' q#qqew%I#SuBPÞ'-ĥ"#nJ0Hnj])yzIaq4μӊ#w+[|^Q +_,sY;eydA`n4w)3B_2z)̺_Huy"bVt +{"ϖ*hۭؐ5X_8M +jCf 4.d=#q +ێq99q-,Ӷ)Js} .`{+ܧ5s{rd~-_WQ"hA/ q*o0ȯb ;ETΖ~zu, /_pT)dHlD ;>?9AE+õ&a9,%z1i쥿hNq}%%k6#&S6{Tl'KrWE w _ ~Q)#rvA0X)UX`Ng4|IߠyWt)긝TኮR&*Sf`V ezԙUh1aPq8l:>eVI]YWU &nn)Vx0`K0":'WVS"@gUňr!a d)A]@0IfO̢>TiJi\^G!K-/hXz}pD3;'Sp GHgcjXnrz1+@n*w@nAk 9+9xc什&[lgu?(KvzC~ܐr2JG>xO0x5߇u;Υc&cH1:AZfk<ֵ$Ғ4sc\_1ޟ_QZ'Q2{2sx)nTn#U2`N(8#o?\qH0z 0Hqs,Z +'gT,5ce6`YO,~+XX.a$sa-sƺUt b3d洞) Vh)ENu:R v:{oO/Jc& 8vրc+x%޼oou{=~DeEDs!-_~ +56ە|3-UK4CAWEXn=K[uaJꝀ`W;aݩ"@n@J=h 6H I`ۆa,lDhC:Yޙ<$,["\ߪu&ZO|H Wȍ` A @8cA'}mUDjb&=e&%eZjY6IP38vL 6\h&/f7#S^ ms{VkA75Wgc/o死v'n<`vf3g<t{.߈X:~61{G>G?}<(I\f{b!( 횫xXĠy@gs~łNdW&WkFȣ|_~faPbCh^Uxy Mzͬ_7KaƒF!Aoױ D:{Fӥ8&ZYSTs,d7̍dዠGcC/#B_eR w0 6@<-\ [5k=C/&ι:SxvRDvԸyQǯfN|;3k?n/R5?tݡ>+nvK}eg7@&ȫyߢ.{Dzpu;9ñL Ůl?1`Z=#FJɮP7F71Ï 7m$)rZZIJset['r.uxbw%f:;vI!}[Npkw|?s](Q\SFpmZ'Xl-ffhՇ_ pY<>͔k)< <LS_p uк\]p jct:6k< ݕw܆pt#*'Ἁw==jtK5fM7hykJw~9>VY JJW"#^S7G2xTj^[=|h^ꑸ*=uvwr)nx丷}&iSlz2ʤ 3w"^;Sj#i{7ZZ=:/7ra+|֕yW$U)f7AQK+Mh5Ǿeam O9%a_o+oL| gmbH/CdXFYmZ˛k񵪫LԪ\T۩ Pofꢛy +Voe _HJc"HuX㞿< ' [[ulZhu?++AqWBkL^ZEB +/jINUo%D:::h\*y=g89=W}rXb_ +k/op~7͡'N.ž}XaPqj]N})m2Y7},  f +/ȝ/Bcs]р@w;"v)tHUfRҌWgTDx6#ݼ{~Ԡئ9/1oIZoTڋ8 +/rwt1n@O'{|`*;jlXyN%CzSUI-钌y"?8&q}ؠ\_XcOt~BJy4}¬ H_.t?_ʽs0#WI϶8K=VK|Ysૃ}@zҹuqӢ& v~|rsPтfx +@5 + 5țEh/SnҞ&s{~C1vE(gcfNG?Rw+h !9!"},3;\ O\i>`ޟI&y݊]C|^4åyMoijOܭV21;րKlIn0 tE_03]y|PUDi(z +W?阍jţ^Sv&^$.`v2Z9l4咏dz( b-jNy67^ʼnBީ0+;7&=DɈ1^vgL,e15P/8YQS< 6_{f_?2"^я:y|,PA=.ȳhnae \'؂棴bSܸqAUwvN p,+ox5#LtF I#*;Pm{L9?ԏ^ږvl ?,o`Z3:,j( Q0 GcGX9ưtc$LB]0m޴S2J4ߞުA'(=TK!by@ z+q E*5Vl@ +P# ET37b4-vM5 :7]e9v?TW\vK~Jr%rg#;5&mi@赙JU0P838%:א#]`G0c~E巜a%]739yX^*s%_* `y!L-~_4G"`w!Qn=g57/Mjp;b=VzOpUhqRܩ(Z>Hαv㑻z<5ۆ$Uz J5^.´{]5K@ 65 +DW8ȏbn@.H .u r߫,kF~n#SQZ&n[X7nm"݊l[i@E 7JC@ <E,䗉R6)$~[},?8~?IJlb9PWPlnC^>}=EC2)3w-z4H7ߢ^_pMX!_'RyU3CIImd~i}|:PV ]}zGYfg뚙u]ve|ÙZ[ݫ4hk5 \M?6JĻmK$DWOywܵjuu9x==ު_/çJtCi%_v]BN7ȸ!q{Lqbc=iOw\yyb4#A0g#&?`Oy19bta|n1{j@# _-V?&TՌϿtk zE ùr3^8{NIM% :؇f$U_ \m=Y[˭շ:=@n8=<,W-w?<>}-"sB2ʅBC A'GN>}F/ʋ[hś+羕R]Cz6ܨ-.u.K۠gtM]|ZZU mP-%!6[ e?+:Gv|6avPy8J7=l7!C'7ghZzk\sR=+  V,Xtdn33*T{t0I|(=fUf0Y/~ٻ^ +]zѝXmwjetcVba+~ӺY^ bn?[1{b>WJt]*3_\VZ*;^1`bpgCh}a mvQ=ɲ=Je~tFV՚9)`׫pbh1:!b150{2F]$^DT0zO^[6m3~`ټ#`3^j +1tܔ jWy841oVWQ:КDëFm/W^s# +Ϊ%GsƩMֶI`Pn׻;A7+f++>[>5ŒvL]]k.RE~|kZ/gArZmg z(jҧ\X_p)-,ɧ~qF}Rv͘gר+ݯ%6W=OVت\tQi+Q2*b@Uʥ}T-Z<yVɍ^[K&e!/r[Il4iLĪg5~׏xZq;\OOPUh祫҈8>^wT͛wf>-^ڗGNZ7SRg7-\8iy˗H#qqMY?suOa+gΓ9ς;]gP7wQ~7ؘYrnsXޡQ-@\ˣcXRGHZѯ\1 n5>#65./M?^uDgo;'0U>SO([҄+b;id*{[vJCdA&w;W)،^|ӕ;Ka8w4 C*2ـs^?O]z~Lic>΁`JV`*i>h?haUA-65cB\)rT^ڗ<,g3ҁ(*h +R:|*I!_2;gv*]|xmtʖՊSaW& : NsZSe6TM1='{#2W"?+ bzNbړԒߩmm=Zuط̪뵤1w`#g危ߕYu+ )_9{)n6N|)U'e눦;81UJ I|+O( Q*3B-BSHMl-EzCfDz_Q>k2Cgirf5ۧ5kR3YծQ-F<^!+~XȚ[i78Z:Iyǜ5]?r*Hg]E\)e:7 eO­:VJI@BûS߂ǧ,mPCܵ#z[Fu5j7vFj΍7IyOMO)Mܶɲ^I6d?wmo "rݔp]3N`sTԤ5:hq(l(qP>|:v 8ka4ڟ,M*x7ՠi[M#)=(:޴g[+}|u^[)otF_wE{u6ъ#GHӮ6 \{'5t}ڪG,}n?\ɣ0{d͝q]ٛ]^Gᮩ1X9cYFrvq\yfh s512Hi7[|W> 4Ǻ*~ɡS6;l7WsX*q)7W.$6.dR+YyβN ̠blΘ=ÑǔspS*.b,W+t_۞Ous}m?zw¹}"ykv^󃽐LQU|4iyԘ.<7Kizv0HkPI6q]]dnb.u"ّn{^]OTse;T{S 6تj!մMihٮi1޸jc~oH^.;fQ}B_+r|3W{֢]*DXj_O`wڕk=l!+;7s;Ӵ j{!#Q<&Wzu1=|orMu_̌^87'F^n]nuyUmd=؆Mm~ᮺy\MӕS-ݺXg:e=ӫ:W]/jmd6ME65 endstream endobj 121 0 obj <>stream +MJ#*CdY/xx歗eGhzܷ2Ml,r:óyQ^uj򓬁5&6^2G\?sAUmOP1$$Eň"sY5מs*k2afIC+Su;|r uբ:bыd7Eϖ}~m8t6 ]|7(lObQ31u=~U6Ԅq='U_!SϽ\k; Z$IL;i7cn) F6}]gLxu4k·T%1X_̆zظ7]G[1}U%ԵXR6 f9d˕d8e5A μfPaecXtȘQ]Ag^iMNɻ/xQ8Q+Ȯl͏bY>b&'s:t6euj ' ZmR&{FY/y3fwkծݥhgRU[xזּ"!Ÿֽc>3k SOB urdV3{Z(LSsح^Z +' OzRn1b V%\N?3i2I+G$%_r:jY@BK}Sm6Fx'U_y+o0n_ \'+eԹذ80u +ehb2>׻0םB*ezlcaΛ6/ ӹm~v_6zӬJe|*i-{I]n߷\+Nt}<ذ#r _L|R|Fm F eM ʋ%JVMuqUyلNNl׋Js}Rξq2-DXD +>Wy=˫mAͪcf\}δҎݓ):14 Vy*'-r\,ɼGOoMb>Go$ H2Iro}+z +kV5YuϕFf_j-):GQ$w"j<2(V^ҙ¶G5쓓GEsċD$A*_ /'G"Vgj5lqvxRE?a!o©>62a)Zb4ך4ɻQ=f%yEj1FrH#eOrwXtZO*1zvx%p#n7zYh5&hs &w(W+Q:J'fWEtO!WҺl~n=J;bɍ>{=u4n|q>y_70qS-=BCL:ʛJ!AAb{k :kW4A/ Ez߰ l1[Efk2W~Jm]gEvW`0gV6[?hGI,r"vTW\1l غ6? _ C| +mPė[@.]+%Qn1E{QVmnҀ{,.`W9_Y.ŔѭşNtR2wF&xCNSSx7Uoj%5,0@JI)}Tgy~vrjj&%|Lˠjo?~қWgGTj0wC Z9Qκuun @IN9A3H0} wcI5}r+ C@W@c趴t!/eSgJJuuڽ SL&o=mr +.U$Av%+ɲN +!$0mW fS`6J`t z=`U鞠}4X)-AE,ymk9-wY$N~ʟҗ{Ik٧Fȉl|NBVz-[${!";>'vyp{ n73ps\oE?dc ~sة\,Fk&v.ȥ-i;]J|FqHSjX(>{8i/@@f'@ #A!̌Bm vc .wf +@τD;^y,FrKfTvpR3CU:!)ڼw@tW x@hoHNR:'Km$]Qdt> I9H v2uUﴗr"nq\*g֋~.$H)4So\Oq~\J@M ?V.Pxw9J9N ( +~"PB/JI֧ +eEOkvon jUW\oG@WzrHo(_A4 = 4)̓ (Ђ ƪ0Nxx>*z.A/aPzk.n1O:wP~eOonBX'ommESFx +` L+'x,ISLWj_''!odoF[֟ȁooE}@{vYh:Y_|%B |; +~^V|{Q}ǿW^~߶^a=;Ϝnڸ_,% -8o{:xڛ'`P'?:?{gonn ;(L[v>owp=/W +A+ܜz[;wY +A\VSj>? +d.3]vlc9lѐl6|_ӽkUMEȥ8EHyerGЮ 3LqV'nJWj׺+ƚP޽]zߋ\.-ڠƜif>yxcZ=Ȗ-j5t^T T٩,+BޗMШs#,F)բxE!H{9T=M '%Կ2|8 z{*UJ-wڵμRbvrUؽJS'|ybq$ZHb{Y&yZ)Mwd.qnΝRzwm4ZUYAؒT`<^W^fkylSH>oj1mR[Yso:ueUKw6i\Rhc8&r[Ӳ#Rӭg[РU-OٿVϮ;VmϭO%P1Kcghkem=UPjhT;CgU-ٞj>WG[Vy~eә(2c8,g|r2A9coZИ6/ڤ^m݇NM.@S;nM +ۨZ9uH-Kչh $9b3p*[N9ۺw[3r7qfj9S3Ԗ߆{O SEN)[~۴(N`xDm*})>mQ/5vS+CM|lXV zJ]߾<5 h~UJ׸LtI=H+xSO_WĴ)u-,K5Udkh\ kAJCDT-s2ǙyQ4hk,2n󦯆XUrq%.o)w[-Rd:dLxգuQ(zDwO@lJRqЀvf)ln_.wLKzеAp\{XM~z$wO XݕdO6G Oq"Z0OPd@.#~m\y6[osP`&zV޹DJSgibB-UlXm,"QLrX{Qc|\i 2a.P_9/C`c<2iѢV3ɷ\W47o,^m*)3b5H+}BAA s!QkIp͡FpgfauBv3<0K:0`X^Z$h]t߾V# qSmy) 6s~);Q;qWq5h,i{%d4xe3-Zj%l`B;tRS lvI# %NIH+ )0xl?>q~5sک^!^3tGFisS+Y\עH!icsmm%G7X ;lio&L +C PA&X~P,&p k@q-AϦ }@ -IyWy&$(c Okb 9-gxZdžaI.tՖPJrh7wx4Q)Km{BіLZL- o@+`hZyRFd\ PjI3y~%Jru~D eO-4v#cɇHF@@#oO A7l#0ȹ2q? VZrv󟙲W)59bsYL'yRlg}j_o7ohW1:p!mYm&HH[MRp'rH `w굵Ѵ!oe7I=oZ:Tn4;m >z7? _6+kv70 sMhBl` }` +0O)WF%z}?-ȾF"0'eη{v2?ocztJ4A|Y*Rб:WMm14Tr+E徦ۏra e>z"}Of-}2N2r޻ፖv4'ڰ7Cn1z5[|i45O,oxojo1?q pAq+zsc)`(M돉_ɍz3lz׺i')5o::ہgthYT#z[=  E򔬧jk.%jlb[ʛz/sR +{j-_ysk?: +]Si Q~\Ey`YcO;%]q l2A ]`nOzi $3^|T^,y&û&uhU%mT +Ĵ$^ޫ⵻up:,ds ɏK7"no'Xu!o9MusUí~d<}̪x%"Yy\4Ŭ_iDp'6| K"5* + </yti>?tJrfЗ*W{{-jܳa s#4sNNB b9?i1g=I>K}.41)#s.\vKC1Ŏ<\Wvʢۜͼ?Գj)eӳ?~gkɄ1ߐ R({Ec^AzǴ1pjܿA#>Fwk%a>|%*Q}zGv}h7Φi7+ûYs +& ++F2h ֋fS{NX>k3*ʭGZi=4OIvm(nerWJ{*Dy;jFV]51`K e㮤L%әMa^ ڜ[;X9:-ɳ6E8TQ.>R"p/w˻l*C[GS%9-f"*_oLoq0N ^s~gsj0捚r^2$Ud%DM\W4E8SMXX)eۑ8- x-}KЬ[gmjW5w2WZ\Modv 6A[91ST|hfz+Ѐ9щ o>ϨV 9kӛvtj6v+J͎Ď5jZ=*2P(@—YgD6~5/"C67֬Y]I!jH-"=Zĝzε!ꅙ&<ⷴANu[vls]RW v0>v9mm5}^_ 45N,l:)4~̹&:LKm> xuM J9<1k=H$?_)ؒ;m~/o}+jU|FϬsXv@xIR^T*$-YN06s$ӊc=cnfmYEջ5*䈥݄Ԏk/bhƒY! +6SJy/ x \rW8Xp,zyӆ<(̿)û՗U\lJ9tЍK"BLJHx_+ܯw#[ A;F0 c21٨(%Ci{!ɹ(`TҎ"m{d8H3$K8jX#%%5_Um.&h`G溕/\h@eqT 7HhsDo)D%< 35r7 #*k cX>(#Mg +ر] 6eMl+ Vo<ƳL K*rz Qˣ3V 472&5> kP:Scװ7}3ݯV\z,\ݶrc.K -{ºg9C F-J ! ꛱m; xC72siriQLuL.Syn%$\,m+Uu+m>/ 5dN/vIq"r$ge$1Ct2+=52`'fx MO91Yk}x_U>: .+]fw:s3g +67G^q:~u= 3^dȈOVy5TyMK|jL8r, E1POt+ 1 Bh`);jE* "#}9DuD/޲l x͜@s K N:r5AvBM ~v2Om TR1,d% *$  H-佐ZfH$ oD)}*x5݃Qw[gΑ\'K~ ?mZ7 +`} 'uԆ &sClεՒ˚ԟ`khup`~bo7RrYOBe߭(^ldQ&w^[Aޣ:viv~w0w~xI,oT,Xn=\7kcUGƻT%QZS 9hm+黉N+u4A{k\HarIfAOS~ͫB|/{y#euƻK՚.Yx~黾}Oό>1&伌qV4mP?U"r#w v5 ,|ށSEp\ Y-&oF7|kOb{=(d,c-7 D)LiЋ´UUgӏm7_~4e!D%H62y~R@d*68lho{t͵ЪZkǃ6k:.WR'EUDvsSA:P'giF˼6V U e-n\# Zǿ-ꃜCSXs ^JlL$<& +e֏KKd4y{Ey?0FuZW=ZUrj Ј"tD@&+q_ycHA6ʏ,nk.qO;Wqp22= %r(. +cmZnj{6 4MV>7/&ܯmgDM^j|5 N.+ľ;YqJ^= 꽬 +G?H&gשּׂ,^Au4mzUWr:7R63pMo&->]aZ0 m'*AGwmM M(\-FĹ3k; z&v%|is||p%igv_'թV2Uz;OA'P3p-c|[WwbZ-|K(=lSQ;lKx[ Ck%4#腥,k+5chL;Mob>/j%jC9ml^K6,H)%&w3VB~ sa^ oʬOP&[7 +f6&#J]-Y/2LO)ы咊%tTNMֹDzIԻ U)Mqfzbn֘ SrkZ⋏ɭnP)nƀݵyO iwxQ 7fj~Ŭ4)W-X~(`޽qBd^+*eN'BWV!IPZ1#l_*egMn>I-8]< lFX5btf髚2J3J1xGo@CnbQ-&Frk1ז 5,tr +(\M KMEi@s8>Tsak}ʜh/fQȞq?EkHuղGwK;39(< =D?emk_*KOavRaFi3iNQbCO b5bX lZ{|1Th(Km(/v#q!$&0pHl5 o"y:ӹ?GF8;=@Fy<ɽmNpՅf MDu;-,PMrp.yI؁. ,~|1i͇XYwsD,i +}~ֆ{+U.m1\]30Sꛀ +ի|:ׄOjK+/Z_U5P$fbI½x"t9|^/Tp==c7nzF +i * d%I-4j c^+Orz^GyҾB5nei>-~\̥YT?ɒ8?pJplʱ?V73Z'NHaHMDP Vpqޗ^ 7jTwrt?_nKb\v~;]{%u8ݰ +c]к"'暓g!M\@Am&˛;šJpj޲Jچ:KwD'x7^Z2k཯+F>Ѥ|SwDٳuWh('7$H2#JtD%hd8ZE` ȼmS6K* F o\n\My!<-ϨMx7e;S/0=MNK +g+J5ǣz7dE}R \);u0~&5np0 62JQ``k{ mQc<)oM1+ݪX: בdeaCm!.f5OgAؕCF<eK* +`D&xF~#Aiq E'p p{+" qeC"_pƵ28sZK4.>S0S"g$3|xoO +B(@X.A^M0a8iع$xGlI|%^_e**R,~}Ubgy7ka)Nޛv)e゚ >ĒEQE{{}S2k{F_&\L+3٣.VƷBKͦ&0IR/Y5xS +Ϸ|%Ƹʭc\x.ơM;OW<"\+;k). +83l&.TfG(ޏJe$Nڀ(s +9xqF"?r,L«1tP) 6cPzrŃ_ + mH_%-݀ɨo ]2FP,<72!=5!_ p g[ď`ub$K6s>xv btP +Hލﰚj@?RGG&گ XohP'Ek!@+Q42`/,̹?Z1&`6l/F~nV{lUxӛQӀqXN|Kp/.ndx.^ $ +UvIj99ݱs|!H&N43m(5W/bƀ+ Umph+r^p8ǜUߕ^ ǥú&`B՝Y#/mfώv dj%)l \ъ7Ī`Kzߑ?:?vo iB-gQRB΋!Q1Y{THSgkC#:_ +/4D^$8dKTC>(G .! ޷Ԁ,"16mr\W"X] ]!JJp[-3> OOO _? + 6 zԀ-ۥY2PPͬ8۵#1 6‹| +4ĶK܏ROϪOㆷ~"; +ӄ@O,@<-z)z+/O^eCmoivOM?,eΩKaϡ>mT?qݲU_eYu؀?ZH{})nvC o'(k?4m7MS^nW\'D~LםrT}(/HCew1N!]g_y('Y/ihr9rڤ|! `K^6p]_iޜx̚jX~9"_4w'dZbF=2LnW@ 2)c4Q"]}x& YC;LEdΠ3K,O#݇} RȻ6ֿTT_\5ԺL2A'rv+ts/EoQ;D#P^vTUty嵟;jc`aySڡRZЅzұAvGV͍W6m쩑oFuh*7*6]s0qa}=yRVoVz yڧSAs S8[7D˨U +]3^[Z_zPf]ZݷvзeJԈ}kxHZkB;=ץ>6HW-~l|FN +8Kίt]^cGQJT.-=}tҦZ`J\T@Ininݯ2(XE*䝞zukaqOi= {ۑr [K>|v36YR,O,ڙ8e](3ՅGmPAgacnCΊmrzٷ5E4(6Ӈyَ0ra}BK#=A +2|9MNFtۥo}f^f7MWt}}}!3x* %vnn/W:SUXYXD3ш=d:/3uBK=/^[KYBKMA[ް;ěNf9{zSmw9ު)riELKmy"r(\2i:^]IzjXtR~7&A81SV'nS݌LmQ.Y%p"GBn@VQ^Vo ]Yh2ވ [ +{#d;uUTVi`S!5,Ƥ 4_(ٴv9~ fP,~(I/GTVZlyDզIє|u IHmV,&a1/m7%'Tp)E~nZGNG@WUR 7ULeLُiRQ! +T)gJˊf[BDUn8=QŘ#u/>ʌnVM7&}֏"ƹ\9|Z +Tb4Ï65Y2:ݜJv?~>Ny⣴-ĭ1@pɲ;LBٱڽ2Ro_[ tHꎺDL>GfшLL; 2m2åj\זoT KW-'G[|i@$({ln?=Iv""DμK5;׏lO̱$ޘ:FVHknÃNuX RS!^̘Ċ;A>wxpBf8aY0WYv[˫\%WREK/y0.Yt_ZӠ +TX¼QqujCkBgKݎ#gyY=䉐h D:&m$Ҏ$8O̪u/CgTaYa2b\=5w_4@ Gw': fx5iRTxFpsaY!cX-'ҧi/h +@d_"E -S8_Dž49..g/$Kf(zkC9_-V)-w#2B>;.wPt (xqeL7PKBNZ0;4&W1=(gy6IZkl^lT&PIqpx%qvXvĺ+F1CBC`}k>hPkhY5J94fr~Lk5Bg]DqƬ~漢N,Cc‹ȫNj<2U=- +mX?_-( xHJ1*}c+;wp4xڌ_Grg2㰲_nUeVVdO$Yv)GiwcDM@V3 bdzZdb/ƺ%@dVEfNFmfC;7Ͻ<6F91P0D[Ck:+N:V<*^&<pjEWcTW˹I}+'"ʝUxJ#5@#.s>./qjZ39e dx`[dd+ƨLJs ƺ^#0`rCc+ɬu@oV]@wa ef'gzmsF20K>fF,8}60NxB38{{]RUO+> X{7zNb<(&`ܻmlgdڎv̲b}^6v]3.=`)`Z;v"Z{_~4~~m1Iou׾IZnO-vɧ фn_H _KyQrAMeN!e=O`|\(n%5!;跥ڲӦ]+1Ju&v8 |Tkk~ʡ}ʡe==Ϡz:DsWo͢0~ydɓ8h{x}w.ԟ&:vb)& :W)=Mnϻ@tڛ.=ZrQatG,cm?~n*}FMkur +u<p3M_渜I)7{zV%tZcjg4.p2˷VS'^PNs <1Wx*k)\Q`nnZsӤSOmR!s4&@mHw91T^݌-ԕ_<%́\_"PPjbFf eYXx< 7?)ZKn$+0<%@bW5Zme 4Z9,<_F?]<*3 %+;9ZWY;t¢ ^^GPG5{TgRub<ShͥP=[iI~[?r,皙sfI>-l(uwOEDͻY![9鲚.+}wn$Ma &"`@hU䝜3IL{$fpy}Н[fb ']w16V,ḑ, +ƴ)ז^*wzV~H0tƄ^DSnsIK%a5{~ޟx'}pp]F02lIfCG'QO WvHo6Tb&W ]t _کnr6/TǔZ?q:I,Aszʅw+NX9YN9֟-$Dađ_OV5J?k*|od_0d:Xd:5wcåZYl.bT;ĵE|> 5/i =򋵹Vz5o;ٞq}Ч-A7=UNR1͒O"HO{f]ޒv>}m$kCEs!~Q]W!;Ev=#di-K iʉQ._׆wӞn{^(5Sm{f%%E,|"},hɎ}0"byD Mwϲ^@f{!+(: dt=Frh9W P=Mj͹ :"I9z'׃. GhD"hn/C^3(~!BYkU;BIN.3ԍJ-1>켺M$g:̬r=QN%pdHud pdNGp#ǟ}R>PPĽN!-H;Q +t Fv^^N)}BuH +Erbd.\lNg04BiYCeW\p@:/ n4VA2~=!p͘*o`8Mc, uS=*ȖN (_x5 m o<꫍K& ]]ɬ0 +p#kGWh +7:t+j/x 9xX0)#*3X7([@֥ q\U5kr+,%1UDζz" /DU˺4O$l_^8 +1tm_FG>N2ӑ]@V ? |P{1N{w$r,r L#L{ײ_؂-8I[޺]HWNV ;RLD< !-^`5.z8HyţS7'(| h2WNY AuaHT*ch_:zV=jQ|u&eWLڌ8p '#|i ˪M#(b_Uwxq4 b\5MZq4yF*> +ڱ>Ab%5PĿ9dXfnŴIN(mg'iQiiw0= D1w8# 'ƪ0\Ƹ? %MZz˟rŧVJl?t'-kfVM1=H\nA4|҄4^\xTz]Q82GgG^ +7#`L"FqvOgb,{`OXDh 5svXEy x'侍$uZ |6`̎$dhO&F&ri^avgX7gQb\ZW-v||/^e{>ݺG^InvlQɏcrקp0=Zb BH[ ,~˂G_Hi16 ^Sc:`^Ksbi☗ +K˕ΖFYWCBF ʽ~j1LPǸWf1v[@q.() +[l,9s>C6*Oe>,$o7pj*1B0>˗6/}TWd`WϠw| & Hct[#oV9NvGStVZi@hܿ% +vs4SuU%+&̝+((h޽_~54n<w7#?ZV11N`Ն XNg?Z@]>0`ZHCNu>WR#/KU}Q$܆vT[Ψsߺ7xkzA9r/&Ms:lm}0!}Lu|Cu/gaP}7vtz-3o^T5۽d3OU ZhnNӉMF53G,Iv\s Rpk'.Z*̫L=/P6Ǯ2mh&')Ι(3͝{/d=&C_GדuդcU4Xt + cWϬMn{$QjdԴg LhԨ B! *6߅Z' ?9FYZaj*|CABٞgBsS=pT!V -p^/W#F +MNe +7z*XԢG6ҡSLqQǻs%_CQO! yC}W}IX.ۨ/It玛U֫eEe WqNAwF9] `*;_H<k1h,j=O||GHk&VЦ W߰S[^B:[C{ttCo_ nCkOm3}i +Bp*@apی̣&d;BynS9=L4k vr4WG+GѭawРXgbMn%ܩoVݨyrV* F9oӈo]5牻Fvumv+:/2 (snoy_>ofϣV&RI2#A 1ȾnO Tf\|.D{cSzVxV^lKM㒲(muLɘOJ15,[~ +ڛ1 즁>o?o~#շ""7#+l/Hj SeÞ|7YMui"*O7Qg+(X 7eL,)h'!N\IϊF?oi[ 섣UE&]RGjc񾯭DS\&-> +vz800xYY 2"wۃ'+屓1]$lfrZհݑ xHtBُ 9 !Y!zzS:3a^eM!Tzh$-&WQd.OB9Nn's8Y A6~H {1R;L#RrE]}$!Nkz3 NVlСtrP|+F$8&-)8 l&;fшVd7~Ztt#ݨ)bvt]SQB4bٖ?FZ@ +`;OgdC{E|:Z__Qv&낟wK.|7Vaʚ㵈 ڕn3V3C]L鲑!N4kx= ae N5~h4\ FGK'wo6;q涫0sU&KG+AUH|Vs0}+YÎҍV}@{B%;-;#l!b&W9:OP+Mȃ#ꊌKe="d%;t&X9af Haa1>D(Y˚bFiL|s]2N,'=ƧUyS^3Fn AKݥPG*}|7>\{.wpե)WJp>$S6J^%QuXԥ~vj2u4K ޫ-:V4u54}O+z <'" ^|\ 3*,J3z tm;ͿD7Ot^7+RJ|kPVOb=aA.^^ LUrHk1D8ؽ)|mp=C_`!YH #q{ˉT6/y@XeDGB@2#<]a]@Lu֕*VԳÜ;D$'}u9\X-5x X:tI5ƐVn;>EzC>S;f# +^S!4FU +&%kxu"}WR˄INi,t?ZJ[z%Ⱥ78a_O1&uj7K'-Hn6`,Rht:r|c{ל`,z}FN0U}{")2站6kzJXH0rG +[p*g8I/P&VpZL< + ck +N1>)GͭV vk ʀpJWlP4V*ybMtX1YC"BD+av1d/-|w?jcwk Jr D]ONvDWB]v [%_Y#tnltJ~ Y;Nĥ"$:{*5 +xxI*[Xv rOg1+l(F=BdQb٥1!) gdJ'4G wZObq+i^}!c 3㵫^te%иW šQ%qlBa|=?:B-=&GKmЁh=`k; F13@[mYMu5O9JNOvUQE,}7l{(&qş}ŔU}Tlk ;T.pvSH B]kM[uUQ`@Xs+Fm7blbcq0̊qsN)p]>"t>۹x4dy=${ +y1l!mUCNvy-l<ړt8|Y|T1(G9U1*f1& r|\Nv.Qmy^b|"~g(jJQZwa{.GtoE_DOnF*7 -QD ~K(Xእ w.2&8@G AVG9Cٱ;xoه9zSM=Qݏ?{4niџ=YEqD?w2HXI2@UJr+Q8fݗЁ`|EmJVtjnz6+z6w۲oK( *%o{|@դ?yl⺬p ELG2g}=B;h6%Y.~f%n!rÚVO/RxARvω-=x,qu~XWR[]ݛ^sܐf;hu.8Bz@0GʪGjB7EUB\k]]JEKMMA}E8/L=燷Z?鉿v־t־t־i־vd ogI־vd~Ps8}?v>OIq&)Kt/3|N WEM$kp< ΢:^-k}c#P;PʭüS'ЮG>bzs2pRgNlLoe8!R8}}6&|(HtC-U/9\?~n VxBY~r6$v:s0TmȩqXٌi o۽ׂqАkf)E^fȭ~K,V{] (rV/)_ڪBvbt{36?0aT){鴬!CCzuG^؛$2m<ˉ/dZ%A;kux%l^nw'ˍI/Sm%>SS,JRU :mog@i'D=^X](]${UUF.ۃP Kߜm;;>#&e6Ԏdyo^*!q?iH]v{ݺ+ +?!.r{]qq/9{l[}s22# A@#7]15 *}ShRf~9\p0\W^%^k3Tyv K*P U|{xeϜcXlˊzEu?bY_>{'3>2of +)p'ylB8'֦]srD)Wt6?#W ?`7%]o0*AfKކ`bLϔϦy tApX ꂾ~nGgg Ӿӹ0*%trTk_>#ͅ,D+myeS4|SXbaH+`e W^A#;4`*lq|v[w +6OsfوT_e#yv wi^)jS6T +GM% z6.ىFza2a_9w.&Uh9v"U2&{O]$B*k:"7jւ0 D`LiPi1mw?K}9 eyE<|=`ĂW>q' N)9Ck#EP&S=Jr:Eomt%¥ eB\EQm,|*.x7#)ʱgC dw=YFvؘ]J7aj)*η +1(̩Y3'w4jss[$<2MG*mwX]Xgfh?ӍREXW*o⋖r@ |fm@E1!x@]^5՞Zc WMcQ+\6x[9I`rFh_e;y +?LӜvǴZ%&\m(}~hj㏀ +!y8#H.\L7:OLqCu{J=T-E%=lE=/Rcw +X8Ϸ󎄒fIn@c-LR9۵9s{>Kt/.Rc.;k Fe,rUN(мam$'CgxY-a ?pw 1;-Noч5 S%9քz..G]HSp>cRZ᧮«3j ؕ뤎A%+W(@ʐwt2(/aתp \ɡh{mQWd3s>RƖ41Ώ7ƥK:)X?{?Ð:Rv063R tV0RJ|l\vg l uA +l:JK,l,{B1KqJj[(-s ⍎ep0r>II5r>I a/?+c2ij`?NJ-3's$/eUbDaDv(,ν+n+?IN=B9(O3Z.6zT|5e~lz,C߳5m,HxCșP"\`ꚃҪWzT W.qקP([Nȼn 5gN&7P6{GŎ\\R{aGW`#a0X:>ҋs<i!R&=҆f fe{rAk*sHͬ`yn-jqe~Eg@|(=ex&| dôtl0kbyVFo3UeԨM3 X\_+p㒌 U*>gn%G1& /ĉU;f*nsL_&;tmnm@p֯F 7TXI~b!T0v;fJIz%}R~ +3y]G 8ۍ <_-ENڢqyės+˦THt +6Z`R]ZZvm [?Sn|\jsi$yjƊDՂ= IAcAp#~.Do&XӖM1?bkڼE82wL4DY6DT\k[ɸX EY)]!q*lXL=g]UHtG֑O٣f jW(9 +O)"F6HIPXsFzBl'k Gz2ٰ`W@.OzE*N +q)ϗ9dqUV-r.'*e v2M!oخ10Hlrϸi?cvZ޻AY4GMyj$cA0P5NϼԄ<L\J6$I xK0<Û$$¶ VFygN"!#nKIrě-.h?x01gwN'qi̱JO^w5z%_,ye3LG]NZZ|0A+ڭIb:YXOE?=SPq(ŝ1OmpRE5! WJ yfZcqC_k0޵Vom8L[944'OUKzɎ bnZ!Pɀ?e&vɮF]jurB0nIa_|.s v?vDj,|}̿IJLv~D$.JstrBܚP70D[}-+Y8#Gjaծjro%a|383'tY~E`p@|j}!̪|]m%h5bcFI7Nstmms;5Oګ"yS_6sW.\;IDH=JЬmeXpn?K]+ nUir.%D+L,myiRκۺPS(2נZ nBWJ{(GM3lfĀ,>}b#YSNSl~x2Q !691ڴ]+;a1h]KuZ+YI8sjADJ\m XX/?-.˚TV’@~w\,[H;;si:S3K~`gf|ͤ$؀yLOd:'`T(ו\QzgY3֖m)B@Z:/Q>N<fN4;4{rÖ7GoʠX֎MH3釻M\x&+nw綿Xb&iͮ}*|ɰro {[0-Sʒ k5&kE"z Vף?BfTCNՈsjM~OC蔍y{7af9kOK݅y2ߨ_iSخPnnK?n'q1s*4xV!̉򟃥j..qձQ?Yld[#ڗGZv{' + =#L+fr.~],ICMzT-sl uuLW#'xoW}?HW̉mG}>̟se6)z}d7UCkoyv2C1̾_L̇y9w"3\Η+P~mf{)<=t^nG[@}Ai^Nn;)xz3jJd}nvkw9?K~f1_̶r^/΢>[đhߍ|I2z6>ywN2{? +2:gviynkty Z/xV|C +ҿG~tmoazn{ygN~Q&z<^alw>62?S-&Sq)>J12rf!AaM`h8]Ps) ~4lٌgĵ ;V%m8W (Lm VMwL$d~G|HK$]6nM&fK$ͦt/5grߏ_yq! + 1)r`ב:9$ l=dǯەԱǯVHcĐlUϣtt>r` 3EmmEcJ0`>{1~Fyu4F't7}S 3}]AL`]>@d?m8#&}ۏ%>}wd<×Gxv;O/{{Cbۂwe6I&wwq$-M)5zj<838.@3Zx֮.ccj}oYBk5tRKS#i +e&:JI|U7#|r6 9.#Ǭ_CɤO;A`>w'uNbnvS4S=/ !B$fgiʰܒSsw⦆0R{^$"zɴ1$pBhSӹ C"`I{MwlY|_;V9Ě?DaM|;L3V-9hzaa81]m}CC$Ejd d2Zߖ< 1[-T }~v[cahDU_gv7zvٽ +.nin'a NSͭvԷG`}ֈbkwiCΠ"L@L^ KR]hL>XC`C[ L(+t]MWy t.#Śib) (&bq}",cEƁ~7[̑fk2u[C(mw ӟ>ZۀbIa/Ųj́Dj aDkCbnFs@:1Ek9ZRM +њV?i'/7\`̳6kjr t$WBaɁЈ9ZY"r<._F+q..xzylR2'NNBP2o^DbmYN,I8!xΊh-{pIZIݯ :j@L(NwFh{]|tcK@eV +o!q#F>d!%5gJd~#RT\؏؉k k 2 bVLV *[;Z{~Ncw|(ϜvtAmil:e&}So$Wt +`"zby}P\ %O,k\n a^tb|O_@̌1֒9)Kf@vOE1EG*\XEQJڜ˼DEAr24o(|7пEH!<ˍ$檒1J +Ew:sA+?AjiH +!N-R bCH*inx MN)n_ +N{6ZY۳6hu%RXjEM.e,@ 5}o) F+}ʌ*9A +^=|[Ya\`麂ޔQJE~sB 0.kq'ܑȅ:`lh$ ytMDTTtwDbjtb"+& C_R +a O<Ŝ9w(L6Pj M p&RmIŖr`rI!y,yE;,'uC2 n$%yV\PM{z%^6̻PU=gcR̥K? "^ܙ}WqɒύwsuV`]/J W +rUL.>iV0Rsv1]}ݽl7F+;ϵ}\șjj%xEr/ZA6,7G /N2PK@N:-HfsGm_;Mx \c7kW(vzDQ\~-6WT;fՇKoɄ gf{z.D ^> l&` %^}n[Tͥ q*4ϸ? sS33/f!\*4h3ۼ-).0<>kN۱|YɥR<_EAݽcvvlMi?<'fb.eޡ%rXk` ˶swKvZ27 +իp̟h-b5rFF%Z{e3+ԃu7v4끁U':l"#dv&kSK 챚`$;:glw[o,s/++#ʝ\S_BJǘx;">s[{ ?,#bya8\'VM".o(Oepl +ZgY.jqn"3bYR6Kfyo8SF0&h9?ʞۛZg;t݀N wcsgϴɑyjjU(U0?Ws$srke`wZ`p6OE(ȓJ/I+xLHX9o1CrU4YocۀI,`]%qnY*`\o-jJsmE=rh$͔2P/eGrG;Wdw,u:J"tw>GIڥs4׶NiHib3 02-]Jx7\8iz; s{Xļ1@D[ +><}_\.`&M5[j$ֹE+6@̮  \ޙȌGK:@^RS"Qād +PDr5ߎ ڀ؇@ X^#Kwݿ]E0E?lקH +U;riξ#XqE  ,tuW(? M:^,%u +KI;WƔC'q*+XA+RlyUB9-z$&(߂]t +ʖUS_),~Y]h/D~DLtF dW0׆\p0p%"kty' ΕgJAmWxѷtNhs)/}:Z礷hs)cf)EU* ҴFnXV/uwCqp"+l} +XaW/զxwIrKWS7{0m j}1l^YhrǙ)Piܙ뎌Q"ԗ,Ā/YxF隿ǩ$fvzFZr[L<3C7pfP0 ~l@g=(~CpGjVV#Gr=` +u_,$7\|U9^h%FKf1Z8N0 +0dy|7O- xc(8l$=<@D:Fձ$:DFUuo),vU7+_%4]rB&{ޫ xj Ur<ĹaVjTmEwǞ=C(%WuIL'?5`": +_e~)wMHO`ޑƏ4 OVȏdr(l> =iQsiI~ݗ!`柩;d_j!bRR=H} 1ޑڔiCDZ]cTqMY}iގՉH ȏtU!:m REK3K#-~E+2)_si;/wZ~7EB + q+H#V5rE4*䑞1w` ePHvKhtH4!m9ӼeE!R`h؟Ul:H!= ʿF]4ֶf?!9КZ)cDsHg*L+\$Ұ5gd)B|$w! Vu<[Bz-tհmVD/5R|9B-aaZ-WgOx&4k +m*O3mI9~SC| +SO[*ӵaJ?wx-SM7N!O;J No =f;60j Jh"潑:7Į侮i%#ρðBJ| ـM"VVnepI<^&#C2y:H]Jt:A`1\#ny!S:RG4XtV+HCjgZ 6^h"_)߿#sa̵'F +A2 &1y RdSܑBg6E3=Z]3Hyl/Ky'[Ň9Q"%Gt N #\KKCD.A"!oZF FI~WMP~W7L.'_bEڋvQ[T̬x{9fTL ^PCR)uLAI$-l:1 dzI|Zy3Aч4hp&lX@Dr-{Xj33?\p~2>CCpWU<^?m~zf׺'YH$0>CIa+Ƨ8Wy7_-f.&S踪d=bWH'm IO~0ƃ'qE;떟vm\Pm I%Nx~j] Mn +Hʩށ$ Yw1ڬf%Z}M,S0w;ע&t>`p2{HI1q_"K/vsh:RBtr7"ʝԁrh]DRiVhQ-'}A@47nZmHqS# 'IF,s̱¸Kr +LS0g90IxX3ݳ$ÞYIyO)!VawxEtgb Iؠ. 5,b*mHN~Xu+a\@*%cn(ώzKk;1LnսLcj'ǵga#q=N/`gPȠݠmB@ l~<oXzQ&c9+G&;m'ᓓ$[nwhm[| A ` El^! qC=3(/S[B1mYT_x~ $I#:Vx`[XO5T5; vIXK =KzRĺ8®L¹0E~]\!%d!YhB&˴!Y05 Qt$  +R7/=셹-"`CB*ՒV=U #Ģt,k 5vb4Fqf%y8qW`\sVC-8OsjkȟR2LP2) K3<(`XIMB1i p^O@Pjc8Cwejr/3@낹_iL:RTN/{|h-v!6cׁo/|v|HA84(cAyp{!0_wC^8`#,oIG7+S4 A[`pY:)q o+jV{Uim\kI2w+ yD`-M\40D$ӱ$(x7ٖ&$Rdy™k>M)%l[L푚PU\@1s&@"\ɁIR & m[#dAIpQ;2),,ly= j P[nܖrOʍQ{%*ț[^b +:VЯk+N~C RTA'X-d xZ: +:B xZ: +:jj+Pjߣj_.YXC'^A5td +೶s+X.Mal'8 5M0w疎vƗ`'lN~=]=^+l3k< +0ĀaI= Ͼ"O&"é|="XGy"2qi9DcN[uXrn, K1A)kd2u5 ꀩrz22cjGuuO'r3TQ]|=Ѻ:ZH hN*lKT.R7ݵ](1=p;rឿ7p|YХͻ^xN,C}p0jJTpl7wñ%+]𖀷1N$Z J+H)d[Jɉl$D>G W#8՗GJ CpPdɁ`qp@Le#99ϚÃ` `xE G«b^+çŰ*"8s"/6`9GpR0KX6-4koCcFY5pn _СUZMYb_U E+RGRT~S +ἣ"֋^ +"‘v 4%C"|iIF:#L1l,R8~=R8/R8uy{)LO/ Bp+p|"n $HJɈm6V C Qr<{}g'9#=j6"u~{ H&>#^']^R3FDRЉGzSM8̳t|~$b5_L-/WQ/ϟiJ5,?R57;t|4mt|tt=t|ts{㋵_;ouQt| =w=t|tͿPMB)l)8aﮦ[?lؠU5mj:{}&j_Qj:UVj:V{}G5݃7U=_QMG5jG\辶㫥h;bO]$ŋۤݛCbၰ3 }:ΐꄭ it:4ON%F&$|hXHdF@ճРXC +$tcLjHb`PO]"He w1GfO,Ȯ46ݺe5{+&o vIUNKZ! {*K2#aD6w #6wdۃFw7se׭("}nrL-ʟ(̮;$ATV +?eG$ +`V}B`oidx V2]aWj=HVq3E=qiʔ[\P˻:%#bɲ_Ql9AB|n ڭrBUK(dxWgÆBI;]+zB y+~۷wb/ѨwoHZWn^Cw̺$)!p'{Ý[a녵_#J.92)ٛwG#X_X-~+zsGz΂E/p-,I .v"&(T8G } !!u&IJ&g{]LJsbwPu,ci%U7iH"&Mp6W*b Ev U­,ÐV׸IV1<ۑvX}WSۛj\ۂWS=oÌOO{|)W|0$T=?qC\,VJEBxKk53g ,[aZ -UB}D님4!ExPh;~c}+tz8vR6%zهtExgedVE/TR]OK)jI);uA-ԇMwGzѐ2KNGΪri5R 9(kJH]Jc슸Ҕ%4UVvo4"G0FL Ff@oTE43W_={"2 |sM9lvXCE{g\$N|$M:u4q⤄ FHKUC,<ҦDžMwufAYFUKTIAc5V}tE޾~PM_?rD[ͥFr,]п'~Lž~]bo'~*~.o/IE~|oy8G_?d8+R׏Ԥuwg׏%fW?Ɲ]OXn}ֽxW'Onɤ5O~ }߯Y}D9䵾~!齾O ڑ_ǜ$|D0nO r_?JrpDk䓿 ZXr7l1X`+ oTd¡]{V"G,D 0ݳ]%+hԎ4ѩTۣPz*J8T~OVآDy0j6E~i4,S+iEsx+mj@!j*-g|ρl| rUJ6#> 6Z7Z_ѴK>p+X}jXa)cG4f99k6d &Xn}>"b>ka6LjbӤfբ1{ ֣_p2{ 4Rv!n~H`C.6Xqb^9֡_V h=Av}7bz s×32+a>u@eVT^1pYYS}H,of>r~Z`ƚv)=\}Xo# C*=Q^=PyE@R #q@:}cWy7gϮ\ۚR 0m,vN1&̣ԉ@Cӑ$cZei^0mT ZO겞ד""Y-3lY[Ŧ[?GFKƸhDlO1n~ܲXֵ^#qfl`#yUAloW]61!48N{ԗ@نFeq!9=3'xA]Zt ePDLMDC coz@ƼlMdg Z=v?gQ`q9jK"eT+;WbKX{vՆ@܍t|N}즓S>2gy$Su*"0GPG!Me1t0D6V_H!W+YV!MH#}羱!mVS&DM7iP@y8Ҷxm۠oq +`1qdK -K36L5Zg:?; Jt_DIn$3Ma;ڼ:oJaDMZSw+r{3HS?"e X'k」Y7QP*6:}]Z9I|X{8VU9R UJ"tjH'>G4{E'>D5p<+Z_)tIĩz$t7A+q"#e"(\&CPH% qL!3)~#EJ'¤X y9nwF8 P7Eh" 1z N`אJ/LR(׵@>W EՠJJ흔,"9Wz)wJA %oltJe:m=5ѵoy l +@yF_1:%~ztg0 8lJgIIثe]xJ@{%K] }570Q<r^)iܗS|//0 +!%y vd&U@N}&SI-6_r }-RBOiK݇|\c'k[3ξv/#k m4~0rcۑ=]tIv m=fv㣼ފPԓج3VQ1dF Z귟r!MӧgJ%1TřcKzi!?݊[Û?G5gDuz{d is}w{lj"w߽oM}'NÀ}`-M(6$qC29[!ZX!Z6/M\qֳt;tԪ -x6w#KDbTcuK^]?4TZ@52!̔7Vkeew$X լ< u;>TTk4ݽԆvU 0$~tu%B6D:KMID'CTlIIo`]n - l0$]}۠;&뼅3T(C]*cCG9nG +c\Myʹ&|"W L-I}O%s>hv uR%F{v&M1^b"âڗ&96F0@Ÿ.Rڋ8ˬFAk`>+$5*'N\ʝYQ?dpvZtRLVٖ0v `4#Ttj!צr:IUZFaǁ,O]̈́|hZ Ep2HHC9΅9m$R$PޚVCX}(52HH"BIOyjHqSdnv-e=;ehjo;8fsN&l{}x&q&ftAWZ4RnF1b,1Vie%8J-;0vU19>v帍ʵ&c2d蕉1vI +&KQ0;@?}{ő'ОA3ЭG/@,ЕU 1g?ƉGV޺Y=^3tʊ8yw~v7>[߾~i< ++d<#߃奷ʭ+Cѿ|xGo~_q,S g7k 3q;8;3ᥟ>xcՙ ݓ}n`I?}zE{{'8ȳ{{F6#x׾5v6Gw6G};}Mz9 kx;}MҖ/xgs2_h_l5EȝѾ&lv6 +ƫT b>ToD~(Nc6>xhUW{m~a=ř_lF>]ůO7#e|Ŷ<xWMvM/>vMo?]?qv}{woJm$l,+"w_a® d&?;r; +[h/\SDmܷm臀'!g|%z ƈի6P Or!¯O!íq8~uɕ׿4܂O{^$|RG۔{'i{tVZydt+]w$@+^<5?gϰ>|k%b+yۯ3>n?vW{/ٽ28 D2F瓱;r]y/^WO7OƦo^ޑk+>U@KyX[]O 'wm7㡼vd ̧o|_VCU;67N y{?qu+{?n/n<b+򕽸ߺ}A^%.~~e-HonN_o lQq_ŏŷ^{Ow?8Eu#{f\NFf?O +50]R0{˗?'m#JˊeqF:~ʷo>hr}&o?%O?|Ãض ZKEzԐ^A@?tu(40NuM^nC!w}>#- 6t{_>!;>/_D.^5vØUN_jNw~k Ew׭ɯ_矕o~~߹U~"42o|r 5-O'ΨOxK[S%ѯپZ>gS{9Y_^2Jϳgɘ+=rsi]y/_aP?ᓛ,c;?`8?+wyVe' yHτץ 1= $Ϟ}-jg7M >8 lS~7_[g7nO_޾og\;s˹gezg7son|yOޓ}s|[?9kkz~z3}IWӟ^ƾ/Ϧ7g-Wgclnѥ_~3A}+7g.KW]_8j|޹Z"w!G在.g58͉D+˃s6\o}݇/CmYrx.Ro-o}o{+(3[w|ՏãNjIWx7ޯ}\;t4+_AjR*I)|OhK0ȁ>՜ +ۥJsNSoJS̗S*:B `9Y$Wxr%5u2s#I̔HgIn ]M.%B%it^I43L!!: }$UѲm=nr:w)M9fiAO}z̫E_Nԥ4?-V-jr.Lx9)0TS]KT4{L))? r²&ړDP`q FHqrs60*5/,ES7ԙ` +2y&3JI@^JsULS,^gʔuW()40esyRB5ziNˀsv~Y]' }YY 6!K&RML2 =/a7E2Xc)J0޲]HX>w`00%yh̹O0稠}Pp{j0 2+IʐU(94,-Y +f7ko~pa0Hs4)o9_UYϾui ^r* q``lآU."}s"Z$V5zlޥ.h&t4G W +!D]*0γ3VKl +ﺵsw,BwtَGg ;qV'E@WѧI+ {3`k}у?)Y\%=B![Kawz,ba*=vtf`͋" UAdF9WU{^jf+=uH.#Gn +"L,Шdd䲏EWOkt<τLlzaR'-k9UB yya0GĬL&L6#%Bk(H+] 9Wt7gq &I79"k$H@] +H !6ikZ-㬯%ۅ1H ٬k`I`l/J7k1 +D* 6W?AWVC|y"*AbC$0kE_@EAR^@uiz V.0)ۅ9IA75б)p@_ NDNA[m3 M9WYԀ1)XgӢgm^lulK U>+(va,-7/*ni䄈uhIaNS5Ot[2ka +;hh87</ʰq&iJ+H>-6Ǡ璢yy=g#a/=Wu:O&wqW:lWvO]M Lw;g2+ƣ{Gk0}zkcy8(؂ԕ\Nvv_ 0x+56x|i$Ͱi 2gn;84hm`T+b~{I&4sOԬz Nsw#%=uv_LL7LvJ`#nNGJꚒ"[&{>8ʋ&$.Ψ;)d 15 A61O2lXA^hVȅ9Xm=6&l4d94݀}Vs=u0\`TT3[^k8Q (L{l jp+k:yk>_bYNŪXkյ-ɵ82f/̚ {[T4Ȼn+8;V.5p,i}QXtW\9Ge*&K)k>ļ +ktEig*5'* +f۴9}63v=iCxį$b 洬Lf4!H)uWZ%N.ݽq}u +m5a> bҍ-:ڢ M7֤ltp/]{Y`]+D +p1_fO}Ox43r_ÀFZ.+GmI&Яo\_.0ά!&V;rĢf TUߣ[zVڍ8޸Wxթדag֑M:kn^0 .ߩZ/$S<.G^7=W) ߺV7o7hٻrE7F eKg dIlƓq'c3LՆ u$7 Hh[g^AxK{J |shiaz! ycuSnbC{O4@^_i 4s"L0g<8ͮߓ>{yd7_VZ^-O6h` OZa(&CyŽDVI ,1V07SF΂lHa:H@wȉ98A1ySJLw Rć DdV=W|a:4YDS(w򙦣2puOm} RD9MIT5Z bzp3NH @0LzkҦ؂!J0u1Ӣw=@3V11J]GS`Bz吤@ Ɓ:z +1$`d9`606PR ˆfrvj 5!190M%0e2GSR"PPl '{P[:sl1;Kbhp4@\m` +23#1j ' XG4;{~28[4OdΚ{o]l]: 9GR5V*Eŵp? 0`R4rk:)&EYbĺ`WIu89U6)aDXV/v5pv52[z-22ɪB"L5'er h{0Pu +!${^DkeKP +X\h`4lk+Bf0ˬ[1[< &<9@3$=^&LZCloYyrLN:%`w.X6tJx/5M@kC bQ|l ܫ+4+]hgK:-TYQFOL' u%ؒ:3&?X`JzHOV3 WU_YZqr6ˮ$ʒüsD~[7:G>V:bc ;;އ|؃ֱ-Ic22Muŝd l[I22[U?Π.ٷ[N]Ȳ.ڬ):bR9}hWr@r1pV, $jNe`|+( C0# &έ2YBٷ v2Pb̙,$<2~ŠXsi p^A5 Hz̓ J +}:HO AB0JUS`k|Fs{Y2R%، kr ڨՒa/ee~ UZ1#g fg93 ;>9 erэ7l&!:&g$TV9;)>Av5 jYI!b9آ [ M¢ b9jH'TUTØ9;FNp+*3 +JQI\KZ4 Vp0iOK9e?UE">I̛` +F)Y e:e*`Ԏ@5 + q :R/O@ԿA$u Ad ľ>A*AerbfSa2${&wDJӑ=gQe#((:9㯵VJ +ոGv_ ih,c5>A)\ T͕ӫB + +")%H?h}s{&Y*Pe} " WQ|sYWyNm( EbP!6 +wg!!}>:N4w#t^1/{-d<[chrd`?ٳ#'-ÚEl<[ԼeGfs\k&} +33t]^ `"\tnvFl$Дl /$^1Ol4ɬi +0+!05X_,֟h.ud'8S@!++,Lޤ^qTq`b!VAiel; )j߱q=gWD4E_ T*@r,R PPJѠ.4za4 кbeA!;XX`\j֬g>N:B;`.`HIsnܽoo-WcWnWxFNr7ta-K<#?qO|G)aS.>܀CO<| +_unAeN}eϷ7rr/߂?C418ߗ>a/WcV`}n`"lÈGX< 8es0""}"bLYlÈXH=zc FlIJFy-x0>s1b86aq,{r:D]NdH6 N8eC-[0[}eHlÈoY13#d٧M2MY!srFrs2XaIJ,,˘قSFf32;1t17>slÈYٛ1ϳ#ggzƜ%eK-{$И,:l0Z 1ri',; ȥe\PaDC-4ԘڂNhe[[pZk٧Ƅ<(eg[0 Ŗ}RlȞmÈ>[1Ѷ#lc-hre̖+!vFڲ˭I-hu-\i#nv xy3'O W,{IiH)HI +p h{D1#PAo`q@.m,m-e9IA0 WA[`BVH2{PWrMOvā%!cC8Y% 87p[M,옂  p܏gcPKiB9BA) 6,LzaE +)+( <@ ,e]x + gW{d"@ U ;YAG;jIR- Z|SAʡ +]`+MiG3$_ ?(SWa0&2yl,^-MRP,s,lNS&yE3I. y{`)U-T g&7GLr (lͣ]8LV?BH wF󯶁-%$՗h:0`Cy1'd X":0^ɖ-veSf,dP%M+ms)650zuh KM<dtښ@1("\ +(Y̷tZkXZkRu8xٹ&RH2⻽ajyISPc)},3(]H^R$s@Ԍ`i(-ө[j[p&KrèCI@sk +9,^}T  WfoR"("͊%s9|$t`jY +z4._J25cho^mS:Du!4?NYI`LJfAPkysQgy}(`~"ј uÌwҝKU$'No{vžZ[0}}VrZ};ylQoȦ^mYߓn˾=47ad/MʼnX˞elAqy ]-xy ˾0t/aa,ق;\N x;([0rS}7elȥY]#f`ƾRY/i<PlN(V PK)5 [¢ J=NcQpY:RrVֲfD0kUɑC89>={$i3H!Z,i^.ʮiRCkcd6sy'1%NIȼ IU~ Cku>2O-aXM"k'&/3$ֿ6"%cL:+ wI &9(U&lH|قrVI䘻UXOPm:[ WL:4Ht\ .NȏMOIle[n>꞊-2A ɰYlhڸ ה>\n;}P{K#M4U$.sR0UF/f[%J}''}o(.@O2e4$-jf1IxPr)S\NKsԭۈS~u8Mi#Uyr(5;67*h}#NdL5aY1`ZkCQJ:K>7XtiDE\;%c1/张$bc&$نnDpxĊahzjIRC<+IϨėGh-_U- FCZA +%uOI1|J()]QM^[u0k`_EU*EVKy%c2xHh&AE(F@ m(3eN,I:r03 #3ef!! :TȜMĨhGݕtPC˜tbJ5*LtEgHqI9qo +WDzf_ݤMy(lES;i$A.dUB(2o:oe>+IdcZ嘭|A8+iUYwArVȈ'Qv"#ib^AӤ!/h|ʘ\Wff^ES%"E&nL1O*-r(Z;#KbEvj:g;xB._NV)&(Dsq"*.fGiaҕ"r*_w\ =+cIu<,|W ѐ86+gvHK; f^ImAC :N8y\X :4$+ +QGY t +7]s"G+u% e +GPZxQ}8gƺ,V>A-Yjr B eω`łr,T6[ Ĵq)ȤEԮ̥ ,! 'HhF z^o7f9 ab;QrKZ}ˠM!HRaH+i8HZ"*Rɠ$:w9LJMmXQ8#v+KL"MڊVf9 Rnq_x&1'y4!$rb@:z,Դ%+ Gw!y@4!kiDDEصXKf^6|+lu,!-j!*g!Th!*f˥!dE~ Qk=Aβ0!j;TV`D(&T&&+P§ hcHbP<%a(J>Lɇ~Tp>bوqrJ?bu:W~4wC+ kU,|𹚊9~*uQخ̍|$ǟtC%cGHDȇiCDC?x;h# z( $FBƤ5X]nr0Vc"$"f6*gg endstream endobj 122 0 obj <>stream +--VŊL 7YXa"*擸E+QQ\"jjD5.l+QQ)I$EԤIwFETG,+ETTS@/odD56W:bW+\{Y#*n9Qi(hPϦNA +9+LIՕ ,Ht8 5t%%XdUfT5Z.P&F +*4CJ==уBOJOT>stream +%AI12_CompressedDataxɑ&g~ "|E(hFEh$(U-. &35O?}f~$)4uP?oW"^ˏ?tdzyݷ?ԏ~4_r/˅z?[߽{/>޽G?;Wwᄑ~{ݛ}ӗW/_$o~QnSx144L_~?qrnw_~y"1݋|o/0|1ort1%){{?uW߼OwW˯嗗ݽy?v7/_i_޾~s'0M?—^߽Lټ_~! 1տ,L]* s8̻/oywʼn#d_se˰>»w/46i/rݨ7od8yY4L?ʵ2-:2aI2)ۖ,rrOr*zO]_Ow|Ng/RG}w?'t7?K.W/_}y滏$ P_or/4BUkqŸyɜiT/cP{"kk!_}xw? L:-J4Wf[?f<|M[>Fh B^{ob Ѽzk_O࿿ueoٻ?~l_^ j0o?|%58񽏓pNữ ;ޮgo}7cw_o~߼y_/ϮP!odrx /9x=4?=E/?Qݻg?빇+wqc4w7;7 $o-r7ȏOz?揯_zMSooVzjZtׯ}o?޽}nz-L6/Wxݽ  |?oyx1]˯^5_DM|+lrJ4'ϊ +Wmۺ-ۼ-mq (!z^W~\u]u^ָuZvYe\.۲.2/yIK\°L87|5yyEY0OoMWy/EY眳*9)6ݤtrH[ZӒEs))? o -Sϻ,7_vPe@#%ċ%췝B_?r9B:r]QcBnMWa.Ee^C +10qnjO$:4OY8i/oj( :ʚ2^Ml%1E#YUl.O?8:`2ۗv_2?|b`(3Kbꧭ# Q:*_zep˩>~廯'qG;j^WUW*_Wz]]^]]]_\^u:_z]_^ﯯoooƛ&&fY|Gz +aD{c8:/?NO D E0]FVAV۶m]mv{9^N2^|9_.vyy./o.o~ڇ}ܧ}e~<:'59y޷zppkᆷhp(\2 \kn=F2N^0Y*R|MArO¯ň޽~-vITYTUTKQ=dou$j89帒c/ǥ܊r;ߊ^+V$H[L܊?7od\77BN7Bps,/DيA6tqwʝ#Y6^lz9Xw s<O/o.l6EZfV=DI]bM}r%$zPhHIhKLhN?E]:pޅ'|GPr=r9X\D5{$#gR(k%]q#oAtxd3+~Ip\w?-CS/ [Ai +_FMaVx`E׋^˜>܀Kθ2yXs?r}8먆z1jyuv_g8;ǧhI_| Nݿݝ0MMU VɢB8_Kvyc:vr.d]]d^Ƹ[e?'jً>NZP]Byr$(<'SPz^  Gy׊Ncf([qU}xXx<2#1\zcaLn#(uEQ>B߰韕RyqTٔ#u/}$ .O .YA>C>=) ^8͖_֓viG"9:ﭸOI)0vbZrGrO`9҉#Q Ss (ǻ-x{O;`_Sl`9:Nq#tYk9;>8! T ]RA(A,`JJ`,΋+uaD +++X2ҼRѵS!b, MgW TA~X7 +88rW3 Siy2RrO%5=5HV\}?a َ*.alE..,!@T9)r(r-{˶N0ySHHssJSJRR C]r+&z*K{bc"Dg X颂/TL09R+T2U=x#ukjq4a%<'͢9 +!gnь+H[n &p[bu/ rYn<ݸ1gܽ7*;r=jXO۩c^>tz; +sGЙ? C>p8;lKu8c/kOwkDتpoN&IE{mĘ7פT*X6̓lsO'/n29Y(y &j 2:g8yLc"A39Bncl{r+rkrb)v6P jV3Buպw{pܒBr )kx9%e6.Kg!6B,ߡpsh#`l +J=Mj͞#çÏ u8J;V:,Po<6iaZOn2JZboPE *ɉWus,ULqG8W!cu' lQ~xLcxSi=Ϟ:-/K LbD3'szC[jjҮX(OSדy G]v3/MUmT0r7,᪡Y6.vR.u cu E MTF2ŗ[f0WR7L͝5uǴs+¿6U;s*Q*䯮YP):ѵlVߗ6[2|+2{5!WMj̩, i칁3l& +ިKFFݕuM&VDs7E! Tc(fרe1sn'y3' ~GHߧgGÑ1_lirckE O +F= (.$vayҽ'iP_rV^X_;q7b)>u$;WZ䱜8dw .fXǾ?N:UG>\s"[O^UPSQOйR^(r'DR'QǞ(! +~@iNFUK6xAi:Z)饗Yբ= k+ڽzG@8DkNU;8T 4/ /fL\+U Sj 3s1<P&){a9mxĵwy$L]^ HZ-VZ8 EFAau!Yz +ح,nVB5(aP__T &G/iӞ{͠ .j ZC0XƱP$2wxki08OlHxmq[\\*W>d8B +99QY@\v gυ=9}]qBmP!WFs}uԴt)35 X4A{zx:yZ7O93t13QqaDkcM~*Yd=b<Y' OLy=W;> S(sh'pOW8aqjN==9޴R~#gܢjN)$}B6JO86d/ Rq<鑓ClN0u RRj(;/̢8FqEw^"P +_)^([5"NZ(Ҋgq]t|T`9oVX ;՗C1X\=nP'?Pޞ{qxj/))h8J'q&Kà xy7{zh mȶ%mҏ]g[~Mˁݐi^a +c߼z)7BfQpƸ ` ` ` ` ` `>L/4Ok=%0<:S~>s<8J:K?UfZ/p`U^ּ'O#78{-nc䱡zߵo[l~d!jYcT`8'=8j7UHMʱ7ixt吢sCogK==xS禗prORNIvw¹PeG978uYjr8]OsԚo8-#/ckNT8 :^gq8*[?Цn:jjIa)^*#H:= ;~U>.Ggqɶ'۴]xfflW-j68)Dj]<>S$a~,j+VKeMGi4?9{~$}XՃ>qRd؃Og]çK Rl=!nb֠Pk +d'4ΘC)uSMqԡ@: U;Ah>v(@C#i@gi Gs/ΩΧ埐йxn`O?fF;4 ZIGZѱB4{cyqϟ:>]?,wʲ#j[oMYݓFea`XCu&Pm6Z| QF]'ju(vmb~+V\AP*mWJ24T*r5T1p CKNvٸ1|R1/,-tqY}.b;Z<ើJ.F'ڪ/[e<]l$fcN}W/Tъvaa[Nx_Oڍ+=qjj͘[~vh/g٣7~ޞ}ɓ?߿{ϻ#dݏ.V˛^|˽lz/ݗ{ǻsW # He6˅~T/6j +cNhY&zMM-z\$e'T^F=2]d3. +p|\a +wz4%36YF v"fy,3)$+;8GQlrieøԁYeRvØd4#HJ -L\!YռjYx5ỴKQ_؛<íwYN.k#("*(F `BI##Ϧy> "T̤ ƻE˔y830-qp&,FAʌWbZd-'lHAo %Y5bx>@Y2(+8b ErDq{X/1%YdES~I`x!Z&{J4e|yмpDvs s"id3`Č@A&c÷̡#T("z*T6Gl%1ʦf, $6=Md-vlՔ9VǭhH9扁Pw^K +Izͼ "q&<,̬[S򖣟4΢U~*$9b'Q%f'UsLn˻"kX5t㗢BBdh QTxHn yL йhxyS8V&1f6Pl +-6\$lNpEDhq.dYumNg# bWiL@]0q*"iT_ET$~ehY Nn܈$,]n[d(bvc5 + +كJʉyj.bPd+0%Z,Z +9/:c3ȄkF;KeфWU?t +e2+EmьXQŰW'#">E|E9#r;Ul!. O,)ĔbP.3e֢#A=wɈRT%2 ɓV&|fDK8m+d0m %fܺ-!`jm5Y *ިP@aY +CIF2q%KY})9'`I F٥cJ4`2C6V2 0-gS,qX"o]gqQVD@b[ 9=0i^3Ȫ}2wB +L˺68Tg2<J R?ъ[?iB> 66ձVc(?Ι\w1;/Z\%{| mӏD^8W5 +iYimu1 ilU:},1ꇱg ‰5 RFt=Fq8\udE)'dqeٸè65~)PEީI{ r "5 `Ti:P,6~-ރ0/py3z,iۦMOQhM, 1pa/j40֞×)G!B m2ؠ\oĀD,Qg2A[JM2NptEa3\KBbgSF0:g˝ rݰ0Pllt#kWBpxkJ|)Wj +CALIwSsqKe"IR(,W^b#QnNL6'vu*p'0ᝲZelj#\2SlE™ +xeҏ7mz ub5t!E+[,JbT7sAR6Ӕ\ uZ1F.g#- ) prErW~;%J= pjp,̚?VFlw-?Y{(L:}GQ}6<~]س\/u9Nql2enZ]d_IFnK[ѷn<]-nLciݡ-۩NSNWu׎ӹ9qgcv^¤ݵܱr@;7 wdj&b){>]bw݅;zwA>NzhG\x3gMh  +|᱑SgU9[4ƸR1NyN΢?(Qi$ɔ:4N?r]`FQ2W\=ʭ:r+{kn~B=)v4{n2X,<AH`igxHlYxXu3Cc7Ƕfy۫@ ynRg;"eU)o{4{:0ja-t9I)6iJS%/:5^.^i^;K A +=!'5DN #`J V Wjga@ʋDHGBY Cț64YhCxᴀ +RإYRXy#:QhJLu.-pQ5_q,Z£Q+nd^gh2܃<éCх%FgBhdZJLqëArV>,h#b"jؚ6u* RI5B䮀G|=O` ,]֯LȊ|fMS' !g{h +NMqџ"[.@7.4-bLdTwSmryah$Rgꍋ^Oiް(JrB\sZ =8o|Q_Mg.sh菚Tk>xX20SwjCWB\yD YX>Y'vRؕO>Jޫ؍hU/~}hQĩ/J{-raWo-V;s>[rVթ|V9oW +sv\sQg4c327jө)wH;u'4{4fϾ7wܽxN`6g( 1E~TN/G&6me?j~UCg~[Ije?Qm*CZa!eõ#82C Vrִ+rfں5s.?`<+KJ]X&_~1BJ$q<Co[֏Lұ~Ybꥬ? ӞcmC.duwYhu(|#ϥ_RmAWS,q,I' Ѷb 7xl :,+ +7arSOmcUM+OzKBuA)j t˥A"N@ڝ s*W0tE:ȐcBt.^HЁ= Ch: XP4C'@5: [Mb? C9! Laf\`p0u& fB}BK + CAbA,[t&O Lb,/EAJ !@&$9h!Ow:x?@Rt6ަKZHOQxȞu#Q|5vfLYS(Ɗ2AMfSe闐Z=(V+o/0oՃ xMc`9]_[/i5,y٫.0fUV )9ҥ;nm%(n+R%GRrzPm)8'(J*W$ +a%Xn0 mA-F+ \̴hSW a5bi#ԕ +S6$MC*MmHZ qR FYdN} 3Q+cBWrG`` VMUxlbnfh8bҵ[ R,q;Vדw!-oP@ܵU#e"Y>5B(x5j[oH7"tj/T + +dиFrA?@8D9Z@*E5 f` ` ^fnePjt!KZ 01@ +gG eUX (ڰ1]l40S D7  Fقu`Yhx4e~úlADXG$]["UJ汢L`=FCB[#OAUbT́+ UZKPc_\=5H)P3ѵh͇,OIe*+KJ=z{0fbBp W|^R';Jm~ [Ct$wņÀ{(Ը +aRq !]YF f(5Tf7%n]jn*sj;R,[)=Vr%): ';. XZh̬pЮI-/鐿JRxR꫌wRcKŜOG8F& h4#^f[D%lᛗ^ȂM(BJb AK:YdMWf"NtrNs,kEūH~6 rʂtaY3 +Z$DU +*NMh:QYӻ7`vUbB"7e?cM[ DRʌTQRVRj"`dpZz[-YR>1nfDI/Z<`7FRz1_ sV$F?%100I[cfYtRA7*3DO6vIEj|HDp+N>vX:5Bg;xwreOt(aZX= +Id.!~f-g6p!C,CTTQӱ φ[c;lEXŬ)Tk죭2ͧë)Wjʊ9XMY`,JZ]]B +ZB]}I`!A4B] _T +m/RƲaDz.6NٕW֭5ek{f=0M^iLNӣvƯxZWj|Y/zkemeX/-z2=hWZڭY ɺ i_r,d2[DkGwP@ ،Yov$.Klhպ.0W`<0of),QԐ+n&XQc.]92wK{ 9ߨ: ةꤚ'H>ɗ4pRЀDP@,{6 zץpD >@|h.+0QUQ_BZԡu>|8g8 21tt,X1Q4w9s|U ngzpb 8"uÒn1g,kYr]z}z&SH+HV i-Xؗr[oiPǰ pfV>/r+{cYzȫ2$;6NveϜ ']I}h@2~9q+?W0bͭ~: L**=s =7Ooݮ&s99z*ߙSKvd" }t'ޙ/n5J;rjAtTЩcW'_kFEC33̓gYXwHm>bZ/Nq L,D&XA:O c4 fJA+\A!*AhE9XL (=TY݀B@e9`sY/G%Mr~ |"²JX׃)EP2`z)/D6vPsQ2@ ~c P@lM^n47 BP ^32Y(̇DwZ>HgégwG7|>U:܎f%0!*VQFa`k`f;D!pܩEf(N!F=;EE1S wjF}h`XZ:Լo4)d(@NQw*ENepqfDgeS(fd8 +S@;:sx +j2)$#OẼ sbJGy5|ۀ!mq@zIЦrn[)`o݋,SS_;P/8UHtEU$O-׻^}7?ĵ+qnZrWZ@1Y-` C;)6ޝY\P 'mŴV!"I+2q$Ddp?}a?bTj.Mѳfr8D<;&C3MDld0s^@W4#FlJ<@xt#XqX%bD{ŌeO&f +>=`hV2Ȍwh<@ 󍳳ґM#"蔆wAqtΫsgF3udh D6#W8'f'dPg4<=^JGe/C6ŲY"xq'K}nMcR#&1ZȪyQ[܉'Y(kϯMo<0tj5`!:Ĉip"(nj}s"u{ Pt.}J8Y/8b?a+HB ݭwPUOC)_ hZ9]Qո("lNQDv X<.R8Y:.qͺ2ᕙJ麗 GoO1vciNoA:"Y[,J|y*ڬ7Uh=@o#U % aNj+"EPQ 'z_1O9S~E09n>= Ke־bEڜӚwiU&](*67LJ95ALC k0k6Rg} P"{Xk8VXZA8eQp}z-&\#ܶ\qa+}\{Y :֨.?[Q"͛7Ms'vDXuÙ@j7>XYg77[dc#̨wZHTyyyeZ$*"%f!zB~Q>,V~tc)a"AoVzgݥhrc +w{\uyf&#:;QQ.گr)Л^Yom;30 7a3eHQN`jM""0jP7? ĮGj]IY~}g=kcN>~zF>|&{Z{~@[F=f$mO:ֲIV2z\'ko_[[[F{^.ݖ݀mֆkc xaEqɸiޤ޵Jwe; _WdaMa"sӉ3dI;ݧ\ᩤj\a/(EpMEhH@H'R\!"LoM8E"bY.Z#݀n$eқS +l#403`a%|@gXy77aS z+?ɐ&  ͙hD"p"2 `4gM1ΆE )'Lp:6aEeuiqA3IQn` X=zFĖWжh + EuIOey|:vӆW_z؛/A*9Tb*RV4AW5ϓ(XtT`9۝ BCLF &a&"5B׸qO%^5xFvRW KfPrܗ uSe[]i{$`!ξmB,f;snx0M#:w&Yc6qs7=bOzMNwG݂Yf-[̍f k[T y[/dm՘_`bҹ3z#ٜ4́02 ԊCb^ -ъKQ {c \ Kܴs̥RenJsϼfn a$?Bu:uTu15W/|Z;ꪛ8||;S?ϥsSSq0=e@CJb'C/]r]y=:3x/<-֋[{ `Io3J6(|S;gz8Y +Kj^qAi#[ĖKhI'WfҺ}Jtt Z X0u6Ï|L '!%C YP|;jwi TM xavis_.TfWձv}3C8NDLķ-dlj<͙tl$;Q?a0~wŠS >St\:gnp@ +0CiUv.ĕ8q~/o="9ujDVѠ^R0rc YVVI*yf*\ScA u.P&qY_f}k[6m-{ jMYFClblz3:>4c߈2l\HajS8Kj\Q4~jժl}"Y-"-7ʙXDch xМ/F!(u,|Jol :DPp[f^FZ8ɤjf+ #>\VEp+Ṃ\rP05O8 FTe1[zts]!Y=W&*n۱ĺkm*ζ)l+7\3U9hN#$sl +_t'ss#faEq7:{*͑AT2$W2g,lbR;ȓpc 0e {+O%ecr1QČ'iz " 􂪅>8 g`ѧ؉YDgLIQG<5i#> ++6GDJ}"F$ M[`ه"3E)!wo܂{0U9H `}#3 ^u,_m$ԋ5gرy4iImӍܚm"|q,n.|]!w8 TKK`h9UMoE/2c=6l뚈ǯFT@2YǼ2D=E$#ֿJOރv E3X2Xxp;FJi+ZٵNZ.XZ"aCŮdj7,px8c/h*T:J6loMKu8]DžJu؅#mgnsl.`YE}sLPfzj[Jy? (N.7, f$Dx>|ta{ݫe>eK:įR+0OW]yPY`$~E}OF#:2#:z#+}6}if%[fU:ږuKwIXV`>1pXF䚠Aѳ= 6!oY(+aFQlYu66#[Jd:alǨ4DWDHRN<VX#A:i"xt ǂy$DdE(M|U̩Rp+joQhTfbNHjXLPrAq vwlX^7k۶#kn|v줁L8p~^ u?yt1HO;3f@R"/\=wOpڀǸix yXv_RvЖ|[Cv(  +'Fy4wl׍ܰH9pLBvPl}#1lNy:vbuA{b(A(4r,%+yqzNݬbDc6p[x~dž[jq']_y_g#1B=ћ:a'JZXyˡ3>i(8v>SOf+'`V="fL35țe C .³fV̌S 51 k)*rܸ4f&PIF]GZZ!R=)hRaFf%`SA1X@:"ap`&N6yh A,'X`P?re:TqPY\.1E\ӧ>]l#cor v6reh/ԙE7 +KO X92ŴW rICGAO yM˙m,;OMQ"?C9G906 Њ_ZF7vaH-&NDe)ב!(>j5"栈~ؠJl݌,h"}l`ĉ(f=@f?`(fN/=eͰJ>>`#܈;/[ˠm-@$x(a}@.0;%&v='jkh/+&#@#nn#N~5A5\йUAKYPݼi,F7(9ہB_R ѿ$aa>k= p*}8gԣUj֗흐h^&diB=Ӆ,sO+ +Y.d`ZEJX0)%,צ~QA[H 3 tE((nZE,Vv5+tjZ L XjX!eD,0Asŝ>E*( <sv  0Sj+bl"6,aX&3K`.)B*sr :Zʩ_!k nZ`$v8NӰY<"NډHXX):WXI,6_*`Qf =&`z*Lh(SĕVBED`M`J{ &`KK+`QQFiM; +XQ,R_t)&dQhk,Fe] TLvƪ$6"˰q(Y1ʇe(TE&~tpܸErϘ4du2"E_ 562Q"u4.΁F9^́ƨ4P@#y@úzgVg*f}䤕P%5R> /Suy^Ru!3h + Ogx::H2gLTq VgxVBҌ,Bn}븨?иtNje{^z^tBa@w.4UB79^'|h>N3rN'BX~6(m2:d[ĉ>sC-CyCC,E/evv(:hF١Ӫ23C6G_pdN(CpB`[.01@Bqy[|8t7CPʝ +:Q EʨR^ifhsE.E3s˻lű8h1Pj;-V&eCݼv(ڕk١l;-ZjaEZPDh-#md+kT('*EBр>Y}DV$'mϣK G򜼅8\~>Z6o}Xz_7nӋ Ac +rGT!"P;0Zu<EfjWB!L%Jx'& Usb#r/ Y.踾~pB+jݮP4;S!u#_rdiJbY %.Y UQaΖ:@@we_rC*7"8 ++DN C#g1.ީT مzU?*Ea@ܙTHz*iqhLC  ZetB0ke@Hg!Fj,_1K3KU9l15Fh3ciz&QIm R֜ fJ? 5 喔L˸3zBu`b$ k'-hӶoڧ 3b,`6¨poAd + jK1-`A9h*fb0ۑ7D9r= &O"+REMk.\Ti0v9tlʨKZ"O %%%5Y¥8z/uު3' A*lͿ[k+i50g[ ~GEU:?zE +J&$n ‹6̔ +8C.zJ Hid|>C,5}wD~^,YL9ӝ0U 67BG, +lhֱucV5Tf?#Tb(nI\p5̤PFI/(fb(y?('3Xm^2^*rdJ6gD6pf=sODc2'c+#dޘW L>?3Ó +N S1]g.yf/>:-1853X m_@hIIVh=\mQ8PI-~\V5vbgҤ̝ IdY!9sERc'Iz%'<N9)5gUzsh1W mN4u>9/9 Tw:=i]pףm!N&s/f=qpswv]Ι-s/B4;ttWq}΢ޱrwwoz +uwqz]ȸ߅{쨣E\yȠZp1*J-Jщ\fh)i|=X\eXLZxT9>Ӫ3٢X(5# 8 +ť+W<)m +3宆ˊWjXoNz4N㵊i-\4[v +p.\#LHes׀5iF;5cnxMǶmЮ( '6ƒ(1xi3sa4vgl+6('Z1{᫖!o &:ы'X@՘H~=!zlƹ:A/~/%@Sho::A\J/7kQpN&Λ,5HH"E)J 64%X?Yo'262@Qw @;!&B֨3Gb- vkPcDaJYiUI5Ah0ڂ^"+cj0^ /fk.7+c> /x2W];1At#ĶnkKcD ;~"RinX u:LաA`ʈݕ 3[ӧNGKdSձbԲnu#AADq*HU]M4\ooN/*!wjќ"mZ(@#eXٌ*aeN($+m/|}Wv_gwM3n^a;S5rӭ3)_scN>~/c$?()*ʶu[i.hggO*jؼkؼkjw[^^] z{ z5l^m5l_pTհyװyװywW^f^]Vz{Wz{yWzwUl^\gHxV]Wz{Wz{Wzwel^]جԻYwWn;$ǙĀǀ4UԖgds`Al [=zl(]Fj@6@jZUYyhml{V6ZGGA~)V5"b,©XFʠXFY©duŲUZ#ݖbҘXFeXRv(Q=1(%Vbl4kbN42 +\fu\IlB!Y&rCfG 2d4=$Ö)Y{h 2 RS Q} 2jj>}g2=޾zCIxv-c6G~j}I1 e.]ϻ?%˒x{ᓝ#)X[ʞq0ﻵL<#MySHCީHCiH!4&$w*ѐwѐwh;h;t4t4t4|4|>Ny>N1M}SSGS)f)磩TxhJz|,MGGRXx +Oԏ?WJȾg}}[FYŝ~w3|6ik2Bh S'NHς;j8 +0Kp )U'NO 8!\?%pB8!\_%pB~Jp}tyvCg !\_4ppCS{.Oo lE4JhQ|x47֋7/}M Sjw͞,侥嶢)Nىb{\͔:Fk=M#UpFF蓲r +xl}}Fܘv/pDT3?Q`ʡʶy)S{S8z gF~~ǤoF|UҭQS)T=~f bwLZT;m wV'EgDLf?f):r'>b|=(W61`˯{܍1/I*?߶xD2b%B+نNۃ!4@jjoRDIͻVh^-gY-21)@<=LJk,gYgT v(g^}tdN&` g^0Ǫǫm*SMؙ}|D42ͶT*<=I;W򬬄x]Ez)fiiqB4DQO)@kF5lemWmҺUtJӹ?x~g\|!_nkG_GĿ̏xI}^ox2WÁ5B8͍̼ydGYm&pUhPBxS=O:™%ִ>峑H'Cl4N4fE<}Gm*?*l(&^=ނ +`AdY^Wsk o쬒3A >s3Ey^"䛥8'DT`l&HX]B'~S xn)u+0W lGe/_uKPxb_Z.LY}W:uMJOSZq;G;*5Aڵ kő`dSIZ.aH֘L', +lf8C[rc=Z@Kkzɪyd9N[5N{{!!emSba`D7qŵ/L7}X%u(;(յyPZCXT|vFj2rNwĢV{3 vwScw%x! +JnE3oЕlFZȠr{J)~NR)rq,Tyz$+f"o$^hݜZDPmS,^pwHnTSd jjdPn1n El[V$z|G [Z$!#G.UF +VV'nBΫWj>zĦ)6o:"L\x]W1Q۽MX.BbOb_aC2-x>t{'fz-<8zg Kaq>gq?hRJ2ldgE8M'',>)QCc:i}0Ys gδa)+9|_p9+4,} %y +Ѯ2m㸎 u_t{zYXW6<>jtg$ɫA6^&M.JkʼnC2"K%ζMΖn7NtI;K0${0 ؏6ڎj=dzY&(%Knurb4ut:t(Tv\TRN۲[cv{l]Ml䣬Ul%)>Jp0Eؗ"+G[W&#WOk<7ˑ5PfPvt]nثYU6n,/sTU(2hM l\q*;'}x3{@@̚PPkAu\@j|*Yyރm5~\3K>~nrj^Wk \ә&[OBrw;` +&}*dpcCg/6|yilr,8uW?GU4Dqd2c UXwxK3?~54,;2ʡL>i{(~p)z=F5\/V,CAAR򪭔{ĮD^/Kwp1 Ybu8ئ +_FGjkGɽyR7<7',6~p Hc{cW:*f#12j*o-"{xۦ.>^JlEyo4jb#Of=}.BuͷŸZE?_&h){Uv{Z {9׮>B݁,/ڬ#'űs=nh7ی Pi +e`,c"1?kXw븶8L":vEܧՈͻ1"TdĤߪ'`sElÈ1G|n +/ȈhMa~#8Y@z)?c11hm":eֈƖmDm8"c48oG,yL#\f_`ĹJu%c{_+Tc ҍXGkkd쉆J,ak~5_?DdK,Moy&E>h9rRq"5=SM//YGnlx#V#[6H#/6#^#>3֙ϛ[M/6->O֌wM{nJ֬V8崺*[޽KDTk;L&тRtVn Q{0i\49a}P&_U]GtFGFgވAFhV)Ƴ!#.+=Z_sCG/@(s~ε*[yho*pP?ݏ]~cmֳW< 4hk\8n^mc8$m=UBMclyn;Ҹr_86aƷ6fur#A&nL3 ~g(5q~>~7 _ b( +M4xfwfr+JW$HoxoGߤse3Zwg\4] g&𗐜;ͽOs!e*Hk8?o&;t>xիҟ$W*E:nY8`GZ< +ǵ4Iv+9Tb]PgF,Y$Pk7X+] RYY"zHּMCO^!̠ve37*PUy$`׫*J$ +EC)3Z>=.Q1bVZ]| 2ԙU9]@TR0nųmvu$=r[awǞPcS]c<ɪ#b\B9ؽ1 +S ["q,I߉ϰE]ɸ69 2e_6n"_o*2<*972*'G[;3Bt1A뺧s !FT0'Vc +4GP y\ Y)9^xYxsoac(7ve>⧐GVvaYS/*TgPP-4cҔEY>R] D2EL&l@j庤舵 AF Bȫ yvhӂ&!fs|=b і"AQ6nN +7Јgfi$Q$(C|agWxUafCHnPY{|ryQ^d{sQ)]to.R"C%HKݖfGJ Twt +E@*$Y͉he}=ǯVL\=gDJ%( +%m0:p0;Q#Ɛuiu*Ԓ6c +(~ceLڔ{3Тꃥ8CcXLIVk1Kc1}1],޺`Fhv0m]^>Ÿq4+UUtٯٟ+ cY7Ե+bZ\3g۝xK[* =PYQ1zHgu:/|30k,߷8=+Z΀!Ӓ;~?Trn hqP <&}pFT5CSt-`]yjgO6{cg+mTO ~;|ʳJT(p,Gl8+;f]2#AT +ouO$AhފmBYdt=7{iatis^~4S9:.ZTg>+g8]"t2$8ns}Z{GmC:`w6#Š~qacõ^q?|?}Ѹ]gz'Í-տt__'?oO2fd|} uCo~?_ooկϾǟw7,c'_˟}?ّ5ﻘ3?_g?~¿g{^yܓwoӯ_w>o߯~s'?y{gWgAw03O~G_?_l_~˟w*XaܭD g"cњg?Ȅab|L??_WZ[;c??ӕ>g븢O|/~~{;6㙙L6[u܍T9N nPJĀ͏ fz!H-Ԝjz3)٭MgRHJ(P>,mv<(^OePGˎ2a{6iE%A2qhAp3s\ `F.*%r٫-q1$p햅:s<R v"X!sj=jcÈĢUt(y,jٳwz) ٳrTǒJm!1/{uIFD#’jSWM*t޴c+.m]9bxLVk9Y?dtYy[uUYW"1rK[BFqJKim lC,{ǯܽN[a>!"I/)eՃv%6 _ +o#wJ)Z>hld)OdX)#\("q"ˢ1+o#?.& 1,mM>ؙSiuݲIR۾S *kx){x&n9&@SY7Dv[Rwy2B6a߄2])P&~5WjbdGHF׽W# /Ld+b!ZŰT_*G3tQۙFajoЙ7^_(ʸ"nLdUHvx97_,FljjU)HBa0ms ę# msfj"LaYuE0\ex?p׋L1ܘW$C2l7~zS{yg lXo;{w4]nU˥ E+tJZ/Յ'XsOw޼RtH*|Оߞ>R/bvpJ?; # ;k|ncVti =j=zm_W` 5sx^]OdJӽa|^;]ŧ7$:QDO}iXӳ=괓NZ +ؒ'$B$wCˀ_#ػN%x<9o[nق$v$P6gw0 xfn\KQ vZ.x`a0_n}ͣ緒f^> in|"2J)`fǝ3iqi4 u#,4 qMk@`^ۼݚ al *i$A}c_kwhyWJ@1h2P],|PdY.S跳g{^Ԯ.? 1.ֺ0=.( +t;eG_ݔ%YDc`\ bUDr5#ӎ11iRUe胷ns)x;M +u.UZ4ՑEdX_sLX2\f$D$F?Az:$=S$6kۨ]ܾ؂yi1 %4+M̱[͢DZ弎|>n"gV=hD]9~HE^H3[ͫHGjӢ/!mmٺMP2>T;;-4]BeOi974R+JEF> -N #+ A2*] h!:zD?JCMS?gAV~f6 aӰY@fdwsIlj5QS +`RVqYzb:pXs_ƢweSj~J[-(?eu4z͐l~vMBC)D0,8pꧤ̛x6c5m;U+&b9Y,J;QD>J6HyraEmVÐ_aTHK]Rp5m:ß"\@ʞ'd-Ri #Vj%q 3.$(>aC=&9F@uḭKl1Fjdc0q I#Nş$ynPnb8A PwW|W +J]NxIN/%77TOyYNWQ$ĉo0!T^pj-n  X;%SӪ;ÒjR.2,[Ss_֡=Z"F8ͱۅlƕo]qoosR(F Ǣc&ijO'2o'cjxyMI*nv*EKWP̽w+^nW1{q1D6t1<˦JnmGdd(|mW^<هnvŖjX,fϺF9m0JJ kY~4I 0W rps^[|T&QabqlgdX& ju eUiMvVbwl ysW[4mXfy{jh1ŋ`vk훸3z3O|}&q%}sdv<;vEDʂW,Uw*LbHpOC0؀xbx ݚ+=>w(jG8㒉F$P;*A600TH6 )KDҬŒݖb #XDml3Yf=3:ww_˔oYz#BgqӅL{cNw&;[?r7b~#UPdE2Q,agU}CumqWa[K[ź740V꣼^u<)MC-j PzxUrM"mе8%dY Tu;6*s/KV6vcYzXuA>鄩Br=ĺӲ\Fӻ/&RVϋ(YDGM abI˞o/q®|eYF̢JgY,8f`3!auw*ǏCD^<ő9d'u6Q"x.7-yR@XWk:, m$ +t^VA7^Y(=pi%/qz~ +- +bAlvWsYymcfhw|"%u)o;]hMh*f +HʷLEn1aebdmdj_TjSE&ᘿ|6;慏VAc=7x2 +(J}~C` 7Ur>doED)BILVq}"ߊaJ%M rr4ExWyjy؏IϹH3P(R–xج쉩2_y0,&^ٕUIp۷t4jrܔ ]}rN[n} ד>zC7=+02uz \\i^D(B}T%_π3b`5wȴ'p}Wn?ԡYEWw]țgxT +Ɛwĺj*2͋8FZPƉZ +GX_֍HX;sexcI%P2-[U!:yέݾ+4Bp6 łVO$9*NZ%Y`1;PN¢ + $58169`Q +"7@T2B bݻɎZM>WE8=5\1^fW!Eb5:vh}U=NuOgGEkU{(i%]M9GLg[. 9Xb2\."V37nBʑGNy45g>kIU&~f{dH?J6*c(U!*uDiЌ0zXl;f$tmٿu~9E/{I6Opage8,C.cajeۣ>X)ePfؼ +o(eUHu뮗]0eBTݺõv9֬v?U4H: KBT81BZ'vT!՛h5!YfGVӦsYKsefyfT}Y.@'iz~ ]Ek!$ݥas4a$.ڷ'ݡwy9E +f 96f+Vjx*))=4Q rʔT(*٣&%Y\#k/;A?PPntQnRWu*28B/c7U%BI9 wm6 +d4-SW5Vran6Zv#:LTjG0b\׺F.&NIXǨZu I T&ezWu1ơD/ukQ&,(̈́UdUosϢ RkٯJ$! Qqmz+;` Ɔ:\v8]R%@S=368.wt-Dnv ;UZHjdds 7uF{A306_F+9o(VIoAL2Kt`\M[[7Ғb+}BBQ3;ࢲӷeaƯ}ݶh4zD:] sE@Y'4KZsz$,rPPDNX8Ϫ)6jܖ7:]a}SDA%&} eR!%SdpH&_*C24FQ4nݷ'VqJ9̙`gz/b[~F((Uh3[}β37 Ȫ y!OUϨX{YyC,@65ؙ-JW/EK}$nD +IZT%zF +wu{ohݼ/RY+}KmՑ 4tIe{ɅimĨN~ +>3 +w7 1_1UhqE  }Bg 'O\&jdxh7Cc@Y6>B8RUܨoŒŲ0Xx aԴX?n wV$YBK[@WXXs c fx{{d7W3T~oKwb9Udl[%rTYxNE&q4_S[ӪP[40^>.N [n7o%j~(% Dm8>J*Nn 3Nj6du5>jvlp|dܛd9DCWa<=Hbܽ{t ͻx wn%gígm B4G9[z Ujot6CB"lK~qjH&EP{kPEט x۠"}E/[!7%諩-& \zd MGE+mk/ɡNޤB6ԯ>?֎oˏ^C hLL ܭʄUuzh>-Ko3ZcV󳜓zWWЩQh/"}Yi1POLQ+8$(nheJ$*ߛEV;Mn,ъO0ywS)rv[tw9Å@/Wh4S:&3tIօKsߝcj=}' /9$͗ǟ[L=β"ſL +^oٺjecT;`^Sa5YhxwUK+΢CZqf7a kq)yŸF&}u }6.H8A3+G%i(TSkbsmӖą~1hW!JNtZ@ R%=XfNM^Yq(0صKdA`i&zp!?)0?$&XC.s(U#e'JC-5 A޶%]7GHS?--͋fUh1nj$Yt1"SR!sAho)ez +JuԶ5\vqz(]L@@0B 4$AOT+nTǺ?Ik\!(JiwZim5,4'(Ǝݵxʹ.ޒC!Ղ#D7Tud8%j+aGE,m"JϯBdRU/iꔛ"ru,g=yKXCܭ'F D~}>laY#BصójZ)37趽σȾl5-v4rbR ldJ*72K_MrS )?6-1k<(VѠE=y> +"Ůu 8.:lR 5mGtOoz(js&MZQ>\g1N{>N3s/>j1TmnosG矺$my?4YuOx%)ê,MԾPo,$aFՅȳQz)_=ƚU*[4+Buߴiҽ]DuӎӚ@f֯\{IWC=VuT*[X|2t`NۅkSx&v}]],լ4sw>(U )ƅ#P)b{ r[a)JGmVde]\+_ҶahT~6aAp + DR#1< qަRR"VZc5t>}Ju; + +[\ +`,/Oi-\7T_"d]c{حڢZ >6G 6m6g +aQw߲ #~A&-DzVla[ۥ%jyMNTȭ +M"χ!LgGŶj徲4)"-H3qwiHdP1OkzTȩFٗu;ĉNBMP̈́d0SаLXlG0᳇QhAVQ+quBJJWL1e)i}ϨOݎڨ":²1|02ߩR ΢j-!9/*g-{ , w*-GCuZɬŷmj۾x* H}XtCPX\Z?FkSKj"h![H|SHK1kS +nl~&A ܶkc7B"I6/R')G[lX;X7aUvB$׼iSUèHn&򽥿o" %c4CPO-CM)UiXm7_E,#Mj|{QpzQZoYbnT ]n,vIL]-O{YTB3dܦ4J65)2`Џ%| +tغSֱ{ᅖ2t$ZW.\RҼIx$k"9CZQWp*riؼ>N cPˆM =OW%V2McMYn%~L5U]؊d9NQ%?yoJ."'T3e~/~,mƒNk6Σ+ %eU?k0zc~%ao-h;vr-!mu^5or +*2'XG/=zh fo{ 7:w~ ;59vۼnubmX^bbX+X Ѷ܆,&˾%>kk,ֆLYŠ?# [UX$U:X ygM`1BJo~Ÿ +[o|,&XLa-`1 ,Y?bt`1 +XlXl,Ư`1ioMfتN Db*XgMQb*WLpd]$bwa\1Pb2|rŚB5+֨5}rŚN0d4z(az?bL%+9&Wl&Wl؜+ߑb"OX{i\k~LbkL\iH\a ^bh/XC/(sq5%X7W)ꝸbJklj>b}=rڽb W\dX_7W ca(\.%!sd5% Wip^S]ub$ WCXb\1 }rd\1bO{c]bdR_\1~JqZioӞ:sl=b+&cɐbpŸ\^ȋ+ֵPfX0sz?\1*\1!f WL4WL.0d0WL:(+C5sz+W%\a\itXg/b~_\1.pVdF>b2f +a,\1 +U +WL@A^b;N\iHiXvW/cp!\a\a XWE igN䊍2Wl+gW\1^3} Na(\~7WLPb:+Fpźz7W OJJ+\bӐb\1f^\1]Aa\1i|r̘b:+s}pXG +WpŦ!qņ1b]{ߋ+Pbn\1^\1e/u"d\1m2WJ Cy\NmJusrVX_zf^W5*W CW'WL3C⊙+pd\1>b]b2W?b;sF+>k\1 +'W cኙ!qtkfXW}q:dUX;7WI6s+\bX+W K5UrŰ/XZ5gX7ZbX*WYptf_\1~B5oMK kpŚk抵WF CMkpŚ"֨xqe+fw0sŦ%sŒչb-*Y+ZbX*W ˛+rd)\1Y^\1+ƥX7WlL(&g7W0l)XbD_\1+@c CMq:#a\1,+ֆ4Ua\1Y +WLgbn\1naMKMkpx*W+f m\d\i *PSez1 bq+kVbM'W kRb:pŚ43W ˛+ƥUX#Vbɒb\v\1]oXAk_\&ۨ\1/XێX۶X+#[bɒb\fi+_\1 W ˹,+&ˋ+&k +WL#^b͏uI\d\d4XSeÈ?rUD+]b__a}sŚ)wYbɒb\FpŘT\1cCQbӒb\1#"⊑\1G+F#VbB\1di+W 7WLm+f"A+6,+6SOIr+p^(NX~q+UQ4㾿b9ScX'QbD[\1bv+֏#RSb8\1+2W Û+&k)RbX\1e +WJW//0+FXr@b}ю\b]Oɕ+_bW ca\1Ib +,+&ˋ+r#]bܜ7WV኉Pb 4\1:+WLȅ㾾b*W cv|sźz3Wٛ+rx*WK+rd)\1Y^\1)2W\1N|sŞ+UbL/͓+pޓp?W\1X?W [a(\1>b2&4bi\pbui3~pŘ WLP1b3W7qda,\12WL}rpS +Wor^pX฾bXsO\19ۖbX*4b:4b+WLpQARb/\T抱)\1 +_VbXN\1Yk +qŰQQbq\1o+F4pŚ$?b+WEb|p\1Ε+pg)p!\6k™|r(\1,+&ˋ+rdI\1OWVbܱS#Sb"fX+y+\1BoaӠ\1oX#Yby*Wsc+gUX#Wq%+Ro+&Cayq+WnWaysŸkRH\,C.[/XNOLq+&caPq{p0 3W ㅴ]pd\1 r+N\&6b W^+WLÙ+F5aW c5& w W *+AR#|=b,N+Fc+\1jG WҵO#\\bMM抵{\1F\1&+Z⊑|q\k9WG)bMű+FSJ7-\1W +Wip\a,\1.pd䊵 b|+P\ 5|p4fX ;qŚ(9\1&;\1>31WL1k +%b, ++F +pHb\1N+\1|W.\&k\1fOӴbo+&ñNXS^b Wk,\1 ڤ +Wl2b1\UyqŴ[\1vÅ+}rd<ЈW \kRߞ\1~hrPb:ݓ+D+\1b!+wت4])\ZS+fb+]-\WL}I\6$G+_)b`R5fpXB*WLI3O+R7bogWw劵WZB\UY+&kRbX\1+T᜹bX\1SƿpX\1Y W Kaxq0Və+ñ\1,+C5VWOQ3⊩pHWXbf*W,+F1+E\1Y +WLgbX+W K+Fj)SbW kuz2W ˋ+pt WLOXW3qHUXشrTFXbS‹+\1ά\vX7Erz+^\*W+WW c劙%qy+&ka\1,oXťK0h++抩pt+E䊩1sT~_bt%~rŘ +W9p(W{qŴ/\ /.bpWw3s6ZbX*WKZ+,sQq_br\1 '~2W|ٛ+&#Wb+Ẁ\1cfb+Wb*//\1?bʮ,+3_\14 WL+փb}\1k.\1)o,\P]⊁~sŸr2WLW b4pT/ W\1\.Iq3WLV/un%a\15$,/rօ+f9S'W]b +F:D +WKxsZb$+Wa^b{qWz WLOӓ\1+Pb]C/qŘ_\1$5+ƚpźFኑw-\1xqpx W)bJ~rھVASWQ)ĐbW2Se@ኩ sdxqźWQXbtb WL#>bPb^\Ub̷/~`/ QCRb/ +KWL"+1sd\1}'W -s6J>bc1bӐV\1麳uf}b2Dq U+&l+&Caxq0؆zRm+W C?s߉+6C!!׮BIfDa] Ca ѷƫ9q$OIOPkb2d1œ,ZPYLud1Q Y |Lc(d1W! Ic9.d19,YLBRb,^d|x"3+d1d12YLLid1,f&/,`&QPbT?bhSz2YL`d13YLLSmYH"O.Ŕ<$Q5bB{=A,FKh%B&Zb^X?I#6RbH!!&ź,&Mźd3Y ˛,BγzYv,.؋b],F\! C&M'_bDJd*Y cd,&k!RbXd1 +Yg%IEzc3YMx%%K* ,ƍ~$ Qbwe4dشYLE,ַgd1άd1 +Y+ I#6Xbe+Y,l!iUbJGbJ&)vZbI#f\bD\+Y=W397YBkASMZbMS&ֿ@5tb!_d1˻'XSx&5Q>bl+Yz%ACd1ի,,f5-d1Y YLLWbTŦ%̚bQ(AS$I+Ũ0|ŤPb*Kd1jO^d!G0jY,,6lASAJ!Q&Yb&TUشdX:Y0*df+~TrId)d1,/XS3Ś,MS)ŤWb6>>bMbԙ,ͨddI0duJQ Y7YLݭ,&LL ,h~,Ŧ%̚bb8̕,&K!")b]bd1V*YYLg/JRb}$XbŢs"/d1z3Y('Y}P%adid1&Ť*IS9O"Uj/Bfs&&IVb +YLG|Ťbd +YJY c!a(d1 /,2YLIڶ&v,&'Yl5b]+٠Il,։'F% K& cd >bTnP& C&Mň\X B"ɖb}] +YY S!ɐb,Wb}@8 BL OXWG%QOTbrd1oaJSصņ%̘b*dz0Lߟd1,&C&u?bb2fB"qI,D'YLe,'YBLl&u~Ťb8,FEYb +Pf>b Y 1BLF'&md13Y C!I19,6ʭ2Yo!X(Ŧ!Ŧb=rH #"*XWeYLOUbYlba XWF&19$SE/d13|ņ1bd1v/X;Jf[<9a$b9 B6j'aȘa0}@U7`l$a `XL R?|H|k':`$z}"ޏx8&F ;LGT'L*J ;CbL6 UXD[U  #CGKS]_j@].ѿP!Cb9_R%c{/T|2%KxqG?K PmPHq qFtgĘSLj#$䉿3k< e̞mxY 2 06{/.^狊!-N|wks:3U ⋦L CͬgB#^ +[нͱ]gܘAаd;\/zUZX[m!br0"TMC8C&z]]W6smel^K%Ab1v"za 6 NkY^Ա@/xw%xI sU3rJ<^lojс^$0-^M-yIPU \\A!󼴓eiFw6w.62 :ܟ jqvq#/3N=h$"u\wXxmg\W뎁.qȴ.օGF3],.K +V^'jz/jXU.)Lץ#uG>*u\WK!{U օ@Hwu.{h,sϖӘa]uӥ袲W-9ϝ D$&Y~5AZEw|VӛX.}޳]Q*\Ӓ\X.Dk9KdUdrFx`X-\Xj˥\⼁ad-X.A +坷N: +kL(~Cq*0*״>H .:vQ*.uH9mϲA<R쏪r CrMA,.(AŊX\ + +(8NOtZrIrfyO(逩*A*P.UZɡ\Ӓ\P.ބ޷ QWr٪V-Hr%`:tEj QIBHSmG}]ǥ|2qɲ;KFv>¢qIdWุ6?3lJ&+YkZDž:dٺ=Rh\b|a6SR [m3[%uF#@\(eWvY גܷ%5OcȚ 4$0o땉XE.:\ߪ0&zK9[|^[#<wDWa&uk Dq<-Rf<&a9SNںJg斪d{m8"ĭiHa 屻Q/M92-ۚۚm1h$ԺE5 b} "w-dFOXs$-:x`0-[l*-lVv"l+—-9_P]ZIݻ4u`k5Z•w`2 jg ^jR +Bn]0n !1rfuZ#3=ZxuԹbRK!Ib%fz=WE|AoHAj)p_DjaY diD-j)D-Yp5ND-)s"R@Z*etƭv %k8AqXZɗ@-D{۾:.O zyGY\h drxpŊ:820eaDl8͢|fkE-CP} fm be'sxY3 +.:[.ÊKV͚2+RRDp0 Tm+EЎK|mdmPLTd]%nI8khKmT|9i]A"n+ecޘ+Lp,Q <uejg+l,l,% 4~YX6XL@=8Kh'*U@NWJ &=E3y 'b} "晇EL pXW7נa]E%Y*5U%Q'i"2ʶ&}ZA#̘+ vؽMZyn q=+L܈\$tcN 6U;*#಴AꗹnpínRl+m9:ڊA" VJ}+<+td.}m@9XVuף U@ XVP1 [EY$+e}$+ jAZW_ +ɪZ GYQTPV*2(+Y(J~Jno@YDYaŒb@Y)KHT`FYɪh00'HVtJlŮ&e:i +'@Ab;\8 d>B3N&*6d%9rvz 6**dEd*tI;'Jm+cN (ViL"l[X)`b;׈`|Xaz9_B}vXa]Ԟ+*uY#sZ4=cˎ"[Oc5TJUt&JOJ{یZ^ڑ(0Vd c%,ढ c%Z]jxc[aXI:jk9im\`U{br[4]80V Դl>urd*y'ZN10VYcJFM݁Uhʚ^1V[0V; +;JYƊ @殊c/c"0VktyjԹ`1zLU1 YaicJ+~-SJX=DlR)+":Rs<ь@J.}"eyXVl+!d2qā"JEw2P=1VFS_i[ьRi޻XDV`}RVH90V'ZҙcEVh>~[Z j"+5$;0V)F#ctF`$1VP sIb䠝X)Ye:"ҀX)˨u> VZKXd=hj 9){ؙb41ۤXqU!+5YnX[7ytw|RXaaԇc1FX^ˠX)%xoP,yd +sAK^X5ނaİΰ"("#*jYc0H2V\Ma% +p3ŪҠX1m+5IH+b%1XVk*yXkaJ;VJUd g@X)H+fk饀ղ[qazR̰b(z J9a%jUzDХ\+<=}s $Ee8cr~g^UHIzrͩT^\{lEMqЫd8Ĺ:ӫ;U>@WE[דX;2*;8 JŪ* rS]jCj],dfW1ovoBlbK5]jJЭvn5躡T~qH( |*UYJcDi5/p +(USlx JZR]eDPFGWI8<$bn誶i$Lx9dU2T +|&W5/ W5J q\AjuzS;jU쪦ldW!bWI<.a(w>2ɮjcQU]*4_*3JĮOvl]%̮bW1\ +TMP$y}f AJ][HPc¢QSo] Y*N*,yAbp[8ZtZBmJ+*%G-0ZU +`^ӥT.,jVY.;jUV +VRpU;R_-d_\%fx+,H*b;J4RcsU$zk*ny=ήz=_$WٲĦrG0USlq 1l9~DDU!`d#[o +-|,RĮRgWq7^NN +**-m;gÝU2Y@7UZ^H*7!mi?=3jO u]dt*@WI9[*)tm,h]nnvɽ؍S=*JI|J[v]^O.t<쪭dxUR=qN:KR1\?^}LuøίZ"_yo-qyW𫒒J*ɩ]RRU Z)-d|V_EoļՇ^eÜ̑J3ϸ^ڦYYW5`0/=ō x,FAbE7U  +9 +ScY /GWGL/3A<1FD\5L,U +jVfjFhfVònκEnחyUd͛MD"ݴ*@ VMΪRQԑQbtO!UiO2(@UnOk>)*tjF;(Uk}bTugaӅZBS!ޛMLֆ#T*QPjTkJaxAIIfRE}hN2D*Ո% DgFS7Q%8dURG>)]&O0sKTQ9ρzRPTODDHpC#sUcԎc gP)DA.6C:"5),J-*y*3[L LѬw) +XJ ;qऀ2ϦD>6YU#ƪW{u *K|mαYRgѤ0¶UI[>'E(hI cn^&eju~۔rD}@-ŪB"4):&EK>'x7X<O? 6[ +xR s W\IN8)*= :{M>mMJ'EH@IєM ۥNj+'eR]7~e.u5ZO]L<)iœ~>xR8_)-H<)9NMIqmIaMIicqRُN +nN~~M'uW8=˛u½x,~M= +Ug46Id:jѤ۸%7NJ1|ZHqRK GE[~ +M +;]u L*YRKsTZvJED?Ўwl7 IPԥI()ink&%HbFIy5%eoFafHR{]]Q<(d%e?$Y/rFI<\U%m2J +OL6t"(2<J:J-{%e)()00.6?1 R%m9IkJIJ7]txW%ĒZZ,gG8(8J0)ObqlwI-1:dҡD+0Qo1äxTR[I57,)*\ %ſOֻH,)(*sWYR&ؗswbIx&;P"\(^t&5 OФfiR(8hRER$YI(EI.|DQ$; R۰j^I0%d&E-ʰ1g^L"a-vФ:xcNN| +M +QW)hR|Ԫ{8)eXQa2pR[H8-:NGf'@Q +I !*Nv>pRjJ^Be8)}ƠI8-$( ˂m˩'Qcͤуŝ QjA­k.C&JўUԞO{Ljoe;l .'a_I=^l5yQ&B,\Sc$Q2SsrRNw+awUTP>3C@sJilTjK>3+TM5 R}j5TPC-YGSU M(5# JgJUvj<]uĔ3tv& |)X6,jo00X=떽C.Ѻ0huP+b`b)8X!eE{^P88μo|u[^Hc%%liqAQ":9W3ɖPR_QHrKb PJJ=lAׂ6j!vYL︜b +b)WmUKlaY kbSƤ3#n,ݭc!I<Ç6/^y=Z*\=~ʖG3#]T vp8>+|PK_)42֮[}#ZU˝Iş*Z)Meئǥg㮒: x5vA6Akv7JgkFwvl/EnL0WC O"*Pêc?5WRYQheh]W!4EJT +-, OiJP>ۘRѝ}+Z7 +`yr +0pr[,>#sX̛&T_I5WvO$ +NE0X12v|8}P[Iɫq@RASͰ"_ud3Si*:p,8auRݼ=qѱP#c?M?c_X$3ox s4nf{F&LSfxBL3gȲUM|>V636fsb|Ws:#݊Ÿq}b}+R{*o:J?V8`rUlzpڪ6ڦOjw5R-/%. ;RF'>.tMEPx\7JC?7=kbbz][-"RWb>+qFIS9m%n|bgbw6qqoKJت j=kQM_oml;7mXT%%oteWk>|Y8iJYaU]韚Uu4sdKS1A)}SL)gnŌi}&ݾyr Ƕ߬G2:&\>_z,}ۙ=G[~aad<'FKICx`/c[tkw̛H,%~1T Xe֟{3Eqp5UsmږݼY sXuo&&VF>8jeeݎֵ [ImVK:٭fq~,º#BqIpkq5ݢ[ o.ğaA H9m0Cؐ>=e^J9V2S7* endstream endobj 124 0 obj <>stream +4Ӫ~,[C7V6edaͩynOM<"Zr^K?X^.Q20j6p!2"*)#JYWH%XRe!I/=[J0Y4Q⋋ʫ'A!''rߤx6#RFOS&eQJyqۙJnEHHu]3f+CӬ⯝E%b?W#]t͌TbHf=90')v*Zr?ϽwɁ簽mv"F+W' +hO:`.YvIWIꈭrf8I +i5ӌzZM1dAXfOCˬk/*vխ|i7eq팦_ +!r d-qUE,6Uw'0׼>nZp?؊#@(Lp5b6p5ۀd]f&ϊšrAF.NnC3Eˣ-}.26ԥڪh uв|Ca[8]h7Jea C +Ȋs L(owD!}7@a sIu8N> orq'oŞqEX.P{8 hX_fsSX6oL&šBiM4(ub/Ut^8'h=iՊԇԣqϩǽݓY +m_CH7Cgjr4ԤzDx/]E67JVU\^S2'ps)COc-u~ʐ xyGF.i͒ʅCc3C$cv8e54o_S*i*~(3I!_zs+`.22Y|yę- I杗APeN"CߥإJ5_fx +T@fF|rpCu2 ɉоm;e^el#XWOaiIrmvZ:-fyf+齗%-ۊ?ij%]ïW:A2ol]Qh$MeApeNK/R b n˝| + OK\ +z<9lNG]-J@4;e#hº+t:;)BmuPdo>CIr'*,k쥭bD*Kg(њ)g ;^\z4VVOE{@xW`:ʰ"`zIW4ڲMqo)<-VBM舅ZvHVҢ+Dy [ҋ`ۤ% MZMӗQwY`l&9 {R*l +SCY;՟+wzҥ'-=姌GqPY#Q/7HmͱbĿ^DEv6M` +Ʀ)R6ta*lNVKF)Bzц,͐O 6E|ɮS0Ss? +Կ-ޫ$>7lKv}0KORa̍C=(xVKOO &5J$ZHx0F!uV012T+*kym S]g|ˢVJ*d*SV]-nH6kf g} >/R s[h7D0n:a4Lx*Ϯ&V=TjPk +@0j z ԗK>9-KXb9_/En ؤQlؼe~oZ<ᶥ3o2uU')@#)ƦB-fLm81$ +>.oBnMYtRrlvޢWa]BgL< R(PR{1(+(@DVNVr=mkxxQ$ź~ =7Kgl<}:LTA8f Ɓi i qw39R}7YHQN['z ktp5jbHV +`}Av&pI$.n.GUA kO>1ł{x*yW +ΣXhet?} M{?6Fa܆!C.A"`Uצ z0憋d>mӨ +5é>kRIyQw\')Vvx6rN +Pի*Vø +bO)i{@Ji<$Kg#Sr!V^¼GFм]N?yWNiX]RvDu;&p|w4ZMʑR'|5#瓽B55"c2SSњ^V66NZkݠ2oV|:T}c~3j>^бyj[x8amt[JcyY` Crdx6A fVg6Ԫ~ j1Eo-7Ȟ`^+֙MTNCkQ!@8SM_*Z6b XHJJT;>lh!EbR'^sSc iY\_=ق[ֵ-/f"ֲg/A}.+Ӧe,SMN{ҭ ltSMkLz,v>piTmWJg'2[Nx:--3;P Wmg1\JA&pwQM+wE0̹Km櫩i-8,kZP]"J- }Sp!b&.RD跠b@?$鵞ЗGN,M;ӐR>(K5p⭝Ns[ʏpfo<ߌ/QeߦMI@רh`* D˅WNži4~=ԅٴqKyu3kEQL<&"2|yYjeszwԂEJfsM۫馳.v&h=/_ph0 kfEa"ՆZc]kz@`s%K^B.UWJѝ*?8Gv{?O9}:}xͩzw&d{ )I)_ރ`[jQ slpٖy՞mb; ͦC, tIXa#u5}ےAHH0ΉFnpmUxjGsIܱ+h*Qn oS-yCMsq-58|7OCMYӒ~QXۤo^4{rht]6+hV yq&!6`2٫L;|*%mzƤkkbVÐ|Uaf(j q?/554-C2T=nbL +;?En#fmDRʦYQ{.c<5++Gk,v[5)u71Qk!@jDZč4^Yt*=0 2sv"nsȍ;3fq-rUL(7TP;BF覶ڗZ=9)4-PRjx{(:[-sE+H~nW'pF܊MP [mkARVEtCUFtC|4S/oq:lD}9yFi(9qsiܘT[ۢ*#n@%|l^{UHܷM2盏;Vsx=*͹NaGa{^n#htb73Esc{؇b`) +xrڷ0ib*%ՈlUU6juFu.u #.8c 4-inI}@}=m!ӒxiMgZ[wrw<趙^87(mWú69Na`c΍0E_zXrD/gb,JA4j}܁:;tf[]QqONUd94*%S[[Z5漭e#籙nV7qښ|‹O +9׭,T먔Q<=LE$DŽ}FDg81>"Ͷ45KpWG gF=R&}p?oF2t/'*b94d#$R* 'yjÆ?i$qTW!nN[tw+M'71ōv$2up1b2-w_[_!Sa d3\vm8S.ډr&TŻi3o@7he6 ˶"lp48Vİ +LzqY5G Ap4iH^8U +ޤ"X=L< p*9Ó +^nG$}%~敁RGkGUAó·79*9Skáa[}Y`g90 +m08(DYU($|DzU$'Eā]7oBiLuepװ99rzM(zsZm gD0m_ Jo-oRPx]!G|Hޛ#gL4Ƒ᥂{a9%ڕBxO/𵩽MN-Tæ)VR-QL=C7OWPP(q3+9,}zگ# YA"͎"{"V]ŐS Oc5HK;6w/EsX X&>7G"f w9%0PjGKL֊[MsDN!|sel=~p +yFwA4?wd0dͻ,E|93bmΒЯ!a,;o0I +|sOS2+aՒa/Kv{H5=|1.U`" jblx ڨ'+N8]+[at+O2Ytັ U=+6hTT ]B#¦QA0fGQ@ ܩw9_W@ox;"^EY1,kCUYd׺%Hié +'Z5)>n)laۓDl)z[cnDzk(iax,UVuKR5CwqϊiWؘHA3TH{Nvn Tq"ŷm$ŝzfQ{Lu>WwC{)B_2TǩR۸[aֽ4np:yPGY֚ge~ΊOA @sZьrﰸժd^TvmL]Rkj]rֹ('\C}Qh^9?//oSHuϦ)lnwAR4K\{zp)}:݈de4V5U;ཏ;A&2XR"X֡FpJĮee!reMVvՠBڦ]U +”7  5ob1#q/KBƈ"^9ZVRU6W@:bЄ j֖ =X SS즮8˞(>+lyv>ZR[Fjո/R5 Ac +BŸͪ;Ai,XssJ/¹Zp:?;=ݕsʹ2˹SиrP +Ύ;>pTΝ-9wZvWΝ^ʹӋ˹6"~i0(Ns׷s 9w>;s]0w0wsgEO}ߘ +KCsǭ*;sǃW1wgT~/̝=sg/NH٫1w$I?; N6ssGJ7cx Ni_Zܡ̝/NjI;J>;%+ċ)a?>5`V̝/3Q0S1wZ#~1wD +NSduzU̝> sR0w=|0wRvr sIFds'G7[SsHfܱh/$Vsp*u ̝FWϕ0w[I$掟T0w>;S + sǙ̝ԊpaNsGlaW0w[ɘ:Nbb+.{J%1w;\3>NO-;M_̝sGlܑw);&؂ӼI;)swb]Z1w(s?2NCR}˘0Uu)Z1w*.;y4}1wR+wꃹC-;,;>Ӗb;势fҌ״`w0wl ζsǿ?;ԂC);/N?b+n+ s)P1wJR1wJW̝ +Ng_̝;s;6at1*n+saTS0wg̝*Nrsj`(H);|1w&sw價C-;;g/0wR+NJIbp.;sg/NsgKJ[m5,3N_⋹ӃU1w .) s(;V̝c1wss*排7邹;ɘ;&;< +NJIbd̝_̝bs'7stid]Rsb';HI);̐>;S3 ~/NSi򭘻d]Rsw[O;l 1wܑØ`N]1wY̝2勹c#W0wLUV0Q]Y0wg探;sw.tɘ;a~1wdd̝&ŊC,;S2Δ_esR0w(s'`$|0wdȘ;psǍ`2 +͉s>탹#_0wdgʘ; Nsgf;ml +NKJm50w挹R1wZT̝H;sZu+~1wR 򒂹p`(`V̝SsZ0w1w|sP0wdVsי2K[ӰR1w[ɘNblU̝]ƌKJm50w=s`P NJIbH ̝%2價Z1wD]#:N>Usj`/d̝^/֮#Z0w|0w +1ԂJm0w`M;>; ﹂JV0wX̝\g̝b4U5sj`RT̝^&䌹S0b1wIsHRs;UsI;R1wh}0wjs:⊹Jm50wrX;=_̝ӋP0w;s b`~0w6 /ܙO%%a;Z N#G^0wxGܡ|0wsgW~0w0 zv$]R6n$6![1wZ}1wXN0wViܱ,$VsCi䫘;u n+s9;=kiS̪`T|0w1s;i*N-Gsk냹;m3㧌Jm1w4TesΊF#?ܝѥY0wg?;+;x?;Âp[1w_jP0wR;ngI);s̝/b>;E+N. s's`t)S1w|1wR 2NsZ0wD` +NsG£`/aNm>;sUѻP0w/d/Ns/ʘ;]NbI;?;busR0w(̝Ԋ=`tq; +bG ܩ{bz̝shZܝNwꋹLQ1w +}1wR+N_bsIܡsG$c%*N'~1wjS;h +Qsgd1wYjs` Qy 0ӬNJܡ|0wsg%̝/`t{*j~1w+)`N̾~1wf51w'MsQKW0w(sǙ̝0s_1w{B􃹓z3aX0w[sZ`P uoܱX.;:  sIe̝vAsQTha*;{f!xN̝K*6vss])S0w}1w8]i7__0wG 0sG`hN/掸FI;掾CI;_zs+V0w!>;J pc(bϘ;ݏ#&)P1w<ssYd̝@sG43V1w4HNߤb=ej!̝`Z;\s'勹7;w7lM?;*0wueyjQ7GRP`0{00wf51w]1w}Q4ms$:3;Eq;@suܡ;;;\}ֳ(Ӕf{7NsV)io_0w1w8)b3;Ś+掚H`B#W0w2N/0Vܩ">3w_Ă37S󋹣a'c;J>;X1w܊#Xܑm-;}C`z-̝1w/}ahnO;(ת`Ns/b4 sG;rsGگ`l ;Ssb\䘻esZ0w(src[0wiB;j +`̝[ܑΘ; _̝+s'bbh͘;s/= scܱ`آ]T8N_ (cP +3?;s'%a/N1#T0wEbV *c0I,;.bܡb1d̝sgy`H]'1wsтRT0wx~0w8H̝;T&̝/[ׂ/;e>;sgJܕ`p+;)_ݹsG}%bE-;EY/zхP0w`4 TsG@cS0w=\o sȓ1wzK 掆`T̝/Γxܡ|0wU̝"[sGN󃹳~,U0wJ}1wr2u̝_̝sl@Fsg匹#P0w_5sGKRm?;jsgyNi_`΅ɘs?;kɘ;z;,; Y3#?;};YeN#O[0w[1wT̝D)ܝsk1w}0w0w*Ns'5c*;掔zY-chYwWS[G̝sg?swZeoI;?;%+悹/0wJgW`H|0wns6Ai b(Hʘ;s&b|1wT>;1(;-+Nc,;]9sVȘo<ߌ/QQP0w/dsw01wz6+掊Cܡ̝ +NJܝ4b./s1P1w*Nul_̝ sZQ"1wT̝/`P +`)*n ascOq%]RXm`$.b`p8ߌsX0w(s'勹 }̝n`xm8bW-d]RÔtWۘ;O8cK}sr7;fR1w`xEpDܡb;ޠ; >9mb6Vvhӽ@wRXН&Nz|@w+莵FьݡН +) +tGcQ@wVtg^PtR@wI-;btGhLw)ZAwں_НtGhP  @wPeNi!'ݩ8|AwtG|AwڳUНttGssQ[@wy|Awt'|Aw4;; et twbϚAw*$,%d*cHݭ;jۢdyP +Nt뮠;<_?6󯠻*Nt;<9 +p[m!`*, tgtG讀3(;tw.;6xtG^C-; NtGP +Ύ]*;:v +;V/N+3 /@w8N1tGtg~5 tljtLJ@wV$@wT?]& 37 SsfC); OP %0t[RAwK);S3莜y! >)#(;j3Nk/n8z`tgU@w-55tG_tg՚tGTAw[ ߹lНAI2NA +tX@w(t'WН +ʠ;jdН=$;0TН.F%%;q Nl_td-!B\;}|HUН t35l?Aw|@w*s tGutgaY@wFAAB); +c>~M t8tg{ @w[5Н>:п;GQ.W@w(НtR@w+Aw 莨Hm%N!0b'tgtckRAw}dݩRPNoVݙ/ 2莚Aw@wf Aw.;etZ +StgjݙAwn;CH'(t7-;<>/ RAw~Awx;]QhN8Aw4hL);)t35(;W>;*2<ZAwwН^Nb|@w tt'/;">; ?; +cT@w(>.@w'3\ -+Nz(dVtHR@w17.) tݝfݹ2 tX@wL;?;itAwН>,AwZ}AwhJm5@w莅/6xm)+;"t 35C-;|+;)taR@w(tGt[Y@wt m,rAw<>;3AwK]SFUНwt#W@wԟiƏ?;dJqtZ@wН!o~Awj tG|-L͠; +Q3tgͨO:lН_ּtgtt +hQl),^AwAwIu=tݑ/;)tݡAwp(;J +.) tTݝ+;;* +N +yt*莕f݅P@wK НWt)X?;NK +3taX@wz>;ZE +N3uѓi!SAwtG +NStG7U)ZAw[ɠRAwt}@w4ZeНv}#f<⠻? 3N$C&1KdT0MRicvήS;-h{cpL[ZS{؛sި'غʷa>Ӟpxcu ĺ0[6PWg>? W5VVw6-VIuXɠ:>7N<cծLkY:y\ͺX+!z0P7 cB(4%.< +MSGK<Y`:Q.lYgb,}YaARtXVpl6 rN}vM^@:-gdK!@>fqnsT+8:y,xw).*ع˒ :rusй/O0T~s +)9ys{keV6GvWvk),$hv}zwe&g;hNKg3JDdPm؟1sMm\̵y91smzh̡Y|ЫPgQG5թ7^NG˩Avyr'2ZN^zDŦPi'#/( עzaS88b@w7j/lV26n5\pUqMVqBsS㖐qK fMc\@&fQ}PCm~JsBơ ȸ z.8dL*^@5_;f髙[S \c>(8{R O> e$TV#->6CBKгXqzuE偌KJBm5q='D&)06:lFSȸόj A\腂S TbwQώqn`8쀚7 Vr "1[Lgym2E;61N +>܋1MQK0 a uA1:jrއM_1n+T'1j{w 0} @ӑ(yq& +8c8|ċ#Ƭ8(/n+Tu2H9"հg^CIiU0z-~1p귵θ8vcZB# 2,5pqM1T8F8pq boos[Fu4[3 p`S=^G|CiLCCI ŊC8CpHBX)kh{HĉÁ750qb%Nu:fu!q `{ŇSFi*X?0np'EPoϧr3m!qޖ7eEp  +My yS9dԩg .7YC 8w,|aOBe 4gi,7m#:l|^"p wnwMAd\;g<@7#v /_D7.D7{ * t#JS H@rH/GMH7O. +0h&BIf>nH7 +  *э@KD8 +?2M >ѭQ&5@k& L7RƋ`}=Vn\ [{#yLen=@bXl+1PfMS̳-n ꦀYM:lAH-ucF"PP7()P7"q[ uCQ@~? ӍUd0-> tɾg%KݨL:sӈ87qo|7̍{T <`z57ǐr{<8n M\& q>^>O{|7dzn{V~g4ZQ62# mQF䶦Eܦ} H/rVfXm ;DCn#n-mB&n(q_fLm?rQ 4&ź;܆mG3m( x22M_ nptH}r5oB7n:)32qt%ܦu{nS6mS΁m.ͩmOifh^ȶׇBl|{N[۪ +Q)Vq>dOP^_R,Z +gw7զ3M-rsڸ'/iS9!Tgz KJH3 `೉g9f o?/x6F61֜ mx~b(l^ka5|ml@(0,^JeS12"nL6Y2_NV[H]= {l" +dSkǦɺ³TM0Ɔn?XlMcEaS)&/¦*7t줽rrnlSlWW9oi!yXke[ïFf &|`SMqYVZ_bQ5-ɆzM2aL^S u^{5Rk0\D |i1ʡ#DАs ⚄˽aָkf54;ij3lTb=^O5jr ?,K%b⬉[5b2WCeVqG6p&^kj5e`šrd3`7_Qw|db«{t[mawjcU:YMc6+fڌƠI(ra21Ք&~H5ahQm*O Z9FV;B&ʖTmim`LR;=@j*),8j +9j0jۋ:*-o CPۇ1>#tZMPSfQ{O:Dca%O:OiӴ}ݜRO)LNW eԆov|\iuՂ-L#)̐iMڇ@2M HL#g4[JL{)iZ1[f:N+`05F 0t+%ĴVJ4i(W֨ٿKoӤr&ijJLLkci-Yλ)-470MDL02v\gMkns^YᑁiR,jiTIPg$yd`Zha)#4U}fᶁikYs^RZ^Jጟyib6xi)44p8a~o^hƉ42M Z)4( XaV&6_Ҥ[иkTʰ4bR~DDKkQ4ͬr>hi gتgImZԓdZZn7hi:{hi>㩴Ǣa]2-^禥LOy{/aiMY6 +zߪ KkQ_`irr⢥d Z-MUgZZà۹<h&YF) ޾[ ZZ;JK}L(+k$m*.0hiJBKLz6_@ZZ#;TX-SYKb`)dVHJM~geF=\O Cb+XX +=rX0j F5'X4f^Ӄ:z^LKjaaѦD3hi(Y42-̪`Hl=F]ӉmwJ@X)Piʂ>9,,RC @G 7G 0 +T* jF K}J6XivVTZ qci ;WLJ@"ig i{jcFJS( EJTo"2 `?֨qXx,4UHiZ [dҴ/RqCfJ{צG5W` ]bdH~&(i? J'o@v-H5F;$ xp3iH@&I5xLPBsyɪr/R, 4)BZ{¾@;"M#5gDZpeBt2H4JD1.} ^F%-Rh. zE)gfZ4>kf4hG󸆧x! BH#2!-)ɵ - i4B񜐆4QDHC-i(4L($ TVHSDHbLH;ཟHYQT3ZA)Ea$_i "m+v,5ifi~i, "Zi(F/" 1#@=DFDHӍ4׼@)44YVXgҬo@wN'S4jx&@ZsڪZA9K  H#g6GCЊ8QKGJ2hNl>L 3@cZD⣩f76rG G|qDO`棡v +>pEHg@1WrBuDFfD-Rp_@*i{-!H߹5g&^€B"#Z"09< i +Xd9im8grbLHcywfZMH~i!b4)<03 +D7 yuE!gOd<{N|R~Δx0l醸  :#v߅:{W#f< t<'ЙJILD~GBm!g'L_L3 Dٶ?a-!B\'l|\n0:2LwیmBŸj8[Jf \&W +O2L Xt˽ +:mP-&P'zUi`3v\3ruF=B]n0L3e+fOw/Dn+KTD9xf[H8%lFR̦6La L1C|ƘM78^3~Xbuoٰ "ſ3, 8Y;4O22SL-<|1%S˶2m,2\R :l Y )Dg$bn`Y02m|2$R2GWP@fb>^ 5ٯQdڑs2lWî#A,J&m5e,[AمXZ$\JXQ3L] jU-%L=BPfA,kꇠ4ˤ'DˤȊebT8 WFg-`u[:LW m%!˖ed iVe̾nߘl YXLuXʤY@.5Y&m&0=`͚ q6׌T5Q&͚a$Y3RTlvPT[?俱ySCVoToG}n%d,lVE4Z{F-onXR8ꛛՅ1r"KUTF[d)ӞK)]\c0D@c;2Syf))v_kw5Y]yL럩 ZbU8EĜr3:rGzxzt/}l 1iJO}7 & 7;b>iAEsᵿzi҄a'o6 Ds֭ ͼ=-k~XxD2fL}^)uJ4VlG^q;T` 2[-VW s1 % >+?N!b^f &o +|8 +ҥoB'hR^+c2Pu ._?32z1@|+#1)c6Eh3pfц9䪻3vK:RL^Aa \jE㧬g1&e,fZ;$~|'syВr|j}T8¥ɷg;A0ݠhᶀ;Th؇8i]O}5D oRO۪vRam=3!GERD/3# duɴ%jZ<熩 e +Zvu8CvdS2M10aWgk@EX05;KJ^{/C)AS^) [ ,xF ҐhpĀ0?#}Sk ~L-!xµxKjkUݓ%ɰ/!0`j12v|V y8ǢIpvZTW$U_`:*,NoBo7'}5"QEIR&oh]P-vNn7e^)΄QzTpHst߲Ť~dE艿Wpc +R. Ǎ^oR.{HD3OÙKLKlpMڛS|:}[Q6 ̶MZb9Io_ĥqX>6*`;>峎TCI +ͼR;HYH5'P*ԥ(8;e16OʰiS,}{X;Saaue46'Q{aw۬jkg+؉8l+o_ꈬ˚y;xXvc(VO&@mUrnӋR&xGʳoJ)D#w}Erim~RLgȤ>_:6%&͏:!FQLB?M~g1#g3ն: FOwo^j|^Y;)TK`aN5ꍓi`އY:گkMUd+냟&_[\yކmUfE'uV9XF\ڸQoEg2< 7?mג$9{z}#@p8\rR#hE"fAhPⰥnyhVV Bsf?#bN_'΢pݴVryrP~yT"Eu*00T֐Qc2޾N:tɯȒn %B⧬͑;mUO@[|O.,w%\gͿZ *LT_S`e}\5DL)GseeIRO3ߖRIW{|r@oGݜmd[DdW- n[,ңC&T-F=Rn}r֤bYI%kӔbsKH f\hWkŽ،OMWI(5-lއ?nS1vQ1LuWb;=͗?k;-,lG/"7b T|,,EҁNͽѲIjKÎWL3* -7Z ֮T]vzd}F|SpMke]mk{ cq xr<5rh1ob%qM HvTTꩪ2v&Kw\B-6wX@wPCQMtNublveIۣP9g9R&m{9Ow`g7*Pj3V).QksǨUsOJw/t% lpl&ZfvG! ؛#N߄^C e&LU=~ArC(|8es;9Q͗}N'KyFcBJ&PpB$MUIU<LzMœUvbO9(osiĦh˻LP$\E}Lo}@Y𣏱e3˔,z?Y&9A\~ol%%fЉ׎Nih, wK*,2c2SimFJ)faеVKGys|O;+x<4H泞2eKC[nW( KZIiwIxx^"tyfe`vꛣj6 _&kt٧b~=XWe9XֆW(5W65[в 3@a <[e~B'(QwKWTn.DbRj9Fh86,Lcj}S9GEF`;AvsTcu*{}W?EiYY;}(Z\vTխ)Z|^yfj1wCI -c e 6A4L 05o!Flg,'(u'pm1 *M;Xjj6iZE_Ë7>[avRD3 "_3J?ݓV3Iy]z1tVMӆ&ծxl$X=6>ymR[y{JC\ +);鶼B{(NIVfwki? +( cQ,]vVئAP HXSQۛi'5j-α[Jj96!Rx%*{lޢߤh=ݔҶ@l֎,BCw|_p*#i0EiW ˙r^2 l*V+V<ۼRO/]-0q7}kb+~%[Si-*a&@wKwX tRbلG@!$jݔnK1)Pܤ4{Qxb_e?mm笋m$PO^[ډq^.-]v^2˄əo'ELvF!b oܴn1Z w>,i* [%^l\]gR˪sEiw+m2`n86{ R֐VCOXꆵDvU^3qsAsәlN_>=}8"}H7Kނ 0G.Vi?d"D;$d~+$A㴮2tO'hchuݞZO߽|Lswhv:H%yU<`MgR Fg{uCg4N0LPFAi?vO=ط8ss@kԶjQT3O꺝N$ZHR&礭T,:)oݛ7U)s՚'Ñpw'O9Ϸ;˕JW\-R,p* +$1jN&W)UuIbRؘ$LC JC zj|H1ϳ'r{"M`ح+N#l42ZȻ- >r<< ;x#RIUa<^dj{H$.3lw{4ҞGQ'nثkpt,ɻOډ0W_HOQF% %rn˭e '#ON\Z\~d4udRU'ErܤX^m>!@r5aS aڛC$0{aQJؽL8UA# +8UʤeU) 2#̔(B8j](B$R*e$A,9dQ[= &}DFcDvkODS:;D]E-=J +&q )O69VU$&ĽVI0/4nN荵.nΡ"h[]Tr(kꮨ唡ʒKb QKʔ5r,"wp*ԗYL}PAPJ36|LwBu)BS/A)i_Ngܭ $w{$TZÒE I%QeA48h,'qMKG2X$Y~1L ޶ݢW}o'FMn rB솬zubXn'n?}wP5_)qG.dgIޭ՟{e7 MhR6rZ3p+ʣA]j<,@#DV Y8 u@ +7ԑ '$4~ˑDW6vZ(QL鴔 FXvZ t 1ڜ̞+`9̭j48 0|%`9} +jnH%uP=+ƞ|J;ɭNl% ѫ2gMO BVhؚt XkMݣ)+#%B!ף|M8сI5hDu[̍իξm?rkaz[qW(}) U#f ̑* |OP'rԘȩ'z7-1T#X[ruKHa,*pd24xۆyTTwdN6˕`o5&[vV<`%uHiޝժ%cNFmd_0|gnZGJH}њ֣[C%NTt?NԈXvP| +0)'8pX/ܿ߷5EC37}S3Oњ^ة\^3:NȻviv9JM:#i&ّꞼb@>)'%Tvǰ{R4U!'YSؗLDopWe3nqD71WEI80(Әc+Wdo4PN/1XvcPLP&b|eF8.s5ilUlAC,Jgm+RK Uzw>[K!KaHb-O 5۵ c1n5ue.0:0Ĝ`j\9/bes9n@&l}C0o\*:5 +Y1-5bEERdN*NLTK[<{d4qܪJ/s5zdN  2+U[\{BPko<$(ݣd4q0樏=Jm7 ++#G "8HI~o Y+r'aN7 wg;=mj 1 ̡|= $ +5SqMwgMPB%[y"2OZwK9'bbʸ5Dkb(*eP&dyVTv(,C;)s-k+VgaƍC;ᴚgMV%s[{}TlJśaݫ䘰{$AĞcxwIumaq"Pl`x5J9=sMRLJTҀCy92?&sC,#EpN8֞\qPw$x'%s4sz$<9qr,㢩QjI7Z&)Ɔ;7SIn};N~C7ک8>-B1 Wܶ[f&&PƢ3G[āE1;V^󖫹{swIcT +=)SH5JF7# p۬ 6 +Vl +*c"kG@5,aGt`sRt|h}I7bCŒ) D{8_\IH:/]C7t3,H}rOT o6xw"%r(vvD wߺ") +P9NS9ɨ3Uq<2qE"P\wEAUq_$׷5g@A:֠@۽wle7 N14;0m5i⡙evT'c| +WU5qv5km#Y>LF6_4;^˷[kFv[kXshof6.4p7_uft ۘIOi+{apEbi=>qvR-v;YNvHZE0mX}ٱcl ]--.TdL_B63yOv[߶l;oҫF+%`R8b= гk#fS*}3Tx,Zr[+T">-iMiLj0F/kQ[_=@X=Z# yCj֝CLU--עpoFsP m+T=ZdY2hTJȑT+G̱O6i߭c eDUV*s+gLu eP^JGzl~,M }-=?rzb"eYRK]PoqYx@;+Ee5r0ɴ'3/#6@Ea\g,@i*o@uZQrN힭j&n%P%gMy[-W]^:Ư7G!Xη {)O+8;Y`« I"ʥrOTucD2#X͊ΊYm^,AU8b; #C; /f7IYZ^azD{[M]3{$b ˠaP_o13#qpK(t"\\Rº26}{!ؠɐaރ{OM/1oRir^xS3J8HsQP;n(qpjqwFGA^ +BQfU;άo/z?k NjUW];N JO;ˆCI;&8ZIɠ;cAđΠ;"3N$wН';-5{AwdtAwk'N6t@w(}tDZZV]mt'kIh\ tW`64EYjS ]k;r; tʠ"qZ8fE- +W@w|;D2Nk"?fq@wWVtΠWt'suM%=讜(#@w"/#q%qZ)ly۞[7]O8wXʹ+8WΝ]-' +{i(|rPNɹ{1Z:VIk*OV[5&]CIF>;)Q&qdΝ'Nl̹kzܵz|¹k$:9:5TsZ}p%q]9wR3NJIyrZ=8wfL.9~ܶΝ̹cĹk NjIɜO8w 箒r@~r^Μ;MszʼqZ8w(sWխZ-;)sUEl܉9wO]Ug Ĺʹ[TA +~s&stj:ݢL"KJNjܡpqf] p*/9w7Νs( n/dΝl'箊8wU&_Me-s|2s'fsW_9wU箒Mι*ĹwY9wPʹH8wm>I͜Fws]ι9w(sι?V]ʹ{1a!Ӈ9wJ.ʜ;Ν̹SiypP=玣?8wz2UM<8wL%.Ĺcܱ`O;[ ?8ws8w;Ύrts7s7ɷ9we=9wZ:rixr^8wpwĹȜjEĹkJ.N&IMeM58wBNeΝJ䞜;Iܵ^8wypP%qZpf Ĺ24wι9+s re\-EN;ēs+s@s'TVPQr?8wzN+s7LNɜ;o;92a-q5Q(qdƃs#3qdۼsߙs'ui}p Ls( ncN;slj$ΝM fHΝ+ήsGh0qdTVTsX/;,wOdK;YOjĹSsB.qʜa kJIV'o7] tU][ƹ43X8wUDs'KCL;SVΝ);s8w(]"q$ΝsWձ*qzrh;)s:9w;%r̔ĹfN'N Ĺ=seM58w,sWeɜaƹ{';s'%s*;s'aܱsW龷r,ʜ*̓sWYF;)s">ܡ&{;U< eqrr¹w{iXɜ[vUvӃsWt8wvWݢ,Fpp5qdΝ's8w(Ν̹f]"~܍{nĹʹjpVΝOΝ˙s5q|r +M;|s7s7U5WΝ<OΝ̹9wut%[9wR3%qw}.fTVPNE|rlB^9wr&eT&nhRPhiP|rxN[I͜;Ĺc5q*9C+NʓsS˜ha %qzo;䞜;2NnĹr<8wR3O +Ν]ݏ7Ĺcʹ|)d9wSY9w;\2ؾq'Νsʃs8w+qN̹S(¹[ɹ[DUK`';**qj3NOΝ'NVNĹJM58wU箞';MڙsG %q;יs'OsX_g8wr<9wreΝv|r˜;Q3Nm;JG?:βr ; +Gfsjrڨ\9w7%Ν'箩?qh8wOj5벺plιq&ΝĹ1-J;^2箵 p$Ĺָܑpɜ;zs<8wX8wlrp?8ws&qp>8w<βΝ^'P sG;BܑHrw+Z9w4MzєiH;6s%JysGwĹ+N7ɹrh8wre<9w$eTĹ%;k6Z9w$;9g3pǃs'5s% ) sg +#JrtsG$sy+AEz8pJ98wxi K6 *as'1sdʃsrlsGxc8M;2NsA=sNs8w"s5;ĹcN6L3,|Es'8¹s'eؾqPZsBvlp8qޙs8wʒI;v ʹUڊ;)s';ɹGVΝbQs2ĹS@)ɹS(sf"8wJ~rԕs8wI͜;) N>9wd&Ĺɹ9wONʃs'1qsιkbΝ{s@fsWiyrȌxp*s=3QιkqT9wa|rZ8w3s]S<0qts$mΔs;Ĺ9wR6kmA@ +Ν>'dĹ,f~Qr(CH;>8w2NN)ɹc8w5 +箍o 玑g+M;*J;Ĺ9wR;JOb+SA)?sj>8w_9wjrΝbyO}9ntuCfX ˜;(srJrwIsGMRqĹ3ʹc玮2sGBܵ`$pĹszsǞsp.Fsɜrw?8w^esg7)sȜ;;$shQY¹C8w/zp; +#8w[9wԬstݙs/"q}r{ptĹ)<9w~$ΝHwv%1;f,tDzA)G"n[IwSXIwdR,XIw3p%ҝVO]+B{8~p' D#. ݡ&ҝLktz'M;DmIwr]gҝt+缭t23鮖t*'Nj&Uƛt'IC]IwHwA$t|LIwZcgҝbtWs%ݑHw(tgy:;DCYIwtIw' Wt'ҝ^'N@&iݐIwSYIw;`dҝt4LQ1Hw4|h칒Hw>HwR3NJ&ݱ̓tWF!jퟐ4eet7ttL/>IwG"Iɤ;ԕtHwv碌Jt97IwJut3I;k}$3ɤ;&ҝf'ud")M%O3Z CJS˕tpͼ'Ju"6ͤ;dҝOҝ+Δtg;Nvs&ݡ$ʃtG |!LNSM&i9Iw4{fҝLcNc"%*|v|%BSyJtP&IɤEYHw;LʃtGJkm#ݩ#t'5ܝHw*%$fҝLc4t]&)IIwR2Nʓt18tKȤFJCyvAkpbG7]~!i8ɤN LÃt\L^%ݢ,NLkXIwtʖIwZleJCxtLkx(=6n*+nAXHwZ?Hwʃʤ;.;;3m"Me%ݙCMNj&II;Nj&ݡ$]NӣL;DBZ'] 1&+n ++nQGD8$%ҝƉLIIw(+;DIwR;B|~%Ma%ݙHD]Iw;$ ޼t'#t OҝK;\tGՃtG]"QwHw;{|'O;$ʃtHwk%ݍD"HJEYHwS ],'YwftG/ ݡ>Hw%JJbHwT$]'iIw;z3&ҝ%O]=7ҝҍ2鎚NLtL.$AHw*ɤNBtZ'BtWU&ڮd;dNW`;kh&nk'cWjNNU2pi'k&Ig@;@<;f/NJV4;wN;\YvZeםxK`5 {1aYTeb£+*po+4G= +CsPzM ]!qHW"gy` 3J*+GҽfMH@B'D"C:k.tD$I%"T I!v2tRJDrx &>tG%੤[tRq$ +$ٲ] Y"[ H@mo%ҕj4W1OZ!k]/u4:SܽOaIDG~?'NK;<60t*ZP_)h:S SFjjA'`< aMe?Vt~WQ^ΞDMs۳?s`V([i7Nye 4pP7ËrN!+q;Ma 1hsZL!rRF%֜&辷)oEA +sd +MUG̑e-c;rw:n:X sEce})mROݭ9N0W)%s2x%IhWZq0W}~$D`/>s(xV\!̹G|0b +TaBt/ucޘ ̩;*-J_&aJV9/zZ s>\ZX}="洒i10\s[bp\Xbot˱LcPa%{0Vw`Pj/ өs^n(+^nӂ¨ +l\WEˊ+ hXrڎg8'F—U\aaMe uhCop +r5c;F1rCXrC \>]@ +Cg>\NaɱC&+\+[f8gAAGhrRq c1[PFz61NN- 7SJh av,LEu@ MWm*vFs{-vTVP[P "5qeh9f@aƖ&T-ٍf>劼"ꓱFA&B'm})ٽ_k*'~f{h9)4h9zj1/ZN <8qc-W;fleAM5r8OBέe΍,WICd9\r&:rG>rvӄdP4-``Xu.n$+B71SEL+WQqWNCGWNoՙrƨۉ(T-㡤1 +J\4N•+f +:ۿ3WN&^wb\&B?v[qf #̰W5X93J_*Bpz)8rwD9 W62j'\v 'S[2ir5]DŽɝwW$XɮK0rO"Ài78+CF(!e.olrzsfR t~|+.Wz^ WTC.o{{ߎ3 +5qRKB͂g,FRɏz&DZx#Ly߫+łW]q0s<>qgwQ{jQ8t rD&,W +0L+0?تb a 1(qZ6oEz&(c⶝n|n( &n+{t&)EL'Iٹ[+&N*ġ\[8 'ʏsx +y-ƒwny|hP⦲R8cai1Mq[fn'f^8"1uؐ{CpkqHTVHT WT%Š!qrZX} +z'8c;d j#E@P8͒ qvss Hn-77' $fWzz} sen7o\':ű].',pIx888Wá>pR <V s=Wk9n( 7Õy-o;̈[˜`i_#6@N-x.iy +V {<}3&ܱ颺Ӛ"pCXpSt\\2N( 2lmu$` +,8ܤ@8CA# kw48pE ~*SNcYєt6CBR/ +V3N'vNJBH!My>(xAZS*dLTen{ %ߦ7t7Q,7E}7#Tج"bQfsߴ'+<S^hWfjfC"oSYoSuUFiڔO3+jJRUVW?c'3;!7oR%[QoZf;MwS\^&MDVw>[05&Wpe2oz9PxN[9}M]  [U&/q\2M BV#?olv9\ަuV.@⾡!u# w FBYq [Ռw¾A`r[e}Y͕@iD}SY4}Dto&;o\}m6cI I=os?-7;MI}7 G's78 <`w&io5oh%kj4zgܛ '쀽im̀zkTYAoeyB 1oa3 +y=`o2&ěǤ L- gh-#*b2or@$n&M +xCoŜ"LxӉz7/\:xÕ`G^orP4o [Q--'MY?oz7t_oj>nzvލ_nTk4O|l;ƕ {_?Q2=uuM6Pdɕvwӡn`D0Dw"݇4q{GDŽs"47mއ9CHnrσr2Q"dɯݛՓatViV\|7Ł!𮽹Xmj wNk\08m3OcmDi;*6pH0ڔ)?IB')e"m1|kjlwc( 8:pC32zF}TwY|fylJ:;y(ڡljveb]9lɷc[lzUt/mއL]ϭ'ȵAc;}:`lI,60 (6`A%؈*tă]GWv6R'm`Hr^rւp5 oED5e Zw`U}^zm͜]L5uކFg߬՛ X]\kĵ\S9l$Z6vI꤭[akj&^cZnI(RIZS5$;gMt;eVʚ8]倬5 o2!(S"k~jJFW;~NϱtWl"V+jfia@l5f;}霭fVj;'YMWjiudR|Md[6BGȰJh5T@  3h5Z!n&VO|Vy^M&wAV@2Q$et{unsa}%jzN%yH&uYjE!')cՔ 07jlL`5-`BW&yV06V+du_-J4`5L;3c$O1Tgՠle T5dWTSOpHaHT5`U[H.NiVksfZێF&U+bU#܊U+=j2V)a=LU+Ĵ]jF&VM{ڼX"@NbRt KE +p 4ٝ UM" f +-o vX5TLI#%Z!)Ksd`ڱV6x;V蔇;VpX.X5 e:V{US1#޼1 UӠc)„XҼ=H1`5}#JVC>jRUlFٌEh.V3jJ'=jJ|*a`ՈpWƯ6j]/Paªd`ռpX5)+VM<Ueſb Um1j8 aH 3 8LcU3N]3VƣX5m`=5ÂUSI,VFCŴU+%y`(`!qQ,dŪ'X5HAX6.T5)AUm=j#(jP5oP5U;%RHH@W 6AUS=VaCnU+R+Uͺ>j[X5)~&. Fy:̠\?jٺ&Tj ˶tqB*V2ow Fb8ZYjyYYaNKM;gn`^3@Jr8pJ @~OrLd%U87V \= T(:bEMew-ф~EVNxR4"} ҹ"GIHj-9!HjU>J̃&KBEKMR[6`{bFRSR[q 5XjQaqyjZ"xjSYs6yj:-8iT85PFKǩMaũ-HZ<ZMq:q("&Ϥ NMna6MM`,DS-l9VNScmZ4hjBbqP6R 05)L U'K `b[l%䯦.HjZ =G9oԴ&>@jud0j +QPu5E&1e=oԺFԁO#IO#)vZE +:F{K Np: ?3۝i=0AM`2_Kf|6xNVjĭ3vyKrVN&FI/9:~ ɕ6xl^#.!Mi.DvŢy]׉Gd66WTO:LMU MsY!k &v>q&K"i>R<[bЦJt-$4LXBtTpC *FqGB/|3w+N|3^|3@;̖ɗ\fR4)֭=b֊7 +QL7S6+ެtRx3)$Y t3 K,fYKGwiQijGt3Ys;vA7+_{|Rs͊|m?7ʊ7jʹ(3zA`hj@B7SʍYb76bp3f%"+ q'٬^1d3-|Yxh3A6C(BvE L'Jc,ӊ;=6;6* TVTmf?8DLH *qG mKm&(mVXLeEDJH͊F1+%]fR)ͤX~h36l8 A6+P6fz&s"@MeaM1fDaK1ҮulAF6n2VJq@4 +:cчqlSB7#aveI1f/,3ۑf5e<Șl3)Yf:3S)#]m6mfj[{b8ǠJ*nVH? +-f\*Kgꠛ،et3yLYpHViML n&GpEYfS 6GlF7#+fNAk֫ZN~e*w-f @ZFnW›k+oFr-ʂ7j+yR?JK v%c_>cm?k@:L;O+P>I~_ '`'U>omHOW;BOP)!}oWOe^vCo?OL8g<ngϩC>cCc[_ 7w7-yoM'mtQ\?ɞ!ómcU%"GWg%yUAM:r,()k\tb|rSN7JY,Gwcn +("o xtUB)%W 3G 2mhuomt_sH"$bAZd^eYu~V +*Jc&J:jv+A'.{5iԍJAD%MسyYnDE_j:J;8׶&bq]x<vDvZXc_xݘ?A.2 uD|) 'vqx":D/#}e vJU.W}uN6;2Dr_g6 G<pniXU"5>ɹɸ̆Ǯx4TqX;'z=Oxlݎj7QM;.{3KXxp!#d$¾8]܊}-Io.5qQ_+;e;n .v"{qCmmp鸎Y6q|i+]yoX e&ӥ3` 35 kM֜7_C$Ѧ@.1}YgfmoeiN҆ڊ|7~{No5ZȠ_q?V}:خ/ŏ{Z/9_=Zmjv;T<(> }N\nQ(Ϗ|O-z`h|Hߒ};L3^.gU{};~Իףct~qlQMn?яk1n?};G9.fcǏnN?-6<~~qlh_7OqA3$6b_o 5׬ԸgH7XQC&JUud|~SR-{R0NQ˸x=.~n76갭~ _Nm#Nz74b$m~dB|_<΃K:Yyqz4j]vD}\sg=D?=߸Mr~ۤxOsBhNE/~OLk{㦖ǦiKٟE6 W+Bv꼏UMmy'M*vZoVn? bFgLoYv^_ re8a1bPs|wR%q+u&?"j}Wx6qL9;@Ze6e3=ȶϵ+^!;߫6?]c|O#ia?w'e=8qWlݯ)_hu~S(|k~ZrP; ᗐjfN 0|o>9ض-.CTOޡ|r|z^~0Nx/=&Am|ey]Eq+q緻 +~=?-F >(LFh?׸~SiUۇ㵼40ztuwՇ9pڼNMMye/Dyg@?j9J Go/.[gQixyƶ%^r32Vxu :JmV,DWk?vO2g OOlWX`| m︉o*pN)HRDlz߱:h=Ak1ۍA>s&^䪿q+bςwf5΢A 6?]6cc_3 g*;61~H_>ø%)qܳlkg3t2FxI +;ѷ۟g-Fꗹ޺ϟ:ݽ~Y7σ|گdy}y1vV3e5xdzm7Ǡ61m*-5u㍯GmD7?/Mx;hƗy2yqvmfu;.з ]UgEgm@/sh8#ZļiB/9X6f eXΜ +}Z8]m炙x1V_ (>+ON0&BkPokȖdצݬ%7\MO5X>&7,o@=Toc]C| +e!/2M׳35auÜs5Ƹ_n`5)vU_ν>8^Ťw\H= u c,`zk<~;F,"KV\`1^ga~vո,ar-}"E˶Cʚ>{1x1>99lGZ&q㇎k-qa R5=2o˚ϩc(wpi?Ogxq}'CQ;팱vU!υ@L4Ўцh_vXw1]b`/6?OlV4'|~if01mQz(I}0 0ƀ.?tΩp+:yk,rN&ΥeXM/d:{)XS(NjcǍy:rau+sj4 :{[2BzMd|v#6,q6e9|M,~~Ҁ/|Dp$&r+eJ&~~?6ֈg?:můwDVqf Qa!Q3U0d_t^jqrp{PZ.ch(O1qPv <O0/3v!1S2}>=1?cR4X0C1~90O1}}m &mTL<bM<@?6<a@>`~z=*K4*yw]@},u"Kw8V7"$0ܲ|@ܴc4hg1Sp+p;Å %V1eJc _erQ`;>%ص^o )9C)DL!zXc/qpA ~Z-#TYH,cz}[ve/9<X \:Oe#M]9y˧ VيrsSm<ڌЈ"|:3\ȷvԳA܅6Y"x+g(/q66;=}y5_JdzBcI>Z-csDOxx<:Z :Xc<2EGym4oζ12^̧y1j\m4/ԧ}|@6f\3PUoybbW/+fv?w}uy1摓cu\/tߒVe3۱ q;c"gJ-:̣sɯfJշm=k)]>%߷J^U'H1 G<+̫p tk[jqEZ_Vı){c#GJ^%_ukG:lx-ȩ^[~kJwOsTnytr?ýqn.S>_yXxA=ɺCPvg%gl{mkPzuYF&N_"[#r3.^RbOa7 $ՎtCtR 綑CWg~aw eqG/F @gqW5W, +yfǷ=:u"E> tp.7/CZD/?ڴX5 1}QQ2Gz<>wiÖ>nl'sn;1pa5nuAw6jl-5/|=>nn! d~wX$|-ywK`X#XP,GUԺ I>OHa0x=ʼoFv#9/k>Qusq_(j'a ~ aݓⵍKn0,3N7@:FJ>oZUg]^ңA>ri}$61292ݛ5 +.{\ kq7/{_\qxQ0ʭ*kl(䁖%Y +h&&yzsn7mxAUV.'Ͼi Qn$Ow! ޹h짷i&UQ*7Q4F Ǽm [$TB pK GTЛȼXb +Ts,6[:RiTMF('-X\ h꠯Z;dyض(LdJ\`^|4֨IjƳp1t-b}6,FCo%D՛/L},DjmJffJztt +P]BI|ʇ)4:ٶ e4`o 7 C zSPPQ! ЅFAWk$be3^2T %}vrw*kd+5NIgkIF`TgT~A)콾aԪGp)W:@HN 8,wԘU$Ez_ǵކEF15źXMD7骪l8f$=p %R$c}59)9Kwz`0gBPs+m%zgD\躬'Um79?R\5mnMf^ #͈Q !^U+(.v5oDh7 ɜݤN"**vlQ yS:WSuL &n= Λم0i#\ҢXGlƀPZ,zCHlX T`Wih]LYHX bP'0Y0).H*yA\7l;S4t`OGDp4êG +&܎`UZ%]&t ﳱ[Mue{T +<6ĚF:3Eˮ 4 &VKF$XsxRE^b5d5uDܔ AO[#%a&v4ktȴ%X IK{W7 :ibZ\Vb隚Ec*SMBbbgыȁHtƖ1l9mq"A'2U̓&̅jˎZ[`mo]gX! ɼR8l`^[,HӫeWv2nHOQ뽟(ؤ Un3KHi Gːd0`@ "[߈ ,.Y$X}9(ɥ? +d>i) +u*\S$W:)5yLpDܕQj,Np0:[,%M34PSmЌ! Ij>=64hR-r k4׳Y\\gkmhhLşYD5k;r۳Kp(Wo&&1SyxL`8*l˪--Ӯ6<%ZǺLŮZCh9y{,݋тXB) >snɚ2ʠ7k4;IO`l ;iRS(A7@sj}қ-V _˩[7Dy_hTmͩ7^+,h=;! jm0ZAg{NlvN"ՅΪX^5(jDE xj1>!&~h'@:MܦGɂP.La)U18]7c$,`L90rrկ,0 D4ʹTW]1L าFs(Atu5/M՟kQh^N +5bU]L#.Z_t`6JPG3ۊ-cYAR_}f)d6)pS>׬d 6&m\#&n`LG BnWSޜGCm)̉V5Y$f 30^44A1@G3iٚ +>ShI@rp\m8³tKGg΢e(WM5`h=X`Y٘%'Tg`lX*/̤5w*p쫚f)*V1֖baP)N{3 ^dG UE;Md姦,KS^W+8OjE_$o:LCsDGMʼqJJ׹fbIi) +6@rI}:[g.WIb`^O՗\ںedH"m56R"N}s`=#Kd^fych|+DC&"}-L0[D@LA [VvP$*C8:ÓG('N }cUr[P>[(:uAB[ +kZ65W:PЍuX ,'9ˁd?Z3iNwvf|56Ԩ0M)CƮ& Ia߮X#5aPSxVA&͚fiqi l:޲k}&dEk` H7$ǸFް Mk(j@\pr7: jd?U3h ՇSc5EFs65с1%Cpeu3OVu\}<^⳹fV!#7.;7ٱ3lW+}"_0hRMhm+Jʐ\})vX1|YR]K^1*$f_dJ?QGX+UL1,&~ qp6&3NUdjV'c!rMO$r +f()n}Z[Au`75)f椗 06Vkm|ॴc_?kNAՏ$05ezP `]" P ]s + 4'ly*vlOg$rꩮjj]jxzSCK5AEvQ׏U*`X=\9.ͣi{Z!OVDЙ%R#(4r-iCʼn-8K:G7VuIfz{y̘i!EA +JocWy.n2xx +pZTbK['6Gټ"H-Q~,WP7 K Xәl +z.alZz.>&lώ]e)*p3jt 13H׀vhwA#X9{Uʕ3`o倐?9b }:wH`ԣRA&0YIF +'koQkgUm +AfD]A곹^ZMw~og Ѵb@Wy.+5V} lkdzȳFIҢ C iB%,Zn>Ih &ͮ:EtWKsP5 [`-fX;fs_-3?Y SLZ6I6[.4"0`(|K>+2Ci7rI̓ +*hʉS!Ygq993ykZp1iA$]0>My0.Zt֝$bDl_s|O܍5FTȤm8n ua0;UD~]5{%G j;>JAСfs `ٺIЉRaW5O kGͶNsu G\^9eR-Ehl(=Q!NA1Zkת&a$*vg)'ٹ*0H%NVqXA DF<CX@2o)F.(A@ 7f1I} 376@;4gt1P;a\6s]ofUuqq8e@.պ~V?LeHw<%fu +e*ٮ->?av@o:cbMVn5Tbjh«%7Y +t5/SY!.)ӳi4z=WS6g*Eɤ1esG꧉A*Ըv :#VVb-`Ogew\Z}l<}m.*buZJ5-ì&#&ִ=jFsZ,'%$ݱqbvBUdŕ]-c:fQ*ВcS.ZAO6n9KJBs0-0N͍R**zZV +ǩj*G|%4jBrM3[bR$nb3cMiS0摕&#r0h +V ʃLI;/k=8WcC͕X`*ٖk[fH"b-dOphLto< +Lh(P5|rEY~aphcSG +]SAQYo;GvPMD@lYm6|#):W:f@2ų4:g3huӨu-lvqeAF1Hz 7i8-oZvvX-/ճ>n1}יN6+ZĂ7A_wWXo7GwPkȲ 5zh*sgۙv+ EL$^ +s4؅w!u7Ь7}qLR;!`8>]ڬ2K e:0״)~{w = &%cdi']g"X$kH]Q q{DoXYRjnfՒŒK8_X&Jh/T`bIp@%l`-vw8ox{q}wqёɠ?;u/,<_w'y}_]\C.:*Ӻ__z{{x웋׷?o樂9Kur}qV_q?;yw|aH&xLEOyEߜ_|K|MO/K.^'Yy|>ywl7:ѻ[_xϭW'{Y?S!wnzwy~}vVȫ[}Kۮӷq{ޕM]o= +qnۮ홁=k.N?ߞ`<®o;GĘOrنg! xNv-4R k+ǹ/nݞo.ζ_zE7i%7ߝߞnG.};Єŷ"OW0v{c_HxlZ,]{?n='zyqӋ=  +ݒ-|'z^t8¢=W77ݞ.'u3?9ex논*wuwc=H܋ +{}qyc9p[sqosǹ׏)"~[󧣶@궧iO4ȻC&e_mz67~DgpkK=m/d>j_m/D?uLzZO gzU imGJ'|@a_meυlCv] 9|M\h]__ǓNP[;`?\tۮL(:llneC$ +IĿۂ|s,ЁWЁrrpG8szvfU+s[/닻wX\}MHu{p*FeonoO|+4y; O?| zM;ݝ^oy\^\nDsvzy!>pks [^_\[](fwf_s1f=;Eg6Y3pf{l|.9l->μ{g_>pf8~38|Ll"?_8sg_s?pҐG:g\pa_<痻%)>l|}EKWMo.mƂ}w~zN7! m_sq endstream endobj 125 0 obj <>stream +vyEwujGߡ˶zN]~.M5';towXß<QԖ <Q|X-Cwh\vY4ayxpzNĩ}Qnrsۢ=G sD^]ڈ=Iiے>ys~O;t4/޼yu~F|=}~i~dz_W.=o tf #|.jʉҺw +ez e<[ϊbs) uv6_|WM'hŽ1gosƜ%sƜ1goӍsԲCޘuٽ1_1<EyiqIO2I4"Ӌ?ԭ6/>CڢZs<~ysl'^c:#O<Ǯ!tOwn+/6O/3Y螅+\+\=9QSg=} +t_EUXU>b;S~7o~ϣ ,\uɲ}Ⴇ% s DlvVE/>BnǮ|ws}^KO{駓O&<}WJO/2#S+^!U}ٚ)~{9| ω^^> tB,!g/䉳Q뉳Џ֞:ݕ&9螃>|LOX2 9n-^jeݶz3t{k;=":-Cm]9wwB]2m3 O ^n  ^tYM| Km-?"G/ȃxMxGϵǟw,=2!i_38~ iJ=o &ޜSga1ǝǴŧuݗ~(oX`=#vu1^}usyߜ~UO퇃wSY?ʏ[@?Ɠ:8x.p܍.^W +9 6yͩ;vC.ӻۃ#qa(?ݱO幣i,?;T(q7C.?H>Nˀtytx>2 ǡ }0;yR[ee@!LL.k {eueTb?;Q+epre]Ww>p>քSNŽ8ḋRa]YlX(g5veo01&cq+_)1IDγa0 &BR>vR\~c981bqSQB<^p ހ87 rCrU +u+(X݋9es )k؊!'>/x/Q= . FƲod| r, |P>@svsje2ή`~I>"D9>zPanXߏbL %~;bdy %Q`$se z"H&25(9񪼖qRp:f%BܟХA>N3'E$ +qX$(". P|(bDpBPY:0(:= + +~!> V+?;ظ?=\ty v \n]ɝǵ/4*HE~KuC_. A~]m +S3Ŗ ˷AC-Vg Έ + +w~r > ! { }]MdIH{@p.Bă*3)|9\ \7 Z +9 +}SWŕI.{PwNkxe/zhyjȹ12xGf?0sv=hа f*{H'ɡA8#_$ *P"EdT\Jt,_Ř#ґh!A9a&+7"(/bn`v9𽲏^60wJ:$a)Z =Ow#P8fܸWvt닓qljő`3-G(/eV rE" sWʾ~\Npzj! | =S&JA@ H0rCNS ØEWvwƱFzB#_9!XQ`<&RC)Ang;l ܊_O OA9`O~Sׇ XHgؤWH -&b '(c ]PTm*(xo׽! +B BIC$HŤ z$Jv׬+j˝1R&+MT]y 3XrZψT`Q8a@nH}_*"JYx=K~X<;$he<ϸ =ŽDQ`zo>iهBa16;!T,8]\, RJ6T ]VR>{N5%nk,H{A}˃֑#.mU,妧ޑx iW%!eX.Ebok~a.at) W"gXDH)D,xj} VG\jl [w*@:7E%qakuw "@:nPxUP<(\4Tyvٖ‰ZBTP/wWt ]`wav_bFB̏>ȱ7 N=wshƀά:S[æ*] F+xt9ZJ-46pIFR½& @kZgrǕ(0hxϥ&r:W,^V v Ƴ 4栎9DpWoQXa36HY M;܍+ +X|r9r?De\ m#z*l,QA&©ypG|k=V8vg+`m^YVmBh']M;e@q@0ыǵva^WFmR5O(E欎@tY}Tɮ6)bš$8ĎHPH݉ńg RV0>-k=xL$:=;,QwE:) /@d ȅS\k$yi喐b@IZP$h$H<@'VjGx7%g?XZ:α7f-=(5WzxNԕj+TC(FK@XoW:_>E)иdS, +L"N Ve5B>,1|Pg$~r#?MSO<y>:kQ`VT_;A5`HNTWkp3[Pq  Ⲉe.Gr$VJwgmSYck: (@ddu*ŁItլVpP_PZ6ͷGd4]g8E-bKe!F! +ISRO#D([ΐ X`pgtvD\ȜF-VʧATs$:wB)ڽr 4JV@9"t!PA`xA)z'[ o5f܍=g߻ɼ鋃XD63,CV>ua 7p / #t cg:T9X*m)ۙ,IiST^U/pnK˧_ x'9R++;#W/v\ @`82\'EZffT@JgPW Lr?06%"HCQ=8IpJ)Gyb_̷~u8; &HNL +Ы?[S +$Ddeyx*~c!7C̠ 1@ FDD%Ip"JSdO/3pq~} ҅L\ &/C@vGm$ԆB#h>9{`BX;Vވbnqڛ8G6Zy啥-xi,ۓNYx<.,liy-Lsk_bݤҀW6ja@!/l,0soHcߠ. + OkuXf*R^h0zY?{yQ/^+ Tu `>BkK tl]0s\h-NAe5,zFa.L:8~DzvY2\0ˢXfYlXfj,39f qPBb@6Tc+-˒.sl/>RocrcAr m)qG:g3~t'!#cV%0B1hYO9ʸX\T3h\ZE]tBXf"0:Iݣj'-2`ACBP % .%OjVԜXUJSYH:"Y7UF@D,p%.Kba;$kEcEd$%^#.AHm\<qsq*eA+ 5xr *xb@1Rb:Gitё/rCpB}RiQj^Vr~t߳PLKy_3)@DNW+!F?&"@u>TP(![8F`]yXSA6ag"e͒#Ekaf umu h:8"N¬S6JL` (9 kv@``2 +ׁk݃ +j>ŒJBdz iEd*5/֧' <:b@gȪ\Q$)޲gb _~K t&m&g}̋Ģc[H gd%|({:^ +CPف= Yv&[*(ͺ朼]3V2댚p y"7Jp=f_8mNQxSt< +YpjI8i$= V~[OS ̉ NE;ԑקPHYtd khAAyў.-Ӑrnf`GS-Egg/S6<bEG!Ohr)3m/{~ gX1 P4ɌT'S֑qf}dM!#,PE!SJUy'9NNerβ#faѶkOl  {:' H1A"6-{&۽|KIdt`4mdzk5w^3^'P2jf/֧')RҨ_~?ŗL%Rr|wuq}zw_*V/yT_\%RaA +-_=Z/קnI2K贂Vlg__Q׷/ί7f;+;2;ڰũllaG~zxGv<~cgOGmEIx_]{iyKNnyLݽ_"ׇurcŪxWQ{]p:}Z Q'W賄(Ӆn$duǣG>qjJ^+_oˆf3HZds]:]z7}a5mV]։i7;c&f;:XP2q;9w/޽-gr~妅O/?n]/?n~5(;~;g77ߺӻFw߼x-2~uhw7w.+'9;OgwE5\&κ <B}QFZ$U.TRB3q(ҫU$y\bi kzE'G6^2 'lv'-^ᘶBz_N+n)t|Sڒ| 0ȥ +vw߫!I\[~Քx;E +iH|p{_GTvZ\Oe{W?Ata a{e>pvs'5u ޟ}:#˖'Sq0{d"q@t7ks\ګhJާzZ~!!x`VV\~wpDYl'rEmBmnn عD^p5ѳ!G\ b!)(A⸎a$~"KrB0ꠘ%{7 VToc{jI~i.J$thCCX) b7WBSkzJ͟.[5?XܬӠhĆs8 + R;p%@GԦiC AR0T !P[p{ӥ]5'BAbQ1,"A @:2;c bH$v=>Y7HELDh;tT0H%tHBM5$zƺt I?%Kz/w-GdSF2P? l50u;M,Kh!,-NBl樂V + k^x0H3g;шrVYMu;1 8XIz U:)b|k0[ՍtlDҀSX!$.ߜ~wr./?=9Nξgonn;o?GioO]k.;cbABLbPvˬi1֕󚉣*L^J;H'){--4((BQ +12 +%#U(k =jQI!j2z(3"OQj.sEDmE G3l +;\q >A-AشNBv,vF9"1-%"Cfî ?V ^CĢHR [Y5G{{E!HvB2:[I@? (ҔgI[4$(q2J3dppHI%`cFZYzG 2Jϛ,Xd5V):1 E Ƭ ( \( 5R +[,~ ].Dig +NDv7L,fxCBJd!QFrɳa \ 86b}/!PهmDSl,)/y9uH\N G& +2 & 605&:ABiWXƀ}E +H#1 =, +(7>'JLMlbab"w?f8d'E\dr".VJHq~X†$'8J4y%gF+.8IҸ˽Ătw]!)C6Jf $0xd֦AJ}II#2Ӂ˂;-; EfbvR ɣTK,uhG\PD>NH:`"GШg ZYz&PVE)琝+{򁒦uLylu&ef1 1+YIE|/mB31Cq#ό62v^JZE=IFa1^U$AUF6@E2ȄJ32816 +xوPVV[ؗ#k hruᵾrbF#ރ.Z' GMb" pkd~4{At"ӖcL96#p,#T\?}[` wQ9AZT:Vq=cY-AR{`#j(lV +dr/ zaTK 1^qP6B %P|,yGq4)ڱE@ČԜ!;QI$BTR׃Y0p+ +f};ՙ &"M`z.$^8"Jj  ^A\ӰaK+80z, /試¬k z?ŽV"-vZN;K`Ѝž|#\IZVSPxQKI@ $è!Z4+RLbduhlZ2XH{,)El}F4i-`6E>;Hs^Q Do,Ҡi,.@ͣD+}>z[#3M) ^"Lf44~19o(iz'ހy6BX,#oigS3ןI HgcVeXKU~()z3'lh\Vy\"gcŒ16yڷ`y7cwԷoZݼmޜN#X#?^\۷?\}s8}qyqv5ilyQ]w8 ny",~N]3Sۻ[A +&Ф0+H8:jz o>0q{@=fܪ lGr lG8:7-NMkFsu\7]30uFm::Pj?`ƀNW _8bD_79N#qKǤ3.5H../c8ȟx9j>xY8x+ /@`<-6"qD@FPU)U'@ZMi9 }198e^!l&74~}*$&}!B8l3}gP54zY6BPRV/hmKLH@Q +}B\xo7} R I7wSҶyE|–e]' DvX: ":R " +HGuII9 WPϱFYqt"( P7M~oF='2zLTQ^uIM,zeݤQu0d{M~o2NAv^W~e&'*^ҹSA>dXVe+gK ^D8t:KZ-HMk:X:(.X+ A!CS~ q3!C]/+ݦgLPW1 FMvg3d^o6*n~Zd?g ^{d/R |rnHn0E8!XXt5ő Sr^7&?& cTr +˔Иu JE*|uJPUJG`BE@$Do@F}&}; P&,Vd$1TQv92T@* AW`'6\XΊ*1!;; kJarPf٫z>>#e.O >YaCb)]ql!)^OuC3;k1ƮlKq~ه .K Z9ś$g )ͤj䗇 (%fu@㜁U:{λX^E[ĩq15:d.g].¤ia6ۻ(w9 *}3U858U' ȓ4h]?CN|Թop=j_FD _(uN/kR f:j5/ L7H +u%$I/iW2x2;>e\emyl3 +4vm:b 0#j'dIOUya0eKјr#1QL<ޜ'G,pBwĘ瑠~i +r6cQ9.g +4˃o3|By 4I<͌ͺkM2|ˣS6G%=( _+e{!NDI:k#/ +;K SHC?Q +ƻO5m&:=ObA7hȳ-iA^I4zk%(t۬?h L ]9&ϊK|&Vsa4Ԃ=uli7ۃsDcSG8ѱcS6iٲTgJw6dGql14L1%A4DL2 +d\Q:Ibi@ V72mKULl̯dr͘@uDi ФOMqڢ |bmi"fLf-@s`:ٵ +0P=q\,HxA"^T(#s^PjB49 z]T6لvSHboG=OskC4[&*~c5U g"ZWQҙ,@UEaaFٯM>Q}RKhf׍S6f5Yajn7G":Š0.a==4WZZ`z>rvӞ1`ҰfnHJ7+4i-J9!@)Ĭ]j_X ?h tʝ@^*Ӿ2~p*;/=.߼A3RTOLhƵǴ +2D~qb,B4~"-x t̬|T$JF^CTTJZ(NeRWɵx.+Ou_ */i51`Z̈́ElW-/Kc% ͉$66szAD`Hliz& ߘ hȗ4OAQ|5*cv.PC] {U0]Tԝ^nK(%) Nǫ֖Q`_EnuſPĆ BV}UfVv%sF$+T^8ԉ[ci/0iAA@edI= C'gSI៉}& =ilIg/w8thc i$].˜R7yZT a*jJ&h4&HcШ@sS4ulMQY&퀹]Uu 竒mi28FH rl-@çU O9|Zr 䠢)3çU O@6r̞us$H@V>9|*çU O9|Zr +iC 9 iӆ@V>9|2e 9|\r +0YFc*÷I*U 9IW>9|\r +0PE>/@j x>9|\r qC @W~w*>9 35X>nq* >9|Xr!c|\rj>9|\r!çe O@6r +iӆ@V>9|*çU O9(SAc6Ѥ50%ǕL_BV`K 3 8ט 4Ә 8Әg/4RcC3ܜZc^(&.+`MC1?4Zvw}ywu ʈNrZEU[4ͪ-'K.A$> ٛÚ='nNm&;éTEuќj 0ԍ3mY8@&mw=4&8mTm+L[NZQÅF[6 U[X^ eOǤ U[N[EUm@yӔjUYN҃,'e;qP{mRfsڎ[RihhR^x +QuRfɪ7Օ+7r4]],UWѱPu[^y-AvѩG/+i'*WLN(IuVw;iUYNo PU + G yUė9U[N$B6V6e9i' +Rh2U]_yUWN`(  Sʮ {tf&PZYko֮ѓ{slTO4['*!+~-RMOn@\^M{'&:fzMO8B0eKhlCBW-UiȆbJr + '/YLOP?{q4@ \/I{H4Q;ٽ;PyĎO;eNBfbM.tYlKbUyl:1h {ԵG\I&E!H'PStYLoҀ ŀ1 jka{1!\b 7zcӳ08\Ϩɨ$MY90g^i5FTo Y| Cfq EF \ zcgiPBs /ͭI¡4N`|HMPh WtX7huMѱjGq~Oل>`Eg`=Jڋ?$r8Nͅk49ŹaL,b4ʚTȨfD3|F 'QsNf=ųլ"\>WW+ɚpnS6!"Lq81B 4Q j<2NY9،%MKr.2,ݹPG$\IkMKd5o>B&cȻB]8)EkYJLDd2+b,TWyy>۠aYg1@Re$ 37.2/ FJfbnPDǛ>GpKTSŧ_g{%|YV[^< 襤 Lj%4'|")PKR dPĖ(u7Z")(AwI#fR +v FD#$Fqdj[jL,βi"6 2/e7w S1ȥ0ڥ5$a}:hZ;/+y~Kӗ$dI^ne2`-2 +!8+cB|çA3z==͏g_0p<5ְ^$E nϥfbhFH$5YRFT[PbFT4Y#V%ʪ܅ q`:`QI{O[78}-ASc=IcjOowM;MShj0IWC#(>^,Ζj#HqCGğ#i"њyF|j"߇.de3;jRytjNԈSwjާіnD B.Y& 0Q9'.;KD\Zb c17WWͰ}ڄPԌPu)9<-ŪjKɣDbq`d䙨H!? $MA\J,ek`c`jd, l^4)ykTJ 8­-$8KiZ^fR@MjʻX~XϼMbd&nf,|BYn`NnNύ@v~S[$NcElZ6'BX+K_BdtehbdG ؖ o8"M +KkDiT(5XI]8L\!'y_PWt1'k9!:/Vk5܂Ӗw dmH8+iQ5߉NLG,Bzh#p}Ҁ_-TG鏰!ZMwD6m0UQC?c@2oy Xb3r `ƍ6c?̘cF+}l5| +0Ä%1y mF3 +`3oa(`}l>7qd IoNNnp+ +տ$wTk`g50# +e@2{#ml8DKoJh7Api!^6[6[G#2 " :k5 ™+}^%ޡ JnּЌQ8(CKFza8KHlB²ty[?MkLqwbAMU.=Ѵ9yHI.=4%!rr]ϴii\9_N7KQt]Y\ ͗*+cdJlƓ!hZaрi\{5NU +~+-7rm*xMրĥռ@D0QKCKGސoY\q=j'm ˰RP?d7SD|Jj4pr,'$ȟKhbPI4Ѳh^7Kp  +ӅIJh{sZb`̀z$o A'  @[ )3c9WB؏S +- q%hd03h{!WCm4%u/aZ!$^Qv^>$Q ^Rcr,Zlg /y + .3j8nY[Po| C7TCxzԡd087LJR {@.4<2F}!1,.Gh0C@RC_CTC$.<\M'r ϐ|)Bx\:YZ%Ɛ27 y1$Jo`xHt/ ߖlS-CR F;Q5ь%o'`]qsQ$#P@㔣y[+1> U<L88:y.G]%E(RKڛTB"Z2C&/jSRvA<)q$ԋ\2S| @^HX\CsSD(I,+x< ]$S#w5`!Mn +@Kp@EY_o^"9dS$ ARiQ$4,Psap@|@y9p3&pK @iTN$^PI$~x8 5;rؑ2ORB! sN  +c74P@}bivy5Xj8 dY<~i΁ I@&HF L37+a%l(P1x5@6$Fpm&}%ҔȑLOpG٘6˖;zW hUKp 2 +ě!!j#aI(U>Z7C<LL*h3xS7ȫupA}9xΜgQ D" +.]&e[iN )$%!1S=)D/{\< -2@=Ah/$Oe+!^A9$oRhM8EGwnxa& 6X5p2yA&a$<8D\0Wdp\X‰u].#@^;Ԏo@RgK7rс1o!"PջlAї!l~O ))=A$eh^A ]Y 6"1f)A.~O @ֆ"p 4ud>K_X]$C":"Z6;Ȼ~XҐ"B9 PMpȹ&pA=%(x;h"VDE--M+jj4-#q@dlV~vSDxA`!COq Lϐa&luG5S*`h^L$"F h,2e2 ;i@{w019ŇaEỸv%T i,ÛK}-*5ѯAW"RiSm$)H $9DdAxD $,*P.Fg 1Hx dqJ/ȪoA9F]L?a[P~ fO}Ȓ͓[_v.I p3`Aιy! 8j(CnԱ2V'Īih"b%sЦ(*T^z`m@l̲$!T]B,jN[D!<$|Sxw`DD÷XpPc9e4k7cbPPtbb22H|Xkk@"k.XF͆%%8к`p ͨã#w-T8 z +LQe"A1U'Krr/x*Ch089EԄDClf(@ExfkkR@U41j$ `>BB'v>2L×*j Ljʑ3:E˄7p1oVj yL`6_X􇀃p`5GDK!/nDzEAtQa8ΡOr ؎B8 86"Ofr~g ;Su;D8rݒܬ"On$5T,zh{+͡O +s|#/8!u y1xEe4~6LHZt0DƑh7lSPj:/ˆ$μJ@YȴO9 ^ +0iz IRL0p v ŸgȽ`x>5>6Cv*&`^(cW $sՠ2vU +jl1K}h8Lqh6elD pMk 6PYg4Iaa ߨcQP#Q\ jI8nAÂj1bAnXb%Ŏ&@5Z .א9ӈTd$ް 6cEv +bIC({T >!+ j&cS`)+XMd qR3,F7'OP!̕X> -b/(a/^V4^G_:G`ŌyiD daD `sɢYc"@GF3x_CA\d#z>\i Ď0ZtZbцP40|B\bAV@bDj<CV"932̈́V~F7DLX) f zWy"C @q,Lh"oJ-<;E,Cbyňp*^`8 9UM,"@#!޻`ՋCaLƆ,H؃n{1xin6hO g0[c!2\Ё"VD9e`%atib@ǟ&" ۣ1'_ZQrPﱸ烕jl +’FbǠ𪨭qG5C\8^s(Rzn7D53=Ə+ Z"fA|@T3G;ik=E9G1Nȫ 2Ix&őH%LE|H:2y~&]ÉUTwP,eJ"<bT&T"o(18e1OV&,XpHi4V_.ۆKY5OD"I'x"& xZf3fJgXM V5x ک .XxeZ +P_W/A&fV4C>hI+w[|dfFwEMYX[]! `d=:2+/'c5aR j&` Q8(-竱K]:⎑x?3n6g): +ҸCz 쟱ƗK:>7GG+B46ZYE/bѲ?ih/N%dC" B@) l`}9?r+>#uE3oIlW;"L~AX;RWf @b+"/C?D_WLܒ #\n,T;$I=jwSiyN_R;GVZhWnUeE" ~$`:Z%TybPǏ?ޣ@gsen Z,.CG ;-x\MXݟ즺[RXJAZ7Kō'ߏB1<8T4$B%)fx㡋 +>c{F::A#FfK~W>S~QxY_# 8?4$?~1Et N?2=G qR:Xf$2􁔶ђ˟քO$1 E춘-j>_?t SJU~Qжoǿ6*~OmwH_N?b <Ǝ/wLZ*øW'L)7ul[Bp7TkGn4{'c+>wCjD@qFhqzOvnvIF_ ;9Il8ٟ!5˭Y?.$̑v4IMB x=?O˸#~FkrӟqH0H %! +,Y[? OIVe*qC(;iG$(k[/ (IBaE=gg^߰΅q?yoܮge;^SC%J. ,=l <0vfdf&pғe'% ~q ?YI~ҰITL#W1B"]Fs<۞?̿9o6"TutPT5(Yϴ.]ߵ~wO!<&Sh7hme0ݟ>C4?Vynoχ`g>? `Tqi3(OO㓁ԖJ'8+/-ه2TGhp fvXe$# <"?ig[>\]^ɸZQ1;-+tr2ӁeD_BZF2m@~N޽8caВ @¨ݨ)KCIVm@t¨(>CAY%P>A jaw"s> + 061 3 +baaD$P[S)^QV]/<%cM}g^4߫9=)w(0h +Of@}< 0N7$ .m+{faX,0 7&.c: +0WƄt6[NG=HɩSr*k}g4qU#$P55@ sLT`p9T_Qc$ymI!e!H$xɹ0kG5~) 'cb>WYh4f3~yF*QQ+vHz<[j Z_QBv!¶Z 0yMۤ ]voV @q<,!JbY B1ʑbTLXhQ :c,_. r߰R~62tr50(u2N6JރIf0Z߃f0>p7C315џ1Q>+_>/;K[3- C? I?fyT*wTJ(,Cu '|ɴFC»k Pow2&{AyYb;P3Sضh"d; Gƥ`HF_TZ|<'K>I梪odxDa Cǿ2ڠoW/RY[ϗ ,c[ݬ\4I5)jO@j|T,Rsen Mn-n7r! Hر=h~۽A=3xͦ`By6 V-Cj!fj5 _=tQ'm| Η4LPDr7'Grxkֆ@szT+<,QA7?n#Rv4oa lLa;l/wйZ-7刈ݗ4 zrYp[[|4v=`oK jz|0P: ?]GG$GD2Jj҇Y)n}&~0-C淈c5}jWUewZY)շ;jM ¯D//hƂ䡔r7?<H%xOjARw hK\]ZAh&@MVUW 3 xGx.yn/1;w-|2Aujt D +~;QhǫD6?X'p`/zRf{V,7ԩ}?:j}ٜN|jLJK5]t$SַMЊ %d z_k6([`'If3Z &z T{^&@/US5]O=!jx+J+x!L6w+ߌqBlTSۃ;8k|ջ^b ڻeÍEpc>2i3]JU/_CKgǰFu!\Ctffzhzj틦-.m:†)L9,7z>:U7>Bm +jڎ^}kJ!tW`b. yy.!~C0<3H6u-P;ռ.^}_" +qd/pjTL7~0hd~hVݏAba)Pu^s18:] %#ҡ}3ow?l e)&}4Kg aJ?5oAa|X7` 7Gl5#0|4#Du{击x@'Ȫ_l饁S8n6_.N{;,HWX%R`oݠakf(#:gzp!_pBGp*<۵?¯3> Z~A2&nU/vN_bR?j~L4Lcuƛv~LqGPRaeKߕ,4#p 0?PH3~ɒԬ /ud:yRG4pRmgK\y*+{H{i/ vFܼGt mԙͫޏ+2fJ`)ǃ|)Ǔ - [8+JGjuVjuemW?VOD|z^?/㾒_0OEXB]>B 90>)H+Oޫ'?Q?Q,ACDw#c즑)[uo:+aLO +]aHL-JT6ٔ"dVJ#2EkfM-M7Cq_oMix (FIB==r:-r8[bR#u^֙(qn繉#b(uW:Eo m|:]7 {h]9(7c͓ +YgiNN6dKV~SIrB#IP՗O4\y9E;c ,4Xzw =r\o{yd:7.󮞄sQDŽo[$鶔&N"SJ6Nm?ɌI6 sb{u|%.QuR|^H-+ۛ\yGL[s=Zߕ}@}ݪk=fovFDrVd;랴:7ܢ]~-v_t/J4ΩKwң˛Apz0l?qZ` +iLokʬc:{5gr6;ȩRR}?W\ڟ_j"Nז6n^V~Nj>yy쯢*Byu?V`> cc{/F[mBؘ2y=#N47v_}qpS۝3[^.n<|u3AC%9rU<%Wv6{JƝ2|SwD9 a%?e +8͋ X+Un. .{-* q6IUD)\d"ұ6)ci{-ZçXCF.=__0оy:I?DQw:B4e ǩ@ǭ+o i2$64YR)_|aOMz:y34otw٥r^+,N-CEqv(93[}eZ,_vGO-9enS=Qmzp/Ot}<- iM;|l{{KX ߦw +ә* 5ˤNʼXϳl/4EgzX]yIҵ֍Wv +폯C [/vz[rrzݑG#Eᝍ{{#:֛am?r +6uйƸGl6P?k3yc- Cx=Sb9nIV59rN-8\Az]Rio)?LO1ܸ`4Hg-0Oh,3x{CA|PҸ` 3[9\Xmd>%MGN%ly|@OO*%w-a6YxaH"b8SKa\ L [kl!B^NzCz 3+3eޟRli5?IPcg+cqz͌|.:gnQF{qغԄ>O'\5#u6qt4xK'Zw5w1 ?+Q>|umV>2ڑ۔^?g\r3t<<WnRnؼDOQ3EsÆpSs.tb/J9ܼr5Ntኴ\"4҇Di~l Z儐!t(ROޜlk>_Y\UU^;3O ¹$mC!#{ k_L_ٕ-Ip-{zȵ׋f LOr.4?{Z馲&o+ȅlG7ل+7B[Z[eڗ{1`>m|y_ ғR\ɹw|vśnze=-(71RVQwe>X?n,+vfO<մʦᙌ2PzBsU2l4ߌFz2ayܶÛ{,]9޽|mi]IQo,<|0y:S7Oǎw,YG4vsZ{\/RtN W$gT3'noO`(gxvXY*\~˺]qQk_6n9mbt?X1^{L#>Co +ݺPbP(vRpQJ=oN.N/ǜW<pݹѱ¢U*q۱7ڋSv}}?3 +]opoFJm;qNSʳmӃc=ҕL?yos]Mg)Җ ʳxly(g"pbPON2f#%d爛!D3#7&agn]#CGfz+x5CCnNkg"բhh(c;xˬ\w6UHqwNRB2]hMof=BUܴnb&|V(=MwhmHlnȥ⑹n5_uaWt?̩v%Y͗m0>6;)xkMmݖ RH:'m)7GV(Qo;sZH56xv:[=z&ئDzsOl5vf8xS\!i+Ŭ裭cb5]<ˋٖ=InQ+•"#Xr0RQRLJ/fb5mR8 +;eɴ?owʆ;κSIw.OY}}*|#튛!p%q=ld,- +QiF{-kخmpC㊾Mʾ[$ E:ۢ(B%:wTni+UBXn~+-g-1]~3VJ'o/kb]d&8)אJr=kQa+$;{]']VhG*:oQuX=M +|`AeܷN/=b>X=o^(}ilrF! }K=ӳ$dP"5o;/z:Sq*חOf3o]?d:lM?JzkllcOZ-=lC'vTp&ZC]np-)BUX܌o5K#Bϝ~t-q"ͷh.Mz#pg:w=$>fKm7c-W@3l|6NW,qNɱM{svғxnv[ٽ:ܴ ӏu[Nč|*WrL CKbQj4(4>fL$'E  ?wl]n*vvJ1s(M_y[+f +'V}[,-zv{*mLT%'J΋v6}+|zYOm"+ו'B5z-yfV[_]G4&_ vP +*Mgf#aeI}t{*tSufW2^>YVgwRu\ڕxt|j @#+׶-dvQkˁfdnي/*;Xڨu=TvסULRo&N (rcwI-]86-RM=^5yIlHk gJ-qk/RףVo}P7sn@V%4+Gr;2o7\RthSj˷T>ιn6|Wa +ܔ'V'C_e\(#bX;$wӘ¹8?;; e(쫰^w*HЏ}^z ;{9s +[-$o(Enң:D^fC6_[dMW흮0| Kvȴo]ҁ&.9+%RO?R2Y%F&^94Y>&a;kIQ)#C.~p$Xn7~dIgԵ;OK:q*Yfou(Ɗ·mJ|.RZ1Tf݁Ӻm)unwAc/>Zílz]}J AG%Eu{;Go4|; 0.{ҍQ ݏn)Ls[QWP @919{Vk &ciyDs{$߈{M$6C).|dze|Wn;C[Wԋ1KxfTzY"ܦ4 VԆQ@,8L_6#$Oש'U)g|L쳸Ab Ԃ7 ԾHݬEyž&T@3CNW,QڕT" {I'=Oݲ0<ub %w"AM+O/AL8&" =)E zL9B?{pŔfmOqk})6իr-"CMJǔ:y>yf! LQɓ))Ɲtp.v [P.ؐu_ۥb9dtT?Fi;>vȧ^)LMD70 vNk֘9ۮς fR=b5|{d[vXA X᱕Hλ":fbxkԙ.q 눺qO+JeR* k +BPXfS^XY>VM6&6Kw'UWFiPivQ} +ѷ^y&/]9ST-R%{*"B͑G@S,eQZTC{נ<0޴Ūz.!.;S?o`r><+ii3GO |՝ >RȏQ1]þL,i;cB|O@wc;D A6=f/Bp=ŀ$ru) +>Y@T6LlKZ /2F0HېۮQ$2d!9U'(S{=.jM'i#dϻf4HZ#HPF0A[mR#0x] h?1wvI28-]|\1J`_Po%ZBlx`ȨhV 5Wԛ>R\B}މV#}n5͠~~#jg lzo,G`VZߒVM UԐIjZ&^k#rlJdVedmW84yV=o3}6߂ jH{|'fw;ST#ĺ^61P"kTo)wi4Y)eO\dIYTA[,olT(/@)J7D_ u~Ï9ĞVW<ߣJ U rBr͵Ʈz,7>|Ez(ZWכ_TWBdsvExFYtnlQO}K+}ᩣf l)?5{&沧VF<ܼ~ّԒ99kyu6X&ɨH(^rO{y :I*7dNe_N-}9ߠWP-ex_:\Jr6xov2yf4.^%ֻި}"Dh^^IIfDy,ƯrP+afǍL{+<6¯EZ+t|AyBHߔXi^Lk_9|/B-555ʻ׀KQݟ3~Gҵk]7oлm@r@zWvz{EqLraQ4m"|t$:h~&XAHmIM@)y& ah[]{V}h(FlM5%+_>1p U+ΰ4j߻aiP5Q`렓}f uҏ,pu*WU|&7 [Yݖ^re,YKzE*;VK&b(5c[AW-*anJ}v- ++ozCVS.g |BA]f\[(ut3}gP +j |]pVM-nVpS#Z +[]n |yR[`Lm35 +e5| XUUXЅ,'S|:}7Q'|IY9ej?m(nŀ5 Fp*O7q3ncR!@0+h7|DJ]?W$ 9IS[]Q}OQht*Q7e`S=uY[ zg: d&8dzѾ/~S4SBv. ruYtCG<]<=aVG9֡ؿsjwGUzmjF[?!s +:%VC#ɱ׉?Ztumj^ߗ6m1 +!z>ª-u||-G9lRY!ʍtK W@(n hRًwd;Ҕ\٣^kIGJhu5{HWF: +rŃ`Oys I rVQ|=JP A8g/,egY*1q=}ֆ=L?}˼0"<7r:3٥8B]{X_ʹȌn$J}:OԸ-ab]u;zuw1z^aV֚h<<-z1>'{ +Yi?:;9hb@+|]K[e7[lu z4P6;P`(WшW +Eo|ZQCJת[gÊmk +D;)@ $c;9Fj++c e\x5y6'Yk5#[S>S3gu~-(z'J)_=@쨵9N"54gѧHl>Y W8i{J4G~zPnZo!O~Xy,vxWӰ5O重E\9߆q+QwYq$wZ9%X6PWbFɾFΩ-j9|dŪ`rhXή]q)z|@U UncǍNbU j Tv;0?!?xbޔp `ܱƽusjݭԢMRlk6K +Q`^ka_p0ޙ]0fm Zm}>ИYj>Y#vt֨-|lM6.Vƻ.euF-~(`Ƌl^G̍= ֗ʸ^j';tbzK O2R,3%?,&nBk,߳ }j  YB-"(WQDB8TJ"?㩐 &T&_+Pd*~|*FU_S*,i{Y5Tv"y5b7 .|ËH buJEU563Ǧ:YA֙_:t~UK9ur)'(הQ7Uq5 MdtГ{ S 57'n^jϧ^ll&wrX,q '6 1u]'[]Y)+p]~}3~m'TeH\%i= n:1 )&6-_գ˯!?  +}ʍ܌J%P˶9ν2?iOdshmǽb-%ŽfĈ1"%ỦY(K-wKv/#a›'n~M(õ_m,Fq@lnrɭ#Hvǹ2ҧsJ:2$UiN׼cQc.L̜>z5vuUVUߚR+ r R^=ݏmyfE};piNz1:6eh|v6\S&'Se]v-\8n4b\E^hh ^*1I Y䗕 ,R3}>,t'֗r6 +ZlMrgME~_;J!Ѣe(L{5w_-y`ϻ4` +ޖHXl枟ŴW{/J!k燾&[[$T/pS9|/d_߻*}nYQq)쎕Ɓ@wrq@YJ!z.y}-9ݷ\m\ +^EQ͏K eŒބ}Urq8@B4WI$Ů5<%ISc1S:UmGhU$@az1I@\0VuV +Mws66ɷm%w$p/ua,ҜՄ!;T= +֐>ezg,"-ۢZ;)LPo뛨>v+iu%'sDO{Mao&Ë(f6/&>]#W0 i+Vl|mGM%=Z D2RwG{6]2ҰhRi< oV ;*{%p2EO"ZQmzdw씢' X 11-iupԖ%q'o|*ivc8XwO_qkt!1 +WS.z1#d:(D \ f,8V. [S]hPe7K59͕y +Jchcd*3݈o7veE< loz*FՍTY{Ox]u (A@IU}a`0YW1_nx0-֖Ȑ r9#VkJmf?WRzǟ7ѵUR,XoҞ 8ANS~hjh? Kn~D0CVTC!_ܮ~*5 y1m]Z_=(5hs ,m[BmASXX4J]J֮Awŋ +m/ӜLIU?'*0IRY}TC1Jn+'*Tj$i \gaij>.BB{m DfU6e7C?s!B7X[?hoՕ"D:ɯts/j&K̪`%򙍠+UI+UWOrIԁ1®91ڐZi]D]7M\6,d.W$g27'x`vzWkCgC'`Sx>eG$槧z0(˳FPk׶5| qN?rx +"ZBj/<ȍ$<'4jnJt■^:!q\5@/w~1/l$Q8thQc}y(}RW$ \-N.2{Lɋ+Z WN0775AY9ݑRj|XH ~nqJͦ\IT6~OW&1l#ܰr@%hjgN7A[Fe5/h 0wĦ+{SO ݩ9hVvz (Md?o^kpҵ+f"ʰ|}-pPoNiw4+ue4U&RUΦjf㊏(QB^|ou:zk'T X~Zw1T˪In{ 1CBj>/03  uLT*s{ʘ@&9͵y=DQ&gL(k|p`8Mr_t[hǩK< lݡRg1meR4{5P꼵j4D7Z&7_heKFBt]藘PWyqvRD⧝ 0\V탠Qg|kӚQEyP!ͪ B.ص'm}yf{36-oGN%3~<)LjG0 +2g+z/q翻=s֬k{- +5bOEDωW?gԯMPٲ` +N G㺬wmmU$q!d&vg:4X"vOq&vVӵ*ĞM4?pțLo# +VS*G\ڬ޷EFOeRaPf +[3etkcEǷmDìVW=97=jICVm٧V=ntVts@F5|`6Ǎfͮ)VDQ`/y] Yyvoo h՗G&vѵ7V1y +p}-8gRHI? ^|T&U>mR+Wmn+ +IO}܌I?\RtkfZmt0uZXE0^&q-ͷ>, +׷E+!M ƂQ+%`ʎY++u?V0X၃u7$87@YL<]aEJ7?{a@yn\{T^v:]:49P{zZoZ䄓:>46)W?/4ȒMHۙ?BkN-01vc;Ji?tOƐ N/7mF۝oWw\{v%Q,rkhT5vȪdkdSV!a3q//tw1mcFxB9Xj =j¦\g|tUQF]@4!'ͺ966c\8uy(}:6Ydw堍z [m$tQo(ϋj`J_$z p."շ3J-îST A"UgKd3!SNKע +RoQc)g=i7%е|Ϋ{:w,BMLb ᶙY{E +Ksv } +jzy"%IAJJ!^HQ67z3ae)ns }81u&^sIV~NV">39ƣ4ݓh3rFhI\d8zinnڴڼm3,uƭq,b68Y)jE{(UE=Uj7qpW,sufԲD3B}#i^fh uHnt Ʈ|`^|~EzΛb> i%%"9+mD\qZ9"ͳ#nFbx\:o?(ҵ|z&{ֹ,CI=`j 7|qCNoY~WEnA颸8Tj],.MnE޻stPO+tC ۊ3XE*)+a|t{ |}bW퇥啉t)WߊHF.z?چU{+!UR=Ҧ̖Z^_Tw. SWx_6ClQˊ^52)xޱdk2"ˋE^ȚC/:h~3uU Qh\uwg@;@/RpbQ25IZ vG YȺ,? ܹ.X]$qfUSӺǸ"s?zYrӫ(gjcZ/lQHS%Y>A;1t5~$oPw49z-guL0g'jO~^j #WE)? r|=(%M0i}^itjwGcN˘L-ÿ(rOPYp>9錆)O̮t_PEiBU@X%"؏eQSf |cÞ37Ǫr*y[3঵U6/Hj`)V6N͛ߢl5CPϚX&՛ tP]-)}K d)CsBV^h ,%ox +*LͱVٳs JQAgI@od5f,Wڒ6 ;9s qgfOGBНNGD"UaHJu}M[Qiݹ_*VȜRkLoiZ +Xgnw}0xpƗhfDro +ة5ex3qe_ڐ|a w+׾rB-3TQ7|_ Lw]2jY|[buDb +;ޯc򶜊=DUR9̴CְƟ}#H3 =|H˶fL`X1=4tĦԴ/J5)n?B*u]$A\)G%.nNľ‚Y* "g/~X2>ߍ-}[[,zhsO}B-[A?hI-MGkHp#ct`pk] 22f z1ǣsE+7:K?.!BoӤ.2G֘5f; +4 f%JñjmVto^㼸4M׫$6mYkv~ 2Hb'L{wgDrڛ/,[I̔zu0G?xQK6LS??-Pw 's"{#9x/öZ7So:\{ѕ $]ʼn27fmCyu܃^7nwC@)A8&2<[W5tÒMyMaQĦ~(amF\kR@qu3|pXcޱKσ|OȽ\4НG̭K8X:&+?~J棩ӊvKAOJ`@ߝ$VxHBLN<˖W܏D/ZFwRZ' CMwҢ⯲]ʤ$wqP*ҪTT ĸ䁀 zQڰ-1!9+YmUIek +~Sټח,0XZ=}?k{98KzIܝfIOL雫ݤJ,BYq]IƷ0̦}ڭq~欩Fm8$ҩľ+ *V漪L Z){Hu3_,V[(cr#]'X q3ix[\w U]`߂n Fʌh-`ʹRwxe9lZGJ1xYjPv~~+<5yVşAsxnY,w +&d\48Xߏ-[ߕ{Q09p*^ h(Ȧnqzy߶\d6a=y;M5^~3U&~v@a l FYK d?P?ˮΗ?Py3"P+^v۲]7g;[흒OOze۟uiWd!yq:z)97Q4TlSSx)s0-c!Qy'WiWc-LNhDƒмdmD! Ck)eՇX>S\2/kK+`V^S_]~n# 7N p~&ݮwG}I}s6N{+ U@`Jv!F;xێ-bLHsj|:BGwJ02]V#Á J&OD6+3P;uYXmBtpliEu7ezΩ]yY߰*\(q8KVD;7).!LlPt{Y-<}p@M끂2 +, -N ,V֔^=;~7JȆ2lEaW^4W׶D _ޤ%V'35Dt6=-jsI YJ>?Q}b~*;:0|ZQ; ,7h$aLǸڊ+Ґ '4@;/3Pc-VOњHT<\jZ#w'bJ}gģMq 98RM*m(-CuSd}؝5DHf%6ѻDܗ2*o .,+hlztTZV^3085~iݭBIr^줮 2n-!'j`mnbGhmͪ0AnYF;>Saw + U}Zo +W'~ ϔKܛ.񳼥,+&^dA΍kb _ExWTreZQ2Mykʫ!8dIe/RZ{o])V^xVoqZEgʃzҩ^? q2$-=~,u7{4KbuME{lCPab9t;B(4ټHkSX3"7G܆-,A)f7}t w}Znj1?ټr)݌xd($sD _#TtyFjw!^^15}5#bz֎d fYë _|&xP,):HyץMo;[ Wf%O֦:2Rx eZ= +5sE柁Wx!Vև" vbw/jodg_R;{12ӑBZ>య͕Q}sC6;bD>+lA2(3ŜaZ12Z9[F5H0/E_O}IRQy/s@dHAǬQiK(YkHzVv.Z0͙6?zz*+UGx=3E*~LӸ8U2>KԼN/?@wt AjnAl6&+Q BxЋU|S~!g\*Aʈ`fgx!2"ƜA_ whTQAdp<+M?gH}Pyy0֍ok(B(5{c0ԬcTҼsX.in[3<)6`Dz3y5 +0eyDUOKnĶ(Gl߼/=eYZrҡ]v ău0.72 C" +^FS&v{Ozv~Tvza1,>hx'.]gpEZIǺNi& \GI +7֧amWS-|7 z[L%X6Ί +qkjz~3v);s߱ȸ_#MZɻHy{M+FA3R[x{@+"k9tT7 Aci<er>rPNyi6fN]?vom_ [}vbB+NGqƄSRNKnSD4r,{!k2~T+떔'VDzCifR{S$.ֽt.:FoaXiLy-B՟/^oYtGݧ`^\Q7wkGJʢ2ҋ5ӕ6!3{Y~DulMZj41hg]9'jv5O˒;a,dq_fs,[//ikzKQ=rci"=vWh\|AܥMO5I|WCe/4&XN^2`/Q(:5}ZL=*FpuQ>z%@_ZE"-)㈁%$t;LD%]Xj~hϹ#\O48iv#YTIw󄯜*mJTA8'H˼ UG;dbR$ۀ#[ft ֤͞s|X;{X:%%=]9/"X#.цÆs+MWfr-Y:({_*-Q~`[kJk2][w0kYDa|ޙ #4tgb)qhGu.BZ*^VYXS+}RJ{H \U=ޏj7ՒG~؛NXKkN/y, tV0$Xpn'y9Q-֫ ]-G4a?@ JŔQ/ FnRK.7%ˁ@!M^ljWh1s  2_QV,o[d<` #n:g&jY~ dm q_30I~tkQ3c$b=5}3PMC+~N3ni)r{5B1wY.Oe?;)K݊]ýնLs H"hvْY = )|H U].s^|X:7eqܰ|xkU^'/5ΰ)NO#ЯT'ne~yqY_7YEKZK+ߦտkRد_ +fᥓkz AYv+؅fy,I"^#mF>$3wu;ڵ6aHFIO,7tNOҝs2v { "fu(8^;aY څKKGstCwmypX dhݫ≗6|X[Ců|C$j_dxwQtd'?.FEA)u[G/g ^Dx}θq$mZbYjw*>*%c}[d3(-?%Iqx@ΌJbV~1էmМ)́{/ﶌ-uHtJ\`*y{z?@|룁T+kM')ibeR*ӂgc1|֯4]~ 1lϐ2A~.ABAֲ"qΣI1#gˀ+zrk<>ʴl|]Wȡ1x* խ;};7VǒRz@.Yz^`!)ڹxPsY-V!bMi( +ʏ].:lԤ#Isr|x%M.M(X䁥֦psdy6N$a +f$fկX{=i l.¾)W>pM'-37K=ow!#7p ՖkUK@t&)3W'}m*\׼oGɖӺ`#AY ֽGc`wWZ?80uĺo0fĹgrϒV@^H$Trz'bP".Q5^O¤LSΦ6®O(.N:cdDǏN/fZNX// +T "oa*+N΢HkO?D0xMX,[./Xr8wPg2WtD#Ľtyv:BAѕMU, [oG3M?֪jTzS/cیUֶYku)drM_)őjK@S?fH(\𦐫ߣ{X4w |ϾfMzR|֛uKDqllK_@8G[d>xNԺKMyq 'bW +MhŝoTX `9+ #e+3RM0Gk˨>1qhlߞ]enՋ|Q6Fvm)EUPMޥWwA'UaD2TB"ε:<<Ѕ´hg 3r9Ok7P!` ;NVIPj Xu]+8fGggq(:/oT"Q(b~{_)++vV'c2C)39*d>XÂL$ބ>Iz҈VhG_)zP˓1PT +*imT%0w6jVY2'hU9'do[2 ZN#bN讂0|T'Ց&׃d^@YA;9Zk'[XGg6FsQ#d >47ds4.. X`F e 7R`tVVr% 0,T!s3 C=Kt;WUņz?MG7#]~.%pl`cNo5xt E]# 2!B觶̕)+)GղJbի$UG+38*+ֲ?T٫UlH"li>C\L|zz΁6gXeX.U(4ZmP;IP i8+ҷͳg-\Ŏ(GXoy,&^*ƍ9Q n$23pP+CڝbZs2"oE_o C]Џ#Q ђzD1*и9$._yʧ\NvdLit:#xУX9I$2^t*čԻퟰ@4EU{x5nUu2nwfc82ψtf/'@`OcּHqW6@: 㛗U5# ~g8MY5oZwk UtjK(rgi)#_ Dĩͱg1X]?Ϊ,ⰙjYj>l10temg݉m~_t$y2||bJV SuTDR X=6kS#/x+if:IZmAub7'*\G%S+r1lSΏvgЬJ<0G勜W +eUPqAy8qt}wxwi8Tѯt߬:FMJؼ7)9`͢gGO $X)U)p +ŘP*d4Iql5+#{ +TnUjq6đ\Zr̰kc`{XWXo!܋+gVr޾N++xGi@bg9EXøMN'3f@tQUm:N2)vzrFf,;/`g5E[c>5K'ISgM1&Tg[ƴuΉGm["T/vjؗ4fn`ٗAJ`חQf6BVWF/k4%G)iȨ`Ro5Fbp" ++*m+qFvz{o%-пp$kĘ:CS7y'y/3?rE%ZGT=bO5XsS9Q@‹u絏z"vi[ L̂=Pe7Pݞl?Z m:nGM&]5@5D: ϹP=W Wo>KJ27ꄳ%.FW׀PlNV{06l-Y~r1\\E[M/SQ'~kfTNsY8]x^ 3ueɘc\mE87J[96:9Uמ\i95U!;yx՝^+Y+Z,Z/z#{r>fWk ΄ىc>VsU<$"OI0v|I]OBHGUs\2MϦfӁ9\E &U~@Uvv=nI: onCeuVlUƟa}; w}U|tЯ(< NM+\cY< \9]L~NʪGW4K$Z@;l}Tf2mQ(àֿ{ +/aӚ1wIגk-b=n<4'BB,OIVT&m'2?J+ha/X݉6 =f=~&KH 8vyr~e@NIVi֢x!ZB ~]2#e!W:[b5sb;>VrޟKd㶰VʩJ ) Ť&7%v|IuWW'ղv>E.kT^軞:[.4gͣEg DP%"@JY |yvS> hOV]jE>&$o%CM +`Pvx\!-ťYW=Xf6?PvMܒOT#Uvx%7!NyhaS<G~DJ+?C[ MW65}'L6:ݭ6FiqҴR^@t0&o[ @^%R;y#JP!Q{AVFd5bo=n&ALt^Cq~TJ?Y4ASպCIu_ 6< btPn| ,vJYV!0' mR7JXr?Ismk-80^]o~L|C4{RO5*v&=sg_(Zueg hCY3m'[~oi2}d^k ] sj;Y49 ~/OH}֕f~5*?Z,QQA?ՔOd_ITS?PNϜeɯ)9ɥ?Phd&M:40<7;lj4iZ6V ]6qgrXm`wVa^L} Rz'F3  ~Pqh%cr4ǀ{.~GW5Q$Ǩj Ε4b7f'x2L(5|bĐJS *#,Ў`紞}y֟m*Ρ5V# +wd͢F8m0ۧ#V4iN\\SرFsCWƩTi׈o 1>PXUwetֱ߲ pZ+ca'bY^&il)Eծ7m+OT\CAЮ.% '"O[a? {ūt?ޜ(]'jqF.+Q]Z- +HIe8h0B=.J@vW!qb9һ-r ̺"H݋Le'Ϳt'%CN; >/=7Q679YB~n &h꿋&)<"sijR!.=THqպւr/Hy %R+p'9OJ[[В\*]2n)}9{{Hi+n=O}¼C e=+M涐9}QHZbqyzm]<")K=_iVSfFX jw{+U0%סѓtNs{ܵ2/a +}cVF`mFuyOI}1wIPߔe0ʞE'.щN+B^'ZFg>R +  ֪yPiydjc;]5~rq8b]jc2IdLt[Yfaǐ)u6"`8%LqqAqCWBj`if"XՉ<7wpCEA=y^?-tf{䅫YO`g~góh׎a7+TϣCnK՗[+u>J}< +zKYM?@&qS_*2Pǐ>jh1RIbWW#OJxXsfg_δϛnn=*UcSboOɍ}8z`%ޥ(UI"wW #m |IJWB9@V +~;>XR̞cqQW{ѩHxxQ~A;sqgei*|G+O>E=C&ʭ@'²l1s uՓʐۉ=ɄB8(Qh_ʎ^vtHQ4qߓz#-oNܿsjsekqw$bPkɲXik)Huu&ӓaFgH x>wW- + |3LyI +kl=$l*oeŎS3!;.v +b?1* U]n+MgXc{RTmԿr wPО[ش&- W|~]qdG];瞒:O "􅹜20oYVݙ2ʡ`՗5MM_JڞQR+Xpb +z~KK3vGddt~X^ q#$›%Ej)Jl,>Y +]l'w~OI@HzBЕqZQWB<ߞ]W_B[!MifSʝsDob_6g4wFl[~Xf+$r0IV endstream endobj 126 0 obj <>stream +]>K"U*w_ƚ4k5! 0mh}/鷕챜b-^Rm H nXʵķCtsΔ/0z]v߇ 2E,ˏ%H,Q~TBݐǭr\hKgۄ[RӾшgWgyd8P{-e1ZyhI'sz%%1H3 4S[(*#m\yEXڜ 1D꠽rn(?ѿێ7_T-fsZ" >K*L$hkZ7q;J@S)09eL7rp*#Մ`qgQg}%9l?@TTC"׎D\-A鍕7bQ1EZ⽦p9"4{msµU$3^=9 ZP'u)W.a|M-D"( >p +fk{sAN) nbOhA$0I=3ļ-¶ꃮ9zK|+)^},u,eu%kJW% +ywH`H.PuFhC>H?޾ m51Vׁ'j4[0Ww}SbMOEA;4`} 'jTg4|T֙wJ2[£w0kVPK󏎎 +3Cc?v2jt>h gE<zxTՖV%?KS&ߍtez֞TwXҮ9}c=Ҧ4 +z5X vc|.NE82'Ĵ iV#0gЭiYXwM{)rQ2*WlӌURFȠ֫ 껓xKbi_]bWwk!8ylZ_ݲ x$[=ej:Zao0\7Fsa( ZA9h5)* u9#*SCbDWj4̦zI-:&(U ϊgM}9 9{zA;MBіH uKN2s +4s>?-k4ax:%˙{GU_f#qgEx|/s:7̕糿@*hHUz7ÍU)o<; qUk*6 I\ӿNy /QŪ>z"K/%ffrv9:5B9Ш(R mлvWX``xIY*"W¤[[_enI;> ?zՓoc*GOP^& ^7 hrdڗ<CgHp>59+j H`eQ\W2C/opWejB47R܅!|#+8ơ~W F-돻ar^e[~vS|O*E)t5 ZyX<_n?KRRq̷ y֞]ؒ"7(k5ceߥWB +w8gfs{Ћv539[Ou |ײI\v4~(YAP^^} TkzOfuy|?XW +zʾ{nҳr`ݮw] 70SَK3>}YpXJ_Yp.i6`9SB5K :Gm8JS*n}_|:@/owMiOu  |E79V[?P/\E{#Y(; +/ Sc>Sӭ噵_Xw/?Vh)fЬ$/ĝj j{'w,wXhwrP9vEt1lm|ޫT!͹VmL< &Ky^Cw:9d(TZlmquViTZdq ^͆nzU'y#Yd+ӂuz$xqU{ҎO)+];=::J25${*[RfRi&ygρNtˑKEw v&L/ݘЅz*^^ u`.iZ׈$BTRd&kl|Ҡom37Xl}wQ7uy@A ##*Oەwi.J:Pc=[i;jF/ 2q݅Qզ OZN?0E:z0与Uẑxˬi#ŬvHy>^hYo̯y2rNZ|r 05 ` ND ޷+Zȝ6Va#UM܏oocH$(A1@kymwl_'F>#.-R~@d^*CPMZvK,0,}7O3haU[vj ';,B dBA ӀOQ۟uRr輦ğʱq%5TXg^a0Yx/+{WQTqxFBY=ط20n-iX_ NH?6r#"s1oJa9SV3Pt(d4HGAZd]$zցNYq;c_J$OWb?|̀FK-у2;6`~>{~98oW~[<X,:]Jsg^vE~aYhV܊0WC(=ry3e :lpo5-[j˴~*f1[qO5AT7oD۟(ŶK-N#֔ǁ+x/€ 669gs}{o?~$VU*ۭoPoYܜ|K2a_ V+9IdDKbcW)UfPqv;qg6NL.ZIԶV)X,6$Y端~ /Rc}ۨn>OYA,# im`0E1Wor8XvjV#641#%)"~!Y||c0s_@C]'=T;l1Km=9+OT9ZzH_SŤVIN&5P'%1`*w՞\Lqw]:?mcb76};B +DĜ 5%*dIFCSiҾv +G-=qXf0>mi(%PеٰmPvi3XA/BkW}|zS}z$u_JQc{P7-}ۿyi%IՂY3$5UT~J3j2DV\o9~ߛ{;@U󐄶U +PWP^NΛOy)m?OvWKOCGYS~?9~^@hʈ4 ~  *wW%)Yvt-)Gx4x6]p)D4'PhN.wȺ9\ Yd<'7$Ye_bg`~43ҞZ&eTUE/a O#Գ8Q9u1mOz}>c>gy H2䨰KhxEfXiNponEY\IjʦCLhM&4E!2vl̆f (ݕ.=Ӻ\ECM}JcGKL]=xBF*8W>"6;4zMh{<Q1jGvKe,cmHn1R֑rnܪF,I7iTosڳV/}OW7I~}#ǼKOPB|YЎslû$U䠝v>RZFg;Z@'>f#Zv 8DAp6;5*ǻij0*Kh^y@Ñg1JE gٵ^F0r&FŊ߬e +S#f5mdv"yM`2 +DԶbU!îrP^x=qsp/겹gόr,ʔ'O+߆ش< mӳjSFϭMU$0gYv"-b)dxt8ҹ+G:Mk4m~skFT ++i%áxE5&1-[>O:nR73kHEܬ_bx4D_&'ZixC|WF 01POZEIQXTӺ"{dE ֕|b缼vf7SOdlfy3hI5}/&ec8Z fu$3;hoҗg 7lbkeK?|F%5UkUc-OW 3ec4+pK +}9dU'&_~z|XeDZuէ:J7bI\m)wSGqetʵ؁a@4q-cAQ=ȏV; S/L+YOLgq9lkv@̨h-`1I&5S| sBn _ד[?pAE~Q6hx"4:bTaf9Zzķ+j <{LPj+9o^cO'ZY;wu5.N`GH?J-9p!pS v!ۮ(zaQw^^͵܎{*1>ͦssOVMkuGiXdIŎbF_vxmp$8GDc=wM4}uߝ8ߢH Fz DҡX.M?!G44C hS4/ 1=&SiN7JVd=+M<^l =t"_SHj?`w_oVY!m* TXbZ 3C8f902,{퉃mbZ'IVkCا2FMj}zj+JZ/ڞ/JE?l0Sfq9^>(bH>;VU8R-K~hj:k|_=~Q"a3BG<P\K9k]@#- <msRbLq؟tij1zrxIy1Έ4w+ݒ7{Qc@=[j)!Jpm~>k\;" Teb;/z1fҜ?\};4FS=;wb}wW>)tX>-s +kq곸69pZ^ R!yUꙻO#Y¯jLϔr +@mR/İcn0>2b~Oq{):э^X_On{nTz|ML6jpATYPaWyǃxlXSes<8U["Dϧ"wJi7n[&݅ +KLp/EKc2(l@u U ?YO6XRZL Wk~ȷphytߨ(%ܡEš3PӦ=2^Vtqy9۫{&"YZMAvj9̼70G9n{ζoLn9>?+9HjJ q(&kϑQ6ؤ;rj=Cc:;B7?O+59TOɡl \gs0|t8'+oF:xjWpP^Ơ7PIH +:5+oPߘ#9(̕8]֨x,=3m.wr% (j;>5 _pV =J̳j4B#Y"}lAu +d8Sm Y\o{vr~;_j֝J#u9uSBͻn!sd^G T˦8% t6LV|s& +gs) +H=1^`k98RzuvӛŖ?4@y-zAgAr?KYITF9@3ةN`^nXdKWG6SgъM1h{K}} q܍~X%PHCd[[?#\r{A>MLW_82)qX)ћ4WI3eO!yV]U +6{]6%;v97xx VZe~_o j-z@ז1X[KjRyw4}pzG^,LU@v/ΌyIEWe[1;[_Zlà`ߥ1f8lV/fK1t+ߖxVT8}}Q nFSCH+;SXv*s~-mV9Uź^|b,[`1`[a:sbkV<Dd{1]pd b"Qq*8WgaQ|?=Z_309\JqkbrZ-WNԖRP +LyrHCFD oA &Aea}ZsiwXf+1*c}B1x0td͡m6hd=8#~{lҦcA`*mQwt *xkOn,`OX +~?m_& 5kI,|+^cCCYwIǯ!B }Sdᆖln Yu3lmGPʨ /EETs/?s1*Xu=Od5zך)S=:58 4ntѹc)yUIx6AG>)mΠBra^:WUqz睘7)Ūd]w2=c+2*ق\ՖJa:!Po+o2=_{a+X&%^B0, _-ݾ8NG]U|zP_:bѴc4ՙúJ[evy8bmdinqs#bpiD +$'!un(Me߮~.L]|0fWʜx=-Q;X0] +\6sHC/KhCLý +>Wu ,O|&)~h_+YqX0_b#ٳd竏wΊU5IyFUm_b]1 +5pe vCb֟Ԍ}Z[Ra(0;GsyWj֗@q&EuуBWx 5}s*)H~GT*ooY@rI?`t+4$cPBO^i|rnndpPPܡ8AzS'F|0o(g}6kI־lcaVS>xnB%"VNL6+CbUw4ș[wr;x{sf$3ά[YSLF;xIyTTw.kE9#˺Zu4V+/O'P_?QEa9x3t5TWXԴ;[nꪠ割 +gRٽ9ϫ!hC+lԵj6'UޒcTl5=Lk3[6a@Ne8G|왙78du{}0HшDFBbgz2LH 6B݌9M?ɟ6O28064ˍ2DZ*vi̾iV2at*M~ǜ]KD\AxQ%&2x`_~ 3\ zLqMߦ@yA892BpΩm7jse35t*?]ksUXLDܚ.QrZ]9/(ʼnkq}yUt#PHچe&_iE5Be,i'e[O` tu(^2;d)sZ'aW=Z[vRߕ\QJPӍ2'hP~ +R>vܪ ېr[j : $CPqu/3k1ȞXMF̴_ܸ䰽z쪽7Hxs8ipxa=\ϩ xz5]6z E 7s^3n'7Mc?e7t rC ¶7iɡt}A}-Z?7蒽, o~A9Aha|Ņkbs\L/w:80֪Os7{w +ã`8 +P,+_ ;}%3r&Z@pLI_P*+S(Ν˽(jR|Q1`#59Jv:;(f_F$&07nW!r<+o`8(!;.9Y{@C^ + XN0[Vm2VO> hT9Ce "x*V:Fk1VNxӅX6_ޥC)x>bdлy2ڏĆVu_)D ܍#Ig?>x3|N5jJOF$S2&=fvVG\ͼ:2 {} 8dxZҾ3e] +Ee H핶ȕQHgK2߰o =$A]pQ8zsN;nk +T&U ^ ?k9FdqB^[%ijl+exX²3RZU'uu;Igpz#'ob|dz~{nv bf{5gf IU֕]k-7m;NY57"l+=yUЛ}N6 LO~ V 8KbkE4i 0P"MExƘs NE%Skpϳ!&~G.pCL.v7閆kپ%> U~DHEgGU~lð6Imj#8No?3Siv)Z6Tj"mQZW1v\uKI% F-l`~b-gam|ipޝk23njz…g%?riVZonz7x)l Q`N?ξݏC:?,;ux蓱F`q8o=x2k7s;%ߏa:l3 %wJ9dz-¥W|uR:XlkWRRr~U…Z&en'l4J`y)`F@qk?t_:{2u67 +Qs$VCf3T߸G\,MՎ6Lc&y,>Tl )dS9n*w}AQZ\x<99r%$} K6pvhTTeRS'PrՆfe=2{lt43v7X=Z`T_6;sf&@r8{uյO +$eaIƢyXYmH[2'SNǽUx?_>,aIS~YgMd7Vz,B*d.Ϣ J3-f6bPb?hi57 +EQvr5|nFEy'v(}is=+,g\]ri_V>x˵㳷֯h[yhbmQ֕ee-U7h=4] ^Ξg„6:&W.eom;'VӢf=1;٭}ayZ;{x4IG>P?0o=o8o+ `&)Jjܯ hC+Qk]._"Et,0uOh|/qaq錻| ;dsNg~HE57zu}2蕬"wqb?3p7m9 }ղ|{n/5OŮ*n{D|:Vru9; }ECWχ]B[c3P=GQFQ^5Klsg5~DdxO{=/Cijx0WD4󵳁%z]vl.&i_ܛy7)&7!8>mshoy9Y68#}'1ڏ|>Uc ;~˖6FqGX>-V@9.&*\=z2ڷ}Oٝ'O_o/gC=6Xcq2Qi3So$6im[F'X<|7$6(hxh_oVҲn7maķ](W=Zu|LmR/,= >7s*{{kᣃ8{?HXrh=*Qc^ccnŨ?2q$ƿAIN(~Ek}ϵΓ-N{s8evw6`NMQ}q0MՋ@k阺. h&z(i* w 7bcQ{Ŷg*+Ԯ D}-f$lZWL ,v1ىF[t{1 ,*-tqZ>&M:ͤmMմ5 ct2=cN(^6[i7E?!۰džA]u%f8ٓS{gi lVc%Yvf %T^s_v-}qsQ€BsP4Wߦ[ΛEw3ҫ>rb,'^v)s׎t-~&%nz_XXkBB  Ǡj( Bj~>[:W6Y +Y%k:;gkΓuLz#_7i9)TD.$Cb< D?2z5~^N3KjdǮ%ߴq c. ǝPe-kjiN ;31~uE,lsֳ$el7h[@UԹQ̉`'7ql0z<0'n/U3~X*f_j=@CYK 4oޔ/9I-drlpxˤE¡ 뽂g޹Ij7c6p28<9/PͿ~oytu]' b%׭6z]Zdٟ6di=7oqZ%+d͇K߭\ # e$[ӣ|.gOsTsm+TŦvrdH|oa8Z={8au]Ln6]Z;ZDj\s\9%SEnmB[=){مWǻZNL|]ʎ:X@ϓtz) gdvf=̜SsxMyCOЙӐ*ɃS8_|hvC̛-zn {WS9=‰u5HyXDqXѫz=w4M׼XH0`Ŝnsu*ÚA89~.@ɉf^9]֦.'7iXf$c1=Ya:.|Y ի%hqo<8ri>k%'ۓ}ԄϜYUv[S<ɠey3{;xz˳]9cED1xyo7W~0?TR<PԹߩ?Ooş?R=e&9&McFFSw% o\|")t(+Vܞ7e tAQ ^;Xr4]kn/n!SP8A\w~5?Enp:]~v+(Rgbf< +R)ՔmJ<ۛ̉)@ wNVyM3/e9zoC!č"wsXL1l H\E/j(IvQ] ֔Rf҅WlKP +y!pXb¶jn.HN:=hifowb +W!)J񳊋Ջ +2Fc` +uaOn$}B!#[:._KzQ=AQo$_x 2VGT]]dMo~Xi7L^Q?ԂN8ȁa?e6 kc(5SgcK0`#;;cOi;4l$h\V鼕 H-1a+^|Ph'ؠu,YXTN|;1J0Ɖ(׈[Hb&IčS8rfDxEf\kZҊwjh6J öiΓ=Ef_{ +}lVlkAY;NsF؉{U 4 J!'dUzh Y]Z[00,d?q\-FeW L8 +Yp[@>f}|]l>nUp0%SA6Do{^1JSD8鎮hQ)o[yciaIu_ :m2LO)w4N5Zڮv%"/6v@mslMcً\v+.a s\8Y˨<h&7sb8]x?o +ۚ(H؜FW85^AeW\  }f}(Ymeju\cyw|ivzIΏU9 +5i!D0BMGwRfxn(5 &q(g2ex9~fIWE:38Z:Dp|"=^;MiZ!jrNuum{{ Y0x.0f19׻:k G[ԌVe9`VeܩydݵҷB2QKKy&8yZʺz"AZg5LBٮ䫫|z׼ [r͔۾ ,mG[v-}:n7ܜ!PbՐՔ5du_n1f2nA.Qb.N^+ ofɪ[}kˤυ֥#Gx*5s^&Y)N0לd႖S/_m쵭Ykz;XFCNײw +i +wc01$e'SNˣ!VJtG6$/Ὧ%p0>X뷳ivuCaUmc#LIevZ@b­fLl}7~\9[m(bZdQ}JnB2q^Ţ}BՌIB *[\T1Y}FÚXKRB/c=6m>2Jݾ0cF, +>w4=/g\YG>xȱ:E}vE4klv PGO5*#O|ڬXk=߂ƳY4_zw{K'z]:7Ƨ-cU7|6RFeOcnYЩ@|p*lU3 e8bds{HUK +LbW +:zSS7C.@mzW[x+D|^;){N9Ϊ||v۸>Z.;a)\q*妥HZ+db8zNSH@CpLD_M]$kONE S ;-9˵xerlOSz ib,bvIl!9H8٫6vhnj;+YB+edp.v1mXHʜ\q9  B~؜՝ECpӊlqy>_"k/NA<oLJ̥+~@k[W̹w+*m4gͮrX.a諭v 3fou]B}AVŎ-YJ*/b)xpTA6ހswDW>W!{yXm'+X<~̚~Xyaa磥w S~7#8]s!ށ֕?rTSL{#*✎Pk7wMIdZ@WOÌ?Hn]6o$KɄ~FUbj%u-)ghvI2|ﱱEX{2*i3&O%,)3})ubsAS E鵲b_˞v&p>v^=(4Qw?>jX' C5,FhEW*EWa`KA-bv/o'#Eg6%khGP؝WWw2tYǩuv2_2moqSKWw9XpT4E]0ג6׊6s$KQ4<ʄ߹*j=?$7xXFES+\M^MNO.PShV//HVp5V`0(Q69zvz|̛:9ü./F5FN YFyI4 M"F]l>w=j[?rn^P<}~jVY{s--]pXĖ=腖P?m1nn4OS/Ut-,QF߮=^zWμ{koe;.@c>_ȹw T:R~"^[̩&9\yړ:~ݰwyžT^/ȌU7Y 2RX`%qc/'(]vZ[fq=7`_)H0'5Тe.\.JxNZ+TTE4x4-K!`G|\sWN +hxaZj כ髮8fPYm]%XUMfЮ/-/*jmZMlZe[yLlϮܟ/V92r .zW:Ph~~;.o .'`Sފ .Lyt m @mZ]5.5c=\]CD+ϳoY6wu r 1lHC+tݬ(eؾ[=gQ^e6톘YoM7iNO&OqэJL; Acǃclsz-*dd5t/KӶOvKQASe¢qRef516\0HvTV_]Hi髡*`3njO4|H|/ 'x9C\0izeXxh_9ݘewZKMY)Lf՚NehݸKY*/p}ڢ&-1} G|{k[ 4ޢCXC?=e4ͅsx [,mFSwS6̉Yʤݱ`4t[]Ǫ/#8G +qw?cU;~viԗ&x(Q0;/jfv)*q!wp~ՁJwc+7OzM-;2WA>{Bf0MxK,l~cinu*UFe95:qXwg!2`j(Oa p~/z;;bS'gskI94LLZխ54`;gÊ/[LuV;*[Yoc\'־c`Fԧah +W›708391r~qgKltiMO#xaJwe)-UIHo614d6DɣW;W5byd/_6}TzNW崨$7"A8trvvٜH 3P οn?5U8Q.F ff,0[6p](i؅BUqznR}SVQjZ8/EE>׾#%1sG'C_*")M['dbdTwKܵP^ 1 ˬqV>mx\cxov0 xh$q(eSF[`Xo6;/[b_j\b dZƔI➬P? `[*ա5Zq^ٹDg~^4Ll hF#[v|w+EA 7g,ac#kIޝ?VG,%I}b{_Yh"!wZƺy^sKM b8PM8R=P_TQbYzt"}ˁrE²IݪGJWo?h4!V6<=vYZUx$:p/0黫xoI9߮.WK0Mm:]II"֧Nuw/߶,hiC[Rj?mS+f҂^9i uF4߈Iwy,7 +o05ǥ1Ͻ1_ViZ=M8;_~%ݴQ׮ Fu u,UD$z}!y3hl 6GuGÖc8Fjsvof;1tۄWޣqmF?cV-SieV,HL Ƚ.#Z|i YzjDd_o!O#bJӧ,;]>eQf7R.d y`g{XEN@v o~c`Ɛ3Uq|DfP^jbmg#u?U-&\MzoԣؗvfBds +E'-EY:TA]hK ++@@ K0U ~m2'44Oe{V鸩G7MW2A jq91jEG>$j;Muݮ(~!DBܩMK_qN?vX]07.NO,rN6/?V!K;kCS'5Lp+mfoFdD5(̙|N:CXS՝ne(B+=qfpުY[yzRAvFM3&=m7%yW՟q6e288iJ(\olgGJzCtlnAz*ty:V&D2[Cvk {MZSܩp]lL9Uu:rn:-Ig".uxZ3vf \jޝ/NdVZ?Pq>*vJ?he~{!HS3@/>jr_mFEV%lp-~\dU 5-DŽo),r+rসA3`㪝jjIU4ْ|862ڱt#nzhk`jE 4V4 ה-e6BSY'Tkʴ4ƇDmjMg zm =jL>Jn̒WCW/z]tm7,/UjHB]nM+ixM]?~T2T!SR7;+mHI]rJT6g}2-f=gu\dzVDMg, 5Y:cJ^L /=Wle +Mnd%1䳆 遛DEM?JC='PR6Js,rB$þk#,4𩎜d*T@=p} Cuѓ30=Lv&U[Ofߞfcŋ];F4.C6bm@,Ģ/c$[P#A?/¤^-U`e0o*֖0]7L_JKҿsk}ZihxW {{P߇,Χ άy#8{C%d0zNw: +i$<׬30i:evP]k3n,ܒ BS^ *(RPYﳲ+2]#Ku[:ޡsL[Z A&"T=I&P ZV#nWTe="?ȣz]H֫C%d{ gȚ4`Uڧ9HcMno%-bzjlؒMڕ-)ż"y/VX ^Kw:uK|?v厣}̀ha?_0wlxx'ƥlhmE`Pj ,g,7n2;@vdU +9KҖ~<-` ˽KЎ_8cHͧEZNҗϚsځﴒF9pa +-ñY$]%+-oPݹq^|U{ֲ_u[K4Q5Mjö +lJq(/,p;h +?vfܑF\^h}%5n4K`Z2qNY q÷]G[S3֣i" uZ |\T\Is +~oP"r'+JUԯe5}wuM߀ܿU q3o{9Np/,X'0lCKm/|47fmAd"fҩ*ή$C!j2Qzb2R) {^z2R7b.j[̦k!(oՈ~[1>+G'X/H>'%zYZ57_ultL f>AHKcN }3o9q_ֳ NhJnn󖜫=6җg *%6 ;G;#QJÒ yܪoRT|..1$ K!2QDS/hb28͜cʅ<~~O^&۩~Qa귍0at}XU'+ J8 Efq j64HctU;W͝Jh1{.1kGizD'!dv$Aev I/ cSaF9Ln'UuS9#K1}I)QF}1 +q/AEPSdZeʄۧ=AMt?z]`\oA3ЛcC_ +Ko~>B ݬ[~?wn+ψ23N}\{6BnhYkodw)3:2= +eU~H-1/JD vS^8oѢOaѵ[u6jzLmcaa"C^ܯ͔ItkFt:R}wy^o/`2<>I]kDv'R^+k續t2\fo *; %>P]8_EMhNY=ezm&w2}mԊa϶>Z}*Y25jo9$̢I7 ߹Xu)]ϻ>kR ktb9jz3^,1K?G3ojmq>'7°.KٗW !X^eGWR*S>ۆۯBeS?h(m;\YVmޙyG'V(" E<'!StdgYeCij]FN׈LD@!5_ov 1-aq~P#rSns6|j㞭^^|p +?2?-GMɗKmس㕥uŖnE~=v1a]Ywzw*LINϋ2zƹ_{(EeaWr8$~W™˚Ri8RxWAyߘSKxѣKy +&/yVL6N6ps!Hs;`S/>M'RQAH]meZu;S:( eeyxڷkQAV^~m ?̣Y"LYoJ[} TJ5+(xj@PC'iDj2wt/)t |l))S'bZ_#+b5&W寏`ꯝS| f[̄=6Džb']BD6,6R?k$A+WoI~ϊlAsɖCopDZKG0Fِ+y"]JtetY?(4 +8wGӪbmW ̡_"=R'zn¥*n@x}$fЛ0x(Ei9~xN%bOWF uV:ȤZ G{(luSb{aBkX=(Np@drRఠxbD}]O*8ϯ~. 8LjZ/1R-앛=]GKZ\k -E 3,BGkd={5m{m-7?${ kE(U9P{g e[q_zWx^&..DnLA>Ț(їNT;Kϖ鞪Rt3}q$0p< we|8 4k"6v@}8Ш3 )nѵPk Vkj}Kso:ІڎSYsYA21(k;LUx2 +LdM.mے$Æ5܌Ҿ OXL4֌KAxDFTXgB y;zyRwLC$\nrĊzWf` +'CpWG߅JĊ1el0_ < uD*۫uu줝έ_W -~o:>fRPO@6@_&/Ji7Szb̉=X%qFB=<[kvX4cg _m37th2 ZwjU::VyM(|uXF+>̒pz4=}V^>n͙L=\B= FqyYXo#svS|* +13qFji;kEZBMZcN4uh]=tr0-~REDޛu'qp#Q'S,~Э!#\Fct%lX%3bfT'ua^3g!E:)ZTaX.) D&t5ܔV?6,f =ǘ5`=*hGpKU+Tqasq*+Av#Q(+ ;P1zoݮ⧣+=I㨙6K!y×{)fA֛!W SiPjY']XgnqI"aG1ȕpǃ7lwhR4 HЂ8/շ"Y.7HɬT +wݵ~mrk .tBnwo.Ӟ*F~曎k1a1U+1jw7OV0hEoydxS}s)u +ڳ9Q%7O뿏;1NYܽ{:27*0~Nl*fZR{o=łOyl);n*wlPGGyMD/\p*n {SrlmE9(rdM7:r\1ݻq1?)4[lO%چk˅tNy>=kMG`(Rv?cIYbBFn#Ҭ JTѺd)8[^~BUۦq5̯Xʹ=jvKZ.|&BNr>'ev3LJ<ߏa*UG=.ý_fWuG{110saѩL)uS,S$VQ_dkvR_^*8VYmdO_C w p S!2Xg$ǑSm?k ,ыXhӐo,ڝG>/wF>/koT =}q{~VV -6mP|vs;%ǜZ k4lЪB(u' 2HGG.t)5鎔\m2gӴiQ?&^h-7pqo\% +;@^Z-p|vI@T*+m=> ܵ)/̸/?Ք\OIOfg ;%;4o:xI{Ή6V=ibb=fݱ$q\A+޼Շ:99J[p5NlK`¼`pH '=uZlNZMפ}淎ps4Ҫ:5ҳJlbM %M肬ŠLyZleK, ).VO̎o%XsUZ# 6c>F l![u'$YGO|<28(z{xܜfCk?ݨ[_GISrkh֦u*$t!k@r [R\aW*n4Mrtk G@2=9TaHzS޳n[k9lk**lckFpT6pE,?Gׁs];lUMuۼΖ[Bv8E^mQP5vP_.Z,$MƩB&C8*ԞU77=K|QtAGЧ$q&,fP<'WmdckRf ükd><(*[!_*bm+Z윏lEQ+h+{/TboBI5S'u+u~.*pb]%]?Rh]]S%d~ԡΉ4JGlWTnO(9d?.w @?h"}t-6ecz1>)OFr܇F$;FU`nN$6'ſҍѐ`IT™Dh4K#Z 4@v ~Dw-t[X7Ql_ +?_isgqg $ӂ@,>IP}E[?UTrZkŒ\wu"tkԂЎGJʨP}Xĥ*뿧gW5d,lX՚(t[>.Lj.T~֢?+6$7ӗԪ3R8*uR9{N߫qNB̿NV}7EPk%@t}st^٭*AJDI䜳@9Qw:ۦ3fFA:I pQTJ7Cyu2O-{[K۵j4 |w66Z}=$2M#Iny,k] (M#[@at9ǥMtdYwf. 8U$4v+=Z$˴}Hkڨ\e.~5#!3vkv "_ +X*#S'<Ģ#F=X+G7yu Z8kL _QGo<׽eGL+w<涴k]xlOf*9}z W*)MAҒu+&߳@zfJvB_]UyK&S Ϗ#ܧ#g,tGǕ#حr?vޑ5Nuᇵ4iP+H_ Re+FQ3M2n%^e5h&1HkH+~Qy<qLlfbD)+vݨ|[(}x6BE\jijM~[rάӰaZOБpj}Ao}ήpsA.|{wkkkz?་Lʑ>@q|wr-2C"; xuutvt&5^uӳQ% ҁB*ax[f*H-޹;&~:w+B7y9?%e|2(iK {FVd~Tt1|nzӵ;=x>an7:y'#%yW]77J|P?QﺎNOҵe &;(w=Jk~Ag&?i|VP5^.=oM)ZgrEO$ƞ#14ɎV녷-kg[fPJ\n|tt?PDnFIu:m;{5#q\ٷu4nRNX2?hkV|?;o 9Ҟme":t_n4K;l~ZmqPX>݅; j6}mmBwɱZ8?>o:X!jyN[t˜EE1;$Q{-aצ2DG&qXS= ]*P͡z\yժgK48̓˹܎3CPZGvҥ^;~ylYM]@JhT($'W%]V£e|R?ȁ| y~X,VCnڷi1wt)Ҽ};HLyrR;sEX:$*1%\Be7.I$`>"K߆3?NڢV#}XpE^tko[o%9s[E~Bf#^#Go&u]{jVAx ֳLZTοU }:{mer*5fZ_d%Ùg\165݆a +ɐ?,rB>ܻATo#ZeC[= ?fM<9 aPQk0O?ॠGSh 1pW}(ZVr$ /䔶ClU[މSrIx O=(qeiP10yآ'VcAi}Lm&63| {FGa {PdX]\†´e}TL }xi#3F + LYO1C.LcaeSw3晡|̉ZPqnډ˚3`m&V/>J^sy/V;Jg.U6 ˭H.X3=y9a viR#/V}YSt8H?xzpFiB>55jCťK_t&Y\e!"vvCHԒ7.bB۷xNM8NmelC߷Sk{ N쯒0 h'e8{XV(%JVwg_y>kjTFUWk_AqCm˄.C7W:)U8o39yxJxnůl5+"e.Yc곘ۓ-hZj::eN{W^6݀sѧqp @Ec2䔹=Zá-s9:3D5\)#د]F'ͻuP.wۄ;qa4Z˛TVZ}?~_fIӋ pJzi>oI䷰0O=̗41Ni%3,|^Cr$\Onib}V%'ax;._94;R톮3fAOߤēYDhlhf0*~as=b4)cr6_d?O}|46&f^V+GLu jCj9}+k+tr/F]ks.a^oΜ^Z`Fߝ8tu v(sߍXNC.lZ{0Mɻ7\Up ѲnI2T.>l҉85+0C߁eVLy]>CQO#i_/4fW3̗@V+r;,>'q4M801V!j~q8.G\{/u i!;/-* -tˊ۰4pS +քK:c[RIvm-{|zVG #0YmE ~`,f,PAyeE-|.Jao-ng,-*Z1$M+#U6vZHkY1"f[[ef;cNZ5>5< EF +Qun>(}iQfZaxPu1-5DT,xsi62UӬfZ ;R8i[v9GkVqjM0R:*ώ_{Y'v ) R[UA 6u(RNyxɞ. 建nVqUѨMͰb,̝[Yf'"|wv2ߛ&ď@;tU)oaװqvE7ll"T~I[}x`/?Y^[^T>p[{u;@(lptݽM+gk_y2ٻQxZm],o;{>Y="%9XclpgL˖_fۖдԡ\F7c]#+4c 18-d=Q9^E^b +r-v쳛כku+q@OJiY-Ɓ+TbtOn#.Pߋu/]-M5/-r!ژC͚jEЧeaEG*'{HV2•m<e=BP^eh|?oî=qd[|t~YLB<h.+h\qaU5ϪSiVOM͡wÞIS uɫSav>˂McS-i:gPGtƷ#xc{Ia~{=izkk]:\Qi =hda:lffCrO5^۰ԙ9ǭ~m`]鎬 lNp!5<[8sNQsaWlN8;nyPj8]|PDcE\@`DSfD$Zpfqc(V%t;KA+.fΏl]gpJPs=2vL,ݳӋ554x ];UsZSۓhd#(睽Ho#? wхIk\;8_<tcsJ!BÚݥ~g䫚QjiSX%_?(+nѸfn"vً]th"'M;bz&wNSAEބ#Wjoaؓq7:;ioHj[s_fWOi"+kV8VΐL^#jm;`jYY! +#uGM =Aǯ|j8t2]AMTPc|оޕ{@ey#wMKͫF$FA1Ve1k=`:[)ѶDž^RST:1K]Զbk5Ƭ?mnt2X~dZ#.>uhxkkS^aa\Nۏ5diH1Ϡ\`+&w|Qs5c3.pȒ*"g (%yb*XR`qB*Å$߅==ud#~d3Yx}~NY6Ȯ!:[[5w ,~m }YIP3r*mgd YlDIg഑_ /A' `l̙0Aug[bS> v}Ar|2N74*)).;Nv>wn4Vz MZ*v3V\¢K.k6K!xOk,ݙf&ʲW:}g_۫X+)ӷ +9jTjȑjT3#$[+enHA`圯_-bw˻m۹fb\hmd< 8|^s46 dJB[x.9-'uy\ܞQX=rCp2?S}2H"ŘtD lC[fPW2%n u@7Ro[W}CxݿY:FKQabȲ?,3{\zq{h#ߡztg9rο6Ԛ<؃Gߛԟe~Sd~o8t +~ݥh<8' +È0[/ʯ6`؃P׭{]*uV5|ڨxx|"4f"_F)ʣ2d{Ɋ/qPLuKN!=|8 +.;wpXm[|[Q}8\zc%7v'XLi}+wINj ]I$gmx<j ~DM;>"JB6uһɧKCmvE Ϙ 5gy7Ml\ UE]>ұCB0d0(ݛYE'MMT Dq>w !ZAք¬U08>v +Sz;%¾ BٱM7Mш@:ϡPjX8KÕpRqBvVsEz*Gb֢F~ &hyX%Z"ᠠ q' +~'&1_ 嶜4;RO& PtiSFPvi|$ֻ }9;ٰ=K(%wLQL+{2x@28r7vO[iG,TP[p#PTXg^ɨ^So!a~j0+H~U7v\aM_r,Iv\X..2O=+|KJ!ZP%z@zWXCv;KG%jnzW6)W||i`1XK$hZ)eڢl2j'GGԩQԇׇH]90̒隨=y;mk6"Qí04R13XH@"Yd/:B~]LK* /IW}:~ +f).\ʠ):]gڼSߜO~468}OaRBV o$F +yP4>E9厪G]򻖽`ݰnhI :jzבs 4"}zᩣOp2 +lW[YDkU (޺kVE9smcd.z7²?b & ni@o>pn/Ctnu7P8LuɎ7>~=\YV֌3 {;X{NZVZd}%3-m{kMTy![Le9Y%+ݑ>t kmN`]jGA>11{ ֬W̻ox7*2TnjH҂miנwQy Hr0侚!l8:(R`y(<ٵuApFDh?-"W}Ǟ9. 7NTbpQw|ޮ{X }b98^lg84|'i48$1 _g(M.{f2P1ݴvfN1zȪoN@M73۶ɯEZ}0=#FڰlR6 CoT޵Xuj R '2j +CzwЅ_@X&8>J m"kyyeu+ꎿ0ѐO{lLv81_ԤvWfz1RA-Mˏ8a:?I1c{gTs!#wJk>'wO}YjJdiPM)E`yQݍ5&8`*%-šLg筵:kmP+ssѾ~VŤ9x䬳QhlT3%#ہcg eU9X9Σ&y:9#7Ϥܵ?mIYؿKi*.NZ޳p)7x7qRnF&i=4PW!KLsT1}9fp2F,v>v;G,|Gܴu68'w 6&~a1*m0-gcQ$|M( !mޭsfWv;U]9[1:,Ȣ Сm-Dml#bv-W?:/_"hwuzV_ck)4sjńcuJJoS_(a/aY-0_J-\K./vϦz$Kwތ@֍ɳ x0wEo%!̶YwπS~5>[Úz;Խ|}Pw5X?n\ˍ_OΎ0carEks+7^%6{v4.y=lwouZ4oڼhZk qΞ>O:mWMUt4x-vn_g:ՔݚϤb>lj]1׫R;rG먊e+xdg 3V{A V^~4`ۘ2N +^ +?] [zTv})4f<+9K zO;߶y8z?YFRд^kpala8 1%}![vű"pn{3R6& 7^9"~]٪k@5׍*ouh&TK9 qD?'G:p#Z'WWDTߒpx+*bŞw7-,m KQ2@9٘5+gPAx();'Etc#ր+>vC%813ϦEzR$%{2JfSmN2XtZl6e*-OTWߪ}}`|p -4sx׺6 x}o2LX467gC]`ʼnF`¡Ky:f{|Qf02MBwGMVԉvrנ:d{| 3{<zpy&:Wٶtɍy((2_%RpZ>YX:x*%T~S)\53GlPqށ"[&0PUm:>vL2[b9h8cZ_V%?a:ہ5c2)fe6^6"u4]ka$=6 +ϫ.Rs& 'yӸqB҅P#ahv 靐A?wy9~ +S@)x +G%_mQ2>ƛ>ڟ<Iv~ +yae0"YKJe&SUkhj A&qm^w9ߢPwQsБFИ.o n9󿇂^Qu6?cOo7+3J1u;e˪-uvK8G_y:"z=M#>)#]>T;0)`{c`n~^ Ѡ+xr']PWEfߔهJSV3ֶTzes 5WWy0=’sfjKd|qG7ن&g 93N~;Qx/ M +Y:p)mD!n#o+ơu/@z5kE'QYl啯t.xh6%_7Hy$Cُ*:r2+lKR K,Q{6~U*=t(j._;KՑthzJ^[э>oD)_,zv 2f Rr]}}^z'VY/pc<&K-\2)乶vHDҧkVm$"bwa汸X/W:N讦'wNW;QQvTm(h-ٳR=J,AE&ME+8ဳ#2σ28 (( +"w̷/ 9Xkw$o[bZGwɉXm :貗vxVKZ$,13tN4kV4C +1/[\;)VsՒ<9u +41g +VgjSWnjJ'PtǶ6Wej5Mm%Z *i:U]ʳքBlOmT@~MS|qhi^AɛGsgGW"4ngž1mKj-ܧq56yvDx/Ι J̆YIFj؂c +K|DTK4vqU~:L`C0f0TT1a`wHO +^LKC~ã +m2/O߼c*5,8͔.ЭzX.wGzn#jj~F ,ㄏD + +',_:CleqJ&QI&g_lМ852jscS;emݹI LN/.^s}To3 Fnj>AG& ';.KpҮy+\R(! aH7!dp3%%0ͥ('(oTccGO[ +3 +{ZKZ*΂J15<_ˬ5;g)18+e3PPb*az$#8 Y=f}wuku seǪp@]yyz#dI +,|u$' }%سzFUi}fP+MKFg+~Yꍼ'e nBMP.2ȩDr;V302Az==@F:))A--$^դQizrc#җ~Y@o'GB6[xb >^5h5Bd(׿X*TκQ^ٓk+'j/14ީ|cYV)HsM>…c~ˇ-HG{+gsj3*FLB# Oa)Sv&6L1ӌ$:ꆏ %7*jgtI4`thm8^o;(+U++.sh39d&IdJK[ҩ$i,1KG3Z[[ahV41RlxT[ C,}c x.``䈉AUꐓ+2n⇀rϲL,66d9ދ܋;?bu{#r͠h׀&7D5 ▥$|v~,s2mg:x1#",[\~fx;$VGQl1Ui\쮉 P5{I'Ѕ!A}£i^3ht ]R:\cˉy Fo.׫)!eg4008>͉ iB P;Šk[<$~?HApsļQ#5k +΁VU@/kUiWYYB:hŰ 7tTY~ס[CSإb}Umn~)I:g٤AmUĚ9(f'n.LQݶy\᪋JmiN^}2Jأ5Ծ^^tֺY ppfI!z7W@zR>Af>Bt4ԇjT- %/\ZY%>BYa@2z.(i/xZ9UVlrBrM!29Oa:4ƶ`To|UJNgغU!f*BtqÊe~}Ѐi9 o8ɭatƍB.[ +{8Oڱ&5]v݉|Uk;J dV^+ S˽kO؅gR*V[QlaWߟB# +rwg_eSvCցG:4]T(&}a ZVQтSc b9A^*d!<қacqla,*2+{dIl%ݵdU0,{L813Z{cx&]Kо$Çh](EXE…4*BznѵU/ɽ_N,'-|2"JkC޵x^82EGIjϻLWKT)\?1sǚ3~NyD\ F>tb{^:Kfi +-,rYkf}eJ頏&"07%٭@JN-9ZIR47&Ofiw;@eG9$& 5*^wbBLCOTki RL՗4:CsGіݚ0nij/Ewlm^9+"P! qOBEy,+16Di1.0+vݳӾ"cy_SѼng,מic`8#n%}$rb3d6тxWs9vnq a)n {H;=ZSaR'_kE"3%*ԝ nV޺] ǫ3iThP=8 +j-7R*:}%'VRkxZ͵q53¹,c"g .}זUaU+:Tâj.uOI#U bv ;^R ıbXYX`6MJʨ[hOFw8n(&garI:M9kG#br<=g.m /ТI݉z`USFse8Bۤv+P1h}G@EތjR:3ѝ +!<)ZY\lwIotr.2Z] tfk*l]2 G{=+%<ᘾ ^1nm:@]o4A|Nn pb> G+Iq Vgқԯ̵1$RMlAhehQiY/)5K`nTisd*N O̺3̔CNl>bdhDor0/7)Y Qx>h d醙x,H"WOG9ӊv +n`zfυ{F#`ΧS@HyZ;}BXZȸkjK9uvoC񵴦ג}IcriŭUce<ʓ*C)iqJˢ@ S0S)n>Fgʻ[uf +e3_T>x:L]]t[lN\$JiO\T(a*fuzo%cj,@c~me#D9H*+Vc/&hRj5WV!J+Xd7C߽%iPkV:6(.[gg## H8@_8 F+\hkO}/tvk,F%Lx{w! .7GQDT#2~6dأvF&ұ^UՈbu9YddbJ"iܖa=o'Mw>'Lq'=7Q9,Jj]9y u9 } xqsk~*9kvXR?N3T=v-?̡WJ FY{=b[>F&&dV$Pvسd'qL -ywܥ8grT9]-i7ȾКuScnpJ_l|?zzVt(,yThQv!?t} |Ɖ0.Sngg}h Dނ\`\Vݲ8.O +HQň4_tg8jvD< O-( k͗pƘI=$:F쪂"6}+F"Quޔ4.JwXs E9υ;bD(zi@BL/do/mi$ |l0DN'x\|bgO>%ދre8C ? =I~[! {:0y}F;g*"Y#<={zO,_Q׃GS?E(g 3E'KL7GPAt1lLBg> eOcwufkFBi3W#Epa|r[h:\ܲZ_q==uSA6r*tiWƿ~)YL''.ᐬehUihW(McgU^mv|vd$r.X &d3uꯪ*֕fpj룢p,B XPdGWTvi=:cPe4u8{7=fC)_;tEӕA:/8"AGo߭ tUo&hg_;F eR ,7yݍM*ʰHW5uCn +oLW{劰IToݺȓFAf[ HDԬ]+{qR6+cMt<_)s@oub_x W+ԼVS3> +uXDxɋP[!S٭<: γs&̖SmZ3A/aw++\~O@GS~Ֆ>]lC|ox <ww Ⅱȫs p@b*m\n&ʑrNeCn-U}ޫ!|~+o( 0ڱ+k&KI-[[!7R)"o3o*`s DnXBYОPԅ$ppovܙiu\[`*yԨ3#~2?D^h9uVZ{[8weqk.w- t@ΚZy0c=2x;K;K}v6Sl- rh5($C)u:5 \D D`ۉirH/uj[U,xm'ib;ӺrAꖔ+blsYI~O(aRU`w.Hͭ +SNӁ%^SŚbc#Rc4-@1-9XXl&l 1,nzVwm6ڕI&E;1[W<2{[w$V'DӸ1XiTjg5%/2u"܌;b~gq:BZ^ z0l +zSމ?ln i$sMꊙxky{e-]؁1r<\ A$wq R8Zjmz G2lb\j_L hV=j +E4++$&}PI=Ti||rtb׶,w%( "[rnϗyh9Q}gfz ]Hrj^oศ_}CY=+zОX526G̨vBEIS{v[>"aE}  +^)nγK!cѯ(yq2% tjcb٘-ྍoQN>ȲCe;I|L=z_@Ġe,s- |*p.-@sy[@ +Q6Sj:V֡WWPŨ͑qxغdH?Rl-WNkxVH=Zke(4մyKg +Z;am`ܶjѺY+_@ T' o6;} +j.Ύxudf}$:8}dg~O\9h%yv) FOʄA'SnBDLK-h7}~O]"?{:lӑwt*~@L-2KZkFՠϟa]TA_֛[KMϛgI׫X̯v%g2s)¢}[K;h~?L;h~?L;hbK;h~?iO4Ϳ_3lyKz~ӖH Ŷ_߶Ss_/6z~'XJat^~&I*A +;[L/`'өdGݮ~h%[k}֔BVͣ6,c辕n6֤֯W)0rPѝ/8j:%`M=7ŕ0e>_fɼklH NsוRpt['$/冷u0dUkc"czSpo?h:i|h fӐ 61aI_&ozW=]WX*M2[ϰҞNgjϸ荁im%׬]H~ǡɣVNlH5 *r&!}iuC[rS5Z*_]dn9%pMsƥxyy+a6t#!i_AsԖrP:wlHi^[ic/X6}S\AHa;ӭ|aɚR9sR&@s~? @@OUɋ{^Eӌ5N~іOqmwĴO..:kֳC-6](]exd̤:0m )Q%Cvۚ:Ⲻ41ny *Ceفf|.O=W.eȷ~NuGU۷ t̶R)#֑t;+{}< ޸Y dܛ96 6ҩR"=wYkI\I#[j%͢F^Wޟ aWb1A{Se~(ݍb( K[}B4[gTDB캊 9Fy4|:OHYa|{+;#i5>S"4q`nxĵ> k.nekr^hq5b\ +L|:ao;3PX3xI*҄VA|b'+sLd[?az ^O9̸c5ڤhPp eB@Z>-pbvgf|&k}&X2V,^l?otxK 8ڳ X~i`>rW] +z'tPw%y8Swjd6O'<ۣxy岶;ujw(ݿo??J;z~?LY/]m9zZK k_mF/5Kz~?iA_l7_/6o[O#ʺ;rGP0c\}~Iz`mY9w(}]ۗe YRTԉKk#@]Wϖ qfe2c3d=~)ѺDfϷHvlDt9[>r &x\kT hp9j +{:lzN[SF*YoQ#6W㽪Cx?z)Y1%zLz}D_Ii.ਜ਼ȃQ{[eb-;sw,rΞt+~65|kU-V @=|:OӢOY7轒r V?38Rwn^йu&EkÖ f d!։bP.?~KSR^Eov5nݸgt:5mp=8yr5kk1ﺹ.=R8){W09|f燾?4B%j)Qȅ<ߝjf#`2!]>6LX*d0i:>SNx#!|aH+!%*REݪl>.ِN2AZ=E k |}~Ʈr3=Ai.W~Fν!.{jJ[In_m,yqݴ3%#B?~|2xH#:vEZkC%.!A )ΌQ\aъe\)mեԇ𞮦BNoS=i|Bxo4%̭iVNjiy]+gq=m ƾ& `x*/EO[~NJԉR=md4.7kY3ă&Uj1&<é|V7i)JeXTiS1S\~$Po_KNɈ{i^qs`e_b̲ƚlZ fQHJ~\*h&=(*&X֯o U/%H l_L J$d\$: k7J+IQG8UYA V(#u*_/o%v*Rv">G碬dClӶ],H#Vݱ +4sIq1QpU QyIf[.X HeTUv\cmwl+9p tW|Ssךd +gCsJlm#gi@6XҘ&q3w.8&=:v^]0̜8j9;YSico]VW +_pG5+4? )Q&ՓG3TRFV>/f٠,{mg ƻـƗ`3bA#-KUmb=d +GS-gw'ONJŤlga3WIgn{՞acTْ3>d\J';Q|ńS*ե,\&s.ݪ? tI#-"_)D; +$ kZ0zc ADGJLu^ eN\׬ hN+_c +;1@=H[ LNp@eZyG7֢)аBrma ;D L̪kTϮ UEMRv0t59Roq4/Lw7NhKvEg8q]n`Dae0W{i~L6ӨlVֱ1vB2]|srXY3xQK٢y{wX@-~\azQ:uZtךB2c7H ˺-yhrv2UETT^!v^tcM6b:VZP"^ː+ϒcɓV tDSW% yJɯb\}׳*Җf.0Z|r}'3w'=AZa|#k.oZخn%{/ -P´f]fn +R˗82-pW M|ڬ12,+涨gs +Bs~'L_Sn-GrVM]d⌞~4Andv 㱧 _BL.1LaUNKAԑIV"X%pLݯ{9]LϮg~= ' EsZO4Q|OUK+ sB#٭ӄ +x n/} +⃥u7?J;I[w~wK_~Җh7o4=_ ~[\SzLHu0 ?{z啐g2Ӏdj*wxpN {tc elU竌5n~KSzgdܼ?z3:wìUrŽSDRC~74Yٻx::2BRꐿ~m.oI ~ m;-̎ۅ?Y)5>dI}?TzC/=ԯ5G +'{;eYzysM +v>m4T 7p>pvX'XKy L ?g!cZ-{>\g%_# >]&/29`яsۨW5m'~~&>;`[ ')jfܿ gcJݾGDԯX[ J8f%OHq=$%z1O虻رkL04ZCr_=-ѷ}iE].VEWZ h/MkxSLsodLEE> ((-(* 7\yu__a43fu=BQwAOroi헯~!_(Z=ޱ5Pt7Eg[ɭV1MC=nybij4ȆӹӆN:LO-zY+5>o~M72O7!ɖ2uP.݇$b}2Qtɶ;E[@+ ƛ3YShjflOv!cz, 0 V̥!G?JXCɰ6(w_h)m0`2WEh\v;[z*ۚxz.`Z`f"?zOQ$2 g)'BQ+).7G&8'_n6# 5G,ty%ۚ&L,z&_4N'jKY/Q7K)=ndoᬩGlzGڪ~\%9%J ʼ0L67-+/CsWɕ?#9P_.HD++ݑ\dmPaӵA}l oىC/Hn_܌b~_řZ8(\98][m9`!\[GAN[*v"R3Ro]~C&%ʂ~eyRHrP{|^L\ΫX~mYh52m)-+D>RS@fRyUbsYD`)F,>L8gbiȲ|!†Pv|AEH-~{\dk%x속pD!<"Ȋ]xNN39[No5Cn|i~RNPR },Q\‰;#Q +'M!Ԋ h搣hM$lYvZ?l1x^݃ ?Kͳ8:қY%:.G{:c.˜BިTăŸdۼ|\g/'GpT4#> dTv –Z.%E j8`J& +TϚt~|*|)f\HV6?l.7d,މ!B\15&1Gwl#"1$\kmՓZLH!usQ"GL4]I,Yb0jG%#nAF>6E^,=Y(8Y7eF\4[^U[w#PG2sr&8;xO香V})ynEƅQMP.b/2g8ċQ;3ʆv1F*Ɯ^BϐxP93쀺7leڝ?Z-hG&OXcq~[lSR#98m2!@9X/95fFkWiiOޙb87玭r2X*6LGd#.›ҺMhv ߌKHܧvѧ +JD^C t2Lʆ1"-̼:Nt2Sq+h8 ].3:`WxmCMjڞBg%tbs$+"~!xu-Đ#zmHmxXkQ4(ބ7 0pW},ͱP%9f w-zX9#։^Oa-5ɧY5-?[Y:Qs6z:S 0{&qYɾw>혻ȁiq0*CD1~C^74?f /7_n/OWK3h1jwPsQ+ jPZ}iƐӁef!4d_q;W<a֝u`-)H]PdMr2Oig&&`SF*^ vKdZAmOY?a9Y`quCJ?Iz D ˏ@QUܹ8 E}%p%'A;Z3oi[ +Eci\d|XGs] t nv]7ՙG)֗88' +(zDbهoDZ}`]@UdLdE?kz2]j̞eϨ0MSnz^-bj7% +&Ba8ꌣGI",ұɵ>[c sn MHkVz{O~V%Ɯ]d:hұ]=o,u4@G MBQ1BQq>m'}J7{񗃛'&>Z^'S2`gr;g}LM1ƶM9\qwU+h(K^>~hn)8W}ɷhYb0H)0yhN籲2mZä~HjXJɽi^ꏫCP<Q_1[nAy>#"֩Y(_6' +nwy-i>FKū uٍvGe_ti[h"1o Ro`URPT>Skzdi & 7ΔWk R_Z&g'uMF-U8_ ';t5(_ LՊ<;nUW->?Mbsn:['jLev%7碉`;G +C~]`7:O"xT+H*?Ģ_XڎGD&1tg/Vo27X^O.S33( =}}.bƑ,l* Nɣr\9P[D/ѫ/ڳ+ļn1S\OXRŗC'`,%@m~M5K +PvƃП.{f-[csbkO{ jӝw㒃~2&h]cΪ*,[멓A~ 1JY8K(lxhYAelˏ{2e[*g$a֯ɶ>/ḳzDa{9 Veiq)ܝ 0c2,Z>6}/۩ɷ@<¹_Ķ: =]0^eV]H]YMpjq9mWC#{ÒHt;j)Đ?+T}m`'\*pLǽ`s }XnV,);PQqCxIi4sinr`= lۃZM={'a- 9|v`EAE_Bn#З>Zah^vubL+HrF)C앭ӆ'oѠZǻC&W4A}@ş JU9yWo^ [/cm%|V2M:7R>yˏvNJ*ôznPBq%=,m:9l,53Đ 𦞅2UO(}t3iz ˍOoɝNh0lU UԸM*f)8|:ëE.pz20ZJnb=}>(\PYN*Ƅ>vHh= 0 f.IoT!e^)s'nDI/C#P b0ګdt\JfdAl>^"Ud8iZωf+eܒBҚJ-Y=qXd[Gv^>Ѻd}=3u :fu蘾A{e5s8W W!"cd9oM @*_+Rc~e<q_-^0]?>N>x« JO*=z+UhB3BV6_:!ODS g%t6Meα _v\{Đ?+ݿ#eE:NZG|R~Hq`Mx+X +PR+5rSmJKfMWݣI2Ĭ5i2z8@!E>hѠXtuz<1#ggvԮR8K=.:?k ZYgE]XQċ +a?Rooh~}f ǢWkwiƐrCVBGvU]]Q++vK}4$w :`q+PS{Y}W7IaoSz7etJ7KwedPnCt1!4da}JI(JW26٣EI]hqQ|P3.{[(aZ<{a;и9wb@es=t@ OVma8 PsZHҙ;>ݖ}]ogO{[ٵ]{^gn,"|$8[^ ׍qy/UsOu!,|`-9y Y `dz@Qr'5us{HGlǪE6+x>sctF$m{tڬuڤg^# SI)ܡ&Y9;p+eP6]˽NX[\AijkmJz1NpLcD:=烡3*KE[eVJ~?@i86}>G:I9@c˯S)c[JryPXu}t׻c>f}uvΕ|l~ {ʝAѷڇ!kJf%Gv UªB%}olgt~~w31-YlS֕$Ikz^o5% endstream endobj 127 0 obj <>stream +|<<@wg W31v/Ҋ ކ=1,wy0]oJ\ꔪKV$+w(@W\n bȟ@Cv +?KYeR\Lv݆Wh+SJXlNDNRv-դ*+9.uW}7i/ V<݃͝@؁.p'dn&y448 +߾bmRXwz,塚 +Rj oMD-b2@M6Ea4zr,`8 %̸ΤbwOˎ;9CQݝKw6y]*_.?>$ڳ43qTiXZ!Z!ZLʟA1NAr< |; 0Orq6O"K%'і5ّ9JEy ID" Ss|r0^u`&7yܩul:yu_FЯTwXWh +E"ITt|,4Y}uP>F[FT}NË+/oNH)LoeSzGىt1'Gl*G qk1C~) *% +jU~{rS]8us3TE>&Fst{MEd1`ar^:I_JY0ZTHҪp2ҩٟ]za]rr# ˄.St)g' + +|]_ga=>E Ejj@9<%*T-tHJ q=7C~'?A==Zf*$O-=%>b=)oěM`k˙i_P6g1Q!D&YTJM btJ-۷%Wٕ䮐뵵Ai(NkQӍ@ctּ1\'h FpQV7 /THNי7a_IM[B yCUJWiSK]Am4S'w b1λ"[7Jf0mkN5E_rXZ"(1+4{ +vvM nь +2MM2eA)ͱݍaنr#Hpa6 ๠&7kI^ʊy2۾Y/Sl]Pixǭܱz@ޣ.4ñ(2Ot{bFEQ5AAF{?!-i_"Z2Kv5 ( w{ wG,>n"Rg&xfJeZy# iR̗F6G*lqѻ&+ecUiYb=9G\!txiZ}šj6Ok1kܹ!zr('#L&)mRK&:hG^לxD 8ձ3IttO [Emd@F؅*4䉉SF 6ckBj{W3!wŒ֣ 59+ͣc-6Τw`j_z=kvZ-ض bȟ(<([P/((@( V#rbA=|W5}wdKT qN/z,>u +a]xV[iL-1BK{u|_pOE gT1~C3coh6<( +C6E_Q~f]SfK}eRce'6[MIW[WVoooA.@;>(hokS#@ |'(#IZ-h]gr&.7=|!y:ukuJbqgW?).mHaܜGmM$؞{=nW5g)8-ڵ^³{?";8J6){{-b2]|bTcV:);"G=I#ag{,ksǵ7L6#ޮUkq4.Qp;?脄U&kve.~j vM…XO>/S}Ng F +2ugZi+D)eySZJWgfKSuSBRĕVYyIKD/Lf1??DѴ%Q`U&(7=kϕƳEqpgo]֌Jke]5dNꓢRpn)hN@(B@p*@Yjjo-|I?|[ssfُEyld5˷)! P/.ܼ? a!??D;>KPT]g?PDX +u},4CܷD>>Dm?~2T%./ܼ$*96pt<,#9]|~M(j*u +Euy* {gS xI'cUtזzTk5KCM R|'fKsƐi6&QU`d1nFwTI/`8A |e}p>l CA)eonhȕe{G^p7ivezGu|qBSj"&㺖Zy\xF,s} c*o!ײ P-*qN x`DuiGgח4']]4~㥘ۼ}߸wNӹm^Uܔ42tiԸc]cT˷Y+QBq˟zMxӷhӼgP(Ց5e)na2d1T8}x55x1LFCy~' ytC>Xn=j4;ũzՄCvq^ivcBQX:wt*pq0 +s԰lSd0~?)@wR =cO%t緝UVk^ܖ-0'RLTUX]m7)0DQ ʕ c[M<@+fd~hmP=>~QDp99M i-,jy֤G,peOoiQy#bT}Љ!x <(r(&.l*y{T}}*kQz;k"{1D6sJg3'||:E9j>4|W +no+&YVlþP{ +cczbȟ2ɟPĈk k[JZm8m +k:%nH^JԄv!glG,]+v3.=^qwۜê>ϵbȹK1mnR_C.nVs޴t``s.{.6pFVOQxx'h0Qz;bHoM=,|ܺS\Cbqk6<;Uߙk +2q&Wǘw^"AMF>ӿߞ/4WT~cqBvK0.D R<|AcMYF$?.gfGtTFsCiը$HW W= +`1az;r5-;*J7#םS>tO]X>ٿ縶)ͺվbȲk *3&&b`Oơ9fރx_Z gE,yb=%]swL;%;BwA/8۾p]6q!./}˯<%Iu-0/ہ"3]~Νz +,.~ +FfKo?ݮnJ(*YEڳ6rUt8yoMs4%=b5U6`%zoAxrJVm"w`}6i(nj{turELe*Ev9rrM}6q}m{m(ԟG;^]Eȧl($Y7$xN{T.){仹Rr3k9Լe; O/ C,/}Z-KpBLAM;cVF[O~R6r5μg U@Jɴw~ i +oX=P-@We8c% PX7g)m=ţ +[ cӹOB۵GcmHncFrK߬Dsy4O,,7Mj 5q?d/6yC.MfYYHhS{ +SjnwHx9tĺCQ,Wr=8Uǿ +[| +6C/k_!? ?Dyk b +H .P>Zf s> +sUөux>!f眒ϤS\϶}qK/Ǭ07[{Su* <|ޖ,[sT(ف PYwV{.(|SxwsYf魴 : *ݑƁǚht8 ^ᨹuՆI7sK^M!tL=@~s4`y ?>w`-zM>r r]?x1Mt$u'*37rIuGlIIÅ:z*HLmH<.1ك8 uTkMOt&1DCr H*` @}Yjn(d8gն=ou'2 /̏۵kEɻy {. +-~o#T̓X,mWE2If'b6٥$%._R +V]~/gPy3\d!HӪY޾_V3lǎi\+y$G%#wihi Zm' ?4 8}ae ϗ=t?Bsziq \榳YS^M+e?IT*SC3kL8iZ($D;m^qPLl>4.Oj' +J([krNv%1)}'T>jۊ,rM%41۝Bc.;(ѩK!]1PlrmX;(=,(N<<(ȭvjUgiS]biczsPݚn(z>f6fw&soA9ourv_.v OVn: >+$WpFn]PXp NJ{8hk{kDvoܖyC4m紸*+_ۺLF22}tnwQ8;'5ԩyN|W:'8hs>#*cYrUBn6;;̃~@n|nV`B7 oT(||2d*aQ< ܹTqyԽDo&8Qző:҈;K7tk?ؔ]qsE`d\6c7xzc(q>(e_[PFV$z[G]iw3CTp)A57[ubI0syؔdnuՉ!QeLU/R>E?fctdl$ ֽ2r]l +Ew& ;g RGԣ;e7vLO3:aPoI ) R:[Fym\\0JϪ}ݰ,S9@l 9-Ri,h.v1 +#! &ժE{+|j9Ys9vcR6PBKq/Ͼ]FLvn M ۷V@kM,q0۴wÉUq1姣NOXYI goMFƑ;?}cZmB b_(4(ĸ</x] u$}v97l1:nU^-˛yxr,$ᨻOhR)Dno`u'"Q"<)gj |fJTV䗳0gvBzcG_/)$onfv>ݤr9!eSSRl+7{eQ|\!yhޙŴj0"MRY4w=_cdCTܮ9sZ +0 DKcHr{2"|o 7!=wiv3|asr&/|VugLX]ҹ~8zksm[/&c/cf WdrQS!AAbYU^N*f[4eҨ!22sM);)$yj}\xA5sW:H7xvpGڬr,ájp61Xψ@!]'\调C:ηi_ٱ%]:Q67p7Gka1]Mp*k5Yd(ȳ/ܤfc1d>;|\ҙޞmzke*VZX;k-ԪiOCӧ_|0](lgoFAPu^7,Y8e%wXl{EUw޵-޿~l&>t&uѾ.v!|2=V*7%rhR^#<Ɇ2 e~;dtjH<*ش2Oe 8*ឤԕS1BjHOJ,yYWwEJh_%w.GZVe>K~46 !umxᑬ|m3C +߀|LhLh$f>x. 1Z&H^ΫW2"]sw&a=kЬnkl%^2Sy5ckeZLE,ݗVcSM Q8gF`lu&E @ ȍS;Q|\dwOh^1$NOp]a=}5P>n~AfѶ+ T0zODa(emOPs(r"R"Ջp<Ƿqȣ<+Ga®.v ]M.^*u<` +qk b/ k` KX)  +|]X&wO%c;E*1]S}VBº,=Hwiq[[(u6a֜uu"пuR'ȭ]~1e[9PO/1cAc g(N:§KDs(Q0vk߃%[< i/l3i8^w~{J7u/5pW,/IX6O@) _f LDKFK;Ug;4vvl,DQ,P*Jgwfӹyw'2v19e&Ȃ( ( +@+Z‡n85{D8n{*56| 02X 8 KVAz~My5t/ʡ:{X^=ePsA|bdTq*0*[̋0 ɜED * wuΪ=׻|6݃$=sL7YѮ;uo|[\ˤl0篃)V z8 @О9<צ5K}_e +-)@ C([re@>QUWZc; Zyswi:ѐ<Ԫ+=u!9Uѭ)֛plzu凉ԣ?Dg  +w'AD̬@!MnM3XP6s*Ur˻-֑WaD;ŧPfڇm'w_VtҦQj͗69HKIaW{)9U{L{ݶ5* 9Nvw6e3f N̯=~}+m`Sʃ_̫?Is5E2^ᅑ8Ɂ>"S3"gBC{hh{C7`E8WW` ߎuk}t)'S`v*\-hf=ìw8ؑ, C=D^*!_ҎsG::}Mz:\{` V!Zܶ+X=DF}&s~U摍0Ng߂> ĝhZz!`=LVlQ˃-x2R,9>)y HTi/~6A"fK_Z#+I&/Vج=a=n甖f.>ҤeSY46y %]wXlkm|&[rFOoz+`G \}NO9j/J/qwGT;Vlk\mpϸ H^S}4cWI|@burSz D畆霩ϼ*ԸLZ%+_/w=^Re3 t<:uMM{ȇlk]A(/$;+ZnKl5f(fޟ7歩S7c=^ Mb?ȟb/8{hAIf{ZefLb"5{mȥKnZ\J~#4nt :Jjzj}vR[5Fyr&i1\G,n48vj%{d um&ͻ՜R1g]{AKm)M>RUgƪ\,U3Vi#)yu%-#'Q߽b2rE- Å\19u|g;KmԾ{zVY}dB;7j47 DFś,oʩ?~1x "js9֪ʧTl)j r;H2Noܡo˕ڵ1gG+RHgIWB J.: e<5J{ӅW<ٸX,gq!@P}h${W ($z`YQVȽ#9H +d9Urzm|±8Urk~\Z~ s)~-Bh(tX><YEЁ;A..礡yjT;j6N;BSNRc>lnz g@+Voņ08@nKN ڃB93PkF^QHjmU~ V5F |)τW^*(c=ǫX h64A l9|Vq0ǒM[*Ijܧr| z+sg^y./ 㶵Bc:ğ~Xn`f){4 z}rOA~Kf SОVrh7 ^=A^B˿sSu)E3/Yj2V?n{}nw.#?.| e1O {Y"] Bwv +}fN^/}"Oy*$ù8yG0\_4S'u+<R,ꎷl{C}`Rx,8H_t|\){\{rȣ9wTog r3ڧ_7g$O7#.m? +]nFo: +: @ bre6Y^%!%oi,ZStc-r6]L{Zۮlnw|z+p_c?` 0:`c_ _ +Ϋ*>L.wa勣{*e#X]pJ$\vB!sHL#ڬ*@Khxsu>Ig0ZπU(tB:ݒCq%O(3פi$%}t+:l[oy^wjW G?W0}|oumqmê|% \f3Ly5rVf߆  +$7@}_;aД!M6ޏozHX歟a42z {'B =Ylƒ>v&;oF絑"dwϭ:)1Xa.vcF0^.B V!1֠ŗ=k]\..O,l0#¡)w:ں}8nWVN&K6VF/Y$kZlFhlC_fG +ԑ)ss=m4dW+|1yc\ÍU lc֭^9ozz{Hy + (v[/94>qʞ dMq+T*uvϷ|rzήvN!Y\^ùadnsYi[oZՄP+3Z;\\& g|S[o99\IUgUo▒Ne g]M0tSy׬g+:y/ (Զp P`Y~Κ#VOQ]3o@^% /nJH,i>UJSfF ˝Aקy, +Xx)4/w  +m/K"($(T0=s<ѣ5kӨ0560{7adƫaEt9?PZ0>sӢeFpr<>7cn +w!!z,݆-5bé 3^[B} enrҎRtPoŰN"` 0v#`.)b#sFL +i5zsu5MJ; b)^13ЩзP_=y`A৺g% +Z\%TǡN\F%]j9,}l26s:u0zNk1 <óymďmp]XO?IN|щa,^j{XNikmP[c-^UxP;gK:TpE ~5>|Uzd6m ^*l1 +_`%%9,a lk nE]I:lvz.GewZƣn MO}-t|øI>x 6 ^E̜y:uޯkt͞07JP`j.^җ]-FDŽKʷRߡC׬fg!R͘ަH{ e^i#)ǞvQ|^8uԫXQw+JZ$ gg2;ߓL6s9dg蚹޸|,>i+ aA7i/?qE߬Һ.ta(ݠmsyuvW:ztnpg]f 1sc_.{<4Es #;W^gn|ZY8ٿT@9HEe"o޶RN[@Q[ɥ6>=1p)'FuSVX /6 jר673KY]ኪ}t9^ +jS4]`ȏnj)A!:EqydN +yBč3#[+d$|AVշ*kTUJrZU5>:J!'p#>?4NIWbl}reyTԵ[Z^,ƥƮ3:{2[FYfSL+=lk,&ҩ* 5"7]闃NQ}1;x(;JY.9׉J^yVu&.]ʉXDLofGk[ˈ JZjy?It:M 1m D_T4wfhi|fpk43q2Zm)Ug̬PM5 #MogOL^-ǭ КUwrZ[ +RꌺjҮUn,4liouR+r7~B´ +54 +&[ڕ _^EVjxhBqԖ+̤=WuYh|T e<+ogCsIit]h6?DIԪ9괉ׅ㈥*~ LT&}|ҳ&12u^/hȀXAn "2es( hsudN8@*J Ut?/i(,w0oߺEw27\`̦͏* +؞ XBE +}J_qZ%j+T{}DP-SZY ˿9Td7&t+J>j䬹 +r +}6Д VQ`VP*B# 2@.?pZmnPmbQvPjw]t; +j.Aa`-"{T '~?&J9@[;M2R>T{,.(BШ8eNP@ +o[g浩6gФH;[&NQOak? wvШ@qM)e^-x}A`g(`ueGJJN|^wT;9_Vg;b%7Bods~&%Rw(t@ OP+UXS)X?sv\6t'rZ.U2vVcUYN(6] CK{{5)"8'D8/vZ;HyS Fc/xf,uX_-g^ݍ-U\ko-om4힬V^ܻbjAɬ_78DTA r*#՜#^ғOmNNlW<)uQE$yKf7w6fL=jI@wGq+TaޕzN"=A)'F$!!'%uxD(0po ϟ_ + (DJXZQ!Jg{23nmt|2XscMd FOp mk|RK:1L-m[F)Ack 3#gXia7WJ9J`RxX#"ëHʬԫesboV?=z3&LJڟV`MyЧ)^M>%V|J&_|*7P#(oAN5ٓo61zwM(JVB9&t;U{)RAmEC Cxk{Snq<~fN~nTSOT޿v +}gPXɩ+R':z,iC  +@z6ȏפ%+{2swUb>t5+eRNg`n?H]>7~lsb*zȍV_M&,(_=."=(ӚTE8*u] (/80򰾧Y5wo@-O9JNm?kàc򯀳弡Gv%yi1OٵHj>I5Ga9\&2zXw}ێz-̸ZX0{_pw.ݍb+Zl=J7Hh¸ME^jvj⬷~ľGof}̢ uf=iG]D/sJ'Ŧǰ &<`hyL켻ܒmKK{N6!WVAi4647qmJ?HZ˿b-{]}yMU[!Z$.ߤ0?5ǰ,J#og ]ԺTP:`괎yaF`Gli7nw#7vqMXO^։X֭d/٣D?3,=i*1fT~I>=ؔm5BhMZQsJݧ KI?H3ixڮ]7a% 6Ij11Nu r(/]h'_ H'"~mV_h43H=[WJV-ԡ$wG)9','=?BF.tQ9qkzQUd獭L΄ɴWVzkU@yfbR +AT>e@!{~SnRO8LjAԯxNrTRr/rKC9:~p F)6[׸ zۇ+Y催!wg,_Ye!8TAVjO"hNb@_@47o .@ʷmC8Pcru|Qu\Z @r'_.JyeO{|OYHu!__@SzݶKi<86jlD624'C G +56,@/ F>uߡ̈҃3ANO[>jrt]_;%6oM< H |zP)B~Mšuă9@ +JV63@* [@ϏdжW PcV9t(cVO +`65;z@ rKw1@bJm&=zhOOݟqI'#W +/[{[%pXJ +DrM[h9(];4*uBS.c4:ȗ]ϽpP1X]#Lưڈ؊\ 0`Ր3ﻚ\+)@ +u+hE)Քp<ē|*=$㚞q?ȹ4s= .*M(S~Eo|225?j͍@ޗjte:TH:~>*֏ǯv,֫;whn};rPj,ނxg:nP^sW҇caatqʜ,#F ev>o^#v.N"[klB?ӀFJjKT_MMZBVB$b\ +#o;avjíߪqZ_DL5p>O[K^ԣV0~hu.3@^ŝdu8s&{_+QCDstXZљ\nALqgPp׎\9Sh}pU>\+P/?rNjSz;ʤGinTh1iV E6H(ض eJ=k"\@iィp[K +_Mb3<7KuuEc=ݖfd&qMSsRe%{Zi/R8Td0;`rokޠߞ^߸QCEF +$9: YEipg)ȔxDLΤ.?VvYePL'iK"\&fpGo>SiI% 9#U pS@Vv׋1#xFp(ֶ^ D.qS>;f +UB=ݝ\lj0fH*cG _ sO>"+4ÊL{ ~ -y#6)^-LZ3yo&YW7h59ǜe f6hϻ&o_?N!G?}q. Z }8I~\05Vnj~\m#Jj]!W[[o Ejk>%=.dZل|V綏ג{aHתWw$?e_Alj2ֳXU +056ުx䝠)V[4Dc?X5wv~W4*mt4 WrbN⤴z>J3^w#:gHu0uIIxyrv=^O?yg:˙T-IU-|%"0ϦGTO{6 =VT%;\jj{hs,s׊ֶ}',+.LA:j&m9S_r\dD{>j1#$+/C|.RqJ }k;ԇ<}xt:H9}ncucEnX>-=Cw.6|@wwrĝsiKA5>SdSƍbk/k݇UT3'Ѥ{(xyk[eÉeX:j2cfVjUS +m?r1l|Jk[zbCfI鴬QP3;حilVVXʣ^5f\ž{zUXFOT$SQd?ÅrvB.L$+Lӳq {+tg.x >3!mF%}nSpmmQq[BGWܘU<%oTr,㏏[۟M4~+r8υ&JB#&^4%S~+椎 ڱ\ķ)9ײP! h|r \Y˅Ʒ]f)u-L9|ob@2"q#꺋yr DZ+oޒX  mv|ܪO'f҃*nf'n @1N@6e syU9,x#b%q.OGy.k +E(ќbJ0;ڵΗP=30 l5*ڋPe +YP@xf}~O99TPuj @8q PZjf 9r40Ej/<2ڡm^(ۍaj=j FYS#WgtiLG@j}%헵NA~ TTXQ!La56/X8]qA*TؾS菝U Lϼc#5gK_> 7xCJxro>0|O @ͩzG/!6񃽲f ^YzRcBݖ;ZŽ =Mqj<=#@bS9fw4q^1xF'Hȱ},6B_Y,ή˸youyW=u_hmW#vW;;4.S[`+PhDL۽L K& up[L'0 ʕC2铐q,=g X5c&:(W_V+<ؗխ%˩h4N7/ǁ}J5{rB # _o=ê=nq~Z-Q5SȺz`w*QP>Z< _u^-vݝߧF~Gzusl8=;>ZLK@[!&w9Jx8wR=8\ H g}+}~ui/&qζOy1j)ixt2UR ^\]T\+Ko}9\^9l/S~ +k֞ +c~^2DܑPqvq;ύP繞6*J)ox20#LckJ.Vѹ[:@a&`pQN[dC-s8p>dOm_X3N|_lnzylRXN9;ySB+Zb2L糼dy~e2l"lX gZE?O"Ӄ<{N +6;{܋m?Q"]Q69]'i%$ny;e?FLVf/b@?oB2 +di+rt<$w6L突KP{]nBsT}mrga}r(]׹*唥3F5?T2q^P\,ҝSu i\Y.)ɯg&ѡ\uҩz(rxw{7;#T{P!oW ,g56\EZ{N^KubJ387fhΗNG<,Z0 D +3ZCK?/^7)?ptŐK1ǧ :߫ +Fc+h9pqK8iw7_2.Qϸ;zm^GWʙgz #O)NQuXWߚQ?w{~Xt=C|xl ZRȟQ[:S +>0SZ.RGypKa:)b1 ?=3ͬm.H}{'N@Wڍt V[B_=RsPiho8\i]?  +R"eAQq*y w { ZƵa}̤1*kj0.G+h?X&4n|J NnQmtVQm+^Ӷ49ȫv]U<5.ݮ߃+dFnȖًL=:臥bܺ!YN*}thVmeE1TѼf-=xEN{Op[ګhRvD3o93c+"! |5gɃ;<.qk,./xz=~u,otiU(5ZSZ|it_qJ:Vp8lr׺]Rx^"PLwSYjM8)Q",RQyfTR:Nu5ζTcޚ`}kTp?54.#i!7s+)lW &g\/dAι\*6_Bf`ĭDsyrPe[\iryv&MU3Rf6;-0s֝6Kl̂֩Q]ۄoδflړ{G?=*Fδ2&Is'.HRjTY)Sl3aMiFwlߦ5kؙ?XVg@4E=[oFeNܝj9mjx!`[i`bUcIwhra=&(CSP6GplUc^>%)~0Xsz] +?Xr;%BJX/uYX+a]^ދs?$EeZ |yLOCS9RQ+)ŶFQhVL=z;-ktf}l+Gֵ'ЪCI](Ԑ+טS.gLb69*Y3"Y_:Kd>+ x#wyG4Qp&@.@@uG5:[n@ Pjߧk-D2iz)b[z^<@pր!7L6O$x}}8}w?B @OG`Hv!!1@NK P֛,r9 +I؛zg  `d  z`ɖ0!etDoԂ@'ez,2/ ##G]J@{kBdot|zhyS"%z8˿SN4_>~-(xA+?᷀?B@G8 Nz%yD:nmt_,Gk6 +Gd:`"yuJS덋dky!4xqaxwӜ8웽>wr*biZc;֍,BFX΂qe +Ha=ϜnnmuZ/x8!}Rzmg#)DA?pts S(s!_2Vm0O+(/'7K}o^ջ'\4Db'y.r\oL|=dsN+m9ַ3nz鴵^af]d57,tиIDnVMD(/nf* 3hpj㣺[n;.Gg;[ V-bf=;ĔR6r~D3 W +٣,'{|I9. ӎcCx~*ev v ;ڭsw[틎FUvY,\ٶL ;NU=!0ڬ~е[bDp&Bl5MLjuapwB搜YߡEilf>Oy[uUxrI>鋒/XtNLG3;\^9*:E) +Wl +H|]8;8IBY폓|0z:Ĭʬd<49VVbҭ:b/{)2o +b}he& 6v7xQ!}I8h?8y˻,YtWМL$V$zϦĬ2H[nDD\@ޚ'A%LiLƃ8YB\'bIArY:G۞c{%;^/7ڶ.'VilVHKri=t<' ']ɡWHp-ܥZ0?64GG6RGͽeX)r4wdVmiY J&l +F߽dbtcqR +Nh2Bf! B| ^[Gon@{t1gXԝH"ʡ*W~t]7׍ƸU_)F8eRO,>gA}ʸ4>m j=V-nj+7ׁk{ ň27o{wmWKK3(ּI+׈*Rw:U6l/9Δ,/]JD`fiXn4\5DksSdVLh򹿏d^6?k@ XNI5f>A~_{ E;Sֳݲlf?d5.gW': TyNāBur6';(5[C Hn+Tt;Wf^!z +8H +Cy*dL?͵Dd=Gsزe_ +~^=g49-q{';Tjb[g:5€Ֆ~"z+eS* +8v uDֱ֭ok:х$Q$>MbeUwc$ [ z%f(k+nHQ?l!.оs=i3k6:SͣցsIg;n3t3]7`0{@c^=b?&My1& 6G9frj0eJ+f"eR)Lҍ_X}>ta^ٽS +eJ I3'Ei6UjDzXZ̶8V.4yl\5'ͤ"qB_f6[S;խc&`~(hM lެ!O3NLrm48RzoJu6)%KWZ$91P:ۈÜ*GӌzA׫M[̼6䣂iPGjү흚Q>5cj-"W_P sm{4beNW*޸QORǨ^"`ۨB}i(נ٪]E}iaZ2Gْgܓ犧C/J,Kd)\ovFa?00IqVt~f+j(INI9hήI~>z|9Uș0aR>(i9|⭊2l %; 6. uJ#)'3V,]aA4pRPaulPi{lwPUSENL[(y MU +5j5 &:˔{*է'G81MV/u?ld7,r*8rqOcD,7RSEP>̜cIh^Q¼ +M":K.{I2m"XC1edpZqn`2XO9?Z~Cn,@i 5H]Md]  +@ơ^3HNIRm Ƙi H=D Ҕt~@ 4]lKxҽ9$^ +V5\_m$@qv k -@ K$߁"H?/@z_!'H/^eHQbO'C(u߿b|Yx??O[fi8e=@;5 Y!@18º}=%P`^gsGSDq'lٻy*^E+eʱwRAb7&oOڧ%{%u@SZ1]X8ۙ,>jzllBp'N\=>0+5Q3kf;:Nkl+댵y֫^CcV*'u @d37=gw{n݃/sg=:-#ՒۻI^v[EFepIi睮-Ǣg s9oBAS22 _V޾[sx8VKŕ!+}KVi`jee0YRzUeiEFaoرW&: SrdzV#|ϯhP7sx|p] rbJ@Bv{YhsK k ˘,M*({B4ם<;+8y:]X&ih)+'ZzQ _4RG ^nzڼ(~DIH mksRS8v+wzv[rRQzɔYH{㥖U;Եգ-CVxbkxvWϞGzÛ9f0,h:Xl#OS[;ʰUDŒۆodcnJ5URQg8 Q=EJKr6~Y lcXGtnҍla+g}2}2> >I?j޼xXg'!ެ:p\bn3?:9yeLTY?l;>?2ӹ֫s8ǟC<2T 6ϽL6 ]h)t9??'x%wE}ˇy<֗./F2ϫ%(.fKJ@:Wa"~9UpmI[ wٍRiШ?)'=ů宒}}T~tqLQ{PA9) dc?^ m9SޣqUlHLRX[qv CP\ ^Ha^;/`* pA?Sfly_U m_9xe])HXEɅ#?V}]>69Oㅶ+;V) ;jNX=v<n$i[l$,/Z*vZl#:+x[/Jo)7FT"B3e7љ޶857%(<]e#E+To}xucq.eޟ惽4TMgru+V`Pnz$B\ЃT aa@wSf:,lTc]{ܑZ^T 2B*ݵnNI[$CS//~?*Ln ^?Xs.r+/ǵ=[rKxz.ޓ0OyrƤ&K 23a Cn +-bg". +켧:LR?~o/]WtFB i pxJ,3\햑MVo+/ZSHx)4fR! ;ۜHt7O~Rl'rg7Ų07K6 >@=o9`=~tEGP%]D~CL { H{|]w'cUu;M4R{Z=5e7=}Yi]2yftÕ;?؟@c^аr@qO.hȿWQN-r{) n nWFӶL72U~mlAk33-~^)mZ?gѪݲc.YVkI=Z(z|y+|qF4ƝJvo,}6Gy[=[^ڵQz>JZr~1PyRTTJ9?X|< Zl!؟/*@ ~nݬj笾.;7wU;IoճlilrtuЋ2 eu[,Y٠b)WS*:fb/jg8nVS:M +Fa}RÞْ /ƥҽt_? 9aLvA7^23p%m;㹮wł,P +;wd3;OO/åQkѡ/-j/{)-.WY\+/y +UA9TR_%h^ۦJN3vP_FJD9_Wu; +׶93 랦O&+H 7|"%& \;ok_Ln I@xRّ( ]-)ׁŶr]eA[zG 5[kMTx^{$jLgˏ--U\M`LfMnBϱs\uTX"$ջg]a =YZ>eR:y}95;b>T-od4+qM7=~4#џIH|W$qbc5@n\}&RT͌+[P/+mMsjV֙.zSUY؆^)6Y9RhzuM-O$sO$\}UU!e/JϏw!b?8INYy+׽uڸ7,IHٰ8?1Ƭ"IpۉȌzem2~p~0NбvOFDQAvkCpWd^8-E,PO8(2ɠ,8'fUMDIcsPì+Ob,f㲟Ra{=7wa۶6Q2 +yѪX8} :MVO_U0&-Y3,c ^c [c٫VR#:ӥ޷%p\wA#]Mm6%6ݏ1K gRdM NTY0>@ I{.7\XP$ *-t{02?=i֮fx Q܎>^ pMͶm/j +G#/)yQX)GDRl-,3nBf*?o M9vf,ֿO<V''N"u~p%t2dʨվT׎MX^ \V7{zxʮqύvjh[)>%^BXt>uԙԚ9xIk{GPRB؋{kVB/U ?.mJkaQ|腬莇WҧzbXGYVOZWZ? pzl +C3ϝE #xCh)F^,8X n^+80Ӆ =@tjW! *OhLV?H:/r6'?#9;nP?^Y |3,ӑ9S7{ ۑN>;*^-"];$Ak{}HݒT,mGEn_/8Ghbl=9js>Q*CF0B'X,{2}*#f1oĶo^rqݗDq)A⣨0<"F.B~둷slөl sDw5h{I3c4M\5,Zt&|[JbzBK? $ĕ +=Srbfe3ם>wkUha꧌[qqIene)@\(7z'V=ǂG4 RƠ1få|wQ|OʾMGU,ɛ2*r))8$|Fȥ_Ⱦ|)D)6Z +Pe' .H>e=I>7ʘ2ND،!js+&fqO/W)?+bQTwm>{~d~΂RiN4g_.Y ,Ró(^:ݥ")  ,ᾒ-^jO^FvgemUoGoN9sFlTD&迤9ffii~u9vr,z:i;j$V&&kKp - XƷ<$'9o|nœ5wri'(/$_Z"WDؠΐp?IޡXcc ;c +&L?}2a ʣc7(fgaN i!a{r֓t|}S#Ǝ +?Pqw?>쯗%.nF ?2dϬGº}߬Uګ hF Y  >)؎K;/)w3 uNRcّHe^=\ykF%[6!7V^?5<.wauѪ=nġynlypȻ׸uMԛiQEӼ@ɶC7|%vM+r^Ͷwpևc8;}y%lfU@/-s#r$c+r^pZ M6  +"ivZ׼νbpbYn7P|#J+s-qҟ._zf^..]\K呞w۬:;lxNYvkfO','ͪzM) )^*:LJx~ umV]S㼅ܕ]>IlSgW?yNUof ̍q&S*Lڡf7f9@2ߏk2r8[y̛iy\Dr}[VY.";8l^?=CE,Vv+P^rdN.l& i-8)(Ҡ\ZS/s:]},|t!{֓}+Qq+GUdkw0ē2$'S9kGa Q$qp7.- e& 3Vٙm?>Dkxڿ:6b="2/hs^,VƁ FճVlh滉z!%.&S& ]n*nu(ԏd`P?[x?V*~l=Nx'r:h̿$AHF ۻw%jXBحo,Y'z|2Kv> }SZlV!j) qҕ}+± BM1xQ.)G\Ry\HO7_#|'j}9eB7*cGDzasS90;o=yIgEaYC.q\G 0.֪oFhbqF} ݎCngỵ̄̽ xH^*&?<5Yw!ԗIlcIo G17=i؂y QƲ(KNt>Ayx%𳢣s.09[m0}0: ,dhWܽ<VeOQ9rլ'ي<m@K)soL v| ЛAWSIn~*Bk6wb_ rAaA҇_yCfF:-<]|vgcvryWf/9w]GdXE鏴*Vjɦf3L ]R5…、y-vfWp o,O ,#`ԓ|L]ƣp cy$Z&;Kv% r(/OF?Ћ[jmFfOi5Ƶ׻ŽSBQ`*QO}"lV>o4`(Ek*P.bV qo Y5=ުF!. 3)W?Ϸn#ݨN'/Vp"@Ja2xnxĭP}t+mc>VAڝwۗ?~Fz6s Ӵ:$M}3e•v >8lYfw,LffOZm~x4w# L ZA|F}%V*dRҗGM.ڗi|nv E\ +_VxP`nf]o6b:?x\6H&uAe 9Lus"׽opɝ|,Z\ŻI$a^ܾ5i4N<%æ; .MW]~Yid't鸝 tgXIc]7bww>֕;I'uІoQ9Fb7%fkޣgeMxTŃ\zeXu]Sї,oԵ`f~ fRn$M jbZCfиrNWx-`6h`^F.:L]@Z3.0 1qc?`qen՚e/-+_gNWAFH+76eRk4YVhVwW)``l+ۏ+v-% +ꤼ8eYMv~&RJ}q%@C[ +H!'рFwN'WV_<:Z!ǚޥ,Oz.ַۢ4Xնm{)J+-'ztT¼p^.c`MXK'%чmD[fKu:J[ 1- A/j[ +XH=>Nބfܷɛ$cŲ%o +nd =F*7 ($Iz+:cՇIFO 6 P|B|V%SEP}<,2w1y[ 12}5iⱑ!Y?F|;_K՛aAςomy|[?e3ɢނW_>iʀ| +'}BLzQ]T{c\WYKbkQ⎫Ѽ'?෩!8U(qIsHs̱X +<'oBIygd{G0J?߼ԩ5wӺEm6ZԭW+]Ińz;F@x^ +<\<{$SEYABM*cσͽIf@uK9-6l|;jm,mWz3#bځQV^шspH>p0~.pTFZnj4B~U$Z; dх4M6!20[ؓ4XEf>Ǜfs?#Q]Icج/gN {)Cy\:ps߻msq?u& Qsm$5ݫm ٱ,}76AL7X+~7!!Z]k.ع5+n.lV1/9sBd^*_p%g tr/k4P%(l\E+f>Xs1kҎJsaqxv@{וYnjNhx9fzQ@}N#L>,O#-(-5I8we0^Ёkb6Գ_V}M4Zdb,r0?fVl+s +=EOvQg{9/\Psb on`ٞPcۭȔfgjLt:r*^hmo3'1p 팭TD\I/H lG{ˊw:E#TcΒ0ǎKyp^~ߚ1kd#G1E]3?U2ae:xKsH@̕^OE9^_^sXÁm,_r/rϥ[dzs ^)h:k}:PKP˅H}oa޽.,im v5@w/Y#EdUikEG +0 3jNSvU?[:SP\콢疼θ7lc蠈{4\zG9h.Age;JsmMX&PSxw9d^b4o4cH, [:Bhg~h^|){\, jmo$B煁~ x~IyyL:~@~|~/s="7XTSɅ7C tL?=+HcJ,C#sjkՆk!yf9nr5L%Jj \907jO^œs}[0zopc/c6sX+uϷsL`nŊ>5ojeV-}kv}xj%h%(7IuA=0.^dz;f5&dx}d^cmrcxaV!i79˹zs_~@CUzͫߴKk& &*O]K9[E슚>MW0e])`m>Q-kA܋'+l-M/KYC=Xżl ؽ,CM nYo>x'- Ƒ,ޫ›nDB*i4JLW4M)zb +:b n0pXiu,)OV? {WA[=ab hVuN[%aj'tT2YP!W,&Ħnok9jԓjaGDmltiPц> PQ~PQҨƨX/Q1?^aUWe懙5fK|f`ƒ~=e Omx789ٲ! 1hz䝤BŠ*o#76*-uI-}1E``>P֗NW5lL'v3җ]W{O̮(1_6"UP]I;(Sad ЗB"{ļt)1fq :K|:vھ`4F 1q5֭khMi5$ۼw_˿_vL2+c<*(mP#'q a}J +BVDs~cn#YIt_RkFf&a3WD\B`wwG<^vǟ9?כ;`HjTb5rxjTfD>(|(~X~$[P(3"@XƝGv,F n)[=X<4_]+XQ~rQ6 ehuNeB}kg&cy.Vʈp,qd4(d_20TAn~E'Izts%騉%8g\$P'XglI*$I0e6pƫl -WAaE_GaȨ?$:g u޷{ܒ7'F"EfT42,hK:&iܺe Ҍi>%^Y\{kۛ.(*$ױ $}{];bJ[MF q|.: ͢/.Y/_^m&:x>ʘt$9)>)gYgZ|Hz V}xQ{}ZSЌ"GQDža_RGh6js$H)ݵ\dƆWOa +M(?nW'v~0kaWs!GAzҎ]|jz^WSPrtFR_~IUzXdU}i.O3ՄS lQD&(bpw1ҳofMhe1Vc]Ժ[ֺm\`on9g)H,Y\ͷ9Ӝ ܖ9gLiλ_.ϕtl;p…Υ'*gL=֮w>}Mnvtzi8!pcGMNkY9:ֻOfYpId>͓%D0[|1ٙ|p:-5[^B07*w8A.6eG>ּj!˫XayÖ}?x旬AcO1?qoCo#@O3Km̭NRs-J]ت?ߐK8VYӗf؞,0-q%ɣFJ.39 G8 L0d3Ρ|I3|۶Q[[)tEر^Q0 lē'T|F[ZVi,^ +yX:ܷZ<ۀN`&e8SlX+[ ˮ$OOv6fz%5z?y"4mv.OW\¹%l51(C?:i-ggu&O>Pa⣭ٰcҶ U `z֓Y(MPfK|bT})bC6ܸx&y4AQƇ+*[R-[)/"9:pu<;>Ӹm{Od5GA-(ӝi}xch_Wr:Bz-O;Cui{n(A譏#\8gs͡l#=SCai#<NQqXnQGjz0^Ch HȅCʀ瑠oO];Vਗ਼ $ tt|>ɡ}Bh>]ju]E2QQ_kPTEcZDZE2?̛ا#H&C҂ kV益bkOݡ8R(v eF-ZrQ}%k<&\6%3dTh﷽!Hi|Q\k. nlŚ_GYhθTm.Hqy:!W7Uv˄D6 +OqyQ2$XwŠ9q%\>=2أ,2y. A]akH='FmZ+p[Cbк)s *~E`J1n+BoUlp\;Yfe/@G_Hx6A-&2#3]j֭׏7;otp`d\+toe9I.FX.Jr޵'E3,љ7 xVֽg쇼X_/_FA2W{NtJc²:ޠ'=(r*82Z-܈aD"gP@B?Z(~i 9@lllrFd~DI6֧(-tͻٜlhք9hp]7:o 7t]]]CÒ+Z ec;_Щ??7-<*,Q]U8>LpfIG̘m -c`3eciֽܨ:2 A:Cj 7ԡcAWx{|=xr1e=Vfs>0|6W^-չ^mff82לG^[ݝw4dCMS12*÷jSLQ &Ŋ* j gGͫ]4ŋ).})EWBseF5ϑj*`V.0R?_]=WmJ+vN)h6ހ9$%'ԃz+Ca{VȔ:ڹ'ڃVD Yj!NĂH\Ą$y&KXK#3 :ny8qn!涕C:v/Yes[WjF,w\"SM-b1O;ByeW3a6"6=iߢ9zN8f%v6v&8y0ܮOq + 66j8Z҈hhcp`G5 V]ɨxj9O٢/1bFQK)uU3H4لM7+lS9a̵O D֠BςީFBUSS=Smo?{gWwZP0mԨ+W u2avn5nU6s'肑SÁ]ja\twK ΰ'yXo7!˅!ގ[7n#nFÒ6B?}8f_GݮRLrЖgxnc+\DzNv7֘떟3IWカя$vA5sP.#8rum7T!NAg~_b[3s,2},}?WwR`r 9]ƟZ=F_틋QϨCte1zF f4yoNN 5lk44t:kzdY>pd-|D]g9us_lhpokP>p^L~zMڃó~֍NnML,ǕNpU:ZBt{8/6B-.nw^T6ڠ#*J{C}|EɦzFLCL΃zH@vVN>[LINV`)EKfUbb?gXllDv8\)Ǿ8*>i5hONju7NA 7li)dW՚ ,VVe-rmt%p \Cvaj +CG u:-E&ȟ+G5\ߙ8ζy4ۿӚEe\_FBP! =wm0N0{=p3v[HX / t䑾{̙{*:?;܇~ @D j yQEDfO3 FP:z_;a#>c=n5Ibx1)}e7E+cy]mIx|ĶX/;j$ԥ)9bo=y~?d8+0ȏ(TZ("+t"E=WoʴDeqw}غ%EQWP +$2 + + +΢c`UwLrZPO6 %@@O'@/M|`0Ĉ=/L06OlvJE[D}-Rd/{qXoww]%j/=MӷLӹwLSiSXi QXY +0dkʬsQ |]x}徆S^-&V=ێ@?,K4b5'@s(}ɅK*44OY[$ zqh e`3kv^*fQ=^g-zns7ӣtCa^^DY>6do8ͧ7 VKB{Dl> !^bqpW^N\-@l CÚȷNs~_ҏ[p`gڣ,, eRm?yp/-ԟ ~yIޫء{kP[:N圻TNη"g>e#>yC9(3ULCE]H>26~I?iq~,~|o>y8%y an*Smnޢx&u`w!^>;SG+7vV wи|cX{Gxu4z_֞bjtyU՜>f@UV_QV.)rryH?2 n&6HLk"8}r}SʘKް ozgadzK^ KmbEu'{y~ r~EU7>$5Iy%#u*/gO5!ˋX76_<6zX|2,1ؠUpe#{HZ??c{~fNdcE>Or ^r͢~P`1iuႫ`BNa +\K֧G̓ƴrLOBf=mCdr --B'@Q4˒ȕ%k)pqwDGRmM7W7nz% )DIkH=e +s}}bh|n4r_o]IGf>MWq>!^m٥γ3#N:$!g%F#f}^(!!e(0#.U/cr127PwV[o}]o+5פ=~?J,:NN9d rQS2#%p@h^qklq0'=0 $^GRW_=C{ +FA7^Siz]I }`*jέS=8 TFafpV0e-3- +y8- +-*?j{B}LD%~epXz8/(ͪ|fmϕ{E[#|$b +XGYlm4rxEd043ac,ܶWzgvvA;ΰi]I}oe6/͐/{!~П<2.cZjْ q8ސ>𱍐I]hӚKJ_6Xo9k8aB F&ңVLUSbMVB;V&^QM/S4t+,ݔab'lS`4 L=W_6+nF:m#ZԴu]= cuP rW*fWŔ#E.H8*fPzS.+?`Sbv];SȮ_E1)k-jdS懾wBhklZiGǤ:8Jfi^-z|KIKϨ|6dQMRC9iRXvg/a^(kI+:ot=;@Xh e`& ```` l*3o3}A7Z01M;j?6KSs]ʘ3t12R\XϏ>xkC8h9p~/[-ƻśX=Sgl]spIx0͎ A[˧M[)WUX]^kwI:lASEET D+I hDFJtYjw b^|3~;ڜ(]S;[qV.WI0ahc~|ƒkz*hӰhݽ旣4Ȣ-7v7jYfv3ܿYgڿwME0R>QtHyIZ?.|,0 `־Br2]|j_1] #@,e~%==},KO2\ܧ*\]I|%99MUtZȣ,xHHc`{Xm\Sv;h7ׇalڲ|E4ޒyw^nhޘV59q~f~}gӏ?Vyi8fYP+]c~Zg1q#O`rzkֹ] +t_.W).T 6ZH9IR^YW[CҾ(mPՌAP ; 7򩽺@> yʙY|lp֞e;SE]2'K$ltda3z~lZӳvўxjGPsmó"w~۝V g۲;_ Oq'oǥ5klGSܴ ]Vלթ-O;{ᑭ^v}eS-12+jc!qZgӀj4(U;α }W@\ЇZx@)(Jb5h;,TܜNXeϮ=[17+-p.#g='|bѣmVv滢dۘsZ9/\]şp9)Q_&VXe6t1q͜!+>+z}i:`2נ 702 N_z]Ny8_uY%|7'#$l}w,cw g]>7ӷ7>8T`<`2hiBhu}$H)56}V5g%#7UXe?+}ЀpnYJ㗯M_ѲuFť, +sR8e>73qoy0 VfV>2ʹZurݟ^Em@zfKQd1MUZ.Hpjq'u!` I{~~wa=cv)jy.O[R3z#π{ͅ^HY1"L͈ DxDʏ;џgej6ǭ<ǭ3.?8nU3h|w]\Ѥ9<|*q?ØŽr 5NbR*R^Ԫe&x +f]ܘdzouީJG# vmy]vmw'z"32v'_pz{E{̢< ZU%[YԀ %[$#Yu s^S뺏J[+`OD~wlL|mc\}@:i_6Ƈ#%>!N:E:jj[w a5ҀlGpSqT? ORF8 QoRv;Zls[`OuӸJQ&P&m@B&}[}KBx }+vPTe0`k?&=k 6f*ǐ=OϪngQ}sA8PjiCM!تu~I~sdJ՚B{id$3N<[xG|ƨFV!U._Χ7nl?/?%~CKmK'*AYguKu͝'Nv*rS`U5_fv{4[e u +kb}rp6܎Ĭ5\Ź*\8ۭsei,"W93/W|ߊI5dPκq:e[ZQ=04wOVbh8) #N)L<"lxsO5BxvĄ+CׄFdUFW1B׭]t.1nU|wx+~$Zչ1W%j8l[:cTI42bJ39 +$ kX @lVwe"cߌJ ϑm]#eq`c{Z‡۫wӎqՆ&[bܾW>h6>}hYL@]!OdHҲ8%":Vr0,0)Vnh`])Pv*mZ>\>.VlEPơԲex47M93AVh5N*^D\&1yWhvnКꞑ}mHӸ]3j_0l#u~NcQ gc|4E>e/nͷ2b#4h[9imz 5K`ӦMvW4|6 +R_lܯϲu[2[Jڻ:nV6[ +U2KF 50R*ɁN{s{۸8c `D&Ȫ +^oPԬ6Xl +XJZr]b 8g + ﶀ{AxavGα +SuxcKe'rZ*2bX^+duBތYo?[F_h kr8#گN<@ 4xTΖ<.|n:MUucლ= ^~caZ?0}Ja +%b  @o'@7@(Z茫Ecxײ+qqq#{Y^YԿh+.u(7eG;znBe(&((ZρD6.h>{   AHb2HFGywʗ +M*Z j-Խ't5w ֞E݈aND)<~۟Ѽ= .f{囷E?oDP]TtdgM~Z,01cp)Zx +&wo7;/c,){Ӵdp$M9b_Ҵ[g 2)_&論\Ŭh}~g'uO%/Y]FHsJel#}YΧdzX/T!&e;X 2L2Fm"uM&b#jwݓqӾyI2L|Ml~tDƏGbOx\ u]+Ú|9Dw%}珿iq7M_Fw2EO."$M>W. U (V%L9RH$^Џ0:Myr&B$HO[*,ģʻ۳7_~mXu6}9*}`jz@}ع{ \Yq\4֟c~e[ޯ񨶋i=dkJDh)lVÌS}vQfjA){9*Y24G"}G>+Ty7z%e7î_I7/V$]MѦAmo|G(Nv.F\=9_@vW(ګ¸e~c  ە"8/?͎͢U=@ m"q)qnsɕsF49kYjxZ,s}9G3@=%P7?5p`\ 17LxOscv(6< R/tf~'(?*74]}>y4Jd[XrCUl4wq`N4ÜCTd G7-fNZJo~Yh|I?r{(Ԑ>;zXT®U=^DϳoC5?h-,$Nzdg3.a:b^i%_?9A=zkPWG!"ZעcYX8͗^R3(?O'yU M_?|Z{ߔ܂i͊#1$ǎGn`?,ρ}rAF̺hh ?VӘ.Oӳv!J͑?/r; {sʠ"ppIZߡEC/>73iL209P>u6qȦYܘ3G]pFJf鬒ps/cgeq|K+NT4Z8Ҳ_ GGwhUNٰL3nژi[fv&O#̺Qss{UP?Vn"+ȃyyu7oӌ/mbw슋٭H&^s C>$":R8eeߒNL/h>*n9YYsPB'~*"]/Eʊ4J#+l2Z68WǬZm&&"sֆc#1{ÊR_I?.eMK|]}!" +=WXU7dJ[vco⁴ -Tᤎ7IkY'sr7!`30?wS ȚS+0GAbiYtM謾^T厹O=֔pl=KّlN~/AN+s)‡'}uxVizd|rR9}ݩEQulm|jjΨt!T#5jJz.]҈OUKPC!En g\1x7>ҼK/=oWk[CM[r-+K=7/3Z3ɔf^cx5:+~ɛj%W?x/b?'bZR&ej͍NY'rveV+3✕Y!rx%IcΝ-1Ra[[U4U`-Jry +KB$7׆W4Ưꖹ-nry2; vr OزY3j^ZoXM7#NZ|35ƗC% +S<'zÃTaݧ -wR/Hk}DI'8}ƂλAnԶ]E{ptBAZ]+.ʖk%EBHq&)uQ;M ?庄"4f񩘷җta!D>*wJ9R=HSӻbpuGM'N\uZ{U`[eئB-f!ReH^ڜVaGJ>O<*cxTmx=ȇO/OUF,ѬO/n>MGz1uڷSỀRWAђ;f;L.LrI]ӭgLLI! m\5}q"w@;=W!0ײ~a輻5h}Lyn~uFQ]Ob\u:Vb{60`„il@bqC5+̃sCm6 ةF 4;sE`15QiquF7ꆁUoW<Tkb ~Ys:|-u;+pEf>O5|j/ +l{b6^3R|*x[rź ¸ ++ޭ+x.H5ix)+t' +G=DFZ/]ff/tV-Z.'J:KbI$mdl| &6;2O-Fl Wnިq{D:٬U.[iY ..ܺt?l}9F,>jpJCvct?Ȫ-M] p')L5*$%ٲ RԷ>x^p+ig6ֺ=e|QsAeO B jv^hxipѭw3l](H}Zq#܉EW"6U/$>1pV8'DžFG5)ݼqiOshI?O=}s 7r ^Wym%/\AkwV +n^dt^U4oտ~5:96d`Y|c)%`eunQGlŃ|F!/'mpw([CiԅgסhS\iS~Nr]n%i&t!XZ̯X&yfYZnNl_L?CVd/w @)GYKDu@ >y2/X]}n')y9`gMU?95&8{8[}I_E7P?~ ev_ޟ\ar2b$hj#smveىw +[>G'Od\X?z`M^~/[(D& ]Fh42oiێ>?>~[ٻG}}S/9Ux.g+oONQ'Vj4]\Qpe1<a~vUms| oƪ!DNGH_tnhT"ZB}~JP|'*ΒlGۗqW筑D^OUld14:n5s9fw'VYU_ +5TWV b9j×E.*Imde,[TOnPO,ָIR6r/W8"v[fPZdUoeHՒ%5oka9 R*^`]3Q<[uyロ=g2;5L_Ax/YO|!5 m)S{IĪl;bc+4ioo1 u@9>՞6s+.a? L5yƗkYᲹN endstream endobj 128 0 obj <>stream +%\5ȉykOrx A W\rx}4J߮ݲ;yROjns]I4jX^DnJfβn,.<-)ە KI?=cv{O1%V[}IN!~B%ɯvDhFu.[.u'rOy&t嗱ifuZ&Y&ͺ0c0=_XycaZ<Ϋ&M&a(/C]ޑmӜxE:}`:G8;RL/%󎛷Z.Ymm$-Pcfz;YLGe(X<,f@qAd=zTM?_.WE=WDsv ?lYVԩ&fQY[M;ԸkebxЯè5,^"tYWzPy\9c;+*FS7ArvYA| Q̩Siެ}_{Ud=v^AP~,q!uk2MނوVAQ$GAL0YqsXk~04tu5EюteoQK9Bp>6-رwPy?,AOFR f/ +^е};`&Q; {V1*+ȁ`/B϶F(/.AB-z4k?_VJKJs^5?oW~W˛?4XEzr_s%džr6LS1^kkmB 06&>])2ܒb/L6p.{N[xOM]߻G~ĕ骞Tovcbǧ9!QpeӦAoC==([\tOͫxriT8زO}|B0Qzi=ZmM=*5]q_߻]Of@!Sv|ؽ卍<䍇I8;EǨ~H⼪ojvr*Ż +cE̓L(o~/6kia5Qs;`,\jރYʛX/4=^km(հo6+qJ5_tzh)D.CJSS6uGZJʖR^|T  _2^ͦfF/ unXެXxaa_lWe)U ё7yŭʙc@VԄd۔1 ]$WZVfެ GG>^ܻqY;2Sl3[`~f8Q܅3fŤw+:|qzDnu{9FGj<"JuaH6bO$Uv5Ҙ̂Sg'z#ec^5,W!]>f6߲,Ȗ1Wͼqj+XkQV +q4".ݩvSWtWh$a+M^EnOpSP0I #փYnSZ6Lt}?7HPՐf +H G"*ąĥxRiIb >4p5޼9kWՉnRZk~u.J,0f,Se56P].ydد܉Gqc{sk;ڱ:ؼK[z]bXg7hfKiR6W':l%[ǜXɕ_់f-GorfǨX,Ac +$Dǘ >5%L㮫R\X2jst6i>iM`Ԕf6jBv[@ /K.EWxQl=q[S΄$W +#vʩ @4=ՑtJI1XV -j_YM{oJgr#j ]w4 ͦ#M1"P#[Zw9ܖ'ԟ +![QL+ +K+q` 9lJ9tP+Xi1e_e=<$l-"aJ\b5Y[^<ްdLxDmx`9G/ZOۋL[-E?U4u$*9'PegxJŚsw%Gg%xkܛz0q(yG;HO֐< +\xw>;wzw|g_N(ۜV!$w~|ohRʭYvD#o5EpQħ\¢:E pԎӏtk4Pj攩TӾ0t6[iUv3A{ +o r#S.q0tC0F`00mD3)` +8`LfP:g`no`?exeY|jm\=5|+Mm5xz0d 4`:\6.`gfGO'+;qt_3LBpMn 2\?dh ~.O}ZSB^;tgկUp;P'Wڱw]}N!)<N?  ya>b Qlg0>\Tji6DL]iZaU"ظ~~ny[Ρ;*9h +j jc9՟V qpr @<3)ߟ +?sHHR9`3߯Kڍ;6g8Lh^yͽ`u边b{}i8u{\$6Q),:8u־bG{|[u]F8ExJ}xr~go<ژ.8@G"\)eB;~\?{t6JBNf7]kC2I} RE8^h.jNfXwvWJ}#e2z~?x&ߗ/wPͷҵ.uKV^gul=kKhOlq:H}ܻ1qZqxskR.O.Lp +|lUu<;űxRJ+ڻO.rMV(|XPɖf 6qpm`Fsr3I(wz~TN[hzBYP;iCj$Ue>TA5U40J:ʳ xEZzUrfgI*['z@:!ý$bݛ];V,bXs`H{UDsg#YY E\~ A[6smjqȨwOT2m+Ҕӳ#[bT5vb>;hj 5vvs\2/og{ZZ>/~K 8|㰮7Y~d{ň>Yyj}-\R&uW +;d diTڮ@lXBv8Uי| aZ+EX 1yA6Kڶ6)w2خr< v|N@<)^e꾤̉>j!UK?f3cxo=/GA7$qc?ܕ'jz83]ưM Eq >1c~2\TV]ۍ[|4VǴgX=7K TK[ڗzO#P޸wtդ*TE8Wꓯ͖)#J,|Hfi1YI{xYn֮oT7iSl\5X6(,&:/=T5([8q; Gf_8tu ryyjAUă Wxq\5ȣ7lirv)J<톂ّN&j1 +[f6_*:>V)o0Zv/~ٗskade2j_t"g3LFWRkun\ߌ]ɂ`#GT[e9%w 2+7Q)U 9:L-0Rt.oJt+x̻\~9jfaGR8E)! ]\(2R5,L_j/OU?Qi_LJַ_/@Ц'~C}0BʲC:WgTRj[A6dqh&CI6յW=?a*[k_\"O\Sjk:-M{Kʻo{0Ðj8lnr~IN<ҾD GfE}v`/^qOn/UG VˠZ8,7TUSœidǩBbXW9ʙ+xV.P=}B@al#î 3da$d{I@: 04ɵIqgXn؆ .IZQKRVAjRDΥJǻ\W?9??x^2V3 ȩ( gڀ3@99õzʥR/Z ('%~Pxhi<&VVM4hTE]Ytehr)h:Do}9ࢀ# FNtW4=b@ߢU-;&#)PbKK)9@wa}ΩҦ8?6,9Dp1CIeJt9i6𼷃ѓ +Y0fY2r +`^[E[5c`7`G;C2e~O]M3t/`gCZfTr4ʐ|u4F3mſm! +آ +8Oe0cp}럚<΀_ ? Ji,߁ K$znq jsFŜ1݉̃4JT\ ??.mS/( ~;d}+P4V@m*,J` ĺb2 &"N=?JybkgRʭ=`MӇmpsorC{J4dR{@|9F;?NQQ<&?SzOVg+ʡJoF伆q1+w> 3 ?CpI!tagCg Ua%a_i4]p7s靈 +dS Iu0jk6_Ⱥ$#BG065mHBٚouaD,,(,{s޾;=OA{'5`:_]WcRz _r~9<fKMM/ykJ> ,1A `I6wwͮOѴR:'|o3τt=~e_c u$&8p^ѽǼ3(¿j?WO/pcJؕKT-.+Y*=%~JIP$B+8 JC0htoQX W?$3Os g ":񲞬bd⷇-^S[r׺U[ bgeIVqo~F̏,YJ$GOgj$?OV.ĉ_G&݀`7S˿uiSn$C}ܜ?70o5c ͼ3US&A᪎Swe9CuVjF +$lˬלAI8%7yZ=G~-Z$o"[ r.䆝VMr.W%G42OB8H3Sj{;i =XD?T=;,jvo>A3׻pxk=Ё.P_[$g nD9CC}):oZ[w!?W' ~5I@ r~z<&uMǍUn͗ +[ ?^nշ# +Jp Z.!,3M8Nb _|x;ٺBks.kJr{$۸î4rB.IZ5 +Qkbb[zzͶ+/\ikMEڭ4h"cjQ\_vkȬNF]ϑL=Gˌ=[gkk" [l.Km|=w=]:[n~w1 w3}I &:0I`P(jܵݑHBZ,KɎHB"*'F׮틅^mOO5!k~ZͿL>;]Nn0hz*ZWdζG#lI;41A`o5(+j!ieiY8=b#MqCv줶Zn5)p2t\҈AVmp"|_hF@ /e2dORdj L4pOb?vk*$e[^9K֝Bܦ*G-ђđ4%[g J0_.s(!(D^ZD76gWqy0.V?)[[T 'AU)~r])EQPulx3G'57T=wN<:U;W +|68{oUa0qˬe(:=f+ەoVsK<^'%+n̙2mLے ώ8Ź3 OWReNR~;rY+qS2qw†]ztAZ3v]:BZ}dtv:&Ah7.ݨ cH^lJ/V}洣U&d0 7UN˃=؈100d+q)T/E, *Tú՞庲Er%/+63aHCl`ZE˺Zߙ#X;#Tuf+h?9s W2E>4ůp}@'O=8/LHSC/_RP/ܸ3M7j%&{S=$.S aG1 #+!f?YgH?Pn?aSzz<̯tavůĦsbwqQpUCR^Ǭ$BQL-/߸oܟ)ڽow4؁po4[XwRݠ:;ptln9lڠK2z%4~&N.qG4ܻٝsS^2k9N])5HߟIc-v +=zuNe֡ΗU;m=wmv;q^GC01J.Ӝ9= o,R;@NGoGA/.]n.b8/3>Vh~,а(=rR5":x)u[y,v9y%uT @kqj۪)z B-I]ZiœNU'5]TksCy28yE>oh^/P..CB8u}.>Jop"{ +{57=khrOqԣ^^:8vxgZӥ2<E;yMܒ\h8idC8JRq=c7"Ai;Yo)׬DfٻeT]ig{>eU_Ss[M4\g*9tgsӺW}V*o  +蛲<C>CWH@*>ԕX mҵF瓍XwZ+M>mtLR>+2ѠE3U3MώN@vtRV~1SWut?9K!]O^}B5zvkx +oių xؗ%>aͱe0g kLYХM[7R-]ʰ(W}L@KiHyvJr~D38{33ȻNI$uxaצ ƈL:JG3;bc^.|ƥ-NZ;bPS8#͵^!¿ra,{@N&kA2ԏ5,mZ]{Դ(#`?.olv80Bi9Aꣽ~NAM7!MS5DD{>;/뤷WJyԕQl{&i7:J~=iuAe`P!ؠ\:Vi^}S֨Œy(2_Xđx.iF/ 8\=(lFPI?(T@y2E .:i42:(sڏB1nS$罆+Z}j d:p\`_(E~%}cNC@ϒ7!m>Őv?7wSʐ"unW:2!绠LS]a,pXu,b|R I"R|{2`lSB|tI<_MVGn棟TZSw#\]}t{zu@%{6M@6#3\`p)&t)E" rvpg 8ur;ڥLMbBv68QK!Y`9Cj0O5<g)5h 'w$ Mq؂$7I7h / *}S+ݶ)vY{ee%zu(ۅɇ}>F O&s:M!8'@hͱqm%+ }Qʝl.~PUpkQ/r=wPC38+Ǜ?W6w@g3wrѳrUJ JqJ +0f}6kM3+)ӁFO+VHo }JGϥr"3sG7tvaxQ_YwXv~j 1!b7*n8nV/y>qk^:μaܱ(ҭA|0)À4Vu9Ym6sK_Mz#yK]E,k-la1f1s2sxj8 ZW\SA#Oincݖ&XgJYkꡳ<<Ýz=?x.11_3IJTpE)?;ƻgwZI(\YE8rZv)p2w.1o6.Ot휔):N57>߅}1 2;|0I3.8!ؓŞ8Xt% $ V|[/sm=P,؏=v}H08w$ՇG<:bCawEA;6,Jns8:4$g+2`m uw'eTm#WY O6&ya{ ec-T{>uAv赹lWmv}S$ֹU~[n޺LSsxR6 9/.n^V]x¸X DU%NcLO1>3P?(p߹nh']B!jp:7"\fW~hXqT>v:懲>Uk6RO!]*ca?lz=Y<(%m{w{`*ede:M|yzh̩MGc`_q8C|UlW֕~٠42wC /q)m|EEs艅)&'||)k&\']5fQ'l[Gud6ao*:?~5} %#KьJj^WݓeV ^J=J1VpӨOü,x7wyeh{Rf:~}Jb>mȭa:C7]+Cgea\'ęǞ(qSUS0l0FDźl~|qN}y9~|J'J^y@r{2,mSy<]"0m[dUu +_L+zMiujK]?/Z0pdAaJV9.|jܽz[ww2W'=ETp=q:_>VQ-/%=}iu16Ik%ˋ  zB<] Vk!^{hCQ8D}CZ>_6joqz\Dt[ιt}s5lj3V-;5զ@Il?{c] WZ2J1aNԓ]ړu)rmh6 0v5V{N̊_nve'g_%B1Ml[\9f6 +a4 Fkz?|@#Y]k^V/>m|Q"'m)[hjE)=﹐Qԫcwg5m[c۞DN_FvFx.Nz^tWǵczhj+(UjjȲ"Lq߀$SĖ5򐹩bvĥ +{y/rv1z2ԸaT&Ƀ;E#sDeZĉk=r6 +VsKȀ 2rl|f%*6;{:7f66 z7s)tǒJ8@º* tIo[psR$:>lcUU\;mhS+ _)p=i{x^҃w H_4 ou*3e 3a|jm*K~qER,=g8n*Լ4zj3wX2=<1Ʋ{_ Dp N>{~SaUO1åa sKq0`,>b]X&):`:0L kA#!oX^YEG Nr;f{OqRo]5/VX.x + k)-BJnX=ll_;n'ى8;- `g=}vl[,g<{S6Ӱ7DdӶۘHJqj(*ϰQ5ؓ\&Y뤘 W{gV p ^7'Ex\o9 ebR; +xD.dgĘ p?$jPK踱]Lߛy/z_=9ǧ{i3O__O/<AN X9H`#"Q@",Sm#IV^oz\Xa|{23q&gEx'oQ-n`ROVՓ/D޻uW;w vG &0 $!It8@ds@گ)n' QȈ2JuS@zH WR3Z sPy᷃vC'9SNwH߁N_W@{_ /dbDMtWjX~Ro/P}*ʙP rn˯\SHjR ӈ!2햀ab¥}+l@~S%qPpw/Sp̢ tZ|z"l00g0r|$x}ɶP*?мc̗7^~dV]z"z8u\0Bu.vvmEMWJKwMM92T r1>|2wutr:îj8C!:?10mv?Oμp$3Ot,n| 5RgnP?3q>];܋]OW]b>YzX޽vR?UM/4z+e^psώ;:v᭺ ]{0Pqly/iYN]bv$I9@DD 1'QjEм.al6@A+`5Aڝtm̈́QD|RNN'J;)v ѡ*V"(6Ztovu}x1e37q;ujq.W%QYK +}^E夭-U]Ȕ.s//q _=yz0`Fܵs뜶iwYkpz˙ru.+د5ltb/_%Re]T+!lƬ]JAܧaCP|JRdmƋ]*AA0n6m +D!RWy 䳓 vTn t\wuVe5 VI%drR?"Px0"Xڽ=N,)oZ)FQ:\yY@>q˹޺:^h^hDlV?uCV4se(j^)[az;ð-;AsV|jD|aCoi͎R/*5˒>ț&RtRv+x'I1)6 fzuR!ʲ~Tշ&vnz~hUYZr+=E>3.e[eϙI"}.X}>WmCڍH (Hm_X;ɮZE+>cñe|`b5gS׹_Uyg޽bHM~^ԛĤl瞒4>Ymt*E?0n "^oD@_DjUf}Y~98LvfL՚+YoCSN1VϟW{$T:ߐ_ёΤ 2Hl}:g'~Pa *%|fr,vrS$qe\^2k۹j#`j2{S>9te0< ř?y|2-~.t({7%Hxlh> ںaOZ 66_LZð'ۧ8+L> hk$;{m+_U+8jӭIr6R,-1ˮPlyseP]\ܞig8aSB-ZY6k9Z1:!z/Џͮ:atZy11]cG+czI;e]8}b7 r8`?\uB>ln_~{\S-یRGBu Lc<]oc{?(_.mQ + jt{<}SNRguC}σk/g_GȚO1PS䵯-C&JJ6=Jc%qTcO*܈}ef?1m͗ )X"srAl2DLbXXT@b~>>8*6O^v˝!bɑؖ^ʪ^z]T; s9̭s-gVQڨD*+)q[8>Cu"ȴVͬ/L 'q&._2a߿d@XŽiwdT2J /NVF +MvȉۣUr 2mm/yb*DpG= 2=0+sJ^{;Cickzk*;F;TڨXiȳWV%:w$15Bn%(4~+%rVqD1Heʕ^E\.vVS[Lfo)8>e|:%R/y<EzOB6D%`Q&!EIJ{Sk;>gSA}S5@zs-򀶉Fu衰NѼx#E@b='aеIf=}0L, ~oNtkdkA|L[r;i7g ЏۯG8/FWSIyt #$`n=`-SKy*C0-S=ƆS%i'ZB"n/U.e-rzeLk%dBEhq3- W!` +`[h# UyeKYDwE(xࢦ[\Xx؟ZVh6>| 3RD&f#aFWArD 6oJ[G-_F>9{v7$9J<@0-H-!w@(_ @:V} 6}C^dEvL'.E243!f)h +%qP]}8#p =H7WR@o&U7 U,j" + H6x@y<7 P6;h%`V[!o@H_n5 jn[lϗ'C̜]TʠH3@-w̔_߬gEfHޜ_O' +ܿ.pW׆nߋ +,~ gt @7U +'Ѓ uJrMF$ϫ?'r/\^s{RQ_Yw.{zXո ufW5 *^n1POu_|_9>Dj_|TY\n%{'yB[zP(oU[s:ZB2pqӅu"npW?ͼ6И4>$)Vj*]?wЇcދ6E!^z~ƺo'DkX)y8 +11EģC@oGMzK?g">keq#Ljgb_.ߞOnG~VȊv \Ѩ~x1EJ#FC,Iz+'rK/PrψrU*emYevQjQBήVg&&6ETTUti*)W(:.Pv%ot% F8áCayaBaZtB쏄I!ĩ1f<;r}?2I~zדEҹygDbV/#*7(1',r?ϖѱ֔'f"01< >x x#FC:*K0\o%B\FME\2')cRw`0tpaON`:(^F(6~FsNT:r}uElr- 'uݜ X;wZɡoD>X&mV*9k|ݧ=f]梻VDɄoVk?ٚ +̏ڱk. уhyeTGx"N*E_tv3bϨUǫ*Ǘ{dd3s (Q79/m)&-v˦pfPo+PÛUJmLN3hBN'1W5( +̪dVˬ:c"%M.y?P.]k^xj,) +|ya_+.JGM7SP'Tȩ7IK|?yS\m7UL2%ehRY+9J>8+x+Om~m~zwu1Wy+{+cЬ#ӫRPS +!_hCL@:;O% +C&72kp3ͺph$z2&.I61w*/o~ʚBŞ>L }gsG`t?q!j">w9Pe$P?(^u_Σ撝ZE O$oF4^GD8O#ݑC !#|ܮPȼnޘZm6H GS, +}9N,y'856le$:~ɧaGuclHqh;s6AZV=6EGa d&܄rn!C &M1ߎsɑv6PANvSX+GW +MOD0i!48hƑGM"foz(d݁! ɮC9|XL8` Sؽ9dN NO0S y7LTz)o(#]RMe0}~Sh6'O;к@ȑ<2l`pqjB14@, 3-I +R4ҁC@ͯ|^=q߹\m@\ { :;g1O6piS3=FA-%2#LE3Rz2`HdCH~@y~du##-@\q9ŧ Ƚ3M1 RY@. Ox(}vIVqPffԒs<\#|՞C;[jEY hw=q9hfh@CPʝ( +]PQ5'ַ.bРOqZ2)VܠKHwsԁR<_[7ZYKJGp5g)A+[c$]QCY' V$,NkI@[UЅtMa}pʀ~N=0~3Iz&_$U-&Pbd7`V S5N+M4'2%5V1%~f]rJY3)ea/K}9`:Ge_oB[;ƀ=6#k 8RRsp0 +1{Y.`9Dts7NDzY鲷Oܠ.a׹ ZúwH_rv_#ݲoW5" ۽^T]thz3RLC oÌ!*~iM?)N\J[)ggtm )tJob^/j֡bs_3W#bOx@B|I[bH8@|-4 M ; n2'3CA^-Ѣ:@!O@43Kggҟ|%Q],r +W6&YNiN3z(f"ns@!{C@7Oj|{/sTQEpd䱷Bg wb߁|]jnNgƯ79}PmRa7GVxmR~W?sMQGP9QsB1bBQCuv1 k5$!IFk(~\UۻzVf`..3a{ΝɕmԻg%mN=;KHnsC|$\sp7\Yxvs˃i0 lt;pE=2B%:*g^hKQn5yf*u5Cnܔ]BsnLkji/wǷ#q."vY0hf0Ra +NcM3+'g~CpYtw+mPnɜg^nGKWe(CULyFRXz:If^iEdmuD0nŲCC?*"}ZWze룓:<˽~O=-GJ?sD}W4 I.|:XEu6K0dɾF~Gޭ(=7M}2 mB۩,]MW޻w3⿡MHwDmܕ^u4w[wvOHu:ƛN& +m +m mxx"_;6+lk[`k:|,lBmzLJ'o1vӅtνxŹyw/m';r"ZE67UHjGHkDhuB%5+mjL~wSw#kUY1I+GRvllqe0"2:j3 OUشyҠa3wjwhWSoμ U UX-GXv*} :[wr"畋Q̰܂/yoAūx=dcl"I\CRcwݤ2Q N(м]vJfe%Vxi[4ObEx^ +u*W (h$Ͽ g +kuy9w[V\(fͥUY֠ݓz0͍lN[9m|sD&sz5rlnw<+Ө6IO;{2_̗V'SYRݜ$/MJ׼f MՅa-_k-s˥!O++:'#bř{zͪwgo~jr?d(b }f1PBre M +ɇcrd_I`6NUX{Zr'LAP4 .m0HơfuԔ2 Iq`~6޼0N:WVZgf \! nU\iU*H{Tضu*MD/WaQ;*v?5αVx`&XИT\jw~̑::K[UɊ('ReB8=o oN~ ipgr'Iț؞8$A%?|f^8pbkz>&N U\[@վv_Zڦev,WRbxP|ʊ[?Gy-?TJ-^\'ةkL8x?8}\0*,&yeЫK)T%:X"y2G{E#oO['.") ~nԲ -S#-EZWN8R</^Ì}@g.#>N]z`RuBo!B{_Q:B@m9haΜSAQ {B؏Pnlϻpy&eA9,73[$! y⮰dnAܵ1o3?^D]qޞ1X\~]Hp\?p/ax9)x(zpd^8M-c]hx,aȰp48F#ǩěXR#S:.eӭ WnuH,Gb|0|T,rg?sfcK MQD,4:=`MYIXDnNH0`w~GSW@pJ"?cyp(pj, McDK bi@ߧk;{<"kY-)_6հ0-Gȼ/86(E$M*VVW y C'N|KЊ /a@+H`d%@fgXE@ seRX@) WdJՑO?T*?I('"ZM84p->.@&i3s*pdr܊$ /x(|JDJTY;D#@CPJ (_` r04SjFMm(U)&Q,|g qn4,Ig;.nü[ rU3ފ*q n|rW<'5M@k" zj)C] x7cCi.~; UcJU~޺BETɚ T舒iq*gD\Ms}ڡVF٨ DetR l}`.c,`v +! BfIWS܏|A#Ds d{2w%x.B FBp[[H}i N-9mw_9 Bj "zq'*)6_D. VEF,%ztpRzONProkduDF˺ Vv 2B +]8$FDp fUq%t;»]SRRM-P '[q9|K $CԒ ) j,)EH3R7,I>sd7s^TDsW}hn5kVw&F8n%U濟^@yXP>(rpod4F9l3A;`ܓ_oG%xe6~}6+@'WG,gn1:K_ll +&˖,웹lUF כn^OSofڛp^uнŽi:o WnVؼu+_൴əd]~~dտXzzUO7r`ιcDzq>Vd[6frT/VJu ͂RO3%AIy;;trgzsMq2^dF҆E+?ӡryYЖ޳ԍa_FO4KMr9 Ek!s􆃦@~K/nO6Wm׀T"dc{Ixr2#k%dl_T>hpNXB5DwD>M|&xw/]^_О\M3ͪX;ZM[yTZ1=jns"z [uۉ6BHbV'n6)a3N] &j5Z5TLd;,GM"Ck~ʷv2M+b.^:`JCHْaENs65fRQ=dG ,I?~ +[E43; +Rh-|.aT|+)زdZ{\-a'ԗ׷^^NCkvTYfO!Ԯљ43N7v㸳Hu^ 4|{6itʷE{lwZ*VoZ6ou8`Dʎ +o%kHꗃ[dNjtqn; &i.EyNchl CO-$e{ 7 .`׹.ݛtV.PX|0 +YrQ+mRGɎs8g~0,"}i EE>ML3MBNW+)Ӫ|֛@`W vMx'V S1}K1J1d#1˽/l#[e]tVVG jhc{P&:QvsPy@ofaX hBJd,M9jTTC#Êbp}yAg)Rt$KBfEѝ +?XaX06kY,ӽ\TSU|v"N :=pUߚRy<j[ybX$ +S͖#@(sRXLY\X< G6}tJDjߍC:SgN&Ɲz+c. ZRkgs O6j:kg,Y9(ύ<<zĄR!qdZ؎ ^EEQ?l7^ T).%h,8+n²J_1g)f}V׆B4)U;K fJ/봦{29B9WnҲuDH{ֹDֹ (Λof*[;Sk', ;a:mf-(Ijo>IsJV[ʡ,`;}xQ:{)CPjj[Cd=%R"iP=w|gk ݺKkFDm9MZ*zULIiRL(7I(+.0Cȵ7`^o-8-LJuq3A}ÇxߔhżL. Y^,Klђ [3Mbhc^A\`^bqqfܬ&\ٕ3X0Mz q$e+EBo\|[>?lr0_љy~G9p@E# ['n$*0*_}Agg>v3ִ㛬*&pm}zwv wF9Άa)M ˙L/k2y\N? /ٽ8/3&^R9ۄV$&D +B?(_rwn?8˷Q w,֜~T0jbqeIU~t"0!+!w*m' rѰECY>,<'̋+Ud16K5eĸ.>ms>g0qSk*(k g&3v!z E>@w#@(8}wqVbL+V+<ɭvޏA;+=g*H)m#N685֏kTE{<(b(kW冯X|`CRSf +sHK5BzѷVI3R,\{cLБc&j;XO&]~|i:[cAcrRk  bq')SJ)Yരe8cGb,)^/!.![A=q0ي0Br#&uT={8_ٟ=PON/-/o@yI:7q5-Y ?[q1o+%!UbWw>&g O;%zBz\{@^W@pt]QoCq@,>,  ˻8U )YQD2JDQT_̈́ p%~1 [Ww+5KO@d"Y@ 4 wT)f';@\ U@M@6= O[`GtPQMߙ숸ӴQ2x5ߘ/Xww@HCNW! F.8+NJnAԙ&R%cT%C\SRRz`˿1n,&[5;<~ql8ia} X?vvkOJ g_4mrY(b6POQy% +RzYMo"ow.K8 @<{)~~HæΫ"4yd;j$\")%"- ,8pl;?M|HR;R%9 +D`Diyb˳Jt{<2wy`쟺ѿ./ƨJ (V(P3.^(=~;ny P +(7#^::8tw???6I'z;~ۯ721Hm{4mWf Bk@/-V +q }V+'20.ڣvE? _/S2[;Ntu>5o&Wu>&ӲN.ͿZ:4>]d39tUyg,9%WDZ4ss~k s_f=$r EL6mmT^R\dT'tEAN~XĜ4M%k ww\r:6p /;r:;K]T-&:Mro2vFe|6="7ih!s&7P~~G[^/aeF,3-3^$M7=JIifAN~Oq@69%GX~ uMA'DvZn` GC'Nzm[8wrTL<ƾ~U׽#$},ᅧvG~UGTGV}] WKŌ²cže|[.HJA30*S\w| ll0^e]eKkPq,E,]M oȼ]y yGM:”%+.J`k>a7 `'iKFEKeߒ[q"C Nv`j^n׸lvl犛ƤTjw/@XYVEr|3|,Xd +si35ȏf=oܠ|dq:{Rd&n~n_喝z'wSiFƒ>,X9nŊeZɎⷛmo?D4embtQiQpdϤ켙baq{!нV՛`{9n*ЗWo{%u,;*TQsZc~z$(BJ,sFESq];|-ݛz3w^jkRvU'jl12 eWQr:Z'bu4c-,47UͥKqL]6@ォ'U‹27`@O; -MѢ$gVUMMtGSS,Kk, +>*v,,Y,E+v~,C 52EYٗQkPRu/D*/q,gsQs}IDw(bJXh>ʹ*f(bv~+,Lqކs͊es5^lg~Q0an7cnwUf̷6Ӝ3dPL`7"彽'ŝ؍Pm [ʃ@M.q/ӑgّ;!3\nP:<ً/z;7ceGgU20]mG3K fՈѢwkC.A7$^ÔQ[>\V) +?adx5҈E/lw9iy{c 8Ja )ĸuq35RhПNu[6'<Bq07v<=yn^d-nF. wj^Nl؞49Rn,Ht^@ѵOk^sN߇2v\rX1[L1^0h{@v٨NċR]8Pfl-8W|K4| {#&(I 3<Ψލ) ɂH N8 <RZc}5kx:>ZzA>]CNkܲCQ]6D<x)!HWM' V4L ,aK`ޅƑ E|Va)gFLOd#AgJ!ycsW#m?ATZȭ#ȭͳH?N!jt.B7[CM;2i1=!ѹὖO3JANĊVx4~:02^әr,QqZü?R7L 7/X"E4Sxy/ڍ,#Cf@N^9IQX@e=Lg3g>g0ł'D vK +ΰ'̛+q mĦS=5ęgǚ`v3F7 ]ݯ};@_|z ;Ɍe^^wbyrXYy W$R~pF?Lor~X8*pVgXs 6D=w m(q&SmGd&*<4m83yf!V[}RSgy\8];Keu +ZvKgT;bٻZQO &xwdN8'̎ mx]rm˦HѣK)H1IV}+/Yj{tNdb~PP4ll֩GTpJ۩UtC-a<&"\u#E>mh +ѓ +_.OM5)Kj:Tbg!ÓӓUʻQAԚ 大 n1f:rɔkX%=7<І|xPe܀Il"yUXSa3pW}pׅnZeC>Ĭ믓ˉUИѻ>{/-t TR3bcSr1 :KXGi/JZbPXi| jxoqxء;CCMӰC.AXbΠ_G裰l*'nJ!>zTvt(ĺd bo=E>oD) v/j.U;ui`aaI򣆞m.:PT,Z,:*T鸏Ĭ{{<6l*9~ϲѧ)&Q&ڦE~ ߉6^U836CgXׂ=,Jwè8YTt^\yqQ_X*%4:.0p c}w-#"pŢYVqp$G.fZ_rc~{kME-51=B<[qA Yl" @HPPq#Ad]8 c@f ʼn8DwHA~{ 9skB. ׺֎^`\&B-aA,u̿ )n&:^l(Q]r;3ǀ02@g(1vP͠DҠDCy/\ǂ.42bX%npD͈P< /ۥ%;tI"{d @I6PҭPr*AIHa%[PJxaj$:QbtUXblx YL0PAh'k{G7 n7UsP:v4O4ġr%BkJ/J9``1 (vzӏ[$=;0ivoИ|zCzE ~-4Kޗ^+ePvhlsyP=qPFbPf5/CQ ͟Rl>c o05{o=odOoP< H ?qx_!HLFo+t۶e+P^[PoPϦ|kAtrm(\>Ͽ~ _R$"8/+rMʓWo_W(^kф- ֶ#P@Ī*n7T\ܲXP1/?W3Lzt;hR~uK/W:Zxھz_ ,9ו۾}t.Y/Pe RP%Ae-BepRmm(YV`\noA+ knu͆B  o4xALͯ|]=mCu\AJ.6| ƅȅ=E3ł$C:0N?<:'r̭d.ޮ +HuZl v`sz(*@OBqW~,.!oq]1W+50jq$BMԅK<pV9StOb6J#C!/h?pHIS|UoKJ2F ͬL+<w)e|3PzX驁{t=Cp`z2'W oac Λ$w?2Pp >~cmnIGgJy?1DrQAhL|龘J68Pcp(_҈,FU"%eud Yyd0\i]5#םZS9Yx'颖ۃZDy\v=8vҲH![z6A ls;<[lS_m9%c-pHmtK(B>BmctȻ%Zv5CZh.. qw<YX?rn 猄Ymlo^ %&k:3&T.|>D +yXgvs_t TUTֱnE2ntJa9$O84Vl^a'q隣ghG\,"Å +Mkt9=mCfܠVx]n0>ޡ!~)'|-Q8λY̪5QZBpɕ%8E;EpE=)n6,;"fYmyG@+UkRER0T,zg] Ӓͱif~ߖbcLP[+1C_.ʿ[}˅Sf˅о?An_!/T~\/ 0WOr/ GGJ?g[_iK1ЊM`*K0[sL| +/kgB|n^s(X$ +4I2m l@6.<@KάN7eN'hS @I1Y$83 @xl|\(Vbb w٨΍̣~g$}~wձ&it\7WU*QUdk+G0RBbtfwV=Q/t:d"/ _YǂFh֌#|/ޠ +@Vu/89q^VNmSկLKu\:ܛؤz[E>*!Wn 4wԌ˨zÔb&lSϷ' Y0-]>R0ٯ͔%Z_Ѫ>Dy*?0>h ڈtNdH붿Fp#X== ?|.ך4yr>([Tܺ-HF%>Cc%Q/tpjG: ETG +\Bhym;$B{Xr=8 nV vf(k8I# .4᫾Z[`B zSPW+ϼ_>>ؗG F@XȻ -X|?a$px% {D\x+/*$ą6W~|܈Gy ^zz@OXNQќ$wCL#8"7(tdvP$hDpįM TLa+щ:өy e+~j":pw=k;+m%“fYJ7A\Eje~=h5 CbTa#hMRg3WeN:SDlfOR$~>2:"<EޅD~gTUB7> ~1#b<@.~VL/d T6>.ɗD^ϒH.)I97l1&A[iqcEo6\mzR^l=ŮOQASg1F7%}nl\7|ż0 Yi̕hh_@V!ÆZWܶ;$irjvz "LEH~U^m}S\oƿv^s19`wL8>ImeоqtqD&_7)>d=':䤙щ=E_Нݍ3^եV6@~VreZ 7vlrNwOM3lZvX|$Wq+#Wu[kj⽻M'*}9z)!;>Olq7tz[Jj$tUQm$ +a ^ ꭺL~=vs}{ os2t7=*xTbkΞېEGuf8̒<~(̝L$T9Az%'?"5b寑Rμ&U`ʑFÖր[ *xMS8;-JIM^/F@‘ ^tƪ23><ꇩMtvDK!"KRzӚ{eMtc-Q"5bz{5y,SO:H)N !r +iAa"/SW`'zxmGуpZu@rg#?0pE> ""aX+m;$Vö j\Q#>t+j}T^mmLJ^%F:Z}L@!,rĨXDig S8Kn^"oƄecs=KnOC\c f|D lgH;%_m??,?8ס'*Bc:b:f{&\ٓZO +}ZJ囸d6Z>p[InEC;變n|!A? ޗ_&.0C_.';~\+ - ̑n?^T}_`:V +sa8Ry,R#;@Vg5G'q{%Qz-Jݴu 4n8rQ B80WE@3^ѭ" 0zsQ}r۳Z34Wa=GkW[f$ +$45,[ +W$G +ի(]g>Jq 'NP?[5XT/8+^ (Mғ\&V$m$+&$RYâkEePM'snYD/¾˫$ݫM/b>wL7OuwakɷMv^];c{a3cfER:cv"{z붍[Sp$<6WJ YEu5t# .V`~TB7 JT Bʿǡi$ܕUfB9JFG5A;`+nSA:u :8wŝHQ/w gN3%\!n݃ͅ%ЯI:b)(7te& ف}ޛ.6~k^]Hb'ʊX/cr#ƭ.- ]J;yy9>.窴4͍(U5]T|ҕIcvpkw#VѰA,Gw8 XvZ͝4{斛N1C'S~_Ml_4Fޮ[%uWJ|!!cKb?l.1w+aY.?R;'NGz,0rՇ#KnH[Wڙ|s8ϗybw\`I R.Mj;˖G9hǮ_Ҏ#F#m4GȬk~YaZyktDu^j?go٢KEf<]LX"CϋKs?0iڞ*Έu:OoZ_<ٔǤ㡱? 1qGP{n=>/_3o_4ĘPFG9Fe#\t)3I=kb0g500i06Aڪ9Z;W,NbS:7fr#P޵xC3̓Jo16y zX͇J,ѷJ/,gG\ߌ^՗T亦uy2]窔?×i~>g{nܑd,z[#P`dyl8j%T7>alV+ROȖ<*T*p*_|)4W`  !M }_`_`w c/Lp sڃ+ύϵEd:2ߋz~Zai 3A݃r)qbuwd5K;^<~RKY7) FJkruk6^":"Hl5JZ9nT2ܳj#-`|R_LgMWE$7b'엄? ~R3ucdI[:by@¦FD.8[ +5zXm1dȦ`˭DܕBh{ڙ9 NXws?/%T8z*ޢ0TYt e['ϣ|sqKfkڤN |^#}˿1&}[vfutzN,th6ֵJ4T*^x9IfQnGG'5\ nbT]Y_%CA1.ՙX)j :Z<2-5A|^0ݓ$ѠZv8J~6\.!X:2x`L4Ls;53Muu5;e<{Q`/^veNA5.jk=X{D&}+̥O?[Cf7fL= rF %>)"|SZ{˻gyv!#S[;蔐o^? OnNL'o#ךSJ(꥟;*qΗi[ +zW ֍y5TnR=Hyȟ`t}.ws>~E3~ c@'iY)e!=syaڎlOpLnT]kۑygl$LPx7S9ZQT/nRMŗ{kTrn"|D_-K vNMf +1WS$t/@Tp܀ D1zi9{QQ4=.:B)!j'<ɫ" +o.G&eؕH;{ j8Rʟ@X&^46pTDɘ\iKgj9ܟ]Rav=S*6ԠRn:gGUoڬ"yTZE*Ry{ `Ўt`9F&ytNDaR[c- i)Mml^Mz;~W%Erƛe Geel~.A[cNUZ HˍuS<>bK\%l63pw[be6ʾ[L-~쇩rxﮗ1},)_$φy-_ɠNfE4lg{ Octt9c)&.r}lj)xX"-—;^,R)IO_TP> DFJ2v-{WUqJ:3'gI$S$̽5]*["AeO2aJi^L9} ~w v:vmif& |m2Rm׫\$UGXWsE#m*[UZT>lba ʝ$nmW 8[|%+*馷ȥ DyCXx-2`?)`4nCskLor 33_p<ٌfDL^>XnԀ8UG5Ԙ?`ʱXKT)̳bn\*i23j[5dsƏw;e48y}vnCUlqV90\6 +L2\[j(5 h,.lQxv']5u#P\a<`;AFD6+chs;%ʇ&dR~͆iS{uF @80ɡ(YpʞXңٜtiK[GIWdA.Un5uy_l"MTjo֌OI~=(3/SQ"Vb8Ei.1-Z>]u;VezvtUv_Qso κ}UύK%??7S~J!Οjp]O6 =vq6i襱P׊A+#G=Oݾڪ]U;T?:ܾ +A?$ ۠ TϡrP}-N ʎiz=GD4JS.w|ǘIvZbA;󝆅ۀp 0#f]K' Ur J9@&9l<$dRWنsB,YoG)1ɢv +fs'wb<^-ho*jYjy! \$h9ߓ/M玉tAEg瑇lUGTh{nmcg62Ϝ K;~*ýy0PW l{POk0ns3z9uR}aMXGKrz,ph='D. (TM4`ZZiTG.Yj=󓳔H* +鑞|›H(iImTVUl$[rE!NoWzԷS3O[Қ0Սv)9KݺYI ʆЮ2wU[Z+si&4 dNGN&6)'ƒkQoPP\az;|an/,jMl,gqP1z!gM:en-\}04w)amI$v&h|Vnz)@T*띇S*z:eYZԷɴ:5^j!f4–w,uPlV%VV&jV$2OdZ)Sߘ{'!V +׳Es=Z@*츪YmrŘ8+qrWq-".8xױ؉49D)!U"&6bj7L3~"'P~Z˭ݯlx -gG`6ҽ+ Owi_G^;H](Wpn-Rv1JzAGwP_/eۮ¸ӍU_8hY<2Q^'Ǭkh(G6{jsƧTZcgPRQy +W J,c\ +bEa<[bK,?%wI#(<bo|P/̽RKǍ߸XeIĹjiQc+jDGwmT&__й(|E:|J<L 0)`p/qMaToVPȝ!@9AK&bF|'Vm;h',XUfH֯ ށƍNwG6IvHhVxg՘^m\Ʒqu'f#8/p-[Σ[8=֋n3]7*̐!}JhME+ev^:&TaI%ځcgǮ&(?Ұ%yٴ;\uh!o͢h_Xnl*hk{kuM`M|!C%;j \7˲MtUj˥~Ur_ᶮqPz~Up^jt\}Aβ0d[0r1 v7p.6͑&wk&>PQ?4HC=~20]係@ 1jc{64Ld24+综O`I 5,F]ca+s|k5sCn0̮\fnntԭzt}_Pv)G|[?='X l }n?Pd䲐'O8Vut3EtnLټqC|!ts* +ԣ,JfgT(+5X%".+m[a:N{ļ!'2^?)\#`(qjoΖ$Ss `8l`0is3Jhq[BZcW0'-j;MaލIgb:XVc݅_Yֻ{fL{>ۖpOi95ߚTYؼTl{!ۨ&rN;k.< +)BG8?%}W+]?OǪ'J*kD[;L=|!N5}ɶ}61 r;ra;M?ЄU_,,?,n +jvq +]!کxL)⼐] +gNPO4R8ngwoeg.+hѢwUs#OSrd>+!?<yxx^o<@%cᡕu;`#oSwUJ(_i}Ֆj8؃? 8 Ʈ8rr0WhN|ΐUPK +{A*]+ |)KҋSRUu![;rwQ kNXߵ&NgT%! P ?nVҹ1<&c9-Òa;/^|\/rq;Xp^bPMQLQ~}מO"=dG2|cj*ħǬx}!1Xͮr59Λ:7xY ϔ; Gn Chx&}|ZM ^,Wr|6H}9X[n72uz\<kGuψ<3rQְF3dwgVl}&D|nxY &#}BHŠ|xAq[r:B8w8k$P:fXѢ}{׏7V!X.J?O99a9Ӓ +Q1~YE\ 3_ 2= ~oou0h^_eX eM?6>66{[^v7+|Υu}5RvU_]Cݍh-|&?c@: \#t̼RuRe޿9C+d11gU_viH5J|MIO*I[Jr򺐤:ԜPwϡ5Ă݀R͋jNhc^aW{M:uYHJEхTb t 0 mNJx{?':?(fPNaj>Ģ ""WC!ɸoxXں⯤Ł 1,vNYQOT=o\gjka]iԥ? (RVB>(Y-U]GQHzyR9J)ul՜z>.>[~z7zg,m/ٌmEkq=̎^K';MY`n/qQ!EŔF ~>ͮ&K6`7]j!߇F`i̬gKu'@܇аWa_TC:&v<aOI`+F!ArTQ5\8X*)L2HifQS=_ >!gߛ#Co^7Y2~LeAnW+@w4/asYWbx"顳W9ձ3 u^{=)l`y*o͎q*?* /e* _gYi)|.eտAgbe˦a)~>/13WkGL1,ݻR}I3ҵuHŵN__@eբM]g0@Kz͒_T<1ϭ08,9ֱQ=Mg)1+kϛljǔwǗjk'IƽOGFFAqiu<$ Ҫy]VҶNӋRWJ oq)uJMe~םW!`e^|3pO&KԪcmGSaG9m?ʼnt+X u2WlKD -l+: lћ4}[E9깵p}XH&':Dm 6~ˡak'О6@m +`_.k4֗t8YfJ8Lz?A{tQj|RHJ\]-%YYQTmL60;l|!!!@&U<{SlN^M1M5d6*)Vj0Fv;;?ņ{_YiaǨJa[zVxd~ +u0NML@4 +0Ld! ~!1xzB%b{`}ɗ'`mL֐|w`]QcIʆX^κVH _/OEϢ?Є=U_kQ.}NL6 \%Q `-qK~> {+վX ΐ +wo%'2@|^4l\^y6 gc{e#WB_U蘅 Uk2A#CrV̧;n=3(kJVBj)H0b~UXC9ϋùf^s*]Osvw^`ٺ?p{P3'>ry:cp]יJQZ0Յ== iѫ'= +fA!` P0mI-繼y%w}m/$BFe4q]:+UCqmqN_@b',_R9sڵrq@DJ + +waI/CQvut54G+OYyRxV,o.y^==&|-f8oxtiXr2nx6y[&q0 yPh93pHg<lpt7KyqK|g%WKL.^!*c^oZ}p4Z? ( + +` + +n tJǧF3׭ĖB|ȟ酡j{KјY\9L=6}>9X[rp1geսDŵ3:PT*9ߠcn +pab2q[ KcOkct(k&s}Zaҽ~57ٟ k5C'tuM CO-r5ɍGhQ{ܯ2Ӊ q]iE}(D]YG4)VHQf`hGT)VӔfzֺg?dwBS\ ;f>`(?I +فs{Ԧ/%"bQクm؇kwsQ=%f/㈮%ۚBh38io^m^l*Mw-:RBS. s'XE3׋[P 1oRlz (2%R]s[dg1| gpķz6 m_/䭩4w^Ɋ*FW~?4w yPJ7Ags >+9r{uv8^]ԡEU${h/M.or .Ki$.U,չ9 g_^M;,2()BQrQY$[bwk}n]Ġ)%Y[(tCЅc\+j㵂(mΥy3mg\IRBX$jr(mJ 0(iѐ'u?މEC֪i @`-rI z"50zLߐ~?5'EX5 kP4w]Jx8ܯ-Haz<(Wڲ,S/vq=z).uM֟|Ti:RE|puwL!0uNJI}^?oҠ4( =;.Ǜ,5Z6[\ɶ^d6.vUZՙ(dc<+qlYxwy9y +^y^7׼﹗Z>#BXAZ@,z"_fpI.ڇ0HS+Kdyd~Bj?(\+k2 +# J3hš\kK!*ox[76L L0vYS3X̛:urʨxfcq[N09TOv:mAFe~vl]Fusp\iyw+osI)s/2.7rj8rsKJ8*N8YPI u@3 f^ARk1 +ف[";{\GҊc>stream +Q[(ZS=; +ĤȘ??E&̤:Roح=4eL\֌=v[/|D*|L3Z3LqqF쨬oUbrZo*Jw$0"ւ%`5Q%\G1Ü,z2| ++uvӝfO<}W]]/)1&0]زw GaX?*3fJMd>0${Wdu"vosajg,&+еۢb}2F]%]%Np0xX}wA9vvz](VAX^Kz++bL6:5ތ5 +cy=gy2wy#"Sc9Ah:Ov|J`0%Wb;|!\>ry:Z&nY/u݉<_Ҷnbӯ&}ewdYn+o8@~u<'g&pwwսj%H8~ n`ֈt+yӌz=Ϫ͡{^>Wh~!h+5G@[@3)-]<;/|!q\Wfռޟ-AL>ZyDQ2[qtT_*C= #!(k@ P6h`tAb^[ ̉ի$ MH "-Шȯoz'MBvo0Hh5 u g~>ŕhXOG/'oQEŌ#~L'$R(lhhI+G +3-L.z`ى >#Z@hEmb҇gzsb)=k[lbqk6._BnI;=m?B]]}~aayz;@C"tUc;ɺfs,ak@={Pzp3:).?vs^W3ws7D:{aCqruE98e- `_LWB'ٖٝ] >[Kk{t0dzE)'Ɍ@\_r!? TXRT'4̅ȣ&6 Pk)7]XCۚkٔo$gge4n__sVӮqdDZ?2(x (-(LW'5u;xMF3/y{K\ޛyMeˡ}ƮՖWۍU7qɐkf +5LJI Ɵ-QxC@nO';y3ro:pC?OsOB9leidcpacua9k.g$]C?A=yu2 +_qe5c+Y4$MD +M| +^:)ysa::˜rosQ}Yi ݙt+j2*B~  E#?X9l7~~<cWbg9/8ogj;zpv[Ko|o:sM=CNK2=2}>~vn)n _"Aɐga,7~3W1 +%j s\/416g~LvK ֖ZRqX>+ +XXMLh}O WPsb@C`v/:1)uQ&(śoUuG}KP^eo Z -CH6^z;X_r` rY geDkxO3~wM/=r\+9{jYu|G6Ć];t;,[-B}`[a~8(y.7͎63mXٳ`(aDaf޲yEn0u Gw{1o( 3 e&U+T(FT6gvfظ4:M.x@9(f?YOm+@]gY(xKp"²!=|q!yۓ)lR2snsdc08N NihFP?r|@\;|!sF4(nV(D?ڹk(]Cx둍ce|{]JR-v1G["# 7tggBf}q=ޏ#D0-g_gClݸ|pd(~ꃽ5ήǠ,^^涵 yJ 4wxOa95ޓd0 TTwo+$&%lq+(b g{YG`a޺﫶(;E8jvzp*Bz+]i>d6v7\nԎ{Ō;9g|!CQ)ztAi-nj1?:,u=*x]yu%--0iS\+{ׁnpgD#E\m ۽K&G/BMs JCkS1mQ7Sfj~V > y ^"L*Ɍ\IkðsEsM}!Lؑ `6AٙPΙmf)=v|l!%V j\ԑm*i aL#=oYD=k=t8EAW C +"ό +5VYP2!ϳiPc +W^?S0=Z3>[i7oh N-ՙHǕNa_mmf'Bv!T56YPJp9=qv +@nӠGeOS;i[v2E!1!^Tf)gZ`\c.Q!,1Qw[ #ɾ"IZcC k΃(~!߇(2  Nzw4O--꺹K¶^CW[ +v~Og&/ㅜ0,uႺJKR5 +\'ܛ{l\!yg +WZ紧zM%dS_liu{Y!8;T߾TWzy>QP _)J%0i iguuZk W;^;y{zGW}R?՛c` ~!R~ҡX)Ir}gbL0W ߠ$7q\Sr;RZkM&u@(~6y;kĖ/_pݕ|Mōh%uLl7pvmMvܝ~5%0%)97JhR)ڣF Srr[u .UJUݨ7{Cq'!ざVT>z^ӢE+\T+@m5  { +͒s8IU|L:ڣ"Gn r J+4;|E Fڬ(7{= Ȟ0DqrX3.5ȓ#4t]CMF@Da S*?&b\zG~$X Ĺ)ނvmGOw :AprwB:99u=FAÎAL7<[+ۃH@<,x1.vn^-pMpxYubOa>>Nw; 12~G>-{idwѾU^$VH56brO (ZaY⿲!:uKM +? 6OhrɻreUUq*nzGWuiOveaʍtgo?-?,TXy-WlT@ma ymǧ2=FoPUMG9u,غdٹ6ƲӠ6Jϼd(,yPV{UO:4?or7zX2SJe{Wڮym2Hks{)ˮy=>o +I5P8sP8/. 72(V˻ٸL:G[ϵ><^q>_XM<}Vr\п[x?{$>Ƕ',=d-uνSƹ0xHS;뤲~4gY4+ c5*L H`YbYvէQc?Vy Ele\@9 +`bާeoQ̃Yhiv>N5Sb<J"4XYlm15GK5gmΨT3E+[-"O] :?@-b=M'ڌ>AQϑEyI9QTRKn]jۜw5;mz6]<-UΕ__}i;Pό;3np MFfҬx+ۻ\ã"vHzs pir\Q6y"o:#, =_'_LW7:)jFin5& !rܠfMXV;N]aqsm.}#uږ}b6̺e~j{i]u=ax{U sq=^ymi5v+PYdЫlvJ5\vmc|!bНl{V#)[ݫfsy2ؔ*9yIu0 /͸Q ĴBIh +АQ!T=\ûb '-ne[SBub]}(j/ԯ_\jwڇm>t܍GH=;%Vz/}Y=hdGB-j7rjm򮵓pI=ĸq*-Kޒ`gwq޸ܾ򞹈8LkCmC="pm՚}urrdj*bհ>[Up*iV0Sa*bf:\~C#ĤJ٦|^p3˅|\j[L'FʻH=7:W0ר:\Z;[SVVB)ѵnR%K}aKA,@8<{123~Uk>+M\6:TvE+Fwt Gdf$@ zͲgWcu=keYley& Lfis<3Oޥvzp$.!uXw2;G,K[+$QTz;j jmD33_|7tn=aKpH8,uYpZBqnή#9./V boz="q1@F"e5.jW96B` iCT  [c u7 + +T;_]۴KQyl?\߷Ȫ) +ڋeՂxk4'@gTZ& jPkt] ?(kט~J> +q*Ny fߓpTN>]3dۄfww ~gPrӀʜڀu@ V + ,m@ Tۄ֚aQP-x5孜Z'5|56^6q.,lta(^zn]Kc|~*_Hņ \ Ҁ(NCP +|wk$cINj¡kbpCL7Д9|Q`Ɨ%*6l7E+IW(ܔS</9 +W(tЯZ@@(ډjX¡[\l>ߠ -]:ME,a.#Cpcq6nNl"\ mʬPfPҞOݖd@'tI,Jv-]<)RyDͯA^rO'b܊cMGϽ6.b GIv oͻSOƿ@P9l@|UFяdLH(( SQhMɥ:?m 2Ƃ_^~\偺wA;e8}={YFFYaܚ◵z(vx`GjKf +@(@c2Ƿj{f<QHRRKgmţOpt}[HP9_I܋KzТwٙ3&E?Ըe7Grii$1˃$0Rk` Lij =:h [5ۿ*OM'<7{ 4.;|~,!~(ϣs:k/=;jPRkYl?8߰u>xƣ3tУG6/a+@y7,xgNv57rJV/1oU}Q\x?)a|LfPX^Gj4ǵ`e1ר> G{qa%ٺ.Hf%Ⅲ|JTZ7vgnuduc ~VV^״F(9uG{,ikjndwuCrkqx&Dwo7yS3}](K+d2,AalKZi3h&7 ^!L֧!ћdkϞzV’SWʣF:7ZGk{ jЫ׭\W[ +)[dJL/T(#%7)>hUz%Uh}!-s4,Go,F!/[PY!9>~-٬*kNUa2. Tj X o +ݞPcꙛ{o@N ) +=wP +FD>vP d~XsxZVi1 +Yj_tN3Dt)WPf?2*7V U"\nבĈj.ƚ26'kMr@2Tv]gSP~;"Zd bBj$Nv( ^L@Zo> u;έ(˰@hs$\|N_e= U>Yp<7P#ZzgxHЍzgױJ&@8v~%ODHܷ6)Wd3k*ϙ9jGZ]yz~7+g!D/H;M.)Į} 5V[۪~tlaG~M6$m`|@ӟ@&m U_Of[EcYzoX:nxi^ =drS$R>J\w_`HkvYh-5+`g Pm bT 2%]l( ۤx0.QR}#@5gp+s>ՒNHdkNzڇ~v1r?LWkZ!eFiÀ+I]@f!4%iMUwa+ze} $\!u7Q+{.{~_6-7ةwXxv73-]0AzjT(2b^ږ8P.@2;LCP;3HZ"V{>SlVR̶薾;V5u ̌9VYG=hzQ!Df+)e(ӽ`>M7.Ȭ (tkEGr{h]Ri967T$R\~ݸg Q-eXvV|rJ虌ONEka>Y ٌ_k)}ٞu2?KStϻo\gu[]س%s Nw`>ue:e"Tǝ4>L{D>.0?iڅ6 ~>[Fk]ݳUt䘫b}Av T:,{FvYgg/7oN<?~7ظ-Q\]Fqv0#6d~]fVw.T2똹GN|<+_>-w,vC9,Ͷe[>jhx,S''T +sn.1ѧ So>x+P7xLl8M`E^ݧ;UT+WKS'IM`ϣiloXHgyg1O]2zw{LJq=6 +@](r={EBItG~!Mw$ׅ1@M @+lGH _e=}th7BjvWz"ρN*K:/[g ?/nT :3{tASm&X^mG2'UmWj8ʳ^S'1_Fmylf#O3SWX~ +pI,5/&7G3Ҽ̋1̼n1SĹ_P^CG&..oNn1:n?|pn%Yy_=:one>U%LZe=oGL\H݆y6+#&[V&n㯀wdcGaarwE M *vV-[j3s;fyêzct:lnSB"#|2 +<]+B\*|7b"RW|a|߆%uk6H;A5>/Al}m7ZN@"[.(CfP +#i[Yfsj#%on[r)pXfխKt3ϥ9y¸us⹾+^8e!3LN5֬ehÏ9sy[]]_ޘk%G[lnڹW+YnV;tOM#Xcϡqhv͎2&uI/4(1Uum=>yԌZ)mF6>s]uB:z2GꯝĂgtN޵AAg9k36q]FݿO՟7;궧gYap3Qbv7f^~i.&v.~w2| +s㖮f]ͲT]h윩 >1hlH0quII?Mm\d99Tk٥Q-V+t^"\:r<׹BeYܾ2ZϏ3#+TUBfAkF_[7!\&ʟDrGM~6pWa*f7 L&Wj\.,+3U +eL§|ئi"S[%_TD(&&D._%_!>ߝ?m[nqυ4 + 99CyKiȝw:<ڕp?cȗ -!.< \Y0(U06cj!\^QMLD3Up+Wy0!! + 0Zih84z34@ā b./Yc DlHó| 6 @ kGƅr1o6?B_:K(S5``K/pP}Pth{C;Yhu /r + Ib*}a.'eY|r>*??إ\V Њ] <8^@H[3'j`q`]ga޸SB?@k+{-h|w%3r_e. Dng-6wՠz.<NOܦckJmpUvoS}чR(GqQՇ04/E"#?x✰F|V`#19˺pElԄ jeu@: [D|Ә\߯0 SL.i"Zʵ2 -^ b4K7zV,r*s]ԿmCPl|Ay ^dgzNW]_* pV pwV,"wB|oMh& ;!¨%g:̜N4mߘk2 =EI% Fw׳JKwo#?@Z^Ϟ99_q*O(eѩt[;7ly`^ `>.'X67i}@s;3QiwKԂ}{iυE7j}/.IZ|ęMwAm޾*ԩg sf5$˸lBDoVK Ph̉ݝ ffPK^CyxL'xg=+IהL@z}W^m?zuYb'=;ǡӯOyȢxqaf}\+fy!d@Ckpr:p^1Ua?Q?xRXvḲ7}Wb =?;(sO)e4[xdW:?YcYcUSh퍲P5ZEci"dq*C-0~1vŏb=x%} +phh7 xVfכΌ< =[:)oL{P8\I} +6B}=lAH`\`ypQBTBX:A{>>Ȟ^ 8މwbnp_gAm=.}0suWcoa{QDPY g(<:#yyӏO!RK(';ׄs,`K&;zbP0ܢtXDfeYEФՙe@-}a˴k F=oywCu? {"xyڻyóÿ_݄sʋi htOLk1pX (2U'yj}v~-uIc1@VզwR_%03HtVq&իū[vy;޾G-9^:*bFXr'Om;^-kʭ_ԧ +~zv&UJa +UXުLwG/l[$Fn5/is>:f |s4א3HQWCʾׅY٤ACHf F=ƘEu4~UJVJo,kޑYV8?ev?xnV.#(/Zfnu"ϫqkҾkx.{eƺx8y~-YmJ!+:.)!EPJ(f^b{k_V~?C8N['.h}% suJGLj+U[z5,1 츨 Nԟh릎*ZW߃#}8{yR,b8k!.p.aֹ]qKthvnET0eUNΖutzدTS1:g.Km)XIg~Se΀f.:yf Wӯ{uW`,HPu nenr~eKTq h f_qdNJR![.egnbŎ2S1-8Ȝs$.(P[H&LRW% ?bj4!}=3sbtlo3lv({E)O?r;;eJHZ8f4%U_9RN6Y"㮪a)rM06dѻo4C\a:P><0ZI󨱯]R;^s6S%Zfuflڞ7T16);Bi +\@6Նmp%K UP)n!8@{@ ϪF@u.rY`1@ HlUupcoPK:p[*^ chS8t*CP}@,oyxm{""k9%ǷPς2=[Ph4i\CR٘\?r^ jbqu`j]@ :{D~QuM2y&4;+?yБg 诔i8 )5Ma?Оٹd[]t6:c_J 7zx#v_F $lz :ؖ6WާTiq2{~\[fR/F;OWme.v01B + ( !x24]X$.5D?wVەGW/?!9s^wwjըiϿyzTOå]E4O9T}7M.LI^~GҡT-\ x( +HT=1ti{q׿?ġ{08߲v>;l)&+ZKL[㼼GO¦ +jUIk]mZל:kzӽ<]qO}="]{쎕]jmI +:f +gcޭk٥|X`kqއ;m5(j&j;9>tGW+-¾{ۨ-N6eq-%gQRn_eA P<{.tTrb/~_wY@ĩ: ?F[e];qu/mH3>b*ɤiMEty}T*7pYE>굼Y GF_Kf.YWo'"fzz}79dI;2ʫ<.݃lIƃCq fMoRmdȈ34^Eo nx!<'hu37R/2q'&jucc3'AΠP}9I?ih/~rrʼu1벫dD_:Dyvnӝ)ڛLg_MAI9;qxI*2+]4zRa[fTo/n h"{)8dvg q};mY4NN#mD]yP6}sN6ݩ{|Y|)W FA1Ҏbsbc K`:yzq'u [{i,x?cȉ;Cں5&<90G` u-g5 r3iOf?JT. vc@RLqayw}?x,X<[@\PC>] :Tب8-'3]k~>u"0$=)xuR^[hTa1I{+߻IћޤT{js-+q%++ ߧ (BUsFsu9plbejI9p iB{<3~QӪ+[P!n<{dug"-D^iLRQvM-tPގ I^Y>>;), f_kImbS5RV3l6O?+KdgjBԜ"rw 9?nK6=4jh̷jK} Ί |$ϐjR85@ ?Z38s~1ۦ(=~=uYd{W8NhƖ` +72}%QjjmwU<Ǣ-0%WE'J%{z˩펾ZHkwΗ}RRB+NM}Ԝfkkz;S5M&sXP +[&#- 8hv m7`+Lx! +h£ n*NzT˜[w]1g6@J:6 +Zz?Lar>i|.zr :: +y}о\aNU?A>8("(8!*!asO?fZ"RajѢx76uL(ֿ2Dи ìe|ǜ-r4ZXL&m4k|]lKuUjÖHwt_K9k# t-^_+f '2ѦmֿJtd^$Adoc?3;C#AOst-5+*Qt˟i!KZis/}%FY&ų}lC^'F&/l\a;Jʌ9jGsFe6KJ1+x߸I8lHe{EcR;pRJ(u槱>DMcmj=y?ll3$xaZ٦ +07$u;y`(~IY8PYZprKy^h]h@6䱉[q;;E'Ԣ6_β."*:G'kݺW-(4-˯Ocs0(BftܮD²KSz' pJ:}|Իr7~P0(օ)W򀨽t@ m|PHѭ+("%b7r>ds?\[}h?^˚xa#{\A%/,k6/1~ie~ zk@j+Җ.H9jYPn]#@^Ͷ0+R[>b`~&*d/mVf|_yfTgyXIu907MO[ XQJw$j 7AzW1 .P: OsB-l$Cħk%λ̎=t>^#s7R>_&eM҆bb(5vĵg\7`ך0, }ݷ}I{rwsU^-m;Sn68X-0o}t1Jҥ3nuɸSN1EqIa 7[a` Yƈ/C޽eXjo>_zF7mbKc5J}JzhyjP>V/N==©ԏ#݁tZ{дvhVQ!l/HvEѦR^rDx_Lǩu[{g[~2tja}>iXV08<´n9 ! {3'V^jfwur+BQK`(Se ^3!]ލf^,+P.-7ݮk %߹j'..ݙF8="1>a17b"@ZyRʻ-[H<WƐp>9R3p]B_ٙ9_r8w`q]YPtP+-ft%:/,ڍnd~-]9hl/?}؋kŸ:  }ő[:l65ʶYbt`uD}^L#uO+,1X:[o5ZtKma&]j]lVP4YimZPds ї^E}PofM؄˔ϗRͦuB ,Me:5}'mX;X/t>0 Zh8o-r.mμn9ᷪCUAe!dY2~R?+/X|+ VW +yrmkswYLԘc[drc`sL|g~1/[u(4®O{h6e5 YV%[UjVEuYrΥL;R0 >Cйg(dcfy03+`A:$N}ry~.qT.nTe?Z%Jw-mi֖oܨVKWTNy*|\*mLr\vY8e0Joɇ;6Af>BJo ((#}];,^3̶$V 4}~&^iEBT, j5EKm +3`vk䦊 +n/#9#-Ӆ!+/ 3h"AN$2 +l Lϭq"B,#/xym=oo?yx}ɣzFmթC pykdUc6ҩeRä + x5=1&(W7F!m "wXiȃMkfan"@ǵb8F&v+AH9q2ALbؐ`'Sq)-jJ)b)Cb{C?{ƫ+/ .0P;˺Jej7&"@ |ߥ8ȬD9"`SșmA$>qj}Bgۛ+$F"Zor_x߆ƗAtۃGKqü?1UR8weσ4 @ǯ#@1 PQh +υUvIfqK61]yh,|qf8ާ!;s/%4\,qa)= +"p,>X;`ke\yyHyړ'͎˺:*}]#xN Íݱ͋, g}*lYLw`#U0g0(WDn,} +cOwT ^?\&*ܿd!nآ1n:|4`OG?ge݋welG}ꑴv 7v1 YQ@T@,ߎ d0Ӌ_j e|K ?+ +*W"=lWRh+'u׏Sn>KvZڌMv&^٣fhQRm\':f&k# ~9If7mԒ0Tqa`PMiZF;zMz}s90O(pR\]/G@qe<9)/Fm[,ĸt?JK>4^Cǻ)]?ZG{KIG /Y9?;ja@'o+BuwfmW-{->3+-1As~|_Rjz~f2o^g%Tww?k1[>?f\')Y/z농ۍ=a٣wxz6e$d{tsLBɕ*(mN)}HQ|K?|l~snY]>X{pYWv"y.؄: ZA{ 1'Nzt%42\,%ծUpВd 22\K-*]M(9T +qf/"9a^vޭ?z +ͭvXT/]4"C[[- U +nRڽ>aWkc%8gK[Pʷ6 ڲMcN{28lY[)e3!pZOOWXbx"xR}Ϸ-}3ګZvOD$U6XdV[i%-%<>q͎NS7wQpJIRb~i1sJ^Tc7主z)zeFgtcmd帶 xlA5].?E՗N@wc$OyoV\$"fq}Ѕ~ +4NN ;)/B{vr?d{;زNzjO6z%)'3ѡ;=p6iB'w1U]aZy$s٭G1-Gu|2 6Z!h9nXj,?l_~|v寗V_Ue0|1׷Y}cX},GOҜgBNLrmѾ[Dy7j= vא(%rs / ꕪ/R>BdR COi;)*{3Mm&ȁYǤ7e_WdRN^\ULc*ЪѤ6nԫ z"~vaX`wYfyuϸ*N0g:'Ar,xл=_vS>Hi[Fq4aYZVRMJ}yu?q^0Vo-N0ú+Xy𙮮h}36`5.k>Qs*M+5{Ck%;䉏ҫ6j8jyku,lz\֘܌E[EX>Q\%ًJT'kfʯ.;,YvZ?pxY~rӵEUγ~[Za:UHlp+VkqͷgԷ.g'.?;t:Z5iVmܯ<קItinǥ%lԶh+T/y~6C?w/V 0UuV:Yz8b3g2GdWYTPqnihysepRnSnaQ/z]}n?D; k(ϟ9:e ܑ`}[S={Y2C(겓t pJcv.Q;槺#S,|(_`h^UWQy}קSj0B3WdAeNgݶg+‰~ib܆0\==(uk$Kj +U'5ZjTl^rY~2RAEf@v +Ǖ%l.agx5{0*S|QwFQn#oA 4)SeSV+ }ivB% 9[Tھg3»BSDfjJP 5*%^v?=;{ [r i@11DBs B& Y"(B_ d{A;)A?Loy$CJ 4^_籍agX_j'_#L#r +:1@HAu&w7m +SCrJC͊Crf 1'shSKYR{JPŴc5 ''/i9N0N"N' 6w)C8aA+N1G:LN W(`WttDtqUݰ+/1aO4TkQ$2t cTdd8^kD,^zշ<\4^pzu_Sf9c| +p837DA}]V*m CU2gpH;}f՛wIg::y< MQ=:Ј}EP۹?u +Kgf]_.z*wf)cM)d +>;M/Bg EOm;\XooM?ijfTQ12:bݚsݬ5ŋҹVʝX|4q4z *lPڷ{Su/ru]6,=9uk7)ȧXv;(>7IgOϺoCOՔp?2?mOZJS~l ۘܡV~mjn͠bfQir_>0]@cDB-F+u\k2BNy5s 7H?wzGz%-tisx]11!VNv.KZ+\~u?4>._v"F؈az ni'pR`6R̎`&~،}֗wvW먂׬] Rl2V.pC099[LTvZn?ӓ{* Qր(# sw@t;R+b_saFz'o%}7O;#W6דY#X6x˹;e:b^6?-*3816Oǭ%F Y ,Jl1B>{vqх'ܭ{zHR&k&λº;Ӌcd:Ifoш١%IyQutT'lz0oI 1|] +bS|2LƇNnG+?n(%?REiV86'Ƀ~kWb"2%d3%G!0s.fFFq+0L}AmGy%b{nqi0r` M{qNynA#x{aiE=,?XN9_|&32SȠAL_/ARu_SoyȊ}8:&;?Gen"WBZP`*[ԝ~չb\m3-[ *-ۋC,ɔEvb^P9+&o!Id'dNkٷ{g?CXvŝWBH9N k}ע^)yvNnxu<3˭qSz:XO^~;,??C7)#l6^UZypTy+\ )ٺ|S>!#ȱ{.hlGRy'3:EF/>إKMh)`b1 ?ޘ/k]b\"3(> +Q78zjes}7W +﷘=.֪H+lQiy(>+1M\2\zrnM)ھ:Q[opt+l6\Jq2)ԗ9]>YUݵ n*yuaވWZs-SUɋ ƅNuL26|;ב4FYI:X(D,LTBvU҂>1>C|qdrh[;Lՙd yV`LZb+45tuk3jvN]G%ӱg=QZ.9ZW 0~Nwo|LX1筗r‘ጥ2I7D4KRj,e&Sչp]>4".zbgul(#0#yү^:: E"a3}W8/ݭhbs&sPIMӕ.)6b[$N6^ȁDםَiˀ%do>Jja6tڕǦm&^nˎZ~w N ӽs) Z7>7ZfEOv=59^iFD}Ԍc> /VpJ݅,&pԗXf|s ^zCKҡO|$_;)l53#4;7GzEtT4j )3, I!#Sg >/& F9yyqfS1_ctxvVC/+[ohQ3c2Qa)}@Ɯk?^>p4^6v6 42 :I[6֫.(+eaޔWL6%ϥj Yj4w? /$G*'OQkVkc6oLKCGf%`I#|Rp!WCzכٱ24 GEoz 땲r`r|4Wı>Aړ sSL +oAj'eK8D;H ~,}_nC#<UΥE܌b-F#e}Rőjr_wy;V| + zyX'%DhX8?'C^1Oq\\q,r- [dÁ2@ıLÌnGq''Af+d~$]!0n'XK0Lo~ #ǡzxu +xq2 ΐ ب% Tx@A]ClxVJ ~wbw +w Kş ZEsA 5[o<=D=py 9 Gd k2z4o?d=@.|il39gn898Q6NL;NoK'FyP{)I}OME?|"V} Q"5"lUx]SqiVrIjr3W  \x @ }$<ҡoy^jE:|\GI6=gB]Tn]s:]Ue¤ =pG385y{nqGyTtRw>[0:Jy]b{+x1@}, ,ra%8unƗt\szf68 x{_?^Y[\A\=^ݴz@np;m n~WsT<3; vY<yMĮm5={Wz:.w˖_&7[lCffooB-UaW9!dDd$sYyXeYRre(4풜0ʼn@O&^ܿw>_d1b4O ,޺[Qjt4YHN㧾:|ُ'6i^ >})G}{i۳&G+`nmt)k!Ԫ8~~/?d^'/88kTMp5euh+Fh4[EW/O>Ijnoe3Zud51`ųf)s6 !jOZd=}v} 9Z'2ۗlJhl6`/v76^}qQ~VQpU#m}_"E٫hR%"rQR2RIneeee{WΎqɞQWUSV9IN^HLαeg[8}vE XilewgJ;]EUx +(OEZ'w/eiaz__9;^e|+4lРtcؓ0&\PEA׻,Ԭv)S$;Q\=9Q,p*&¶|YU[~Y|!x}|vp%a{e5 +4ltkfl;;QGqnU,p]puЏY>ڧnIlka!r)xR2Jd|u <د22ëFxsqXA#-;^9] .mF 6vo7 wkH(S)<#Š ˎTvCBY'4UG!ћ EMI7՗go/p1paE~'Ik&PqbUbj`he ^+y2].G B'6ZN["Cg{|X֘p1gӍO^BqBZDqFL>'#`1`V* +~ BK Kӻ[:2£ۘy|hxx&|xzQ4?ű6Z;QVT~YtH ԏ̛n+99{?7 g&z d4P'X| + ;񧻳:|8 }43bAG7 +Kwٳ޿_S xNFοUA %5.4 2#7ܫW,?]?z%n3;.# CavG;6}8!-tbnMcbjXhWʤ9Ns^m09[?q,[^"o;\]ISc}=ch2-]Vt}l.KTzcTF}G`뺒 dʖP͞Ǟ];, 6CUB`g\S yc,nA~*q}NN(BX;1qf6*DsucUъrv\b2Mwqi5>tQ#i9 "3R\n|J^iGRaZgX.}pStWȝ<,OvTx+jr!CAvD,?~K鿅o_ r8h{jBDGڑ5x%\uO,[ß#\À;lY$R_XV?h0t'yl~oui*e=Lq]=+9fp `uSh]kY/,Kom H4ĹyRwd %Iol_ait S-͓O噅y]΃e%;Iq-5pZ'I8gѦ,PqZ2LFDF=x>bRx1bɝcW{Tc.'^mOٞeC룿b}7Up}ORA/$i֓ 5y+V!8˺^;>N&r +m:^8~A`>vkصX_slBYXM Zt9Ǣ1&٣ϲ Qz^wl@qvjjul{:Wz/xFjgmpQV){_M_@u`{!UHfY4si6p\9kg\I6_uY.8 vq6YZ* +DKȒ4 5]~h͛ӛk>!4q;|15 r{A2A54GAf4u27ˎ˅r™^ :b/6mkkV֙: ROŲfAq[Ѹz˫U*}};A|qN9"ͭ1m{QnEX5qL$vx?n!PgAjjNž8PIܤsWfc紺D)Asm.Qvy#v8tn~cL|qzGq81~K:բi.EYL'H ihGցl|oXqþcF>'`{mD]>>ç f/Q=v]}k/c]F_?y>@>ҲuJ~Ub'rJdO0xEO.G:ᱲ-1?0.ri1yF n#{yC2=izVK@yro/_Igv sf&첮(Ia_ +ssWrxgCֹ65v3al\ѧYu^ʺJu1q(⠁7|M#'y5rV2[_/߻ Oay Fn4DՊ*1siƵ9#^\=;󉏓*zղH7V0NE3kzegj +l=vwG@[J*i* ++C/tQN?ˆ9ܰ1h^_' 6w%?@<ҪC4A]3|0->+ OqsassB *GmTѢgCΟUy7JJ@2!ⴜGM(YoW^8M53G3'y. r51=a%}(jq'|~\wnJ IoHOlA8"F,aʗ!q|/uKrWRk׍@w ܐ||=챽\ƛP.p"M)9~zM- >3XW8c饷gA(*S`b%aGp$;s-p>h5`V*:݆y#g<>2Sq3hإXuJfuCXvF=z/=(XrB45$FlF'51ðxLir6qrEܗ)3Smm7MͰ`\a٘#лGUt1?v2Ͳ YJ.|Hy .vN!;WΦĠ`ޥS=p+ ؠ4::7Ɔ}7 uGc4u䊢8V,| ȽPPuqlԊa5J;AVzTrnKFK^Cٷ|ESm!QQ~cfT7rOFj5IP6(Q醈WrUC7%ܹ^M19OlthfI:zlըS\])cza]={NdGvIUnθ^ Ae|+U_UmYemb\rY٣rۥRC:ftysRrʯI/({,{\&+մ*pWR8;Ej\cU>+P*[_Awbh]j`°.ΫYI=.<#whQ;AuNb{XhEPkڎd|ۅU.9xEmXv#nzTM ^5 [/Ƌ2 *s c8"!W86szy19o6O+s}VzQO:2]֚W\;$y_'fe^i5[e!/ӳG xo:9\nv0)ck<m&h[]p|k5~8۫mz$[*'`2_Cq!+/D|ŏZoPuȅ*UڨFGAF]YM{q +tzb\O[֊WV[dIƮr{-ܦ}hCNǽ72/\a.n]1lhm%T_HnStYfQ`vfЛeG1]l-_do&u6>bw[8F\*Fe,6~8pDNf7r9o\fQq +r_XC͎=<͕N;uA[𚛷-WQɟkDLFiQrIշai>~ǫ4# YәT*"Utjjq]kyZ=EV5B 4C n/PnOx76@IWGH=&TX ɨSWaA;,UFSn:o*64$@ӥȁ R%~y;7mF冯u~وWw|T:Mw]X;mK4nH+RVYrRCB 9 k͔Pݩ"e@\=_/ !nhMʲVM4dNX}9({fYkp(r.Nḽl,3ꁥ +j+E~Ŀ`?\aĞr Pi:~unVtZ} +ֈT;+u||(XXR?@آ!>|ƍpv[W)_T,WHec֑Ҝ =/=p&euo 4M˸/W2Uv6*caM'R9T΍q};.j:@|60og|U"H 6JSrPb܉N~#1mgA}PT2|"dLsHxD4 U_Kz"`tےOw],[ՙX+LЕcLjAt(Mo#{%'K#4~N+!(=xd'7ff˂ ћt|;*|AːYūPs*3-3X6#tu앨s"ıG M ӣ=闍.8QAN-`&2j4RNwO>? RjLaTv t#e%L1"/w9dy6ix,{5LZ":լ#ƚam*x#dj{##,PF$4Q:o70*2.[ FCO:B F"7/zgym͎Fu"6ښ#j}E\ԕc#{)vNĔ<<ϣۣJY1P+G +A;l(+4: +%.s?ڎ;hvp +j;mI"k_%myr[!fI7c8vC6 | +n|kЍؓSO1B:Ќ +3YzfA4/ 5Nݘ}*{PR7rV藓NZ5c9 PG-:JLksֲf4A 44E5/7ʳSK̦^[_ҚZgZ!'TFP=R@zV(@C|kZgyM1`3$ $7p[[EucւDiPa5UMv.ұrEʘ+hh YvR)[\UDq*[Jʼ(>wJf0h2akm-: +@Svs[zPIJqJme!G ̶ `:A)B./曼 7mW;-oVPMMBn(j2-*>B<_[>WA⬹оx$r3.σJ[;o{fx9K IW87yM`@sv@_)k.uaѣJLJZ+DNOMMk0pʤv7]U C(`tnN^+ QaYool_z|mx+@sz2`X#Zh'[F[#^˱Ya J d[Z2cXXLy-́/{~>N5r ߁/8QX<쌶u[[ 6(1&5dojid@񴳫<1x^*˗'=Rf{.Z4^IR:_l$huTt3G/\H@E O S +P|a~Ah#*n)-4x7\ܸ(4eTWfGԚ_]nYK, +ǿKs ~ȶTu{mۿGO"C˹>l66^+,-I%G2$Lm19' [2nMw%[`_,~L k/^ɫjd20we]!.PXtJ?e̸N;ut/G%i啤HY47c%pv=c,:>_]o$mt*lDmN:J{}3b6O'wZϢʈ]cdy'x5hr2.cCdc,~:9;$YcQ1)u bC8.ߌmsW2t_ƅ,-S"y(/S(K#+=p&|_ n\׶!˓=.KYY2Xv + 8',''̳±hqq5e_n):58~RȜJEW;;.Z0O|C;|C8I=2O>7J{Fqlrz7(̧mTX +%;~3B7\ <ݙa^q5tGYΉOϷ/O%OޛKޡ{J-՗Mo;%MFc3VrѲϫ%X蓼gKgr>kʝNtd3qjNvk- "!dO>d~qÁqc?m}iCMeg:Тi8^͟eh *I@nagnכ'6Y)jG;i77}:4Fm +jۆ+\s7!FNkƎ넟˷yIt{ؐg2Ok/7`D4bwWksL@G/ym]o=7W*@&m3N[}MLt;_5C]ņYM`;e>uuҦ>Yߏ+hi}s;g]wQ_{[{7uD++gY %.ز3-M_4ohpuZ߷Rx=FŐTh\7€vĎI~:Sd"=~4U|tTvDG>™oPXNSjC=j\reK[Y,[5lk.<Ϧpf"?AZJ9&$~[o%킉"c: ʗQ}{_ ++lJWǻ7yMӬP1d\T]{_ҕ)JeF$V+Rd$q~׾TfMT~PY<ĉ^Gl6|1 'V}ٷx4JК9xT‹45 99P&i ;$J; C/Tcco+XWo/P9iw٬O^W+O\XFͅNZZMx|Ѡv[Eo4<Ӟ&J%^UKö'lRs+١sic (>#Ίs;k\wT._.>jm֜zyѫ(7]7SMWAT!A4ٰ>\6Bjƫs]tuw(ǀg=4X4dd%HKB6s [ \Ǥ=[溺ڌTu7$Ff&q ݊-n]Z7mVԃ>fD1;i6 cX(=zvGN4\KI= kpj3ė?`0`̒3fkNrs}O:ákmK(;Y'w .Atqh5~N`e`>qeBoIyͱ@Z, .1/R/Ƨ8Xn4UWq}6E5La[;OE*4@ahCP*q/aC3̀aG!=pwcjͨ*ɡMh.mv@h M +~v")es^￐1Æmmp9S't9Z8S"U/ӴBtUv=X |gl(Yސ]/#\oI"`"Mp}#D-2FΘ~(8aS({E(M ٸmԀ8)T_G="᠖]_z0Kla% s>b̺bA=1-XNY?e Ѧ7WZnz0P?eON]5O|{Y+-{=4%;~q VwMn5YXj0x<@Vd#qxu77 +oU hӾ7Ã/Slg=$ +omŘr[ܽJdX9QHϽpʃRYAEPrP*siy׻s ڣ) k )IKn쎭=Kw6?CL35zrgv:RWKR2^ʱ̏xk#dy{u5 D\=_{:+gGOS`$2L|/S7aߠGOIQ9"JGNJ"7-> \ P1/vD%n6_UkRW;vmwė!6 Kg_hegG.釕o}%#L3('3G\σDj˕6XHq>:]{ښL~]wzT!orYKXnK3]ptw~J1l3f 2d~jNn4i{H8s&.`SP#/َWŰL:p[!i9=Vi}oCt jTb*L.1}AWښ GABLv!f{ 4Ime*m"uW96NwTm;wZ))jɗRҳHxPpuV!gסvir9[`{l*l,v / $`6`ۧ+`; X[ RtQTd8Sx#\Ņ aOu3ERvu%3= 㥋Z%.h耛+[;:9^-x<Gǫ7r|o>"-+t+dO&$SrT!p0lcWbSK|dA1*7k(׻HT@   + z׌`ᦍ3O "W- 73WBf2Z~cD9d\uF9'6lI| :0o \22 De|t5G@|l" IHӻs@:s=ȢIB@.!p3 ^} N%^^u3Fc1)gN$u 5XQ{ Zzm/|Uy1 /yD**a:Pw7:@@ ҕ gQ[`A{_J.32F67H_zGMo=_6Hf'*%ѿnO~tW8߲0P. +wski9U3oXVB+[~uJޅ ADgfܜ:hz-s!wC@[y/iӈ2?g%ߟ]{AU;Zo+fsl|PS:珷ҍ=JxzP)C-ݙWR2#o`..ūC`VzR\k?ɏ [$8j#?zGYy>ȹ WRբlxPho쳛y[wnŻ ҘN4ynT;;\SsVZگ d{{7kbyojWz͕uav_uz"Yٱp tA-cZTQEi2CJeM߿q+aZ&:gqhsFF }nzdۙio_H;\1"J{uhj܎#W&/J8ch8WKuRMfZ˫qQΑsjhsIuazSth)V +tz%e~5~/|!9*푛$(_SVѕz]jZWk]9f*6XU,j-+Tԣ\`P9XJy  )vJAD^Aq#co =֋8A=*y`<0 T*t>*i12=.] Q\I_T>qT.qölÍrZ!fkQ/5_L{؊H؊إ혧;4Hz̟Ǣ6؃7`Q0u=ZŇuKj{\\7*y*L?PLx`%?86mJ61qS{sL:ը fJiZ1GTN(mA! B;.4_z m^-vXA\ QiE!Wq[LfULVHEB_`Kj!G!hB|Bv#ȍ#h׺Aվz|s/[0l"bn~!YN% E9F^j)_Ph\Oа+t=7Ai~:_r6W^8}vZXkZ,`!3c-kLԃT4 o\;&~uQ827 +24vV6MF,>ײ+ž0[0w~2xJ\RЗXTz=ס΂n'uny} ӬԩomizWK0+o>=X7ѓҤA+fJ^kۦ zʾ'%w:?ͣ,$*W6rzuDzUo>0E,uJ٫ɳ|1Aom>A2lURd]Y7U~uSbFͮ(È*sF')/OGgfE]f~@ 匼^[RзsiCI\9ez&$҇JH-^"]&k<6HrTsz_{޹8<Ng@ eaiJ>0 / pe8%XV#$E~>:\GQomQ;HMӯ#1~rJFxWXU4N;6[ ݮ+G]d_|(";|cXQGKU(nSSۍOzGmZazOM6'm}ًW/<W̄\['>JqrVA wh"BvCAv/Vj}g!@HnuO"}Ey\W4}lufFO2/p?irv҆= +/-϶/mXN7ali'8P  CUeYԙ ұCjt7D&\1d`rqsBEy@/ost}G!F>JM熩OV%6q2xk_^crc7~?x!?o;jSSo}Y^KG|q< r;c6:X{ט +ācrC/݆N:t oav(B(%{ ,Im9(Ь92}ٮuLt6 Õj iM#Z~8Fx-APx 6r!d7y4.]uo`~ZL%+2~=t]*;ie{rMþ.*m+ޙVokA;di8Çus5((?Sd^ET^~MK~yu6҄~!kڗgtmwGz@4Z}oew^愸v}LИ0ۣkY(xaB!Țvw2^~pZkmąs֠tidlz .JKͦKk-=CtdN|7q`ӪoNR;HHzmyGbSmvQ;դ~K=D~uڑ5ipkgvqsjR_Hݾ2y7Ȼ9_oNaV5>Lwwm9GֳX[CxhCYs!/[Ę&X*LJ83H1F|;g11Nwauvi/ex8ht`^Evu>ZA.oZ;xu"f `n[aDTUWC!\O>쥺KlwIu]U)QE{ +o\aΚ2™řLș+$&/Ω,24UЅSJ Ԝɂ4ݜ&mļIsZ!i(ٺ# 9oq*{=@\ : 0gx8R*fY6-Ս0iĬY6ɖ YlMNsifLmܨ\!fd RmRdq#]0I˳#˂v]p yx ++.6fw1A: npD:z[:Z::r!M x]VIGuY,46a)'(ZVf`NޒpfЍc~Jǻ<ݬgE!u:kAC'蔔LuɤU8{s1g,(@ +Lv*TXT U̍\ƚf4_H5 ysu+R<@ߺعb2Jˇ3)8SA3]Ҁ>adSkio 6% *9!gF{O2RsPQd@ب Ԩ/k͆8e҈-'`aJfk<`ؚekvMlOoAk ؠvX$߅-TZswzP}1lZ .{4e䷏rKQzrte=uS^r<|}|&XjZK0ힼ'@٪?:G`u_ƙ?N8c& qn:C%W~Rbyb>֏P{#~>wnf$# wy=u7mۜnX]W]^u{?; 9|gr33ۧsy}8jVP&і_;G m?`P7e0g.7U=(~_t.w7W%5J˖/N4:JsyvPjo<۹m<˳"=gsHz, +%ACRtBZ6v}_ć6|P|v:vzئW!.#{ŭvڍ}6|9%Y*Lҭ9!^xl'sX oq({nA(4|biK,N^fJg?64mtZ=T-=,*NUw]޺t<wjwM-q%,5^ET5JokFõ(tqdo|!LZ7c~3KNخzšl#bP~Q9zZ{[niGRN3G/\j"7f&42ҀuIsq=ckbwQd5znjؾ ly U <|yBz =b݅bͣe97oԖŠB +S]) oZyv:۔5w°l6g&oRg׭kx&} q,7ٰ:wUߞtPzbO UkH.n*a2)L+Y-=qKBJy2K kku +W>/twAl+ѿ-F;~{[(Wn.3}i0_ عTzpuLU LQ4޲x,3#{F&mv)ro] LA14Q ꆸyj`!;+VvnßVrjJu[9_QuND\)ﲝӥMBF6eOw*2V#gKcpzfn6dWP:MYEL+A؇LRu hRwgUw;DWqS9ҸgTϐl؁\օtu#,CK]]Żz*#:3m:ntj|QW[M9űjZ ST|gTβ)yΦȓ᾵ ?f7J[wN!2]kW_#ΘRUa^ҦeK]d}Ll]\)Nl} ɉ;Vŋ¦z2%/VRD{|B#-n7-D)ׄ!Y7zKឪ D˵0RWAYIur#O5SExMHʑlD6&;{ &PXcJo)mOЦh+&ExTGmzTk6$=oOr:FR ý;(t+7Jj +{oUoBo +0)(1IAzm)bb-uǬA~OCɥ<d ϼT2cx[?x#'nZ\)[DccEeV\qZe.ւM5b0_8/(/f^J|ϩ^l rmdrgs6Dz/t![!Y-^_\%J6[\{wEo$MSHRǂ%P쮫ƢBvgl?(c2 PNװ +QO>H/+-?{q27'LSȥJE]@ZgvY|M!)VQbE6]VZ/D.GeonW>z_Q'hBL%;Ҝ\p+@fHb[ĶȲFz^yFO_4?̪MPRӼXE^t}qz8f)y/O-hUo͌>7:d4}n1,iUg^H_26Y`/iw;hNJܷKSY6-lPaxD0/ 6 .t6JrsZrDhWq4rLw4Aʌ\>vyKL2+Qſ'h8"d'j+X9E;TjIΕuD`émPF37 +71WWY|\ḋ=ml]CW4#I01d܋IqR KTM9y9y(d@jQ'z`;B , ]-SZk`( 焂Fl]@!K{x_H9̗Z[@] ЩB +x4 Lƾ$8n]l@6 %hy4$; %AgAR=~[َ.T\u@D/4嗪x ݋2w8C/$IgP0AIz>Ṣ&'E3`2y@6vpM?`V< dqk4,P(,ʧA ;2R$-VR`CN<"Mqc9pZ.epppg4x0 ޫܭ*X&pބߚ̨ H3-\OrmcRNMEJnJ튯 LcH fC|+q7;l P>lC@8/@&D@{s z(Ŧ D5bNIv[$gK2ZRN!>U3J]D"ա.ifQU[Vsob*} NoOF;>n@Woȗ( JnJJdW.(Ͽ[*}Jf 4gL22';)oG+QC@ NnK Pf5 n(d0M_x@d•fǿJG&I7̶Op~_^'4?# Pbs~a4ww89ט}F~~LȴU'*?0ۏ#X_ffR\"{7tSvuŕW·m_Ƞ?]2DM~ =(mXWJȴҙ/*h:iǽVcul=Bt2Bzݰl|P*33'~ZJo%7}.~pܿ7y7e{N"d.Vv@W̺ +gq~^>6֏0seˡ呸>}!|fwvzg;~k\ǫCT}+&_ܜy!^y!ȸKlԕ:ZZ*&J5q>9!V=:uI_-˥~)=hy\x]]R+Jj2~qq}GooDPwlǸ4){mybގ:t.aF [?w8 oosy>3boꠗ endstream endobj 130 0 obj <>stream +; iD^{:ņd4qR˘YsHw?hk3ݫfa[Cl.mDdt<0//[繥(m'*IrQQY9/eu>糴mق֚c21ek!J1ݙ&BO10G t 4Ǎ޻3nzϝ.fS'68>vHѡAGQs$H*[7׺۹a=Q@֒NQ \nNv󼡰`8 39yhu.<ΪkmCHwHP正CO}C_4 PL7OukIqy9+0O/V]{*q*\Wc4j5h, n.s[N Ƌ= w] jPci0؋ZSKvHh|=\^'̗~덧U2w8V;8\|VGjYFR[.;b3Oi?:&^fz:]Nu_Zףijxaҹ1Z354!*%Jmt-yڼ^F_P"R7NyiL;e#/f[-WV[7C?D_>0~ra,JZ+f3=}_BBmWv Nr| }5JV-'gVt#]};Bqڞz+tgpssnvgznesnkhƤd~Qi|d嘜-KmsGxo(=. +*)^\w{ݰ;̵4t𞼰ch} P|z 1"İezł[_aX{s#|39*jKϋyDž8%iQm!_r/Q9+i +YپLhnz[h K'=s$;c<7:Jj!p릫bu5\"y>)Er*k~y|A>TR.J㖸c}ݖ+R}z1oD563ml8wf@=HGW@7 [ZgJԝqWpHO'[W>5ʷA9fQ:5O.G\>}X8-?;X=)ښir1-;(2ljz:&my:T4zmt+txR(Rɕ:o-)c*)CNx T5r>>\Z[.bRZ#:u{cs8 , 2zqxXBhՐ`TrÒP/H>]9tK{8olG¨< DmG_зKD4Vf)ؓ-O&.H9f,ڹtت-26׵+@V[{SYnXZ 怰/pa+HZtEtl~l罈dl9( )qwxU4V5=!,h Ծ@`ZacIG3h]?·RssqXL,QR":!-}NŎTw%͛0i4EPxh9hVx2:8;K:lFo FRc־OuT?oVuҁOдeM}c&iL.akx!pdZ|KhO[[GU$:Z^c8rH~u Km]2_|iY +//Nhٱ 0, t_(؉bs˔:};m2H8*JMrdh=Ϳ D;ίHI|mV&,߈ +t=A;H{ k$+9{]˙;7B/~1 TY[YAqc+7w,]!3efqt0uD,2;>wAYmi"F:92@\;+tĢP> =}4W2sPc&蕼w/#[=D'U*:iUڒ +zzq]u1:ۈ߯}3 6<dRC)Jp#Ƚay(Ny)< + GO)]@VEJ@bwNW洈Rq|JfxKȴ +59|,g81;% +gElfP(n 6z—R Ƌm@UYdS46:U@Za/tNWǴrl?ۓ9Wrg +dS٬Yje6q3!`_ +v'ȷ`\ LO&mSwa=`z0}LLzLyqr#~׽^6!-zaP:yKm{X\"?z|Xkl76V:T߀=`PWvr 7$ +p8뚾&ਧ8&QzA1$={GS^sq+IN;N;Wnko7,b?ޠG~tf AH Z9*Ho <y>aRQ8Tz'WQɬ+Z` 9i %s*LZQ揌 k< b—x@ H-;RJ_8 6;W aZJiEY.*味kbg!ãtoD箴?rp( +ڣ[@t-P3/TU@uU"}-lv1PL k_ ;#~; wk83rvr(~5_Wg4n7n/4cw+}DX}0`q ˥@s'Mղ)lb̧t>j>gg9GosamL?DW_ h[lkCoWܿA?яuN~v}%gK{ KV<,8 \ռT|0S GP~͏Oǵ:~>gŇ>~wk-kypߓA}/OQf9痃#j% 1MAjY6y@\KqċYVLw?V?׺.+J43sNhCI:˻KeaS~5=7å|71h7׏l$gl]_ 6sn㭿UF Fq h?~߀AodϞ1ƟkdMw 2]jq/4NXR|Mʚ_x1)3:XgXVj{Yod8^v}u=8CsW}<ݻ|xU +ѡmzNE:Py$$aen9j``tC^v޻^&|wI;p)Vʏ:J':4 .vun'Ӗ؈M5ӫzU:;-onw>=Gh\ɥf*S[Kz^]£a':A'Vz-4ceo*7rjwk^ UgbݡR7Tagx]āJy~{D7:ןd=ƣTq#;׳wGCF ^'^mq5`y86vP_Cg *IO)GT%bX2^V)&1t֧y6jkKMS vtg'[ WAh5:Te[ +Kݻh2QHvcՙЛϿ i^~Ra?lעL[ + jh\%: 2=.$Y]Gu*_٫,mp<9x`qYB1`,Y[l3Sg>_.e hz>-DYW,6tyXS[&GZvAk4;/_,[1ٍsz_ޒߘ8[ӥf7^}j[wVxZJB^e"P6daX|ۮ>῝p]RÞH5\"we+ 5*BkcP@#`V'/+a,hؾ9VW1&"b5`Du hcgD{(|A]_?2ma'^0vr9 2#nK`m>nixmȔ2Fo OMOn#h iR2RSɸVVaё6;~֖2?[r: +r擊I_jvE'/P7/ET%;MI[7۴BRiLjcLF$S3 iRcc cjT+jחJL)'1)ޑ)v@Ԃ&jc/6!US;J^Q0 F]4LpyUjpW7R[s/D]pRaǦ & eNmIbRȴwRcGrw2@b/P9Z*U8LYy0bޏ) h~,:ڲwՠ^QbM>:,'#,$  »\MkaDHD>Q_[&gcvUN,q@6e>~3a0!|bQ}l;oC8ĄGO6 U:YSV&*##@^ԧ- 7B?I=_*\*J՘pP0Fdih٨RR0?d+E6Ȣ//^y9sѓ\ȑV%Up%n_\qZvwlpXrFKSL v%-_ԥ(\ZD A|":G:s/3 ,W9@ͧoܽ|3-Jc %=xo{cv[°TvEܑn֭oZ.Ujyh%mڄfDF^Mf#ZzpրVB3f|&m$tȣ`Tfwgj+ҧRԈyodO^W{CM ("<(K|$2_VN sՈWXXE +U(>rTx>·+I6mbWS$&GuͥAdKpnH $5s\toPh=0=4-KpϢ +u!>σB *:FRC3p;o_;,|$ +,g{P!5r墟.$6 žG6T;(gscj]ǧ۝r +ԓazn[m8*s 1QC|,wso SOc[7JExϸ%A[<`VAb33N[DƗ E) "n2,@f* n6 , \EύGʾ&NS xe1՝t@QzҺ,jP_7+9ƃ\VRA@e!Pe([} rBKS?hG$(*yp?M5˫QAwM')ᶕqL KMASzf=6{f@`躺t/z&؂nЧ g'T(@w??לe=/iSj=/}oHV)"{ d^QG=q ` `.`qX-1";9] 9`^l5[0mx} ` DYl\B. w^{A7PvI55䯌Os.xO^OÔN~ҀAN|˝>@ߟEl;(iIql9Ʃ}ˇ}AP;C%$5Q `#~2>2AL b4)7 4lH9JB@Hysk;XU:,մ1UzI#rW$CA}r%?TD8|DfOxB 1|5֣V}ՃJ,~) II͍w~paQЕMK)x+c9i_<^jlg=AKcx欖[p^,)&mMYu-Gjn* 8y"|[H*r>` Ş]:K7OWx舳odj!OaR?c!h^1M*/ͰY:F?a=ϊ6'm Id Hλ{]7.^k ّ@pUKvu[mR?ߵQr4gKGFR?$ݾm> 8$^RVsy1q}o%=Ut6St88cn2PǺȒ 2Aj1t9#3;a2:t$m. *jxU"o,je- !gOZ'8I JA <Н}ZJp;T,ǼxcպaJN_+.9ou%U!e[ؤuB/|_澛iǩ$kLTB7݌8v`ᱨC f]KˏvCaSXwX/AhF0$K:B {*Iԧv;(a|:ɇ[n,̗uL.-IaOաD"LB +/c9)vjmP@ޣniT;%`G+S m0C]>zXWӒ .Mw)IWw+~O:._ aHtw(.! +3kYncf}^>YT^Rdc]VDmxbJBgI1.Y0sE;qe=Ŗa6a[{ѧ9ӡZ̊qTL>HŢodf)Βe#akV:<^5lm?d-5;Bc1_nbGy]O7[\1U9L#<5~% +AlxTOCG]&s4H*B2%.2&xԖ B? ]9|$G>_whd=S*|H~L_[_mcd#pBhMfWbEg1!3(1qWgnẌ:'Ҝ@ row4J+OF칑9"ORob}a?rgݩߛ8=˿}JZ|'8z˵|_߳t>h̙S7oE:7w`;Wh.Yj\Y?ɪ`?rf g ۜXS7,|t.tF4YvIX6D5\xՀe-W[/:O4ndh4-Hdߘ:!V"Տk$p{[-u.#d.Mf,uTLNdK8j%R͡x{X(}WT/𵮇<6!KqCcC|k]}?6W'[<ӳl f]JNUK71wˌBc16R ;C,F݈KԊyh36'J]A{ gVn/(fMVK|hQl1Dxn[FΪЫV#:vV$TG[4Gyx뛆ZYjkZ}TW{_XTkg]Wӥ9j{hܦu-MۄF_+ v)? fpWQf,:I}dl5xIBlUWlks>MuȖ +)G(gfi_?&{Y|/`8*A1. +a|xص +r@]⵽;A>3FS j-t!jC JIu|GACeJ~ }QQ+TH75sv!%@\p6^N>-0̗5uNĊ +ْbq01U:H~W+GT:w*j:V{Z&6.9-fBïeo^_^PvЉC?й}ahG<֮Vrm6ɛ*a l6fz޴'5B[ jԐB{B};^=Ec{ʾLSӪ[Llg7wMg[8g:\W\}da/(D>iMkUZCN=Y]^ϙ-RO +on#ZeUYeY}ð##z#Vpr绚aCJ[\`ye5uWvU0LPwKwZDOވVHz孺D:g/ ?*^UD_+x D0poГP96&UgGUC|pGebϖP˖cX˕OL՝j31~TQP˰WQ6T~7icy?~,dzoӜ8KF-^/ DT-<`tX̀žN "[%_79[n)K F2AvED9r4l0I"ˎU y+ZŖ(e&=%t'X#h }2 Ώ|%Hg}e}r5fH$3vb-{:{6@Y[om5<,{l!>llڪ8An+̽Z,ަ5]Tٮ+lW(|C 1&ңs;nP9Uƒ(C-rZ FMQ'lF"׍P2Wk<"If$]4 +oe:N*ASraavyR3I~MN{ )-CBOBʹ~, oFDz{ rAO4.8dJaੰ,Г,Rk@ծ㢇Cqh +e%乐5_{:T i#P^R7`nx1@<)@D\#9˧Ė>%Vi4篦ۙ;YVc g$heR^ +A[H#!,@X09l)l-@B,N#ecfȭDr69m93vdߪr>=)l7yugZ sڡuZ |Wd/,isQ -%BeЀidi!^< lX:BP=˾>?biӀX@g'@>jEɷ.H\du~w1)gQM_'`aw#;ArfКf:]G5@On,;=m|=CX&y@>FtkRl_4?:R,>*K̖y؀Hyy2id;PZE@Q#&`S0.\ >̲LOm`4$~(z|Nff!Sd`R|LX1m@*t{EPEsXgM#zƆ1):`' <l^A򀝶_5]!2|qK|I\nIJ^.ktr+3aO.0=*K&` ki3J^yM(XɹȘ!͓*FhVox"Ymz' ]%& +ABc~BT퀠A6mch& +8l%}2'cABa oO ENmUa,oW  H-EҒZi|k@*@t@W/?$S!6+#;o+@2ߠgLk<[/JN\;zInFBIz? WP2hX!P =m8e;;,@+X._|BGUxhxFb wߢpBnrHbrMۤZ5ڎ@R}/oA}k@o#M RzhnG@oONiw7wBm&_<IoH +/oo-ir)66$'0- Lw&l>l72S`ny1w w51&uRrӂ,1ڞQXr+=1=9&z.ҏ*|ʝlڻ֢, p1s)I2!: +9iWZ˨Y }uW_k1l%̨asjłӀf# ~A-?ݍ6U %'6AIy M,W12~?r +v"R%)*r#\?[A{[-mN9pcn*`>@V4]dzǙ &&{'.s3 +[ l޺0$p5pOeN< w'≠`ƃ󵺜oWA|\~3[exIQ~ci#'#a@oUOs$XnǀXP¡V\;M~껷H_Eq]r|ҳeէ#QX^G\xw`~&Z{̃enp׍/Sg_酝:;KۺPz9o4k盻$Mx%M{|l~aV|>5,3OwHg_yTktz@/J3vqnzpʠ,קukXcZW)r +"r8t~654g˵B)({&?&/d-p n˳/k/ +Es6Y7L KW.UFjjEʇErZEzԌrk껝/GRɀ8k8."o= DKru\݅eWKr|~|՞ xRVaʩrصe5>/۸dvvmtv+%PaV9`RxǕ!k+{rniͳ^6fτnaKC$-W=$䟶PQu? e_K+~J^݂C?+βl8@t=W}wסA-++PFCDit;ښy:MsBVV|) U ~Xzѯd+5k,̷FE껯V78qoM+_iޕ_j94_hS{5! +p'mm33;k\ v7g1AMGS2 e5jfxRLnbSW_|z-}Ldh2߾ͽNנEy~psG*(ͺ~o`v\IM4k\ZV{-LGFj&ve[rb 7SLU}NW>.F]]f_jQyU7TzrVy4]ߞQ * JӮؒB_\,SNz{ +宎#qͩfC,\e.^pƆjI5d*]ƃlxۯI #%p+I+ΚPVI&x'Šr#ISXUX<6?H6G. #ܩ:stlYV}L`Me|!EzPHOh^1sfe1$eg *Lj?l\h)*_Fk/^^.#R$wF>7r;=jZ\ X.XbzKB':`|RثldX"̣o0ƽ֥_= 1]7_U)A=f9v%9!=7o^$Þt.UZ֕#-9eAKxdCQ|qXlnlPLoX3hZsz +tԨYjSVyD.$+3A^(XRb,5ι)^ܦ5a-<v׮5?N+j_c^ +$rTi?5MpK1 UhY{= +!-3f0k[Ijnp۴u`{&.nyz#];@s$-IG09D`E_NR`+?ǤN󌶟{KD>܏gUHٞq4+?ڟE:t_ Ӥ"W`27 \;Qd# +`gVX"&*jFS<+oJ{8 +klk! n>p8̂AW)]sfncPO5RI}Fٌ/4޽E4w9D81 >orGDr LnF"<2:6U&Ӄ Xu>rx] Nox}%dd"257|l-kf7on }q( 6 n|:CPPB 7DPb)caP~,&2&am@bH` &YYCujkA+ߣ.ԱĩOaluIPs%B1;PaCCa;IBKI2Xh$Wc_ +lHC]ĿZ}@+ ގ?# |[[L߻)xY^K?(xF%ER7 Ecx#^ K aqC%u +@~2X@9_ 1  ȓ*J$3ĤYƺ6y UL Oҥœ@# +Q d 4PYIa~,)XKz3@},v#f,{>}C&cWXJoTdD\{,:NCxGć(ဆ- +*7u ,2rc[/uG}e,+`K/VLFk#qDnw)e0oؕԩ+dMnn +o)DT]$C2` ۀ`S +`k 3(\9![plwb9^5g ůf҉#A- \e9\4-Ԭ&nO?%_tnbfD$i|&= # 6K|DW&SzF J->@7NbxN~qx֢Vk5 @-[x2=-)$AɅV WO{'T(+< Y.dv$ @ Iqz]dZiL/VT;1)COKR뤞>r/wOE5 z9X/(|}d%_beK\ .^i,\5dOFl҂$n6I`͕? 2kSz̘iWV(_NEz֏c(ĺ'v7C?61\c~䷙lJ^ɈVZn6؟"wpAj=U: ++|x)}zJzPN_VuSC`-?4{-ʮ4vEr[$?O}cVia*4@3zn޴;u3Oŗ {o׿ہ* CH̫I/ +=Rw7aySi`]zyf]aK5 Gˬ~,z_AmmɋǛg9ΓD^fCre mSoYBr9KhN{p5 +68'۾^[zRxQ/Gx7Ǚ܄gTܕZ/{TVrt˾]\ zGŵ)Tuq\I_]0kRIMӆ +'^:gp֗Eүm*䠺պH.EUNbV{YV_w)HgUwwi<8vr1K¬:H.<ͨWtڛ<|F]rĹӬ~ 4ƟDJ >$9 0[)^dB37+, ފ/8p,듕C:w\=w<Ѭ&L8ČSHmG;{njö_>u`}3Ƕe$2#&%0JX|1xο1j~<ɹOʞzl3bVL8Z  "5u~iʵm3ݳ5VV 騒dbnpgyj3T%J>3e}rIr_ VJJ\)]&wjV.h\Fx:(;Zy{N$ָ?9 >לyxĮxXvXpuoOguG}??zB"+h^qUmZkk\ՄW]RU"?h^fN(W|:懜mL?lS[Qiܜ7t +;. p)e57%U1)}?|z=Cu\4kT WzS[m!PyZɲEs?qJYkmIYDz7?g/3w^ݜ~8)MS~Ԏ8"?Y< %N7Fa󪿴AY)%2䗾Cٖ%7&I7 V6 +%(n&&»W%o~_<.,*zֲvFuU.Ž߸v jz+Aڹjg{{R &^˯0b2xb4Y+ %kePi7EB;R=hK?q5,{!m v̍f4 zIZNaj52j1Z{T(~ʣb*?PNoOZX(V)tzλ|P?(ϭ]t'쥾۱ʅx2]F3M}բcj?4՘ +۴Ĺw?;z4tbե GO g2\?%LCq1Ģ?9z6;<,w\eeYeevwSbcC~@GP~E[ō*IeZSJbjI,WX|eI{Rv75k~r5EiV4kR| +pyr',xp7xl(/^<W.Zjy^:59sk!mCpoc99ԋx{&yUi@l +?h&<3UlMEe8} ;M#'Eڎm'ڕ NDG4m[|5B86GΎN51\|7S^Y `OFLȧg1L8EL07V8,Gu҃dlҮVOR՚T8o792lv\ ܩzQHEɹVHW∕S }H +p*kC> --QY+!=AN|gk{BUU^h=ẮVIzJ+Cv^~q2|gYdHۏ59oϏ$oDəPo|{A1SvL1;1zhkJyc~JlV}hxlܡ7`qpo淒dޗ@,e"jR*rfu< ࣀLU 8RcAfSdvlϦv[#q8#L?>:{dӾuqda~FRg~3߀Л r;5NPD]Ʋ\a=AQ\NH0@ї-3=04xP)2 SFg, ]}|z_^I:;˓7 ȴcYjHX@ J RD(@ >y_e0y|NAAZ6J|ozx(?ǟy#O t\ş׸B +_iPxk^)jP6z7KPtR(R^ +{UǿG@i~B +by}L6hP^P(qk{S!)q~I!(loT!hzGqI;b/CY&耮630Rz\orvHm]/:3jمT׻|&/fJB8 kә@-3DII5yW+IX$ kNm|$&v+I$]j) hag+'xa| y[-KXduY{4iXƺE[$61$'$5$wٿ4܆ (neu2=P2(Z-4y8}Klz=ZG X֯eN7$U$8J5_ ߸ݿy Mܶ#hkwH=^'|ݶ4v6_+@+^@ELP–q$IRu1spސ7#۶ۿ%$QIJBҝ,1&{q-/1c⧸la?1W6Bnrh:Ʋ'ϏDՓxjO^<=F>+?*4Q{JtK"s?^&3o&8t,oo멯14*_=@4ׁ;XS]z/Nލi:0]4q́a&^7}1qs-WjXFͩk|f;e.IXCwX wK=a{/vVwpoYO7,NՖ]vsqiz7gΘ-\zFsi)&u"W(w&{kDdz~vZ=/IlRWu*A4aIب6M;gӝV r<>OQXٯ,~vpyUn=2orC@vՆv\l`2x|{VQMhgtCƿc %=] +9it(jaz{^Vo^ߴu +i"icVs,mVc.KZטB[ +F$pM,Bg~wugmj۾8Yz?M5fyGKTmmoĿV<^>UZt /ltm/IJ ¬~# +إ`:K?;p\}I;3k)&{O`w9e(pi9!"m[& +N^zإ v3\uDCBRb<,}?s4+MMK]5\ƪFW}._j=y.ȃɶzK&}"Ή5m'`[cx1MҦJr5qD>ʝ{hqv&yK㉷.h,jS[XV*ёASɶ)Iٔ'euh!Yt"@WZ|( EBm-Ҿimz3Rr cЅ'Ro`qSu.V}!|V 5~ʃzm!zK HY%2?8 dAt&b-,@A:a_qKnZ߸z٢8ӡawg=of^$ tOx#wLHecQ?q&vS1PN4/wR>8IH;sx޹ +{ i "*!PSPc[7r2T9dCЏaע;ڤ8R&"S̥^}YqWrU$!m|{,.^$F( RvhL;UWyN\c8Q/lkYH1-eQ{OCpN놂r3-%DݣG,֎(zQ8J,׭uJ-.e.Ao&7XOBT<Ük9lלowE;Y0".ICQk96-CJ.9R-;H,O"x=خo`5Yc5%'b6Ă+kedēi0!5.;ƖtʫّkƖ%fUm2)"–Gb:Wj #*c` +z=I2xci^m6>vw7]`Jxs1_CsJyCC>o 'ޮ5SF?x5bҬxūIKjê ƌLeL[Fwh/9_'+7b4>m&frV}IbuUczC aU{c4#߽FQQUWRL_}F/%+~k@z z`8(xN< "eIP7g11^9H_CFf/Lw]@wph=Ktx*t^ +ZXv—'83 3ҍŏ_sQ? +19x?K'esӷsHG}'2F-.P&nx[Cpc~hX/O@TK@L( n2qWf ew>1t"@ + * ]ꄔ8JBk\q?3?~7<]\by!N*'7PH¯&k 'kҽ*3]G]SU@z0>J뮫'={uA 7z'4y78]ka\ ~_ @W|,a`V/y3t- @}񫯋Z|6>lFT΋QN[%Ilk8|< n(KO7@3s$PVc- `b KXA29s 0[fᾤ^cpHMlv3l$1eHqQsH<9[ȿ̢t\Kpf2ͭ/>/fπ5>[y\?ڑ7L%VF}6U̖v{yQ.񧞿&O/tN_j܀x^~eD<M_s- V  W¹( dƳP&(g4gxڟqJmRRBGt].7wtwm)~:Y@(( .y~lx}I0i*uՉ#(ht+@at“`[ЩɿܶMm̆&76aߔ_뗓t6qWͷjh1ZƁF\^7Ra [.dK?#ON)֓76q6_.ʿٶFۿZ} +M0=`lw` MOv~~p4IFl҂l'FXrm;Gxx F{&oݘN_JQsj >]xW,_[5&aCd|=xfYdM9FG~3.6b|v Ӹw^i@̡;/ncm&??Q*`@|L6#gx^~k&%]g4bPV M䜚Iӯğ0gˏfս}9+tSf6'u|=k(?{0u+B,0O=_nI6'63Mhm?1]MH9h}jOmv|*RGὁtQ?vԛٓi̵h+S?n'v-h[_e0hʽ1ŤЖF%opIc~Su3m_FVT/],|5fιpG,=ur5,̪u%DY OM7Z_L0$ +auYuy j~b]eS56?N{E7_eRvNT|)~W60 &_| U +L4;ӍfN@xUkOw,4 `40$k5Fc1[;;.NaVz +bQl;M+7W&zqΞ[ֳ{L8?w[JmjjĶ\ʪYkߜO1 Dsm?UmVxV:Baz,KY9m=(=ָϞ~lth؍nmO6HMUe7P϶w^szluJbCB ++ru5qeA-0|KĶnX+}ߢ`" +wIR'uT՗$1tq5&{2#Y/xb|~3bV&9S z~ZYwfydNT(2$I5h;ɔ֟SD0筈&|zU|aWcPr/o[NY;<^B'4&O3IGH|L OIip||Po%K x_m-auyN9Qe"7zX@`ШPʶX5ùly:BB6ܤSz~ReIiy|.9iG%Y7w^07,x(% +|&)A#ϷrF sV'7&օu +WQm.u{]Y}ĪjTU']\DZpΤ=5pd6D}emKܝMݮ΁V \ ǵɧj\ֻ6e (7!ovR pFf^ᕚ>k2>BS/m7Q7Nopf2^]#pz)"NLnQoҙ{/6j,@Nl&1@*G0b8U:EZfTAJ, ݮ؞N2:[TJe?Ʌ; @ jq@_¨39ckv ŠI}LzXq{S>z 3%$Vb1"Ue +=w:d3W:%ڂ'bNbj'Ǔ +Vy*H|f,?Q'^JU8ؚe6{s%=lMbEP_2cb&{jy),Hdk أLĻ g;JyL= ևp1ADL^v*/)Q{$@vy8}?d2qlQNbyn*E8%+s+.(ly|[;!Q7e+%lKp+heۡjEs?LCC ن](EalNOhXٸ~%}~`e*$I=X%'zS)솫TžgTD@L+'Kq+p'ƪxXTErbӊ>ch-v 2Xl'P X,z7 +su\MxqcLJZ7J%S%3]r3»;9c>*7tDIg":h2#-A_9(.)@dkܱYLQpioBv39erFnbdA 2,8*S*56 m|?G 4JK2('{ l& \ae$ә %M%3Mm /v7>'$` }?A)3Ao3C|~>գUGP=.@ dT>zFY +c"hhZZdX(H=;wh|3yƍ?}}:ޔ99F44Ï,\/ ~ϜE<K23гAF!8K`T X (BMK'=RHWTI_Qa7{N]ox?ĪNƒҔ`O闫7#|շ `xɫ0>C6o2܁`@8l=H^1uvmΝ"!L&UbOnN12f̸2#a"2A rtQU&Rrt]R{`.Sn +«N$#^o\ិ_< >_h~F9]`jBd͌[Ƚ| ]ԇbŘjĆ! ~K:hm +oR][cb%yVY#f;݁rD!W-,\@=ڴߞ sU?7ȇw'޾I_wap*QgӜjvHܒsNb_hl;W%X~] VNnk^{.69z~xJp֐*?Cj-M\vfNonM8Lnn +cT[GG0#R{etopwefԬ'ڦN{x]iTFm(/ytk͛Uht{XW thC34U$hֆBzCO_NIj*wyۚXۗ'Q5,SuG]uۥkԸWF*ѴDc>xlW2ƫ$E;$o%WL'1o=sN'Sk.l6"}bcDKFQQef4Z +D~{bT'јű`lJg۪+JS>ǕXXqHb@v1PuG=itf+rM$!wb:xq"&&2c8S[q&׏a9ꂹ 3 Khģq>ױ-$ g}_3jA~/XyRXk'ׇlz I⥍b>%sAwߒ:};gI':eUgK?VBSQ&&4&uvxcD&_3&.C+9>KP3P%̼C}C؂#vGĥRWJ|xǬqњA#:X_0A-KzC3 2~ZG L/WI"{[|JNɨ=c3sk[*jҒ7]ndB"[]|/x8kƺP1V3aW1a˰e@0h9 G&<} +2 +- DvDǽN4p zNI;Jԫδ8EE®^$}CHBp!/t1tj81F{fLUl9 $ \zFAAZ z K"KfG ̞MO#S↤(WJ^JsH DKAUs:~=0"S:B0t8M M҆?~r\H$1며6Kvx~9w>K ZPzޖ8G{!< +n|0y;賳큷ABtMȍDo  OUwyd)x  A "Wy&Q=0ܶyb6^7ϛpPw@CV;!2>8<0f<}_h1 l*~1 j +Pi'\y։.K_| +<@h9$D.lFGX:6fHA5ɔoǕw4}[./cA6!liAx'FJ5Q0czt?m9/=،Y㱥*8G6VMc)I7{i},IWHKvn5L<]ɏ,vw<`x'A0pvlOvJ^e-h`Q>sXX̫TP\dFnw)c7@A7mee7q_po?_$wrX9+ ה(S/9鼟¤oR'ۛZ#p#kMxAOYP/^s%XhIxY|hL~ i u1zA|҂ N2]*yB2_S@X9̻@Er}|gl*M=Btցi5it0!x6ie*s+Hn}Iх񓫏# ǩ; o7P)Tpk +˂<هE@ @uH4GK.Eaj}Y9Lb2ZY#WBSKgSpd!j 65z zb b +P<O!P$c>qN{|cZJ҈vAs62+C4L\r»nZuݚMݎ;NFĽ@qcA<'L).ܗL06'+} !(w1f%r00+ *_`xM2y)ϣVN/X~'|/~rH*T'J--պ I9G=@SUH +@@.O;6e{v,#o82$px =MH/5|89~orͷ $|+ZѶ @**AҤ7ix ,}k1Yrj_)%?/v(L&$"64KֶVR6I? +dwd['ed&CdviҋQWy_K:7Pa%JV6,m=,7l(-ɶ= P($U E:]P4٨o6eBR7Nڥ/Y/ȑUE#jѫ`&"1|Pʫmёrcr댵שMO/b) -nI}_3\aiaJP61vcltU RUWMSϺ魼DL:33r[NT+i%-?0ZCȇ+8!Ae{\a#iOrcU9<>A]9Mww.I2^l\)Խ~=2mTGT^oq~ή?[g:l#؟U`7X^v>0KBdnYk'8O4\!d%w]gCHC~wЌ`?L;hF&7m9iF_& E WC6ӖF_G~q-?;?_06-R?m%Kömu{W +De`]Vn3sB=ݨqY}3KLxW t{옼ky>DM#$*@ѫ Q{Utu}N&RIqܖDjuֹuk?͕$Î#D?;4g/@8RՅk[˫Z;ZӚ4r=sZ]_Mr0Wh6HcC0l+ D롉U㎜vo\^t&,s'6`CU𻽙.~64w/(?/AݛM}hņ&ӊK*^SXiԺr7ntھgw*S]v +{Ryx-uݫs]s^\p0^JoLfYqS_$J]c-ț٢/!)HT|.>{BSdu' 2qIhr~n3g ju,ƻMK~&uw2)NCղfv?սjj\YAN;]/6Ѣ_c)t[M -kNnwl_2 %\ _W!\eT+mއemMϳҴ6!S~x:]zHBe[_R{-D?;p&O^wٳܲfAKI\3D?b]r'sR F3h!}LJtHtsfR K;|Z`t 2h3b v0́GvԫKI@J}93^|6Q*am 9eUSҒyѝ4Jnûk׵;rWz-^[_pm證l/pDx]igG݅kyҨ >.Mh#1T{oVm;{6UObyN웵nXI{?_d<- g#z/zͺmoP[ +gdYg46ҲAuU]:VsS%ƪm{yqCR~WSo7< diJݑύ:}؊5k=a׫e"ط? [˥O3wOWǭok>;:yÝ.k/򠰆^ٍzT2!;>_쇉~[~w~~DOi࿿-?gŁږ_~q࿫-?GD'D{{_-?#E_'4?gŁh1\ x)  +9BQI>LF2n6QlzovճسF0\y5;ρ4b8$fSPSIyF~ԻvVmc#XeFo=-&՝OƘ:NJҰsckF2ZKӜ]g_ ѣ0htrZed]]+6RFu9{H.ӭ_G1YwD{x+,  IpP[ {-`CpqwhpK ~aHo>4CW\1*)} 14"@z"!GpǕ;[װl}j+'|L] ^Czft'-)iy5b]_W g{V:*V,](P1O~UT#]RJ>vS&wH7JP6 ?ڏ>kd+u]Zc3d&[0i9});J{ QܬKq.m:~Ǻl_ +ͭwq}Ҽ޺6įFb S3ȌWPCcM-w0D$'M<Ƭb5.^nZ?*"[q:O=wX279ւQbC2.ƥkn󊈬ƦH jG2 Gk5ϫJl@W.UH-F>!J|=JlLo;Lv 6!D_~q-$!M8&4?=#/Ҍ`?5RM nBS?lӥg՗<AsƥNS\?*gBŢ`lrFuZڙ~,j{(eCh0P2ROe|kN̏utps單 ldWZp;.KU߬;&6?P1F Q5o}w?~-BhU;TJ}yLK>Zv69ovwXǚ>OO#{<0?3y,!G?ٶEҡS"m';ݬ5s3Y|渌3관Oϓec9wCE^plA O@[R4E]:dsK[۱n?uf+`ߗe53,Ļ6#rHYClT93+g&e +נF Ƽ}#ҫ6-f^1ȳ#_K,spRlj6v;@66?v{!QHH0V̈́R]?AK~ooX];{5N#ZO^c:앩iWzgםzkkw8yAsUFk\CufqynM r{~FdoO\3?WrThVB%.$؇BA˗&?=>;m8;+jzoͳmmM;ye$^rnQVj%4E5KkP0%`v/!`b>`G^qW-sLJ?)­kR_x^ãX +/BuNu6WJ54i i ׬G5!}{A.A^箇4>3YvuR!MNq΀ ޵R/D)Jһy͠;5}NZ,!'|7>«yO1\Ŏ)qkqͶB1Jf^?eW&/yѬċA#AyݼkśTN9^'ƷMu-kf^${M<5SrV2CςkNpI5eX2 ӎDթįF -U eͨ$WyJqNdQb<RS2_%F7m3-z\jv`CAz?Z.Z^LTY5e FMpw>7 Q+㓌t$ꭧvEd%:jPVYFGSTX8l +;Մ*!\=x]Wt9ζCڽMF=CrCD\]fZOhb'Y*vbu(VAgPmBg#6 eH>1~}9~}iğ(%e/V2eoe4JϥD@PyMeJ%LoKM q`e{#+#k.[ȳÇ̀ р*•ڹr|1g|GwDp*vݶWhoeww쇉~M؏b?GOi4#/|H_/?G7miF_x&*ǿҜĉ:pz'n\\칓(y)8!Gzbvqe7fII-U-1&?&7!Q;iJ-Deo&/:ڜF^9ݽمM6VN7 V25QߖOn5 P3>JI6p>ǞJPV"%[q{MsԝX_l>4lW?Ylw標R^닩S0o4ӕ4{zbW7Řr`ZwctW/tKc[Ն=ð1W~9/ +-k\7gFe "=|!DOŀ!A n J5>ѺWwv%G+Yke(ִe25W[cO3\iuev?J-[#8 +?BB|w&|kvguȆceǎ u|_ݵ,QEY09څz(ُChDoVii7qǖ`_Fyq6K=;/gJq\dQHGX59D?;gh +.Tc ue4m)%x H7\[|3ow8lv6gZWڜ)5lidMzb7®,|Qؕn͕01JcvLW{w20ke1jC@ +W5ɿi,HPoy8|,0 lL+qY.Uk{0r+ CS O7U|(;tQ3폸 o,Dk%A"W_[tNW2YؤzO}U]ga]զx<.&#H9\, 6 YvXy/3W~#*\FpTBŒ0CFSzfIvx9jbz4hٍ{YFQQS +[~`;ZvީɿnYAJpN@L_bpvqxQcnjƄH|Q}wJOdq75%(]L"ߟJT!ΞYM=rGE2)]wi`{`8c&bo<[#u*[ߑ,9x[Zkg:ɅſhɨtY "{B2+n2ߟy; 2[^lbnGW^SybVhJe;뭞:Kun1cRf^덠=P"X_ rpLT`goO^<9$my&[c=Սn䶒Q8KR:ٜT\:h fQ+1"=|ѿ80'G"$:^@94{rk˛*VK9E1ܬ3RLvU"77H'^:njDU mꟹ2.ٻ_O*TM!3oi1D%ٞ$D?77Að_h,Z+%U+y"\Gt"`gټo5\N6[.TEiS +_SJG;ME,}6q.hf A/N$*рk觛9=x5oz=.y\>m\ڣ;zmlKluj^1vR9>/۪"m̃0QA3Y(=]gokyY.oJP:̚b>0qji(9\tU*2Ü&&kIy} +6Ey1Y`,7`OBp9\S|2klw+Sa^L S Z3|7BN͢UI.ON]Cθ(hO?}#9ݝ߾E ;6=/a2_r.u_U)Ca-F47}UwX[WU}W:HLy=9K*a"oxczЌ\?TNVĵAp H(G;h'|7G6Ws{6A{t'́Btj~=>Br* |x괾퍰qztMN+7"$AΖAaZlS!`1ރ!s^>vL"7^#ȬOdΕqRU[|ܚͣ<ø ]^+H ފOZ:V'/_@ ע?Wߚjuy~!.+ф(чu^iPl_[U[2pǙ#ocz|笺z[Ǜ,^k`Ki'^~k??yXt H^JJ Jj_qnG1[zt?$+ n#ݺ| z%;MGχk +_)e* +,^2W6(9},.s1 :QFz~{%<'JݞUtj3٬ >߿`V`q#P9c(IXt3Ay$W"*QA_x/t'Cm{z.u ,sfrk~/;D+-Ӱq&~fGn:5]6*73bޣ5{u)ic)0~邿x_͘Mp*Mfxp}-5COVotTf;3;DȰIU LY/#KD/ dq,f`u8xsP.i 3{_._ 1^pwYsmk'gJkhkȶZ2邼T*;)h)?h M-@y@EqRFᾢ(>]b׮#1W3+nNoz<0{Lywhx6;"KzynRZыguby]Au P "

첱|R\in%wGRKvg-2eZtiËg|֓V./D_ȟn-@0BU$4[u0Eg{ϋ2gu蹂WSTCح^-;Q]C{궫I[tsgn6ۛ_iWl(ѽew>{5GO!ŷ;WJrB*hStxJ!3YNud)NaNV&qgx.ih_(l TG@-eد#a.[eRJvug47/$]ߤSc!'5A܈LiPʭAYۍ/ (lrTtA%aњ$oQGA;mHyzkkt~fD+,Na̪QL%~>۩҃;uBT |`yPz|74)7$zhR0CʯH*s]jrY_H-9ٮ? ?H0Nѻ'ef1ydŮZu" |iPO.S疵 {R#vMֳ3ƈb>'+yWؙn f>&[=HSA8ׯ`XYA}W{&WBO߀Y$o{̟8+m_[6Ĥy8%f}+Ԓ! 5Fh;kRXr":|l${u` +B4h\:C~|~4`,Bz*5d޶WsU1ZAb Wɾ?3OKϐLx kEx4쇪#~78D?_*S3cyW7PjU3MvPx'2Ed|3WRHJ% ¡Rr 7&0#LfO‡BO;ll3UBazLsS!kt^ù=ɩҩǙ<'oLUD"xC`ǯ7:g=cz"Verd;w~zC2ľ༿|(P)f +nDn(^>y%@W1jOO|E.t9tZf(ewcW_oؤUUٰO$fGe9i ]]urZ%Tzڴ5n-g:/3!\a@(۠^@fe ٽ!=87eJ09 Oa~ytؼV]S$[ "RWk|3 PѶz)~/ֲRblă\d1;Z|'|!u@ ,Ы+rqA%iU@0Ϩ2^Ԭܟ}=] /de]fV Y| uHiPW:bIqk_LUfoO(&=6΄`j=0>/p8,S%Su ơ*453j))5euluY +9˳Yפkf>K,}؇ +Ps]agqc,Ý:5\Of.c )uUce7*[nWV)_ MYƋ1ˁ+|!EON(zloal+hbQxGOŮpOL6½f;w/DBpy+0RsY,<2\hln|14f!ޟV2|#r *hU͍/}sMDWc[I[5I\EwEEZIFuQc~u|,rcr.gְ1%}ˤpL‡eGVqC$@mM]`B`yRZK+-:#^RG9܂ھ龭ٲ3 U'ZLBbvvn M=tٟR#\=i=˱Oc(^IxONFLQ[ײtvV^)/JVj%9Iw;^/` 5]9ǟcA _ +><]N1nC,L9j3'f^dķSȍXI΋n{PZ"(ݣ)R޽Zr3uЏ QVl鉕̓-E Y*LBLqQFQ"ƣ=[0vgA7l) Ve~ML|Uy~0&ȼpJeTJ:;ͼKXPLA%!̟oJ rmSNU#NvήnHFQZr̦b.*I`sq0 d%T7d/F ';//?[IX\ Tlxx/=-ʮᒸtL䩟' H=/nüMeў$V3J\CX߂a%w=_ [":Aa?Obh9%EKViTYeegGM>i}63ыe-DMqǺ=RBrp<|TJA*"D(cDU tɔ"雝^Ѯc&ov.=:}^e~Η: bql-G襲GvK] &0\Mw!b?RD7`?#.fc'xPXl&ϭ*6/=ktÂA':dO8sҰlsimh4kMC?w}D(o5Ta^r~Q9[*q~_ M3&kx6.;.+a-(f\7D'biɤT Y7*rx/sR]=ͻӪ2PMCnsWTkt-Ԩ3j :opl@floT^R[Nڙ7jv :Aƣ6%ɴleWcE6ZU܊!XW8c>Y~P^ۨzNKN3]_H[|j/kvܗVውȍn.h8W P&ȂtRvXFŽAY cbl&clDK~>>*t6Y 񟎬{@'GN]nS@?B4-MXb݊ք˿U CC2e/@C0&qs}Nqwy#.|݋`OFee8yrZe }轒jd麊ڟopM4.@'"?س]ƞd(3кev<!Aؠ3Xvx/y}tvI.ۖ|ܜrA;iSxùt~h;B O6('EPlP9R\M4ZPPJA}V`\]n]dԝyyiys|g/,ww(|Fi҅m1#b3rA-VdkXiO4kLwc"}Ū]y4sY\?&l-T+|!uwa OVސZ*'. +(sP(.8X):f7'zpG:hyǭCo^?6kp1im`8cJڶ?ȟϳ0FF5s sAi?^Zs$gkce95v!#<*v_ݝwr:b9^۩!bEV`*降Pԁ9OǠ_0?ŞvTc#P2K Ph\nݦPqکUju3XX7dIzGqsQfOzBt',U`IM@}i߉-P^>o!G’e:rƻ#n.Alc+6;7')f?vP/)*!ɶz! +'5?O-ќQj|)<; RLi:S%kLJ5%^˴S(g|nVkj~98dS.~X/:4(Ue; G<"ni8&$,Zh߸~em=Tw\\{b5Bp 83)!+&/k؁ȟe8'3PڎD9sҦHnG+G.KI1LN)aJ,BuM(m D@JxL<3qܛb.5G?Lۿk~9qm$={ ca#Op݈!=z⡤wSUJ+eJUmTMP▝Mk1kjyX^{bƈ'5u ҁf-h7{'i+o ˂xy)l[c<)p +"->+p:j1+NŊt`$y]MnT=-A9߲#zv23Ru-rkFˊ~2,YIELF8Qq%۴*ӹ ݥK-D%!.ßNߠ44>?{#ULoamb_zqʴv7YHETk/mOG5'|!u+mP$zdX ЌJ(-{Ґӳb Ԓɦռ_ixør6h\? +Lp|/>%b&xl685?xF"th;&F[xLD1ªJJU7r{L.pY&RH5(D^p,]J-iPW5|S0K#QR5ڵj;85쀬luޠU)B,O6^z4Ύ2=f!61:3h~#-/_/E6B JFn`^=dT˹z¦42Y +H.x4y8sJy+Ȏߧ&`?J*P w}\X+?Ž[Uӭ71Kll԰t{3>fsfy펉SU >p 10ܖvdau֯Y03y:X𮵙n.&ղU|_7t;R'c= X0Y<%>#EZj|9H1ŞA׫]sYiw|`~j3]* |/ +ڻizᾹf+6mlƷB= M9gxB|8L=MyWx+}S9sy}[߽>VilS@| rWrkrLj +r2X=h.hm1oq(MY4?cRYb?@C{ sȠ9[JPgɇA kM=hR I-@nT^Ņzy޷u[JRʲ/mǶ\[~^:B(>I(Ǡ@ +(XTȇ5o&Wn߰do%zk iѵnHQTh +E2ki2w/?@6PX}d+p83}V}eû2 vyfچ(ς8ZzlB+jAkmha3 7(w(O04v.;G,y::Q,i9-DoG'UW/=.jS*)&ݾj\,Tb8?Dm[q:"P^ ХLk0Cz,~REfkL\G ⴨oεmrO []sG8xXx8tAR ]vwMNyajW{|g.痡IawWjU)p":Y5Xevo/]nYBt|jlf*8˟{;& \6 ]{)s%,.[#-O_Oס-$-1jSgaDoe|uO'ʝvJ^0lwH[ 9.?;zZg(VnοX+ I WIh&,'jenvD8Jvf3rfloۘj3s3)Φ,ҟg$>yh<+pa0OmtF>}#vraCO/z7\mp^M `mTa~ ]h^)[ȠJM3(6ZD /Pt2 A/JOY)^} +bϺktLo:7xDKYn9i$ ԗrwy*It`Nx[fTkĤEړFi-?A~w8GQ+p@JBQD2 ܹx ϭxw4 5q˽CD[L|~룘dS"vNрz'/$?Yg_*4i 'wK<|Eh ZQ?-W;7VX;=5cx>EYaN%7#8jTz #鴝\&ڐ D_,Tި;2ޝQۥYB+\F9{UzIћ< ̵IK3ugCftZ;Dx㓃NgϘ^B*Znۙ7)EJ+i@4?/d?KSmҌia=,s{6OMWd\e28aV!zfԝy̯d4[ֻj8B+5Lę!vLx.g1q:[Wd𺜨yp˸xʼ=k ʹ땚ޮ]kRVc3jn +MNDek$Նî}:j$E|vG`V &8j4aM͗=6(]L޷ja4B= cp ɵRkXUOq5ʴyC*hg9U){Xta3):%F}KM@%}U:faM+ PhNe΀tރ\\f +xSYY%$@v @0XE[+2!_ey+nxz '?BA23@?AQkh/W,OChTIJtM,tu[6-0`09|vC8Aڛ>jRNTܷ GL@.ٹMk|N|{yA>SjN",rA9}<e@ kLB|F|נ1rSMm0y躪CW~CgU-Շ<}pG|̙kof~^{ _,}޳ +ρ6A@ acؠ*WL7ѭFrY}>V~Y-2NyhޥMZNv8%.pOf5Njr6˸aQаByᚿ{N+ B"6q=&W^&X[]Mg넧뉫m'>/Np_RW?7K}Z4vny`oq rӟt(jPP8@'z}=E?l3V ف+V y|y9r +S4s%} obLqEJV;Ƈv Wۥ_ohd `}7r34ܦ]$ڹdYQOˬO4/x>VXuWŧ'?y Pgz`x[Tr6Mi\w5ΰiVA߉w#%ȓl0e oM^}^&icl}whB]Ge7m=!Ķf2t7\o"!ں+m; +_-?wsN`l0$c&{D6r+A"8gc2'>,ڮKlwSa{o'7gծnժ*%ob5Оhx8Za513o (Lsw+9u{ r=_݇m9?R{L~wrWe-]G iaPw(%=\V(fx.1~t4)~zYwz)M8m^ʏBw\I3Mp#-Ah[QzfV2{̌E s0/ tQ5ȯVVԫZMM]ag quD8\j8KE~: Ref /\O@w΋Hr{ RVtz(V +}q5 +9~jP\ٙ  ;Y;x׃6vxB(wk$ +d{ ~vNb8ҶNbjSvMSL5c2*- Gu;SbGn.\s*.&?bj劍*_|7'gaKL%UA7I^m閵0716VޭO?` gi\w"I[yqtllrC@bsrlw ; U}_n^qwnWzL.nW$K?\O6V,o?szh$V\.%٘HOm2o*PiOdTwUϿzo+NŖ{/՗t$毜۾MVC>rgC'<_/r5٭Qת/v7~nBa{ z+g;^y+ +b%g囈f.7_;JvqTvɒ563šϴ!U=A]ԣiNŻy +ۊTNA,|l7ê:B̳aǛu_j5\{=hT.nѫU[0- .B+'9v!~jQIr2Ok|;^D+~?<)t]@8GI`[WNDJm4n^c3:]6tK6*JV))}*ԐSR yrsew?y̨?1j4+%@t|wBCfjiVR+eB2-lɢ@c+DK+.UWЭW~0oAM}jQP%o{vqv]m5jݢ ]N*T$mzBb=?KmkJ 062ק)r S]xa +%˜m{nBM֯^ƣ/#<r}ei$4|v<âc?F0O@a|KZ7 _0!z`wJDX> `\OϕG9 2a13,*'0ӡ=bP[a k7C L 5ǩE9˫?k-BI΃j|*wX ج5| ! c@2-S'؀<У +Y@օ*  uׯ>! S~ "v'cT9hPV޹Ъ;gik젿eK^= N 9@ez +(8|%βv|VuxY80yOEYկ\%'By^7 I e`]7oP6TofcS\K ( !ONZ|??#21SlrS9HGv}M R1a.2GyuDin@4h+ˀF +6O {_TuWؗAZpO#[^ nn[7̧iU^T"-PXH[ c2#(|wʣ_2*㑗 +[K}]ÜEsw![QKWZլ!MڲeO.KEwvo_+=% Pw;*uG hrfT@\:;%os664Z9.rSl]UO`C[l.7-5*Ug'qR~[49B]hCj*;kQg֦+_Zvtzϯ#&~\_f>2cй!aکZƤ~Xc77)M^6g̿?2~~Kbҷ:` 6G+"{z]FvӌZi}+LU +J.n%$(0nUmnB?+a}_(xlvG_l6wwzf] +ִH)k+c~ϛvMFX[ ~bhieb[%ߖcRQm +^1="1-wXė\]8nY>pl(מɧhqTLSw@iNo-OB!(r5aec? Q_NR>NDGLb-{MYZ͆(+2mwv!z!{=.dh/Ig׍51ÅUoUF㧻fˌ-h/jRM[fW41Zon * QvRFJzNˮ(.s"ai.FU8}ޅ4SuQ^-xn,2e`:=&Neif|w'";6Z_oS⊸t;z8Іwr97H/3L=%BoWc/?"mǽ<,N֑u}m%}ٺ-R*E؝V /Z+i3(% Aբ |2}׏a_wnYӽR/ٳ6NHғk]W*Eɷ2'N:^s_|W,Wodd| ƤNV/vmWCQ$>,vMՉ9^_Զ '-._ =@4v>h[76cAd[x\9q Uub^wjz]=x{R^7 ^aZBO蓝eݴʥg&ُ̱zk+v4]}΀!xy5K=.TF qmHo4DW7׎g5#1,UwyP#k`M^'}P97{ɛu3HiIe6>k˼݆$`ef4e/;B[?ȺEr/eG8^. qL\*ͺKs] _ QfP~tؾ5dCV}_NQٜk}OrwA|Nu|X4gq&ݜ%bn51lJm_n.ڭUSlj=U_TyvTs~klN vꫮQR;Mb-| +[N՛Umib/ ;ے{l.w<{xJu^7:^?u;[[/F BNd[w"KIq"W۾ЬgJu.hX)lxJ rHŲ-2Ó$8{x[m1?5r],rs7dZ9'yR^j/3I{jlqh|[,l'Uv+ ,j]ɾSFׂ\|4XA+1*f2 +mWWi[1mVۉI',{D rd$IB)b+<2uRfKIZqm2'K(lN>zUsT0,~BsF9sI&ԖؙX +"ow G0((1@33e()zQ.@# j1`,hfH L5V` lj- :`Xk. P*@;yz*3_Gr~Kk6;_n.)9Ը8{|Q>B77g : 'wpLH`^ +%KtNW^qXtG endstream endobj 5 0 obj <> endobj 48 0 obj <> endobj 73 0 obj [/View/Design] endobj 74 0 obj <>>> endobj 31 0 obj [/View/Design] endobj 32 0 obj <>>> endobj 91 0 obj [90 0 R] endobj 131 0 obj <> endobj xref 0 132 0000000004 65535 f +0000000016 00000 n +0000000173 00000 n +0000046751 00000 n +0000000006 00000 f +0001113161 00000 n +0000000008 00000 f +0000046802 00000 n +0000000009 00000 f +0000000010 00000 f +0000000011 00000 f +0000000012 00000 f +0000000013 00000 f +0000000014 00000 f +0000000015 00000 f +0000000016 00000 f +0000000017 00000 f +0000000018 00000 f +0000000019 00000 f +0000000020 00000 f +0000000021 00000 f +0000000022 00000 f +0000000023 00000 f +0000000024 00000 f +0000000025 00000 f +0000000026 00000 f +0000000027 00000 f +0000000028 00000 f +0000000029 00000 f +0000000030 00000 f +0000000033 00000 f +0001113418 00000 n +0001113449 00000 n +0000000034 00000 f +0000000035 00000 f +0000000036 00000 f +0000000037 00000 f +0000000038 00000 f +0000000039 00000 f +0000000040 00000 f +0000000041 00000 f +0000000042 00000 f +0000000043 00000 f +0000000044 00000 f +0000000045 00000 f +0000000046 00000 f +0000000047 00000 f +0000000000 00000 f +0001113231 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0001113302 00000 n +0001113333 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000448678 00000 n +0001113534 00000 n +0000047231 00000 n +0000448982 00000 n +0000057842 00000 n +0000057513 00000 n +0000448869 00000 n +0000057081 00000 n +0000057225 00000 n +0000057369 00000 n +0000055932 00000 n +0000056517 00000 n +0000056567 00000 n +0000448505 00000 n +0000448234 00000 n +0000057570 00000 n +0000057878 00000 n +0000058266 00000 n +0000057691 00000 n +0000057766 00000 n +0000058400 00000 n +0000058321 00000 n +0000448355 00000 n +0000448430 00000 n +0000448602 00000 n +0000448751 00000 n +0000448783 00000 n +0000449057 00000 n +0000449469 00000 n +0000450620 00000 n +0000456818 00000 n +0000522407 00000 n +0000587996 00000 n +0000588449 00000 n +0000654038 00000 n +0000719627 00000 n +0000785216 00000 n +0000850805 00000 n +0000916394 00000 n +0000981983 00000 n +0001047572 00000 n +0001113559 00000 n +trailer <<08B68B06F4F7496CA57FB3BA5AF8DDAD>]>> startxref 1113782 %%EOF \ No newline at end of file diff --git a/source/images/manual_guy.png b/source/images/manual_guy.png new file mode 100644 index 0000000..2291a69 Binary files /dev/null and b/source/images/manual_guy.png differ diff --git a/source/images/opnsense_logo-zilver_grijs.png b/source/images/opnsense_logo-zilver_grijs.png new file mode 100644 index 0000000..9f66dab Binary files /dev/null and b/source/images/opnsense_logo-zilver_grijs.png differ diff --git a/source/images/support-1024x492.jpg b/source/images/support-1024x492.jpg new file mode 100644 index 0000000..aa1dcf7 Binary files /dev/null and b/source/images/support-1024x492.jpg differ diff --git a/source/index.rst b/source/index.rst new file mode 100644 index 0000000..327b707 --- /dev/null +++ b/source/index.rst @@ -0,0 +1,31 @@ +.. OPNsense documentation master file + +.. image:: ./images/opnsense_logo-zilver_grijs.png + +----------------- + +==================================== +Welcome to OPNsense's documentation! +==================================== +`OPNsense® `__ is an open source, +easy-to-use and easy-to-build FreeBSD based firewall and routing platform. + +**OPNsense** includes most of the features available in expensive commercial +firewalls, and more in many cases. It brings the rich feature set of commercial +offerings with the benefits of open and verifiable sources. + +----------------- +Table of Contents +----------------- + + .. toctree:: + :maxdepth: 2 + + fork/thefork + intro + manual + develop + relations + legal + support + contribute diff --git a/source/intro.rst b/source/intro.rst new file mode 100644 index 0000000..30528a9 --- /dev/null +++ b/source/intro.rst @@ -0,0 +1,105 @@ +============ +Introduction +============ + +Welcome to the OPNsense documentation & wiki project! +The documentation is work in progress and is updated frequently. +If you would like to contribute in anyway, please take a look at our guide +how to :doc:`contribute`. + +.. image:: ./images/opnsense_logo-zilver_grijs.png + +------------------------------------ +Welcome to OPNsense's documentation! +------------------------------------ +`OPNsense® `__ is an open source, +easy-to-use and easy-to-build FreeBSD based firewall and routing platform. + +**OPNsense** includes most of the features available in expensive commercial +firewalls, and more in many cases. It brings the rich feature set of commercial +offerings with the benefits of open and verifiable sources. + +----------------- +Mission Statement +----------------- + + Give users, developers and businesses a friendly, stable and transparent + environment. Make OPNsense the most widely used open source security platform. + The project’s name is derived from open and sense and stands for: + “Open (source) makes sense.” + + +.. image:: ./images/OPNsense-Deciso-Screenshot.jpg + +------------------- + +----------- +Feature set +----------- + +The feature set of OPNsense includes high-end features such as forward caching +proxy, traffic shaping, intrusion detection and easy OpenVPN client setup. +The latest release is based upon FreeBSD 10.1 for long-term support and uses a +newly developed MVC-framework based on Phalcon. OPNsense’s focus on security +brings unique features such as the option to use LibreSSL instead of OpenSSL +(selectable in the GUI) and a custom version based on HardenedBSD. + +The robust and reliable update mechanism gives OPNsense the ability to provide +important security updates in a timely fashion. + +---------------------- + +---------------------- +OPNsense Core Features +---------------------- + +- Traffic Shaper +- Captive portal + + - Voucher support + - Template manager + - Multi zone support + +- Forward Caching Proxy + + - Transparent mode supported + - Blacklist support + +- Virtual Private Network + + - Site to site + - Road warrior + - IPsec + - OpenVPN + - Legacy PPTP support + +- High Availability & Hardware Failover + + - Includes configuration synchronization & synchronized state tables + - Can be combined with Traffic Shaping + +- Intrusion Detection and Inline Prevention + + - Build-in support for Emerging Treats rules + - Simple setup by use of rule categories + - Scheduler for period automatic updates + +- Build-in reporting and monitoring tools + + - System Health, the modern take on RRD Graphs + - Packet Capture + +- Support for plugins +- DNS Server & DNS Forwarder +- DHCP Server and Relay +- Dynamic DNS +- Backup & Restore + + - Encrypted cloud backup to Google Drive + - Configuration history with colored diff support + - Local drive backup & restore + +- Stateful inspection firewall +- Granular control over state table +- 802.1Q VLAN support +- and more.. diff --git a/source/legal.rst b/source/legal.rst new file mode 100644 index 0000000..29eb466 --- /dev/null +++ b/source/legal.rst @@ -0,0 +1,143 @@ +============= +Legal notices +============= + + +.. image:: ./images/opnsense_logo-zilver_grijs.png + :width: 300px + +The OPNsense project wants to be a project that is friendly for users, +developers and partners. In this world with trademarks and copyright it +is best to “keep things as simple as possible, but not simpler”. Below +we pointed out the Licensing and Trademark rules we use. + +---------------------------- +OPNsense License & Copyright +---------------------------- + +.. sidebar:: OSI Approved License + + .. image:: ./relations/images/osi_standard_logo.png + +OPNsense is licensed under an `Open Source Initiative approved license `__. + +We like the BSD license, a simple two clause license that gives freedom to the +audience we want to serve.  It basically gives you the right to do whatever you +want to do with the code, even fork it and take it from there. + +OPNsense is available under the BSD 2-Clause “Simplified” or “FreeBSD” +license: + +`OPNsense® `__ is Copyright © 2014 – 2016 by +Deciso B.V. +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +OPNsense is based on `FreeBSD `__ +Copyright © The FreeBSD Project. All rights reserved. + +OPNsense is a fork of `pfSense® `__ +(Copyright © 2004-2014 Electric Sheep Fencing, LLC. All rights +reserved.) a fork from `m0n0wall `__ (Copyright +© 2002-2013 Manuel Kasper). + +------------------ +Packages and ports +------------------ +OPNsense includes various freely available software packages and ports. +The current ports are listed `here `__. + +The authors of OPNsense would like to thank all contributors for their efforts. + +.. _documentation-copyright: + +----------------------- +Documentation Copyright +----------------------- +The documentation is provided under a 2-clause BSD license: + +(c) Deciso B.V. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE OPNSENSE DOCUMENTATION PROJECT BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------ +Pictures Copyright +------------------ +Some pictures are licensed under the Creative Commons Zero (CC0) license: + +https://creativecommons.org/publicdomain/zero/1.0/ + +----------------- +Logo's Copyright +----------------- +Logo's may be subject to additional copyrights, property +rights, trademarks etc. and may require the consent of a third party or the +license of these rights. Deciso B.V. does not represent or make any warranties +that it owns or licenses any of the mentioned, nor does it grant them. + +---------------- +Trademark policy +---------------- + +OPNsense is a trademark. If you wish to use the name or logo in any way, +you must comply with this policy. + +#. The name and logo may be used to promote OPNsense based products or + services. +#. The name and logo may be used to promote or serve OPNsense or related + projects and their communities. +#. When using the logo on online media like websites, social media and + apps the logo should link to https://opnsense.org +#. You must request our permission to use derivatives of the name and/or + logo at **project** @ **opnsense.org** prior to any use of the + derivative name and/or logo, and we may grant or withhold permission + to use the derivative name and/or logo in our sole discretion. +#. You may not state or otherwise lead people to believe, that you + represent the OPNsense project in any way other than as an individual + or corporate contributor to the project. + +The official OPNsense logo is available for download: +:download:`OPNsense logo`. + +If you have any questions about this policy, its interpretation, or want +to ask for permission please email **project** @ **opnsense.org**. diff --git a/source/manual.rst b/source/manual.rst new file mode 100644 index 0000000..c05fe4c --- /dev/null +++ b/source/manual.rst @@ -0,0 +1,35 @@ +==================================== +User Manual +==================================== + +.. image:: images/manual_guy.png + :width: 600px + :align: center + +---------------- + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + manual/hardware + manual/install + manual/virtuals + manual/gui + manual/users + manual/ipv6 + manual/two_factor + manual/systemhealth + manual/netflow + manual/aliases + manual/vpnet + manual/ips + manual/proxy + manual/antivirus + manual/shaping + manual/multiwan + manual/mobile_wan + manual/hacarp + manual/captiveportal + manual/dynamic_routing + manual/howtos diff --git a/source/manual/aliases.rst b/source/manual/aliases.rst new file mode 100644 index 0000000..8757505 --- /dev/null +++ b/source/manual/aliases.rst @@ -0,0 +1,155 @@ +============= +Using Aliases +============= +Aliases are named lists of networks, hosts or ports that can be used as one entity +by selecting the alias name in the various supported sections of the firewall. +These aliases are particularly useful to condense firewall rules and minimize +changes. + +----------- +Alias Types +----------- +OPNsense offers the following alias types: + ++------------+------------------------------------------------------+ +| Type | Description | ++============+======================================================+ +| Hosts | Single hosts by IP or Fully Qualified Domain Name | ++------------+------------------------------------------------------+ +| Networks | Entire network p.e. 192.168.1.1/24 | ++------------+------------------------------------------------------+ +| Ports | Port numbers or a port range like 20:30 | ++------------+------------------------------------------------------+ +| URL Tables | A table of ip addresses that can be fetched | ++------------+------------------------------------------------------+ + +----- +Hosts +----- +Hosts can be entered as a single IP address or a fully qualified domain name. +When using a fully qualified domain name, the name will we resolved periodically +(default is each 300 seconds). + +Sample + Lets say we want to create an alias table for **www.youtube.com** + + .. image:: images/aliases_host.png + :scale: 100% + +**Apply changes** and look at the content of our newly created pf table. +Go to **Firewall->Diagnostics->pfTables** and select our newly created youtube table. + +.. image:: images/pftable_youtube.png + :scale: 100% + +As you can see there are multiple ip addresses for this domain. + +-------- +Networks +-------- +Networks are specified in Classless Inter-Domain Routing format (CIDR). Use the +the correct CIDR mask for each entry. For instance a /32 specifies a single IPv4 host, +or /128 specifies a single IPv6 host, whereas /24 specifies 255.255.255.0 and +/64 specifies a normal IPv6 network. + +----- +Ports +----- +Ports can be specified as a single number or a range using a colon **:**. +For instance to add a range of 20 to 25 one would enter 20:25 in the **Port(s)** +section. + +---------- +URL Tables +---------- +URL tables can be used to fetch a list of ip addresses from a remote server. +There are several IP lists available for free, most notably are the "Don't Route +Or Peer" lists from Spamhaus. + +-------------- +Import Feature +-------------- +To quickly add a list of aliases OPNsense also offers an import feature, where +you can paste or enter a list in text format. + +Common examples are lists of IPs, networks, blacklists, etc. +The list may contain IP addresses, with or without CIDR prefix, IP ranges, +blank lines (ignored) and an optional description after each IP. e.g.: + +.. code:: + + 172.16.1.2 + 172.16.0.0/24 + 10.11.12.100-10.11.12.200 + 192.168.1.254 Home router + 10.20.0.0/16 Office network + 10.40.1.10-10.40.1.19 Managed switches + +Spamhaus +-------- + +The Spamhaus Don't Route Or Peer Lists + DROP (Don't Route Or Peer) and EDROP are advisory "drop all traffic" lists, + consisting of netblocks that are "hijacked" or leased by professional spam or + cyber-crime operations (used for dissemination of malware, trojan downloaders, + botnet controllers). The DROP and EDROP lists are a tiny subset of the SBL, + designed for use by firewalls and routing equipment to filter out the malicious + traffic from these netblocks. + + *Source :* https://www.spamhaus.org/drop/ + +Downloads + * `DROP list `__ + * `EDROP list `__ + +---------------------------------- +Using Aliases in pf Firewall Rules +---------------------------------- +Aliases can be used in the firewall rules to make administration of large lists +easy. For instance we could have a list of remote ip's that should have access to +certain services, when anything changes we only need to update the list. + +Lets create a simple alias list and assume we have 3 remote ip's that may access +the ipsec server for a site to site tunnel connection: + +* 192.168.100.1 +* 192.168.200.2 +* 192.168.300.3 + +.. image:: images/alias_remote_ipsec.png + :scale: 100% + +We call our list remote_ipsec and update our firewall rules accordingly. + +.. image:: images/alias_firewall_rules.png + :scale: 100% + +Notice the list icon to identify a rule with an alias (list). + +-------- +Advanced +-------- +For hosts it is possible to use lists in lists. Per example you could have: + +* critical_servers {10.0.1.1 , 10.0.1.2} +* other_servers {10.0.1.100 , 10.0.1.200} + +Then concatenate both by defining a new list: + +* servers { critical_servers , other_servers}. + +The end result will be a list with all ip addresses in one alias list (servers). + +------- +GeoIP's +------- +While it is possible to use geoIP lists in aliases by importing or using the url +feature, OPNsense has a much more advanced way of blocking or allowing traffic based +on the geographical location (country) by utilizing the netmap enabled +:doc:`ips` see also :doc:`how-tos/ips-geoip` + +------------------------------ +Configure DROP and EDROP lists +------------------------------ +To setup the DROP and EDROP lists in combination with the firewall rules, read: +:doc:`how-tos/edrop` diff --git a/source/manual/antivirus.rst b/source/manual/antivirus.rst new file mode 100644 index 0000000..f05d132 --- /dev/null +++ b/source/manual/antivirus.rst @@ -0,0 +1,18 @@ +=================== + Anti Virus Engine +=================== + +.. image:: images/eye_on_virus_new.jpg + :scale: 100% + +**OPNsense** offers the industry standard ICAP to protect http and https +connections against ransomware, trojans, viruses and other malware . + +OPNsense offers a ClamAV plugin, which can be used with the C-ICAP plugin or relies on third +party engines from well known vendors, such as Symantec's Protection Engine. + +Setup ICAP Anti Virus Engine +---------------------------- + +- :doc:`how-tos/proxyicapantivirus` +- :doc:`how-tos/proxyicapantivirusinternal` diff --git a/source/manual/captiveportal.rst b/source/manual/captiveportal.rst new file mode 100644 index 0000000..1f122b1 --- /dev/null +++ b/source/manual/captiveportal.rst @@ -0,0 +1,111 @@ +========================= +Captive portal & GuestNET +========================= +A **Captive Portal** allows you to force authentication, or redirection to a click +through page for network access. This is commonly used on hotspot networks, +but is also widely used in corporate networks for an additional layer of security +on wireless or Internet access. + +.. image:: images/hotspot_login.png + :scale: 100% + +-------------------- +Typical Applications +-------------------- +* Guest Network +* Hotel & Camping Wifi Access +* Bring Your Own Device (BOYD) + +------------------- +Template Management +------------------- +OPNsense’s unique template manager makes setting up your own login page an easy +task. At the same time it offers additional functionalities, such as: + +* URL redirection +* Option for your own Pop-up +* Custom Splash page + +.. image:: images/captiveportal_template_folder.png + :scale: 100% + +--------------- +Zone Management +--------------- +Different zones can be setup on each interface or multiple interfaces can share +one zone setup. Each Zone can use a different Captive Portal Template or share it +with another zone. + +-------------- +Authentication +-------------- +Secure authentication via HTTPS or splash-only portal with URL redirection to a +given page Different sources can be used to authenticate a user in a zone: + +* LDAP [Microsoft Active Directory] +* Radius +* Local user manager +* Vouchers / Tickets +* No authentication (Splash Screen Only) +* Multiple (a combination of above) + +--------------- +Voucher Manager +--------------- +OPNsense's Captive Portal has an easy voucher creation system that exports the +vouchers to a csv file for use with you favorite application. The export allows +you to print vouchers by merging them with your word or open office template and +create a good looking handout with your logo and company style. + +----------------------- +Timeouts & Welcome Back +----------------------- +Connection can be terminated after the user has been idle for a certain amount +of time (idle timeout) and/or force a disconnect when a number of minutes +have passed even if the user is still active (hard timeout). In case a user +reconnect within the idle timeout and/or hard timeout no login is required and +the user can resume its active session. + +-------------------- +Bandwidth Management +-------------------- +The Build-in traffic shaper can be utilized to: + +* Share bandwidth evenly +* Give priority to protocols port numbers and/or ip addresses + +See also: :doc:`/manual/shaping` + +------------- +Portal bypass +------------- +MAC and IP addresses can be white listed to bypass +the portal. + +------------------- +Real Time Reporting +------------------- +Basic Real Time Reporting is Integrated + +* Live top IP bandwidth usage (Traffic Graph) +* Active Sessions +* Time left on Vouchers + +---------------------------- +Category based Web Filtering +---------------------------- +By combining the Captive Portal with the caching proxy it is possible to utilize +category web filtering and block certain content for the users and by enabling the +cache reduce bandwidth and improve response times. See also: :doc:`/manual/proxy` + +-------------------- +Platform Integration +-------------------- +Through the integrated REST API the captive portal application can be integrated +with other services. See: :doc:`/development/how-tos/api` + +-------------------- +Configure the Portal +-------------------- +To setup a hotspot controller for business or hotel usage see: +:doc:`how-tos/guestnet` diff --git a/source/manual/dynamic_routing.rst b/source/manual/dynamic_routing.rst new file mode 100644 index 0000000..4eb3176 --- /dev/null +++ b/source/manual/dynamic_routing.rst @@ -0,0 +1,59 @@ +=============== +Dynamic Routing +=============== + +.. Warning:: + Disabling a running routing daemon can be dangerous as it can lead to an inaccessible machine. + If you want to disable a running routing daemon, make sure, you don't lose routes which are + required by your connection to this machine (for example when using SSH) + +Dynamic Routing (using routing protocos) is supported via an external plugin. Routing protocols are used to make your network equipment find the best path where your packets should be sent to. + +Routing protocols are used to + +* improve fault tolerance (if a connection breaks, a new route will be found if possible) +* simplify administration (You have to add less routes manually) + +You should not use routing protocols if + +* your network is small (so it would be better to use static routes) +* you are working in a highly isolated environment, where you have to be in control of everything happening in your network + +Routing Protocols supported by the plugin include: + +* OSPFv2 and v3 +* RIPv1 and RIPv2 +* BGPv4 + +.. Warning:: + Not all routing protocols will work in any setup because they may have to be direct neighbors. + Consider the limitations of a routing protocol before using it. + +------------ +Installation +------------ + +First of all, select Plugins in the menu: + +.. image:: images/menu_plugins.png + +On this page, you can install the quagga plugin by clicking the `+` icon: + +.. image:: images/plugins_quagga.png + + +------------- +Configuration +------------- + +* :doc:`how-tos/dynamicrouting_zebra` +* :doc:`how-tos/dynamicrouting_ospf` +* :doc:`how-tos/dynamicrouting_rip` + + +------ +How To +------ + +* :doc:`how-tos/dynamicrouting_howto` + diff --git a/source/manual/gui.rst b/source/manual/gui.rst new file mode 100644 index 0000000..de7c4a8 --- /dev/null +++ b/source/manual/gui.rst @@ -0,0 +1,130 @@ +=========================== +The OPNsense User Interface +=========================== + +This article explains the basics of the OPNsense Graphical User Interface or GUI +for short. + +---------- +User Login +---------- +Before we can take a look at the GUI options we need to login. +The default user is root and the password is opnsense. + +.. image:: images/login.png + + +---------------------------- +GUI Layout & Main Components +---------------------------- + +The GUI consists out of the following main components: + +.. image:: images/gui_layout.png + :scale: 100% + + +Logo & Link to Lobby +--------------------- +Click on the OPNsense logo wherever you are in the interface and you will be +directed to the lobby and dashboard. + +In the Lobby you can: + +* Look at the dashboard with widgets +* View the 2 clause BSD license +* Change your password +* Logout + +Menu Area +--------- +The Menu area holds all the primary and sub menu's. +Here you can select what part of the system you want to watch or change. + +You can see the layering on the menu. There are three levels: + +#. Category level +#. Function level +#. Configuration level *(may not exist if the function is simple)* + +In the following sample you see a screenshot of the Category **System**, with: + +* Function: **Settings** +* Selected Configuration item: **General** + +.. image:: images/submenu.png + +Quick Navigation +---------------- +A faster way to navigate trough the gui is by using the quick navigation/search box +on the upper right corner of the screen. Either click on it or hit tab to select it. + +The search field is a type-a-head field, meaning that it will guess what you are +looking for and fill up while typing. Hit enter or click on an option to select +and navigate directly to the right page. + +.. image:: images/quick-navigation.png + + +User & Local domain +------------------- +In the right corner just to the left of the quick navigation you will see your +username and the full domain name the firewall is configured with +(to change firewall name, go to **System->Setting->General**). + + +Content Area +------------ +The content area is used to display: + +* Input forms +* Popup Forms +* Buttons +* General forms of data output graphical and text based + +---------- +Form View +---------- +Lets take a look at how an advanced form may look like: + +.. image:: images/proxy_form.png + +Full Help +--------- +Many Forms are equipped with build-in help. In the upper right corner of the form +you can select to view all help messages at once. The toggle will color green when +enabled and show the help messages beneath the input items. + +.. image:: images/help_msg.png + + +Advanced Mode +------------- +Some forms have hidden advanced features, to view them toggle the **advanced mode** in +the left corner of the form. Doing so will reveal all advanced options. + +.. image:: images/advanced.png + + +Single Item Help +---------------- +Show a single line help by pressing the **(i)** left of a form item. +Like this: + +.. image:: images/info.png + + +Standard Tabs +------------- +A standard tab can be clicked upon to open the corresponding form. + +A sample can be seen here: + +.. image:: images/tab.png + +Dropdown Tabs +------------- +A dropdown tab can be clicked upon to open the first menu item or you can click on +the arrow next to it to show all options, like: + +.. image:: images/dropdown_tab.png diff --git a/source/manual/hacarp.rst b/source/manual/hacarp.rst new file mode 100644 index 0000000..3d89725 --- /dev/null +++ b/source/manual/hacarp.rst @@ -0,0 +1,43 @@ +===================================== +High Availability & Hardware Failover +===================================== +OPNsense utilizes the Common Address Redundancy Protocol or CARP for hardware +failover. Two or more firewalls can be configured as a failover group. If one +interface fails on the primary or the primary goes offline entirely, the +secondary becomes active. + +Utilizing this powerful feature of OPNsense creates a fully redundant firewall +with automatic and seamless fail-over. While switching to the backup network +connections will stay active with minimal interruption for the users. + +.. image:: images/light_bulbs.png + :scale: 100% + +------------------ +Automatic failover +------------------ + +If the primary firewall becomes unavailable, the secondary firewall will take +over without user intervention and minimal interruption. + +------------------------- +Synchronized state tables +------------------------- + +The firewall’s state table is replicated to all failover configured firewalls. +This means the existing connections will be maintained in case of a failure, +which is important to prevent network disruptions. + +----------------------------- +Configuration synchronization +----------------------------- + +OPNsense includes configuration synchronization capabilities. Configuration +changes made on the primary system are automatically synchronized to the +secondary firewall. + +----------------- +Configure HA CARP +----------------- + +For detailed setup guide see: :doc:`/manual/how-tos/carp` diff --git a/source/manual/hardware.rst b/source/manual/hardware.rst new file mode 100644 index 0000000..d3a37ef --- /dev/null +++ b/source/manual/hardware.rst @@ -0,0 +1,191 @@ +======================= +Hardware sizing & setup +======================= + +The **harware setup** requires a careful preparation and selection of +the standard PC hardware components for the intended installation of +OPNsense. + +⚠ Computer hardware with the open source security software OPNsense® +pre-installed can be purchased directly from various (online) stores. + +.. TIP:: + The OPNsense development team encourage everyone looking for a turn-key solution + to buy from `Deciso `__ or one of the other partners listed at our partner page. + **Listed partners make significant contributions back to the project** + +-------------------------------- +Supported hardware architectures +-------------------------------- + +OPNsense® is available for +`x86-32 `__ (i386) and +`x86-64 `__ (amd64) bit +microprocessor architectures. Full installs on `SD memory +cards `__, `solid-state +disks (SSD) `__ or +`hard disk drives +(HDD) `__ are intended +for OPNsense. + +While the range of supported devices are from embedded systems to rack +mounted servers, we recommend to use a 64-bit versions of OPNsense, if +the hardware is capable of running 64-bit `operating +systems `__. It is +possible to install and run 32-bit (x86-32, i386) versions of OPNsense® +on 64-bit (x86-64, amd64) PC hardware, but we do not recommend it, +especially not for new deployments. + +--------------------- +Hardware requirements +--------------------- + +For substantially narrowed OPNsense® functionality there is the basic +specification. For full functionality there are minimum, reasonable and +recommended specifications. + +.. rubric:: Minimum + :name: minimum + +The minimum specification to run all OPNsense standard features that do +not need disk writes, means you can run all standard features, expect +for the ones that require disk writes, e.g. a caching proxy (cache) or intrusion detection +and prevention (alert database). + ++------------------+--------------------------------------------------------------------------+ +| Processor | 500MHz single core cpu | ++------------------+--------------------------------------------------------------------------+ +| RAM | 512 MB | ++------------------+--------------------------------------------------------------------------+ +| Install method | Serial console or video (vga) | ++------------------+--------------------------------------------------------------------------+ +| Install target | SD or CF card with a minimum of 4GB, use nano images for installation. | ++------------------+--------------------------------------------------------------------------+ + +Table: *Minimum hardware requirements* + +.. rubric:: Reasonable + :name: reasonable + +The reasonable specification to run all OPNsense standard features, +means every feature is functional, but perhaps not with a lot of users +or high loads. + ++------------------+--------------------------------------------------------------------------+ +| Processor | 1 GHz dual core cpu | ++------------------+--------------------------------------------------------------------------+ +| RAM | 1 GB | ++------------------+--------------------------------------------------------------------------+ +| Install method | Serial console or video (vga) | ++------------------+--------------------------------------------------------------------------+ +| Install target | 40 GB SSD, a minimum of 1GB memory is needed for the installer to run. | ++------------------+--------------------------------------------------------------------------+ + +Table: *Reasonable hardware requirements* + +.. rubric:: Recommended + :name: recommended + +The recommended specification to run all OPNsense standard features, +means every feature is functional and fits most use cases. + ++------------------+---------------------------------+ +| Processor | 1.5 GHz multi core cpu | ++------------------+---------------------------------+ +| RAM | 4 GB | ++------------------+---------------------------------+ +| Install method | Serial console or video (vga) | ++------------------+---------------------------------+ +| Install target | 120 GB SSD | ++------------------+---------------------------------+ + +Table: *Recommended hardware requirements* + +.. rubric:: Hardware guide + :name: hardware-guide + +The hardware required for your local OPNsense, will be determined by the +intended minimum `throughput `__ and the +feature set. + +--------------------- +Impact of Feature set +--------------------- + +While most features do not effect hardware dimensioning, a few features +have massive impact on it. The candidates are: + +`Squid `__  + a caching web proxy which can be used for web-content control, + respectively. These packages rely strongly on CPU load and + disk-cache writes. + +`Captive portal `__ + settings with hundreds of simultaneously served captive portal users + will require more CPU power in all the hardware specifications + displayed below. + +`State transition tables `__ + it is a known fact, that each state table entry requires about 1KB + (kilo bytes) of RAM. The average state table, filled with 1000 + entries will occupy about ~10MB (mega bytes) of + `RAM `__. + OPNsense usage settings with hundred of thousands of connections + will require memory accordingly. + +| + +---------- +Throughput +---------- + +The main hardware-factors of the OPNsense setup involved are CPU, RAM, +mass storage (disc), the number and quality of network interfaces. + ++-------------------+-----------------------+-------------+------------------------+ +| Throughput (Mbps) | Hardware requirements | Feature set | Users / Networks | ++===================+=======================+=============+========================+ +| 1-10 | Basic spec. | narrowed | few (1-10) | ++-------------------+-----------------------+-------------+------------------------+ +| 11-150 | Minimum spec. | reduced | adjusted (10-30) | ++-------------------+-----------------------+-------------+------------------------+ +| 151-350 | Reasonable spec. | all | substantial (30-50) | ++-------------------+-----------------------+-------------+------------------------+ +| 350-750+ | Recommended spec. | all | substantial+ (50-150+) | ++-------------------+-----------------------+-------------+------------------------+ +| Mbps (Mbit/s or Mb/s) - Megabit per second - 1,000,000 bits per second | ++----------------------------------------------------------------------------------+ + +Network interface cards + As the FreeBSD hardware-lists and -recommendations + say, Intel® network interface cards (NIC) for + `LAN `__ + connections are reliable, fast and not error-prone. Intel chipset + NICs deliver higher throughput at a reduced `CPU + load `__. + +.. rubric:: Supported hardware + :name: supported-hardware + +The FreeBSD 10.2-RELEASE is the base of OPNsense. All FreeBSD drivers +are included in the OPNsense kernel, and the hardware compatibility is +the same. + +.. Tip:: + If you are looking to buy new hardware then take a look at our `partner page `__ + as these partners contribute back to OPNsense and sell hardware that is know to work well. + +For further help and support, see + +- `FreeBSD 10.2-RELEASE Hardware Compatibility + List `__ +- `OPNsense Forum `__ + +.. rubric:: List of references + :name: list-of-references + +- Schellevis, Jos; *Hardware requirements*; `OPNsense > Get + started `__ (2015) +- McKusick, Marshall; Neville-Neil, George V; Warson, Robert NM; *The + Design and Implementation of the FreeBSD Operating System* (2015); + Addison-Wesley, New Jersey; ISBN 978-0321968975 diff --git a/source/manual/how-tos/accounting.rst b/source/manual/how-tos/accounting.rst new file mode 100644 index 0000000..626ca1f --- /dev/null +++ b/source/manual/how-tos/accounting.rst @@ -0,0 +1,100 @@ +=============================== +Setup FreeRADIUS for accounting +=============================== + +--------------------- +Goal of this tutorial +--------------------- + +This tutorial can be used to test your Captive portal setup with radius +accounting, it's not intended to use for production setups (because we +only use simple flat files for everything). We used Ubuntu linux for +this setup, a different operating system might result in some paths +being different. + +User limits on the OPNsense firewall are set right after login, the +Radius server should tell the firewall how much resources are left for +the user that logged in successfully. A normal login sequence look like +this: + +[login] -> [send accounting start] -> [send interim updates while +connected] -> [on logout, send accounting stop] + +----- +Setup +----- + +To setup freeradius in ubuntu, execute the following command: + +:: + + apt-get install freeradius + + +Arrange client access +--------------------- + +Edit the file /etc/freeradius/clients.conf and append a block for your +network, as sample we will use 10.211.55.0/24. + +.. code-block:: php + + client 10.211.55.0/24 { + secret = testing123 + shortname = test-network + } + +Enable daily session limits +--------------------------- + +Enable daily session limits, which needs accounting to signal the +clients use. + +- In /etc/freeradius/sites-available/default uncomment daily in + authorize and accounting sections. +- in /etc/freeradius/radiusd.conf uncomment daily in the instantiate + section +- append to /etc/freeradius/dictionary + + +.. code-block:: c + + ATTRIBUTE Daily-Session-Time 3000 integer + ATTRIBUTE Max-Daily-Session 3001 integer + + +- uncomment sradutmp in the accounting section, to be able to use the + radwho command. + +-------------- +Add test users +-------------- + +You can add your test users to /etc/freeradius/users, they should look +like this: + +.. code-block:: c + + "test" Cleartext-Password := "test", Max-Daily-Session := 1800 + Framed-IP-Address = 10.211.55.100, + Reply-Message = "Hello, %{User-Name}" + + +Make sure the second and third lines are indented by a single tab +character. + +This should result in a user with a maxim use per day of 1800 seconds. + +----------- +Test radius +----------- + +For the initial test, it might be practical to debug the traffic going +in and out from Freeradius. The next steps help you start Freeradius in +debug mode, without output to console: + + +.. code-block:: c + + /etc/init.d/freeradius stop + freeradius -X diff --git a/source/manual/how-tos/c-icap.rst b/source/manual/how-tos/c-icap.rst new file mode 100644 index 0000000..a23eb77 --- /dev/null +++ b/source/manual/how-tos/c-icap.rst @@ -0,0 +1,75 @@ +====== +c-icap +====== + +------------ +Installation +------------ + +First of all, you have to install the c-icap plugin (os-cicap) from the plugins view. + +.. image:: ../images/menu_plugins.png + + +After a page reload you will get a new menu entry under services for C-ICAP. +Select it and you will get to the following screen: + +.. image:: images/c-icap_settings.png + +---------------- +General Settings +---------------- + +:Enable c-icap service: + Enable the C-ICAP service to handle ICAP requests. +:Timeout: + The time after which the socket will be closed. +:Max keepalive timeout: + The time after which the socket will be closed if it stays inactive. +:Start servers: + The count of the server processes which will be spawned. +:Max servers: + Limit the count of processes +:Listen address: + The address in which the server should be bound. + This address is usually the loopback address (\:\:1 for IPv6 or + 127.0.0.1 for IPv4). The default value is \:\:1. +:Server admin: + This field should be set to an email address which acts as a contact + for users, who are having issues with the server. + A good idea would be an address, which converts the mails to your internal + ticket system. +:Servername: + If you want to override the server name (displayed on error pages), + you can enter it here. + + +--------- +Antivirus +--------- + +.. image:: images/c-icap_av.png + +:Enable ClamAV: + Enables the virus + -scan plugin of c-icap-modules using ClamAV +:Scan for filetypes: + The type of files which should be analyzed. + You should scan as many file types as possible but keep in mind that + scanning requires resources which have to be available. +:Send percentage data: + Amount of Data of the original file which should be included in the preview. + More Data will have better scanning results and is better for security while + a lower value improves performance. +:Allow 204 response: + A 204 response has the advantage, that the data don't have + to be sent over the wire again. In case of a preview, no more data + will be sent to the ICAP server and the data will be forwarded to + the client. In case of all data has been received by the ICAP server, + the data does not need to be sent back. Please note, that the ICAP client + has to support 204 responses. +:Pass on error: + In case the scan fails, the file can be passed through. + This is less secure but keeps the business running in case of failure. + Keep in mind that this may put your network at risk. + diff --git a/source/manual/how-tos/cachingproxy.rst b/source/manual/how-tos/cachingproxy.rst new file mode 100644 index 0000000..fb5f5f7 --- /dev/null +++ b/source/manual/how-tos/cachingproxy.rst @@ -0,0 +1,192 @@ +=================== +Setup Caching Proxy +=================== + +.. image:: images/proxy_basics.png + :scale: 100% + +---------------- +Enable / Disable +---------------- +The proxy is delivered with sane default settings for easy setup. +To enable the proxy just go to **Services->Proxy Server->Administration** and +check **Enable proxy** en click on **Apply**. The default will enable the proxy +with User Authentication based on the local user database and runs on port 3128 +of the lan interface. + +----------------------- +Change Proxy Interfaces +----------------------- +If you want to change the interfaces (subnets) the proxy will bind to then click +on the tab **Forward Proxy**. Now add/remove the interfaces in the **Proxy interfaces** +field. When adding make sure it is applied and a tag is visible (use , Enter or +select from the list). + +--------------------------- +Change Proxy Listening Port +--------------------------- +By default the proxy will listen at port 3128, you can change this by clicking +on the tab **Forward Proxy** and fill in the port in the **Proxy port** feild. +Don't forget to **Apply** your changes. + +------------ +Enable Cache +------------ +To enable caching click on the arrow next to the **General Proxy Settings** to +see the dropdown menu and click on **Local Cache Settings**. + +.. image:: images/proxy_cache.png + :scale: 100% + +Check the **Enable local cache** and click **Apply**. + +.. Important:: + + As the cache is not created by default you will need to stop and start the service + under **Services->Diagnostics**, this will ensure correct creation of the cache. + +Advanced +-------- +Under the advanced settings (see mode switch on left top of the form) you can +change the cache size, directory structure and max object size to keep in cache. +Again defaults are fine for normal browsing and creates a 100MB cache with max 4MB +object size. + + +---------------------------- +Change Authentication Method +---------------------------- +Click on the arrow next to the **Forward Proxy** tab to show the drop down menu. +Now select **Authentication Settings** and select the desired Authenticator(s) in +the field **Authentication method**. Click on **Clear All** if you do not want to +use any authentication. + +Depending on the Authentication Servers you have setup under **System->Access->Servers** +You can select one or more of the following: + +* No Authentication (leave field blank) +* Local User Database +* LDAP +* Radius + +--------- +FTP Proxy +--------- +To enable the FTP Proxy Click on the arrow next to the **Forward Proxy** tab to +show the drop down menu. Now select **FTP Proxy Settings** and select one or more +interfaces in the **FTP proxy interfaces** field and **Apply**. + +.. Note:: + The FTP proxy will only function if the Proxy Server itself is enabled. + And the proxy only works for non encrypted ftp traffic. + +------------------- +Access Control List +------------------- +You can setup ACL's by clicking on the arrow next to **Forward Proxy** and select +**Access Control List**. Here you can: + +* Setup Allowed Subnets (By default the proxy interfaces will be allowed) +* Add Unrestricted IP addresses (Unrestricted means just that, no authentication and no blacklisting for those IP's) +* Add Banned hosts IP address (A ban will stop this client from being able to use the proxy) +* Whitelist (Click on the (i) to see examples, whitelist prevail above blacklists) +* Blacklist (If not allowed by a whitelist, this will block traffic based upon a regular expression) + +.. Warning:: + Don't forget to press Enter or a comma after filling in a tag field as otherwise + the value will not be applied. It should look similar to: + + .. image:: images/proxy_tag.png + +------------------------------- +Remote Black List / Ad Blocking +------------------------------- +Use simple flat files to block ads. +For this sample we will use the ad list found here: + +http://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml + +This list is a simple flat list that looks like this: + +.. code-block:: guess + + 101com.com + 101order.com + 123found.com + 180hits.de + 180searchassistant.com + 1x1rank.com + 207.net + 247media.com + +Go to **Services->Proxy Server->Administration** and click on the tab **Remote +Access Control Lists** + +Now click on the **+** at the bottom right corner of the form to add a new list. + +Fill in: + +================= ======================= =========================================== + **Enabled** Checked *Enable/Disable* + **Filename** yoyoads *Choose a unique filename* + **URL** (copy/paste the URL) *The URL of the blacklist* + **categories** (Leave blank) *Used for Category based web filtering* + **Description** Yoyo Ads Blacklist *Your description* +================= ======================= =========================================== + +Looks like (screenshots of version 16.1.4): + +.. image:: images/proxy_blacklist.png + :scale: 100% + +**Save changes** + +Now click on **Download ACLSs & Apply** to enable the blacklist/ad blocker. + +----------------------------- +Firewall Rule No Proxy Bypass +----------------------------- +To make sure no-one can bypass the proxy you need to add a firewall rule. +Go to **Firewall->Rules** and add the following to the top of the list rule on the +LAN interface (if LAN is where your clients and proxy are on). + +============================ ===================== + **Action** Block + **Interface** LAN + **Protocol** TCP/UDP + **Source** LAN net + **Destination Port Range** HTTP + **Category** Block Proxy Bypass + **Description** Block http bypass +============================ ===================== + +**Save** + +And one more rule to block HTTPS access: + +============================ ===================== + **Action** Block + **Interface** LAN + **Protocol** TCP/UDP + **Source** LAN net + **Destination Port Range** HTTPS + **Category** Block Proxy Bypass + **Description** Block https bypass +============================ ===================== + +**Save** & **Apply changes** + +.. image:: images/proxy_firewall.png + :scale: 100% + +------------------------- +Configure Browser/Firefox +------------------------- +To configure you browser for use with the proxy, just go to your network settings +and configure a proxy like this in firefox: + +.. image:: images/proxy_firefox.png + :scale: 100% + + +For a set-for-step guide on full category based web filtering see :doc:`proxywebfilter`. diff --git a/source/manual/how-tos/carp.rst b/source/manual/how-tos/carp.rst new file mode 100644 index 0000000..a9ab50d --- /dev/null +++ b/source/manual/how-tos/carp.rst @@ -0,0 +1,238 @@ + +============== +Configure CARP +============== + + +-------- +Overview +-------- + +One of the more powerful features of OPNsense is to set-up a redundant +firewall with automatic fail-over option. This chapter describes step by +step how to create a set-up based on two networks. The 192.168.1.0/24 +will be used for the internal network and 172.8.0.0/24 will be used to +route our traffic to the internet. + +.. image:: ./images/900px-Carp_setup_example.png + :scale: 100% + +When using CARP ( `FreeBSD handbook on CARP `__ ), all +fail-safe interfaces should have a dedicated ip address which will be +combined with one shared virtual ip address to communicate to both +networks. In the picture above the dashed lines are used to mark the +virtual addresses. + +The configuration file (xml) for both firewalls can be downloaded from +the wiki. + +----------- +Terminology +----------- + +There is some terminology involved in setting up a CARP cluster, which +we will explain briefly first: + +.. rubric:: CARP + :name: carp + +Common Address Redundancy Protocol uses IP protocol 112, is derived from +OpenBSD and uses multicast packets to signal it's neighbours about it's +status. Always make sure that each interface can receive carp packets. +Every virtual interface must have a unique Virtual Host ID (vhid), which +is shared across the physical machines. To determine which physical +machine has a higher priority, the advertised skew is used. A lower skew +means a higher score. (our master firewall uses 0). + + +.. rubric:: pfSync + :name: pfsync + +Together with CARP, we can use pfSync to replicate our firewalls state. +When failing over you need to make sure both machines know about all +connections to make the migration seamless. It's highly advisable to use +a dedicated interface for pfSync packets between the hosts, both for +security reasons (state injection) as for performance. + + +.. rubric:: XMLRPC sync + :name: xmlrpc-sync + +OPNsense includes a mechanism to keep the configuration of the backup +server in sync with the master. This mechanism is called xmlrpc sync and +can be found under System -> High Availability. + +----------------------------------------- +Setup interfaces & basic firewall rules +----------------------------------------- + +Our example uses three interfaces, which all have a rather basic setup. + +.. rubric:: Master + :name: master + + +Go to interfaces, make sure you have all three interfaces assigned and +setup the following addresses and subnets: + ++-----------------------+ +| LAN 192.168.1.10/24 | ++-----------------------+ +| WAN 172.18.0.101/24 | ++-----------------------+ +| PFSYNC 10.0.0.1 | ++-----------------------+ + +Next we need to make sure the appropriate protocols can be used on the +different interfaces, go to firewall -> rules and make sure both LAN and +WAN accept at least carp packets (see protocol selection). Because we're +connecting both firewalls using a direct cable connection, we will add a +single rule to accept all traffic on all protocols for that specific +interface. Another option is to only accept traffic to the GUI port and +pfSync protocol. + +.. rubric:: Backup + :name: backup + +The backup server needs it's own dedicated addresses, we will use these: + ++----------+-------------------+ +| LAN | 192.168.1.20/24 | ++----------+-------------------+ +| WAN | 172.18.0.102/24 | ++----------+-------------------+ +| PFSYNC | 10.0.0.2 | ++----------+-------------------+ + +Because we are going to synchronize firewall settings between both +hosts, we only need to make sure that the pfsync interface can accept +data from the master for the initial setup. Use the same rule as used +for the master on this interface. + +----------------- +Setup Virtual IPs +----------------- + +On the master node we are going to setup our Virtual IP addresses, which +will also be used for the backup node after synchronisation. Go to +Firewall -> Virtual IPs and add a new one with the following +characteristics: + ++-------------------------+------------------------------------+ +| Type | Carp | ++-------------------------+------------------------------------+ +| Interface | WAN | ++-------------------------+------------------------------------+ +| IP addresses | 172.18.0.100 / 24 | ++-------------------------+------------------------------------+ +| Virtual password | opnsense (the example uses this) | ++-------------------------+------------------------------------+ +| VHID Group | 1 | ++-------------------------+------------------------------------+ +| Advertising Frequency | Base 1 / Skew 0 | ++-------------------------+------------------------------------+ +| Description | VIP WAN | ++-------------------------+------------------------------------+ + +And another using the following: + ++-------------------------+------------------------------------+ +| Type | Carp | ++-------------------------+------------------------------------+ +| Interface | LAN | ++-------------------------+------------------------------------+ +| IP addresses | 192.168.1.1 / 24 | ++-------------------------+------------------------------------+ +| Virtual password | opnsense (the example uses this) | ++-------------------------+------------------------------------+ +| VHID Group | 3 | ++-------------------------+------------------------------------+ +| Advertising Frequency | Base 1 / Skew 0 | ++-------------------------+------------------------------------+ +| Description | VIP LAN | ++-------------------------+------------------------------------+ + +------------------ +Setup outbound NAT +------------------ + +When traffic is going out of the firewall it should also use the virtual +IP address to make a seamless migration possible. The default for +OPNsense is to use the interfaces IP address, which is in our case the +wrong one. + +Go to Firewall -> NAT and select outbound nat. Choose manual outbound +nat on this page and change the rules originating from the +192.168.1.0/24 network to use the CARP virtual interface (172.18.0.100). + +---------------------------- +(optional) Setup DHCP server +---------------------------- + +When using dhcp for the local area network, there are some things to +consider. All clients should use the virtual address in stead of the +physical address it's normally propagating. Next thing to consider is +there will be two servers active at the same time, which should know of +each others pools. If dns requests are also forwarded by OPNsense, make +sure the dhcp server sends the right ip address. These are settings used +in our example (on the master server): + ++--------------------+----------------+ +| DNS servers | 192.168.1.1 | ++--------------------+----------------+ +| Gateway | 192.168.1.1 | ++--------------------+----------------+ +| Failover peer IP | 192.168.1.20 | ++--------------------+----------------+ + +--------------------------------- +Setup HA sync (xmlrpc) and pfSync +--------------------------------- + +First we should enable pfSync using our dedicated interface using the +master firewall. Go to System -> High Availability, enable pfsync and +select the interface used for pfSync. Next setup the peer ip to the +other hosts address (10.0.0.2). + +Now we need to configure the settings we want to duplicating to the +backup server using the xmlrpc sync option. For our setup we will enable +the following: + ++---------------------------+ +| Synchronize rules | ++---------------------------+ +| Synchronize NAT | ++---------------------------+ +| Synchronize DHCPD | ++---------------------------+ +| Synchronize Virtual IPs | ++---------------------------+ + +-------------- +Finalize setup +-------------- + +Just to make sure all settings are properly applied, reboot both +firewalls before testing. + +------------- +Testing setup +------------- + +First go to Status -> Carp in the OPNsense webinterface and check if +both machines are properly initialized. + +To test our setup, we will connect a client to the local area network +and open a ssh connection to a host behind both firewalls. Now when +connected you should be able to look at the state table on both OPNsense +firewalls (Diagnostics -> States) and they should both display the same +connection. Next try to pull the network plug from the master firewall +and it should move over to the backup without loosing (or freezing) the +ssh connection. + +--------- +Resources +--------- + +#. Configuration for master server ( :download:`Carp_example_master.xml ` ) +#. Configuration for backup server ( :download:`Carp_example_backup.xml ` ) diff --git a/source/manual/how-tos/cellular.rst b/source/manual/how-tos/cellular.rst new file mode 100644 index 0000000..164d00a --- /dev/null +++ b/source/manual/how-tos/cellular.rst @@ -0,0 +1,87 @@ +=========================== +Configuring Cellular Modems +=========================== +OPNsense supports a wide range of USB and miniPCIe cellular modems that can be used +as primary internet (WAN) connection or as failover for a fixed/ethernet connection. + +With this guide we show you how to easily add a new modem and configure it to be +used as primary WAN connection. + +---------------------------- +Devices used for this How-to +---------------------------- +For this how-to we used a `Deciso Netboard A10 desktop appliance `__ +and a Huawei ME909u-521 miniPCIe cellular modem provided by `OSNet `__. + +.. Note:: + Support for the ME909u-521 will be added in OPNsense 16.1.18. + +---------------------------------------- +Step 1 - Configure Point to Point device +---------------------------------------- +Go to **Interfaces->Point-to-Point->Devices** and click on **Add** in the upper +right corner of the form. + +Fill in the form like this (Example is for Dutch Mobile 4G KPN Subscription): + +============================ ======================================================= + **Link Type** PPP + **Link interface(s)** /dev/cuaU0.0 ( HUAWEI Mobile Connect - Modem) + **Description** 4G Cellular Network + **Service Provider** Select Country, Provider & Plan for auto configuration + **Username** Leave Empty (for NL KPN) + **Password** Leave Empty (for NL KPN) + **Phone Number** \*99# (for NL KPN) + **Access Point Name (APN)** fastinternet (for NL KPN 4G) +============================ ======================================================= + +If you need to enter a PIN number then click on **Advanced Options** + +Click **Save** to apply the settings. + +.. image:: images/4g_configure_ppp.png + :scale: 100% + + +.. image:: images/ppp_celular_configured.png + :scale: 100% + +--------------------------------- +Step 2 - Assign the WAN interface +--------------------------------- +To assign the interface go to **Interfaces->Assignments** in our case we will make +this our primary internet connection and change the WAN assignment accordingly. + +To do so just change the **Network port** for **WAN** to **ppp0 (/dev/cuaU0.0) - 4G Cellular Network**. + +No click **Save** below the form. + +If everything went fine then your are all setup and the default gateway will be +the one of you cellular connection. + +.. image:: images/Interface_assignment_4g.png + :scale: 100% + +------------------------- +Step 3 - Trouble shooting +------------------------- +Ok, so it doesn't work as expected. +In that case, first look at the log of the cellular device's PPP connection, to do +so go to: **Interfaces->Point-to-Point->Log File**. Often you can see what went +wrong directly in the log. + +If you can't figure out what is wrong then a reboot to reinitialize the device can +sometimes help. + +.. Note:: + + Before booting your device it is best to make sure the SIM card is inserted correctly. + + +When the device seems to work properly then checkout if the interface was assigned +an IP address, go to **Interfaces->Overview** and click on the WAN interface to +see the details. + +You should see an IP address, Gateway IP and ISP DNS server(s). +If all is filled in then either your firewall is blocking the traffic or the +network connection is not working well. diff --git a/source/manual/how-tos/clamav.rst b/source/manual/how-tos/clamav.rst new file mode 100644 index 0000000..86f0791 --- /dev/null +++ b/source/manual/how-tos/clamav.rst @@ -0,0 +1,127 @@ +====== +ClamAV +====== + +.. Warning:: + Your machine needs at least 1.5 GB RAM. Otherwise the machine will run out of + memory and crash because of out of memory kills. Using a machine with at least + 2 GB RAM is recommended. + +.. Warning:: + There are some techniques to avoid detection and scanning using AV software and not + every malware is known by AV products. + Signature based AV software can decrease the risk of getting hit by a known malware + but it does never guarantee that your computers don't get infected. + It is **important** to teach the users how to handle files from the internet + and untrusted devices safely. Also plan a regular Backup of important files, make sure, + that ACLs are used correctly and apply patches asap to keep the attack surface and + damage as small as possible. + +.. Note:: + To make ClamAV working, you need to download signatures. + Please note that those files need to be fetched after a reboot again if they + are stored on a ram disk. + +------------ +Installation +------------ + +First of all, you have to install the ClamAV plugin (os-clamav) from the plugins view. + +.. image:: ../images/menu_plugins.png + + +After a page reload you will get a new menu entry under services for ClamAV. +Select it and you will get to the following screen: + +.. image:: images/clamav_settings.png + +--------------------- +Configuration Options +--------------------- + +:Enable clamd service: + Selecting this checkbox enables clamd so you can use it to scan files. +:Enable freshclam service: + Freshclam is a service to update your malware signatures. + If you use ClamAV, it is recommended to update the signatures on a regular basis. +:Enable TCP Port: + This checkbox needs to be checked, if you want to use clamd over the network or + for local services, which use a TCP connection. +:Maximum number of threads running: + Thread limit is used to avoid a denial of service of the daemon and your machine. + Usually a number next or equal to the number of cores would be good. +:Maximum number of queued items: + This is the maximum of files which can be in the queued for scanning. + The reason is the same as for the threads. +:Idle Timeout: + The connection will be dropped if it is inactive for this amount of time. + If the other socket endpoint is a machine, this value can be low but if you + plan to use it for develpoment reasons, you may set it to a higher value. +:Max directory recursion: + Limit the depth of the directory tree. + In the worst case there is a loop which causes the scanner to run endlessly and + this setting should prevent it. +:Follow directory symlinks: + If this is checked, clamav will follow directory symlinks which may lead to a loop. + If you want to check this, make sure the recursion limit is set to a useful value. +:Follow regular file symlinks: + If this is checked, clamav will follow symlinks to regular files. + This may expose information about the filesystem, the user should not have access to. +:Disable cache: + If you check this, the results are not cached. This is only useful in develpoment + environments as it slows down the response time. +:Scan portable executable: + Check this box, if you want to scan PE files. + If you are using PE-files (\*.exe, \*.dll etc.) files in your network, + checking this box is recommended. +:Scan executeable and linking format: + Check this box, if you want to scan ELF-files. + ELF is for example used on Linux based operating systems and on \*BSD. +:Detect broken executables: + This setting will mark an executable as broken if it does not match the spec. + A executable may be broken because of a download issue or manipulation. + In any case, there should not be any legit case to pass a broken executable. +:Scan OLE2: + If this is checked, OLE2 files (for example Microsoft Office files) will be analyzed. + Such files should be analyzed as they may contain macros which have been used to download + and install malware (usually ransomware). +:OLE2 block macros: + Check this box, if documents containing macros should be blocked. If you don't use macros and + you don't expect them from your business partners or friends, this setting is recommended. +:Scan PDF files: + If this checkbox is checked, PDF files will be scanned. + PDF files can carry other files or multimedia as well as javascript and fonts. + Scanning PDF files is recommended. +:Scan SWF: + If you check this box, Flash files will be scanned. + Flash is used to provide video players or interactive content. + Nowadays it should have been replaced by HTML5. +:Scan XMLDOCS: + Scan XML Documents +:Scan HWP3: + HWP seems to be a korean document format. If you don't use them, + it is better to block them in the proxy than scanning them. + If you have them in use, you should scan them. +:Decode mail files: + If you select this option, the sections of emails will be read and therefore + it will be possible to scan email attachments. + Mail attachments are important to scan as an attached file may contain malware. + For example, some malware campaigns used a JScript file which has been packed + in a ZIP file which was attached to an email. +:Scan HTML: + Scans HTML files which may have dangerous embedded JavaScript. +:Scan archives: + Scan files inside archives. + This is very important as archives can contain malware. + Please note that archive nesting is used to bypass scans, + so scanners detect such archives as dangerous at a specific recursion level. + Also keep in mind that zip bombs may be possible to DoS a scanner. +:Block encrypted archive: + Encrypted archives are usually used to transfer files encrypted which don't support encryption + on their own or the sender is not aware how to encrypt those files. + A tool like 7z can derive a key from a password given by the creator of the file, + which will be used to encrypt the compressed data. + The ClamAV cannot scan this data as it is missing the key/password. Some malware authors used + encrypted archives to avoid scanning and told the victim in the email text how to unpack it. + diff --git a/source/manual/how-tos/cloud_backup.rst b/source/manual/how-tos/cloud_backup.rst new file mode 100644 index 0000000..e5c6df3 --- /dev/null +++ b/source/manual/how-tos/cloud_backup.rst @@ -0,0 +1,118 @@ +========================== +Configuration Cloud Backup +========================== + +------------ +Google Drive +------------ + +**Google Drive** is a digital file storage and management service by the +information technology company Google. Amongst other features, like +collaborative editing of documents, spreadsheets, and presentations, it +allows signed up users with an account to store and share files in the +digital cloud. + +The OPNsense configuration can be stored as a backup file in XML format, +to your PC on an USB stick or remotely in the digital Google Drive +cloud. + +------------------- +Free online storage +------------------- + +Because Google officially offers a free storage of 15 GB and nearly +unlimited traffic, a remote backup of an OPNsense configuration file is +free of charge, the only thing you need is an account at google +(`Google Drive Signup `__) . + +-------- +Easy API +-------- + +An application programming interfaces (API) for Google Drive was +released in 2013. This API empowers third-party developers to easily +write apps for Google Drive. + +------------- +Remote backup +------------- +In OPNsense\ :sup:`1` you can **backup** your configuration directly and +automatically to **Google Drive**, using the new backup feature. Every +backup will be encrypted with the same algorithm used in the manual +backup so it's quite easy to restore to a new installed machine. + +After set-up, the backup feature will do first store of the OPNsense +config file and subsequently a daily new backup of changed config +content. + +---------------------- +Setup Google API usage +---------------------- + +First we need to have a project in the google developer console: + +- Go to https://console.developers.google.com/project +- Create a project and give it a name, you may leave it default it + doesn't really matter for this. +- Enable the Drive API + + - In the left menu APIs -> "Drive API" -> Enable + +- Open the project and start to create an api key + + - In the left menu : APIs & auth -> Credentials + - Click on the button "Create new Client ID" + - Choose "Service account", followed by "Create Client ID" + + - Download the key and save it (for your own use) + - Click "Generate new P12 key" and download the key (for your own + use, you need this one later) + - Copy Email Address, you need it later. + +.. rubric:: Create a Google Drive folder + :name: create-a-google-drive-folder + +Next thing is to create a folder in Google Drive and share it to the +"service user" you've just created. + +- Go to https://drive.google.com +- Choose "NEW" and the folder to create a new folder, the name doesn't + really matter (for example type OPNsense). +- right click the newly created folder and choose share + + - paste the email address from the service account and "send" + +- Now open the folder and copy the folder ID ( in the url, the last + piece after #/folders/, it's quite long) + +.. rubric:: Setup the account in OPNsense + :name: setup-the-account-in-opnsense + +Now we can put it all together, login to your OPNsense firewall and go +to the backup feature (default : https://192.168.1.1/diag_backup.php ) + +.. image:: ./images/600px-Google_Drive_Backup_screenshot.png + :scale: 100% + +On the bottom of the page are the options for the Google Drive backup, +enable the feature and fill in the parameters. Email address is acquired +in step 2, the key in step 1. Choose a strong password to protect your +data and fill in a number of backups you want to keep. + +When you click Setup/Test Google Drive, the firewall will automatically +save and test your settings and you will receive either an error +(connectivity issues) or a list of config files currently in the backup. + +The moment the feature is enabled, it will do a daily compare of the +last file in backup and the current configuration and creates a new +backup when something has changed. + +.. rubric:: References + :name: references + +- `Official website of Google Drive `__ + +.. rubric:: Notes + :name: notes + +:sup:`1` As of OPNsense version 1.15.8 .2 (25 March 2015) diff --git a/source/manual/how-tos/dynamicrouting_howto.rst b/source/manual/how-tos/dynamicrouting_howto.rst new file mode 100644 index 0000000..b9e4b51 --- /dev/null +++ b/source/manual/how-tos/dynamicrouting_howto.rst @@ -0,0 +1,78 @@ +======================= +Dynamic Routing: How To +======================= + +.. Note:: + To keep this tutorial short, a configuration is only added a single time. + For example, the configuration of Site A and Site B are identical beside one + octet in the IP addresses. + Also both routers have the same configuration except the Network address of the + uplink and the client network. + +--------- +Situation +--------- + +.. image:: images/dynamic_routes_howto.png + +We have two sites (Site A and Site B) which are connected via a layer 2 VPN. +Each site has two additional routers, +which are connected to the edge router and with each oder. +On those routers, the clients are attached. + +------------- +Configuration +------------- + +In this setup, OSPF is used. +All routers belong to the area 0.0.0.0 and no prefix lists are used. + +Core Router of Site A +--------------------- + +General Settings: + +========================= ============ +Setting Value +========================= ============ +Enable Checked +Advertise Default Gateway Checked +Passive Interfaces Empty +Route Redistribution Empty +========================= ============ + +Networks: + +============ ============ +Network Network Mask +============ ============ +192.168.0.0 30 +192.168.1.0 30 +192.168.1.4 30 +============ ============ + + +Left Floor Router of Site A +--------------------------- + +General Settings: + +========================= =========================== +Setting Value +========================= =========================== +Enable Checked +Advertise Default Gateway Unchecked +Passive Interfaces Interface name of 10.1.1.0 +Route Redistribution Empty +========================= =========================== + +Networks: + +============ ============ +Network Network Mask +============ ============ +10.1.1.0 24 +192.168.1.4 30 +192.168.1.8 30 +============ ============ + diff --git a/source/manual/how-tos/dynamicrouting_ospf.rst b/source/manual/how-tos/dynamicrouting_ospf.rst new file mode 100644 index 0000000..954f973 --- /dev/null +++ b/source/manual/how-tos/dynamicrouting_ospf.rst @@ -0,0 +1,128 @@ +====================================== +Dynamic Routing: Configuration: OSPFv2 +====================================== + +------- +General +------- + +.. Warning:: + Saving the settings will apply them and reload the daemon. This means you may lose the connection to your firewall for some seconds. + +.. image:: images/dynamic_routes_ospf_general.png + +Enable +------ + +Enables the OSPF routing daemon. +If this does not work, please check the settings of General. +Check this checkbox if you want to use OSPFv2 in your network. + +Passive Interfaces +------------------ + +Passive Interfaces are interfaces, +which exist in OSPFv2 but where no routing updates should be sent to. +These are usually the Interfaces, +where your clients are connected to and no router should exist. +You don‘t need to add interfaces here, where no network is specified. + +Route Redistribution +-------------------- + +Route Redistribution is used, +if you want to send information this router has learned via another protocol +or routes from kernel (OPNsense static routes). + +Advertise Default Gateway +------------------------- + +Advertise Default Gateway should be checked, +if this machine has a default gateway to the internet. +Always Advertise means, that this route should be also broadcasted, +if it is not available. Be careful with this option in HA setups. + +-------- +Networks +-------- + +.. image:: images/dynamic_routes_ospf_networks.png + +Networks gives you a brief overview of the configured networks. The dialog looks like this: + +.. image:: images/dynamic_routes_ospf_network_dialog.png + +Enabled +------- + +Enabled means that this Network is going to be used. +You should only disable networks if you plan to do some changes in your topology or some routes get broken. + +Network Address +--------------- + +The Network Address of a local interface on which OSPFv2 should be enabled. + +Network Mask +------------ + +A CIDR Mask for the Network Address. +For example, if your LAN IP is 192.168.0.1/24, the network address is 192.168.0.0 and Network Mask is 24. + +Area +---- + +The area describes which routers belong to the same group (autonomous system). This value is a 32 bit integer, which is entered in dotted decimal notation (like an IPv4 address is usually written). + +Prefix-List in and Out +---------------------- + +Only used for advanced route filtering using access lists. + +---------- +Interfaces +---------- + +This tab shows an overview of the configured interfaces: + +.. image:: images/dynamic_routes_ospf_interfaces.png + +.. Note:: + Changes in this view do *NOT* apply the settings. + +If you add or edit an entry, you will get this dialog: + +.. image:: images/dynamic_routes_ospf_interface_dialog.png + +Interface +--------- +Choose a single interface, where this interface settings apply to. + +Authentication Type and Authentication Key +------------------------------------------ + +This values can be set, +but they are not used as there is no area configuration which would make use of them. +You may want to set the password here if you add a custom area setting via vtysh. + +Cost +---- + +A numeric value to set the cost on an interface. +The cost is used to calculate the route to the target. +A bigger value here means, the route is less likely used. + +Hello and Dead Interval +----------------------- + +Hello interval is the interval in which hello packets (detection of other OSPF routers) are sent out. +A bigger value means sower detection but less load on the interface. +Dead Interval is the time window, in which the router has to receive a hello packet from another router. +If it does not, it is removed. + +Priority +-------- + +This field specifies the router priority which means a router with a good priority is more probably the designated router. +Network type usually does not need to be set. + diff --git a/source/manual/how-tos/dynamicrouting_rip.rst b/source/manual/how-tos/dynamicrouting_rip.rst new file mode 100644 index 0000000..a0f0fb4 --- /dev/null +++ b/source/manual/how-tos/dynamicrouting_rip.rst @@ -0,0 +1,45 @@ +=================================== +Dynamic Routing: Configuration: RIP +=================================== + +.. Note:: + RIP should not be used in larger networks due to the limited hop count. Cosider using OSPF in such cases. + +.. Warning:: + Saving the settings will apply them and reload the daemon. This means you may lose the connection to your firewall for some seconds. + +RIP is a well known distance vector protocol. +It may be preferred to be used in smaller networks, +where the topology is not too complex and the possibillity of loops is small. + +.. image:: images/dynamic_routes_rip.png + +Enable +------ + +enables the routing protocol if the support of routing protocols is enabled in general. If you check this box, RIP will be enabled. + +Version +------- + +Enter 1 or 2 here. 1 is “classful” which means, that this routing protocol does not support variable length routing. +If you choose version 2, variable length subnet masks are supported. In most cases, you want to choose version 2 here. + +Passive Interfaces +------------------ + +Interfaces, which are known by the routing daemon, but no updates are sent. +You should add interfaces with networks here, which do not have any other routers. + +Route Redistribution +-------------------- + +Also send routes from other sources to neighbors (if desired). + +Networks +-------- + +Add the networks here which should be known by the router and which are subject to be sent to the neighbors. +Passive interfaces will not be used to look for another router. + + diff --git a/source/manual/how-tos/dynamicrouting_zebra.rst b/source/manual/how-tos/dynamicrouting_zebra.rst new file mode 100644 index 0000000..bfc478a --- /dev/null +++ b/source/manual/how-tos/dynamicrouting_zebra.rst @@ -0,0 +1,40 @@ +===================================== +Dynamic Routing: Configuration: Zebra +===================================== + +Zebra is the core of quagga and needs to be enabled in any case. It can be enabled in the general view: + +.. Note:: + If this service is disabled, all other routing protocols are disabled too. + +.. Warning:: + Saving the settings will apply them and reload the daemon. This means you may lose the connection to your firewall for some seconds. + +.. image:: images/dynamic_routes_zebra.png + +------ +Enable +------ + +Checking „Enable“ means that zebra and all other enabled routing daemons will be started. +If you disable this checkbox, Quagga will be completely disabled. + +---------------------------------- +Create a logfile and Logfile level +---------------------------------- + +If you check this checkbox, messages with a higher or equal severity will be written +to a log file on this device. You can view this log file under diagnostics if you want +to debug errors in your network. + +-------------------------------------------- +Send log messages to syslog and Syslog level +-------------------------------------------- + +Settings are the same as for the log file but for syslog. +This is useful if you use an external logging server. + + + + + diff --git a/source/manual/how-tos/edrop.rst b/source/manual/how-tos/edrop.rst new file mode 100644 index 0000000..ef720c0 --- /dev/null +++ b/source/manual/how-tos/edrop.rst @@ -0,0 +1,137 @@ +========================== +Configure Spamhaus (E)DROP +========================== +The Spamhaus Don't Route Or Peer Lists + DROP (Don't Route Or Peer) and EDROP are advisory "drop all traffic" lists, + consisting of netblocks that are "hijacked" or leased by professional spam or + cyber-crime operations (used for dissemination of malware, trojan downloaders, + botnet controllers). The DROP and EDROP lists are a tiny subset of the SBL, + designed for use by firewalls and routing equipment to filter out the malicious + traffic from these netblocks. + + *Source :* https://www.spamhaus.org/drop/ + +For this how to we will use the Alias feature and a firewall block rule. +The lists for this example are located here: + + * `DROP list `__ + * `EDROP list `__ + +------------------------------------- +Step 1 - Create an Alias for Spamhaus +------------------------------------- +Go to **Firewall->Aliases->All** and press the **Add a new alias** button in the +top right corner of the form. + +Enter the following data: + ++-----------------+-----------------------------------------+-----------------------------+ +| **Name** | spamhaus_drop | *Name of our alias* | ++-----------------+-----------------------------------------+-----------------------------+ +| **Description** | Spamhaus DROP | *Freely chosen description* | ++-----------------+-----------------------------------------+-----------------------------+ +| **Type** | URL Table (IPs) | *URL type* | ++-----------------+-----------------------------------------+-----------------------------+ +| **Host(s)** | https://www.spamhaus.org/drop/drop.txt | *Don't Route Or Peer List* | ++-----------------+-----------------------------------------+-----------------------------+ + +Set the update frequency to 1 for each day. + +Press **Save** and then **Add a new alias**. + ++-----------------+-----------------------------------------+-------------------------------------+ +| **Name** | spamhaus_edrop | *Name of our alias* | ++-----------------+-----------------------------------------+-------------------------------------+ +| **Description** | Spamhaus EDROP | *Freely chosen description* | ++-----------------+-----------------------------------------+-------------------------------------+ +| **Type** | URL Table (IPs) | *URL type* | ++-----------------+-----------------------------------------+-------------------------------------+ +| **Host(s)** | https://www.spamhaus.org/drop/edrop.txt | *Extended Don't Route Or Peer List* | ++-----------------+-----------------------------------------+-------------------------------------+ + +Set the update frequency to 1 for each day. +Press **Save** and then **Apply changes**. + +.. image:: images/spamhaus_drop_edrop.png + :scale: 100% + +--------------------------------------- +Step 2 - Firewall Rules Inbound Traffic +--------------------------------------- +We will block incoming connections and outgoing connections for the drop and edrop lists. +To do so we will start with inbound traffic on the WAN interface. +Go to **Firewall->Rules** Select the **WAN** tab and press the **+** icon in the +lower right corner. + + +Enter the following configuration and leave all other parameters on default values: + +=================== ============== ============================================= + **Action** Block *Choose block to drop the incoming traffic* + **Interface** WAN *Should be the default value* + **TCP/IP Version** IPv4 *For our example we use IPv4* + **Source** spamhaus_drop *Our alias for the DROP list* + **Category** Spamhaus *Freely chosen Category* + **Description** Block DROP *Freely chosen description* +=================== ============== ============================================= + +**Save** and repeat this action for the EDROP list: + +=================== =============== ============================================= + **Action** Block *Choose block to drop the incoming traffic* + **Interface** WAN *Should be the default value* + **TCP/IP Version** IPv4 *For our example we use IPv4* + **Source** spamhaus_edrop *Our alias for the DROP list* + **Category** Spamhaus *Freely chosen Category* + **Description** Block EDROP *Freely chosen description* +=================== =============== ============================================= + +.. image:: images/spamhaus_wan_rules.png + :scale: 100% + + +**Save** + +---------------------------------------- +Step 3 - Firewall Rules Outbound Traffic +---------------------------------------- + +Now do the same for outbound traffic traffic on the LAN interface. +Go to **Firewall->Rules** Select the **LAN** tab and press the **+** icon in the +lower right corner. + +=================== ============== ============================================= + **Action** Block *Choose block to drop the incoming traffic* + **Interface** LAN *Should be the default value* + **TCP/IP Version** IPv4 *For our example we use IPv4* + **Destination** spamhaus_drop *Our alias for the DROP list* + **Category** Spamhaus *Freely chosen Category* + **Description** Block DROP *Freely chosen description* +=================== ============== ============================================= + +**Save** and add the EDROP list: + +=================== =============== ============================================= + **Action** Block *Choose block to drop the incoming traffic* + **Interface** LAN *Should be the default value* + **TCP/IP Version** IPv4 *For our example we use IPv4* + **Destination** spamhaus_edrop *Our alias for the DROP list* + **Category** Spamhaus *Freely chosen Category* + **Description** Block EDROP *Freely chosen description* +=================== =============== ============================================= + +**Save** and **Apply changes** + +.. image:: images/spamhaus_lan.png + :scale: 100% + +**DONE** + +--------------- +Check pf Tables +--------------- +To list the ip addresses that are currently in the DROP and EDROP lists go to +**Firewall->Diagnostics->pfTables** and select the list you want to see: + +.. image:: images/spamhaus_pftable.png + :scale: 100% diff --git a/source/manual/how-tos/freeradius.rst b/source/manual/how-tos/freeradius.rst new file mode 100644 index 0000000..84b3f74 --- /dev/null +++ b/source/manual/how-tos/freeradius.rst @@ -0,0 +1,99 @@ +========== +FreeRADIUS +========== + +------------ +Installation +------------ + +First of all, you have to install the FreeRADIUS plugin (os-freeradius) from the plugins view. + +.. image:: ../images/menu_plugins.png + + +After a page reload you will get a new menu entry under services for FreeRADIUS. +Select and a submenu will pop up with the entries **General, User** and **Client**: + +---------------- +General Settings +---------------- + +.. image:: images/freeradius_general.png + +:Enable: + To enable the service, you have to check this box. +:Enable VLAN assignment: + If you check this box, the RADIUS packets will have some unencrypted tags + for the network device to allow dynamic VLAN assignment. + In this case, the authentication is still encrypted but some metadata will be readable. + You need to enable this checkbox, if you want to set a VLAN on a switchport, + which depends on the authenticated user. + +----- +Users +----- + +.. image:: images/freeradius_users.png + +A user is an entity, which is meant to authenticate against the RADIUS server +(computer or human). + +To create a user, click the `+` button. + +.. image:: images/freeradius_edit_user.png + +:Enabled: + This user will be written to disk and can be used. + You can toggle this value to temporary disable users. +:Username: + The name which the user will use to authenticate. +:Password: + The password the user will use to authenticate. +:Description: + Internal information for you to use to find the user. + This setting can be used to add some infos like a department. +:IP Address and Subnetmask: + If you want to use FreeRADIUS for point to point links, + you can add an IP address here which will be assigned to the client. + The same is valid for Subnetmask. +:VLAN ID: + A layer 2 device like a switch, which supports 802.1X authentication + can use this Field to dynamically assign an VLAN number to a switchport + based on the authentication result. This is especially useful if you + are having moving users (for example if an employee can attach his + computer to a docking station at a desk and the switch will assign + the VLAN ID of the employee to the switchport. + Be aware that the Layer 2 device has to be able to read this information, + which means that **you have to enable corresponding option in General** + +------- +Clients +------- + +.. image:: images/freeradius_clients.png + +A client in RADIUS is a intermediate device / network device like a VPN +gateway, a switch or an access point. + +To create a new client, click the `+` button: + +.. image:: images/freeradius_edit_client.png + + +:Enabled: + This client will be written to disk and can be used. + You can toggle this value to temporary disable clients. +:Name: + A name used for the client. +:Secret: + The secret is used to provide a trust relationship between the + client and the FreeRADIUS server. This password should be strong + as you only have to type it twice (once in the FreeRADIUS configuration + and once in your client configuration) or even copy it. + If the passwords do not match, FreeRADIUS will reject all attempts to + authenticate. +:IP Address or Network with CIDR: + This is the IP address of the Client (not the authenticating device). + For example this could be the IP address of your switch. + + diff --git a/source/manual/how-tos/fwcategory.rst b/source/manual/how-tos/fwcategory.rst new file mode 100644 index 0000000..74d003b --- /dev/null +++ b/source/manual/how-tos/fwcategory.rst @@ -0,0 +1,62 @@ +============================= +Organize PF Rules by Category +============================= +OPNsense firewall rules can be organized per category. +These categories can be freely chosen or selected. + +.. Note:: + + This feature was added in version 16.1.1. Always keep your system up to date. + +--------------------------- +Adding a category to a rule +--------------------------- +To add a category to a rule, open or create a new rule and scroll to **Category**. +Then just add you category, if this is the first rule with a category no selection +options will be visible. + +.. image:: images/Rule_Category.png + :scale: 100% + +--------------------------------- +Firewall Rules Filter by category +--------------------------------- +Only when there are rules with a defined category, the **Filter by category** +becomes visible at the bottom of the table. + +If you click it is will look like this: + +.. image:: images/Filter_by_Category.png + :scale: 100% + +If you have a large number of categories, then just start typing and in search +box to make a quick selection. + +---------------- +Before Selection +---------------- +Take a look at this simple rule set before selecting our "My IP's" category. + +.. image:: images/Rules_Full.png + :scale: 100% + +-------------------- + And after selection +-------------------- +Now when selecting our test category it will look like this: + +.. image:: images/Filter_Category_Result.png + :scale: 100% + +That is all there is to it to organize your rules without messing anything up. + +------------ +Multi Select +------------ +In a later release of OPNsense 16.1 multi selection has been added. +This features makes it possible to select rules from more than one category. + +Example: + +.. image:: images/fw_category_multiselect.png + :scale: 100% diff --git a/source/manual/how-tos/guestnet.rst b/source/manual/how-tos/guestnet.rst new file mode 100644 index 0000000..1e3b2e0 --- /dev/null +++ b/source/manual/how-tos/guestnet.rst @@ -0,0 +1,604 @@ +===================== +Setup a Guest Network +===================== +This how to will explain how to setup a guest network using the captive portal. +Guest Networks are widely used to allow guests controlled internet access at +hotels, RV Parks or businesses. + +.. image:: images/opnsense_hotspot_controller.png + :scale: 100% + +.. Note:: + For the example we expect the GUESTNET interface to be connected with your + actual guest network switch or access point. This tutorial does not explain + how to setup a wireless network. + +---------- +Businesses +---------- +Businesses usually want to share internet access with their guest and show them +a landing page with a welcome message and some usage guidelines (policy). At the +same time it is important to make sure guests won't be able to access the company's +local network and limit the maximum internet usage. + +------------------- +Hotels and RV Parks +------------------- +Hotels and RV parks usually utilize a captive portal to allow guests (paid) access +to internet for a limited duration. Guests need to login using a voucher they can +either buy or obtain for free at the reception. OPNsense has build-in support for +vouchers and can easily create them on the fly. With this example we will show +you how to setup the Guest Network for this purpose and setup a reception account +for creating new vouchers. + +-------- +Advanced +-------- +The Captive portal can also be combined with the category based web filtering of +the proxy. This tutorial will explain how to combine both features. + +------------- +Prerequisites +------------- +We will start configuration with a fresh OPNsense install, updated to the latest +patch level (16.1.5_1 in our example). You will need a system with a minimum of +3 ports (LAN/WAN/GUESTNET) for this tutorial. + +------------ +Good to know +------------ +As the Hotel/RV Parks setup is almost identical to the business setup we will start +with that and after finishing add/change the specifics to match the Hotel Guest setup. + +---------------------------- +Step 1 - Configure Interface +---------------------------- +For the Guest Network we will add a new interface. +Go to **Interfaces->Assignments** And use the **+** to add a new interface. +Press **Save**. The new interface will be called **OPT1**, click on [OPT1] in the +left menu to change its settings. + + +Select **Enable Interface** and fill in the following data for our example: + +============================== ================= ============================================== + **Description** GUESTNET *A descriptive name for the interface* + **Block Private networks** unselected + **Block bogon networks** unselected + **IPv4 Configuration Type** Static IPv4 *Set a static IPv4 address for the example* + **IPv6 configuration Type** None + **MAC address** (Leave Blank) + **MTU** (Leave Blank) + **MSS** (Leave Blank) + **Speed and duplex** Default *You may also select the speed when known* + **Static IPv4 address** 192.168.200.1/24 *We will use this segment for our guests* + **IPv4 Upstream Gateway** None +============================== ================= ============================================== + +Press **Save** and then **Apply changes**. + +------------------------------ +Step 2 - Configure DHCP Server +------------------------------ +Go to **Services->DHCP->Server** and click on the tab **GUESTNET**. + +Fill in the following to setup the DHCP server for our guest net (leave everything + else on its default setting): + + +================ ==================================== ======================================= + **Enable** Checked *Enable the DCHP server on GUESTNET* + **Range** 192.168.200.100 to 192.168.200.200 *Serve ip's from this range* + **DNS servers** 192.168.200.1 *Supply a DNS with the lease* + **Gateway** 192.168.200.1 *Supply a gateway with the lease* +================ ==================================== ======================================= + +Click **Save**. + +--------------------------- +Step 3 - Add Firewall Rules +--------------------------- +Go to **Firewall->Rules** to add a new rule. + +Now add the following rules (in order of prevalence): + +Allow DNS +--------- +Allow the guests access to the DNS forwarder. +Rule content (leave all other options default): + +============================ ===================== ===================================== + **Action** Pass *Allow this traffic* + **Interface** GUESTNET *The GuestNet Interface* + **Protocol** TCP/UDP + **Source** GUESTNET net + **Destination** GUESTNET address + **Destination port range** DNS/DNS *from DNS to DNS* + **Category** GuestNet Basic Rules *Category used for grouping rules* + **Description** Allow DNS +============================ ===================== ===================================== + +Click **Save**. + + +Allow Captive Portal Login +-------------------------- + +============================ ============================ ===================================== + **Action** Pass *Allow this traffic* + **Interface** GUESTNET *The GuestNet Interface* + **Protocol** TCP + **Source** GUESTNET net + **Destination** GUESTNET address + **Destination port range** 8000/10000 *(other) used for the cp zones* + **Category** GuestNet Basic Rules *Category used for grouping rules* + **Description** Allow Captive Portal Login +============================ ============================ ===================================== + +Click **Save**. + + +Block Local Networks +-------------------- + +============================ ============================ ===================================== + **Action** Block *Block this traffic* + **Interface** GUESTNET *The GuestNet Interface* + **Protocol** any + **Source** GUESTNET net + **Destination** LAN net + **Category** GuestNet Basic Rules *Category used for grouping rules* + **Description** Block Local Networks +============================ ============================ ===================================== + +Click **Save**. + +============================ ============================ ===================================== + **Action** Block *Block this traffic* + **Interface** GUESTNET *The GuestNet Interface* + **Protocol** any + **Source** GUESTNET net + **Destination** GUESTNET address + **Category** GuestNet Basic Rules *Category used for grouping rules* + **Description** Block Firewall Access +============================ ============================ ===================================== + +Click **Save**. + +.. Note:: + These rules are used to block access to our local LAN network and firewall access + from the Guests. If you have multiple local networks then you need to block + each of them with multiple rules or use a bigger subnet to cover them all. + + +Allow Guest Networks +-------------------- + +============================ ===================== ===================================== + **Action** Pass *Allow this traffic* + **Interface** GUESTNET *The GuestNet Interface* + **Protocol** any + **Source** GUESTNET net + **Destination** any + **Destination port range** any + **Category** GuestNet Basic Rules *Category used for grouping rules* + **Description** Allow Guest Network +============================ ===================== ===================================== + +Click **Save** and then **Apply changes** + +Your rules should look similar to the screenshot below: + +.. image:: images/guestnet_fwrules.png + :scale: 100% + + +------------------------------ +Step 4 - Create Captive Portal +------------------------------ +Go to **Services->Captive Portal->Administration** + +To add a new Zone press the **+** in the lower right corner of the form. + +.. Note:: + When using multiple interfaces with the captive portal then each interface can + have its own zone or multiple interfaces can share a zone. + +For the *Business* setup we will start with the following settings: + +============================ ================ ========================================= + **Enabled** Checked + **Interfaces** GUESTNET *Remove the default and add GUESTNET* + **Authenticate using** (blank) *Remove any default setting* + **Idle timeout** 0 *Disable Idle Timeout* + **Hard timeout** 0 *No hard timeout* + **Concurrent user logins** Unchecked *A user may only login once* + **SSL certificate** none *Use plain http* + **Hostname** (leave blank) *Used for redirecting login page* + **Allowed addresses** (leave blank) + **Custom template** none *Use default template* + **Description** Guest Network *Choose a description for the zone* +============================ ================ ========================================= + +**Save** and the **Apply** + +------------------------ +Step 5 - Create Template +------------------------ +The template feature is one of the most powerful features of OPNsense's Captive +Portal solution and it's very easy to work with. + +Lets create a custom landing page, to do so click on the tab **Templates** and +click on the download icon in the lower right corner ( |download| ). + +.. image:: images/template_download.png + :scale: 100% + +Now download the default template, we will use this to create our own. +Unpack the template zip file, you should have something similar to this: + +.. image:: images/template_filelisting.png + :scale: 100% + +Most files of the template can be modified, but some are default and may not be +changes. Upon upload any changes to the files listed in **exclude.list** will be +ignored. Currently these include the bootstrap java scripting and some fonts. + +With the captive portal enabled the default screen looks like: + +.. image:: images/default_login_no_authenticator.png + :scale: 100% + +Lets change this default with a new logo and a welcome message, to this: + +.. image:: images/mycompany_login.png + +To do so use your favourite editor and open the **index.html** file to make the +changes. + +Lets make the following changes to the template: + +#. Change the logo to **company-logo.png** +#. Remove the navigation bar on the top +#. Remove the height and width from the **** tag +#. Add a welcome text +#. Make a link to the company website + +Find the following part: + +.. code-block:: guess + +

+ +
+ +And change to: + +.. code-block:: guess + +
+
+ + + +

Welcome to My Company Guest Network.

+

Feel free to use the guest network for profesional usage

+

See our website for more details: My Company

+
+
+ +Copy the company logo to the image directory. +Now zip the template directory and upload the new template by pressing the **+** +on the Template tab. + +:download:`Download the example Template (full) ` + +Enter a **Template Name**, for this example we use **Company**. +Hit Upload ( |upload| ) + +.. |download| image:: images/btn_download.png + :scale: 100% + +.. |upload| image:: images/btn_upload.png + :scale: 100% + +To enable the captive portal on the GUESTNET interface just click on **Apply**. + +------------------------------- +Step 6 - Limit Guests Bandwidth +------------------------------- +For our example we will reserve 10Mbps down and 1Mbps Up for the Guest Network's +Internet Access. This bandwidth will be shared evenly between connected clients. + +.. Note:: + With sharing evenly we mean that if 10 users at the same time try to use + as much bandwidth as possible then everyone gets 1/10th. So in our example + that would be 1Mbps down stream (download). It is also possible to limit + the traffic per user see also :doc:`shaper` + +Go to: **Firewall->Traffic Shaper->Settings**. + +Create a pipe for the Download by pressing the **+** in the lower right corner of +the form and enter the following details: + +====================== =================== + **Enabled** Checked + **bandwidth** 10 + **bandwidth Metric** Mbit/s + **mask** Destination + **Description** pipe_10Mbps_down +====================== =================== + +Click on **Save changes**. +And add another pipe for the upload traffic. + +====================== =================== + **Enabled** Checked + **bandwidth** 1 + **bandwidth Metric** Mbit/s + **mask** Destination + **Description** pipe_1Mbps_up +====================== =================== + +Click on **Save changes**. + + +Create the traffic shaper rules.Click on the tab **Rules** and press the **+** +to do so. + +First toggle the advanced mode (upper left corner of the form) and then fill in +the following details (leave everything not specified on defaults): + +================= ================================== + **sequence** (leave on default) + **interface** WAN + **interface 2** GUESTNET + **direction** in + **target** pipe_10Mbps_down + **description** Limit Guests download to 10Mbps +================= ================================== + +Click **Save changes**. + +================= ================================== + **sequence** (leave on default) + **interface** WAN + **interface 2** GUESTNET + **direction** out + **target** pipe_1Mbps_up + **description** Limit Guests upload to 1Mbps +================= ================================== + +Click **Save changes**. + +Now click on **Apply** to apply the changes. + +------------------------------- +Step 7 - Test Business GuestNet +------------------------------- +Connect your PC or laptop to the Guest Network and start your favourite browser. +Enter an address to browse to and you will be presented with the Login form we +created with the template in the previous step. Click on login and start browsing. + +To test your traffic shaper go to a speed test site such as http://www.speedtest.net/ +After testing your result should be similar to this (if your internet connection +has sufficient bandwidth). + + .. image:: images/cp-traffic-shaping.png + :scale: 100% + +.. Note:: + Keep in mind we have only one connected client in this test, so all reserved + bandwidth will be available for our client. + +------------------- +Royal Hotel Example +------------------- +From this point we will implement the Hotel/RV Park solution. You need to follow +step 1-7 first and choose the template you like to use for your guests. + +This example will be for our "Royal Hotel". + +--------------------------- +Step 8 - Add Voucher Server +--------------------------- +To add a Voucher Server go to: **System->Access->Servers** and click on +**Add server** in the top right corner of the screen. + +Fill in: + +======================= =========== ===================================== + **Descriptive name** Vouchers *The name for your voucher server* + **Type** Voucher +======================= =========== ===================================== + +Click on **Save**. + +------------------------ +Step 9 - Create Vouchers +------------------------ +Go back to the Captive portal and select Vouchers (**Services->Captive Portal->Vouchers**). +Click on **Create Vouchers** in the lower right corner of the form. + +Lets create 1 Day vouchers for our guests: + +.. image:: images/create_vouchers.png + :scale: 100% + + +Enter the Validity (1 day), the number of Vouchers and a Groupname (Wifi day pass f.i.). +For the example we create 10 vouchers. Click on **Generate**. + +A file will be generated called **wifi day pass.csv**. +The content of this file looks like this: + +.. code-block:: guess + + username,password,vouchergroup,validity + "IgJw@Pqf","MLi+Sb7Ak#","Wifi day pass","86400" + "++?f[@i[","!m*)e(@;F,","Wifi day pass","86400" + "bbtK9mBk","f/jCDL3:)b","Wifi day pass","86400" + "iD%L[jLJ","I#FoZ#g!AY","Wifi day pass","86400" + "+4bA\E[I","CNavt@0ck+","Wifi day pass","86400" + "+,fg/\Sv","#22iIL-iQA","Wifi day pass","86400" + ":;Pc\N#s","Y\HuG9vAN$","Wifi day pass","86400" + "00nLb=0Q","0*C_\_Nb_x","Wifi day pass","86400" + "PA$J0YHF","kp!q%9;m)g","Wifi day pass","86400" + "a,mCxbya","LcnCb#g/di","Wifi day pass","86400" + +The content are: + +=================== ======================================================== + **username** *Username the guest needs to login with* + **password** *Password the guest needs to login with* + **vouchergroup** *The name of the group you created* + **validity** *The time the voucher will be valid in seconds* +=================== ======================================================== + +.. Warning:: + + For security reasons the plain text password for the vouchers are NOT stored + on the firewall. + +This file can be used for creating nice guest vouchers (on paper) by just merging +the cvs data with word, open office or any other dtp/text editor. + +Create something like this: + +.. image:: images/cp_royalhotel_voucher.png + :scale: 100% + +You can select a database to and remove it entirely. This way you can +create a voucher database for the arrival date of guest per guest group +(week, midweek, weekend, etc.) and delete the full database when the guests have +left. + +.. Note:: + When a voucher is activated the time will be used regardless of the user being + logged in or out. For a "used time" solution use a Radius server look at + :doc:`accounting` + + +-------------------------------- +Step 10 - Voucher Authentication +-------------------------------- +Enable the voucher authentication by changing the zone settings. +Go to the tab **Zones** and select the Guest Network by clicking on the pencil icon +right next to it. + +Change **Authenticate using** from an empty field to **Vouchers**. + +When done click **Save changes** and the **Apply** to apply the new settings. + +Now users will see the login form as part of your template: + +.. image:: images/cp_voucher_login.png + :scale: 100% + +-------------- +Check Sessions +-------------- +To check the active sessions go to **Services->Captive Portal->Sessions** +Our current session looks like this: + +.. image:: images/cp_active_sessions.png + :scale: 100% + +You can drop an active session by clicking on the trashcan. + +.. Note:: + Notice the selection box at the upper right corner, with this you can select + the right zone when you have configured more than one. + + +-------------------- +Check Voucher Status +-------------------- +You can check the validity and active status of a voucher by going to the voucher +page of the captive portal (**Services->Captive Protal->Vouchers**) and select +the correct database (Wifi day pass in our example). + +.. image:: images/cp_active_vouchers.png + :scale: 100% + +.. Note:: + The state valid means it is activated but still valid. + + + + +------------------------ +Advanced - Session popup +------------------------ +Lets create a Session Popup so user can see some details about there session and +Logout. For this feature we will use OPNsense's build-in api calls. + +In particular we will use the following api call (for zone id 0): + +.. code-block:: guess + + /api/captiveportal/access/status/0/ + +The response on this api call looks like this (for an active session): + +.. code-block:: json + + {"userName":"IgJw@Pqf", + "macAddress":"10:dd:b1:bc:75:46", + "acc_session_timeout":14095, + "authenticated_via":"Vouchers", + "packets_out":2834, + "bytes_in":512869, + "last_accessed":1457527526, + "zoneid":0, + "sessionId":"npd5bd6SIVQeMfIbWBdong=="," + startTime":1457526930.1719, + "bytes_out":1322351, + "ipAddress":"192.168.200.100", + "packets_in":3181, + "clientState":"AUTHORIZED"} + +It would go a bit to far to explain standard html and java scripting used for +our simple popup, but a full demo template can be downloaded: + +:download:`Download the example Template (with popup) ` + +The demo includes a new file called **session_popup.html** with all the logic to +show the time left on the voucher and a logout button. As well as a simple update +to our index.html page to call the popup on a successful login. The latter looks +like this (shown with a bit of context): + +.. code-block:: javascript + + // redirect on successful login + if (data['clientState'] == 'AUTHORIZED') { + window.open("session_popup.html","Session Status & Logout","width=400, height=400"); + +.. image:: images/captiveportal_popup.png + :scale: 100% + +----------------------------- +Advanced - CLI Session Status +----------------------------- +OPNsense has a very powerful CLI that is particularly useful for debugging purposes. +For this example we will use the cli to list the status off all active sessions. + +Type the following on the cli prompt to do so (for zone id 0): + +.. code-block:: guess + + configctl captiveportal list_clients 0 + + +The output will be something similar to this: + +.. image:: images/cli_list_captiveportalsessions.png + :scale: 100% diff --git a/source/manual/how-tos/haproxy.rst b/source/manual/how-tos/haproxy.rst new file mode 100644 index 0000000..46bccca --- /dev/null +++ b/source/manual/how-tos/haproxy.rst @@ -0,0 +1,201 @@ +======= +HAProxy +======= + +------------ +Installation +------------ + +First of all, you have to install the HAProxy plugin (os-haproxy) from the +plugins view. + +.. image:: ../images/menu_plugins.png + +------------------------------------- +First Step: Configure Backend Servers +------------------------------------- + +.. image:: images/haproxy_servers.png + +On the "Servers" page, click `+` to open a dialog to create a new server. +A server consist of a name, IP and port. +Create an entry for every Server you want to load balance. + +.. image:: images/haproxy_edit_server.png + +For a HTTP Backend, configure like this: + +========================== =========================== +**Name** Name of this server +**Description** Keep it empty +**FQDN or IP** Enter the IP of your Server +**Port** Port of the Server +**SSL** Keep the default (disabled) +**Verify SSL Certificate** Keep the default (checked) +**SSL Verify CA** Keep the default (empty) +========================== =========================== + +-------------------------------- +Second Step: Configure a Backend +-------------------------------- + +Now, as we have the backend services, +we can build a backend by combining them to groups of +servers, which will serve the same service. +For example if you are hosting a Webservice and want to +scale horizontally, every server in the cluster will be +a "Server", but they will be combined to a so called +"Backend", so HAProxy can load balance between them. + +To create a new Backend, click the `+`. + + +.. image:: images/haproxy_backends.png + +And fill out the form: + +.. image:: images/haproxy_edit_backend.png + +.. Note:: + The "Balancing Algorithm" field is important to care about as many + web applications depend on a state. + For example, if your web application stores session data on a local + disk, you may get some trouble when using an algorithm like Round + Robin. In such a case, the request of the same client always needs + to be sent to the same backend servers. + For example by default PHP stores session data in files while Ruby + on Rails stores session information in a cookie by default. + Please look up your web framework documentation for information how + this is handled. Consider writeing files as problematic as well if + there is no shared storage. + +======================= =============================================== +**Enabled** Enable the Backend (checked) +**Name** Enter a name for the Backend +**Description** Enter an optional description +**Mode** Select the mode HTTP as this is an HTTP backend +**Balancing Algorithm** Select an load balancing algorithm +**Servers** Select the previously configured servers +======================= =============================================== + +---------------------------- +Third Step: Configure an ACL +---------------------------- + +In this step an ACL will has to be created which is later used to decide +which traffic from a frontend belongs to which backend. + +To create a new ACL, you have to create one by clicking the `+` button: + +.. image:: images/haproxy_acls.png + +In the open modal dialog, the following form will show up: + +.. image:: images/haproxy_edit_acl.png + +==================== ================================================ +**Name** Choose a name for this ACL +**Description** Keep it empty or choose one for your information +**Expression** Select "Host contains" +**Negate condition** Keep it unchecked +**Value** Enter the (partial) hostname to compare +==================== ================================================ + +Click "Save changes". + +-------------------------------- +Fourth Step: Configure an Action +-------------------------------- + +As promised in the previous step, the ACLs will be used. An Action will link +multiple ACLs with a Backend. +An Action is created using the `+` button. + +.. image:: images/haproxy_actions.png + +A form dialog opens and we can fill it out like the following: + +.. image:: images/haproxy_edit_action.png + +.. Note:: + You can map using multiple Hostnames to the same Backend by adding multiple + ACLs and choosing the logical operator "OR". + +==================== =================================== +**Name** Choose a name for this Action +**Description** You can add an optional description +**Test Type** Keep it at the default ("IF") +**Select ACLs** Select the ACLs to be used +**Logical operator** Keep the default ("AND") +**Choose action** Choose "Use Backend" +**Use Server** Keep the default ("none") +==================== =================================== + +------------------------------- +Fifth Step Configure a frontend +------------------------------- + +Now its nearly done. The only thing that needs to be configured for HAProxy +is a Frontend. +A Frontend is a a group of bound ports which are used for incoming connections. +From this Frontend we need to know which backend the request will routed to. +For this, the previously configured action is needed. + +To create a new Frontend, click the `+` button: + +.. image:: images/haproxy_frontends.png + +The following modal dialog opens and the frontend can be set up: + +.. image:: images/haproxy_edit_frontend.png + +.. Warning:: + If you configure a port that is already in use, the configuration test + will be successful but the start of HAProxy will fail silently. + Please ensure that the used port is free - especially if the number + conflicts with the web configuration of OPNsense. + + +General Settings +================ + +=================== =========================================================================== +**Enabled** Checked +**Name** Use any name +**Description** You may keep it empty +**Listen Address** Enter one or more host:port combinations, use 0.0.0.0:80 for HTTP via IPv4 +**Type** Choose HTTP / HTTPS +**Default Backend** Keep the default of "None" +=================== =========================================================================== + +Advanced settings +================= + +Enbable the X-Forwarded-For-header so the backend will know the real IP of +the client. + +Actions (ACLs) +============== + +Here you have to configure the previously configured actions, so HAProxy +knows where the requests should be sent to. + +All other Options +================= + +Keep all other options at the default + +---------------------------- +Sixth step: Enable and start +---------------------------- + +This is the last step - on the General tab, we will enable the service +after a config test. + +.. image:: images/haproxy_general.png + +For that, the "Enable HAProxy" checkbox needs to be checked. + +On this screen, check "Enable HAProxy" and click "Apply". +If everything went OK HAProxy will start. +Now you need to configure firewall rules for accessing your HAProxy instance. diff --git a/source/manual/how-tos/haproxy_howtos.rst b/source/manual/how-tos/haproxy_howtos.rst new file mode 100644 index 0000000..da6df37 --- /dev/null +++ b/source/manual/how-tos/haproxy_howtos.rst @@ -0,0 +1,85 @@ +HAProxy How-Tos +=============== + +Redirect Root directory +----------------------- + +Create a condition: + +.. image:: images/haproxy_root_path_condition.png + +============== ============== +name root +Condition type Path matches +Path matches / +============== ============== + +Create a Rule: + +.. image:: images/haproxy_forward_to_dir_rule.png + +======================= =================================================== +name forward_to_dir +Test type IF +conditions root +Logical ops none +Execute function http-request redirect +HTTP Redirect parameter code 301 location http://www.example.net/directory/ +======================= =================================================== + +Please note that 301 is for a permanent redirect. If you want to do it teporary, +you will have to use another status code. + + + +Under Public Services edit your frontend and add "forward_to_dir" to Select Rules. + +.. image:: images/haproxy_forward_to_dir_service.png + + +Add Basic Authentication to a Service +------------------------------------- + +I have a Webapplication which have to be exposed to the outside and doesn't allow authentication. +So HAProxy with basic auth would be just fine to get a mininum of security. + +* Go to "Rules & Conditions" - "Conditions" and Add a new one: + +.. image:: images/haproxy_condition_add_authentication.png + +=================== ================= +name choose a name +Condition type Custom +option pass-through http_auth(admins) +=================== ================= + +* Add a rule: + +.. image:: images/haproxy_edit_rule_authentication.png + +================ ================================= +name a name for your rule +Test type UNLESS +condition select the previously created one +Logical operator none +Execute function http-request auth" +================ ================================= + +* Go to your frontend and add the ACL to it. + +.. image:: images/haproxy_frontend_add_authentication.png + + +* Go to "Settings" -> "Global Parameters", enable the advanced mode (top left), and add your users to configuration + via the "Custom options" + +.. image:: images/haproxy_settings_global_params_auth.png + + +.. code-block:: none + + userlist admins + user test1 insecure-password pw1 + user test2 insecure-password pw2 + + diff --git a/source/manual/how-tos/images/4g_configure_ppp.png b/source/manual/how-tos/images/4g_configure_ppp.png new file mode 100644 index 0000000..d7a5d78 Binary files /dev/null and b/source/manual/how-tos/images/4g_configure_ppp.png differ diff --git a/source/manual/how-tos/images/600px-Google_Drive_Backup_screenshot.png b/source/manual/how-tos/images/600px-Google_Drive_Backup_screenshot.png new file mode 100644 index 0000000..15513ad Binary files /dev/null and b/source/manual/how-tos/images/600px-Google_Drive_Backup_screenshot.png differ diff --git a/source/manual/how-tos/images/900px-Carp_setup_example.png b/source/manual/how-tos/images/900px-Carp_setup_example.png new file mode 100644 index 0000000..8360e9b Binary files /dev/null and b/source/manual/how-tos/images/900px-Carp_setup_example.png differ diff --git a/source/manual/how-tos/images/Filter_Category_Result.png b/source/manual/how-tos/images/Filter_Category_Result.png new file mode 100644 index 0000000..d90a180 Binary files /dev/null and b/source/manual/how-tos/images/Filter_Category_Result.png differ diff --git a/source/manual/how-tos/images/Filter_by_Category.png b/source/manual/how-tos/images/Filter_by_Category.png new file mode 100644 index 0000000..cf30be2 Binary files /dev/null and b/source/manual/how-tos/images/Filter_by_Category.png differ diff --git a/source/manual/how-tos/images/Filtering_Bridge_Step_1.png b/source/manual/how-tos/images/Filtering_Bridge_Step_1.png new file mode 100644 index 0000000..9f0f10b Binary files /dev/null and b/source/manual/how-tos/images/Filtering_Bridge_Step_1.png differ diff --git a/source/manual/how-tos/images/Filtering_Bridge_Step_2.png b/source/manual/how-tos/images/Filtering_Bridge_Step_2.png new file mode 100644 index 0000000..ca231d9 Binary files /dev/null and b/source/manual/how-tos/images/Filtering_Bridge_Step_2.png differ diff --git a/source/manual/how-tos/images/Filtering_Bridge_Step_2a.png b/source/manual/how-tos/images/Filtering_Bridge_Step_2a.png new file mode 100644 index 0000000..6aecd81 Binary files /dev/null and b/source/manual/how-tos/images/Filtering_Bridge_Step_2a.png differ diff --git a/source/manual/how-tos/images/Filtering_Bridge_Step_3a.png b/source/manual/how-tos/images/Filtering_Bridge_Step_3a.png new file mode 100644 index 0000000..92e02b8 Binary files /dev/null and b/source/manual/how-tos/images/Filtering_Bridge_Step_3a.png differ diff --git a/source/manual/how-tos/images/Filtering_Bridge_Step_3b.png b/source/manual/how-tos/images/Filtering_Bridge_Step_3b.png new file mode 100644 index 0000000..53061fc Binary files /dev/null and b/source/manual/how-tos/images/Filtering_Bridge_Step_3b.png differ diff --git a/source/manual/how-tos/images/Filtering_Bridge_Step_4.png b/source/manual/how-tos/images/Filtering_Bridge_Step_4.png new file mode 100644 index 0000000..826255e Binary files /dev/null and b/source/manual/how-tos/images/Filtering_Bridge_Step_4.png differ diff --git a/source/manual/how-tos/images/Filtering_Bridge_Step_5.png b/source/manual/how-tos/images/Filtering_Bridge_Step_5.png new file mode 100644 index 0000000..805e6b7 Binary files /dev/null and b/source/manual/how-tos/images/Filtering_Bridge_Step_5.png differ diff --git a/source/manual/how-tos/images/Filtering_Bridge_Step_6.png b/source/manual/how-tos/images/Filtering_Bridge_Step_6.png new file mode 100644 index 0000000..3893061 Binary files /dev/null and b/source/manual/how-tos/images/Filtering_Bridge_Step_6.png differ diff --git a/source/manual/how-tos/images/Filtering_Bridge_Step_7.png b/source/manual/how-tos/images/Filtering_Bridge_Step_7.png new file mode 100644 index 0000000..07355f1 Binary files /dev/null and b/source/manual/how-tos/images/Filtering_Bridge_Step_7.png differ diff --git a/source/manual/how-tos/images/Filtering_Bridge_Step_9.png b/source/manual/how-tos/images/Filtering_Bridge_Step_9.png new file mode 100644 index 0000000..424e46d Binary files /dev/null and b/source/manual/how-tos/images/Filtering_Bridge_Step_9.png differ diff --git a/source/manual/how-tos/images/Interface_assignment_4g.png b/source/manual/how-tos/images/Interface_assignment_4g.png new file mode 100644 index 0000000..331a82b Binary files /dev/null and b/source/manual/how-tos/images/Interface_assignment_4g.png differ diff --git a/source/manual/how-tos/images/OPN20322R_870px.png b/source/manual/how-tos/images/OPN20322R_870px.png new file mode 100644 index 0000000..92bf444 Binary files /dev/null and b/source/manual/how-tos/images/OPN20322R_870px.png differ diff --git a/source/manual/how-tos/images/OTP_seed.png b/source/manual/how-tos/images/OTP_seed.png new file mode 100644 index 0000000..e02a116 Binary files /dev/null and b/source/manual/how-tos/images/OTP_seed.png differ diff --git a/source/manual/how-tos/images/Rule_Category.png b/source/manual/how-tos/images/Rule_Category.png new file mode 100644 index 0000000..7e2b697 Binary files /dev/null and b/source/manual/how-tos/images/Rule_Category.png differ diff --git a/source/manual/how-tos/images/Rules_Full.png b/source/manual/how-tos/images/Rules_Full.png new file mode 100644 index 0000000..1f5c464 Binary files /dev/null and b/source/manual/how-tos/images/Rules_Full.png differ diff --git a/source/manual/how-tos/images/SPE_ICAP.png b/source/manual/how-tos/images/SPE_ICAP.png new file mode 100644 index 0000000..9fd0284 Binary files /dev/null and b/source/manual/how-tos/images/SPE_ICAP.png differ diff --git a/source/manual/how-tos/images/SPE_home.png b/source/manual/how-tos/images/SPE_home.png new file mode 100644 index 0000000..c354b75 Binary files /dev/null and b/source/manual/how-tos/images/SPE_home.png differ diff --git a/source/manual/how-tos/images/Trust_Settings_OSX.png b/source/manual/how-tos/images/Trust_Settings_OSX.png new file mode 100644 index 0000000..22c492a Binary files /dev/null and b/source/manual/how-tos/images/Trust_Settings_OSX.png differ diff --git a/source/manual/how-tos/images/alerts.jpg b/source/manual/how-tos/images/alerts.jpg new file mode 100644 index 0000000..cfff360 Binary files /dev/null and b/source/manual/how-tos/images/alerts.jpg differ diff --git a/source/manual/how-tos/images/amazon-web-services.png b/source/manual/how-tos/images/amazon-web-services.png new file mode 100644 index 0000000..a14f4db Binary files /dev/null and b/source/manual/how-tos/images/amazon-web-services.png differ diff --git a/source/manual/how-tos/images/applybtn.png b/source/manual/how-tos/images/applybtn.png new file mode 100644 index 0000000..8d5d34f Binary files /dev/null and b/source/manual/how-tos/images/applybtn.png differ diff --git a/source/manual/how-tos/images/aws_capture_initial_password.png b/source/manual/how-tos/images/aws_capture_initial_password.png new file mode 100644 index 0000000..d59c33b Binary files /dev/null and b/source/manual/how-tos/images/aws_capture_initial_password.png differ diff --git a/source/manual/how-tos/images/aws_choose_disc.png b/source/manual/how-tos/images/aws_choose_disc.png new file mode 100644 index 0000000..d171b39 Binary files /dev/null and b/source/manual/how-tos/images/aws_choose_disc.png differ diff --git a/source/manual/how-tos/images/aws_configure_security_group.png b/source/manual/how-tos/images/aws_configure_security_group.png new file mode 100644 index 0000000..dd3255e Binary files /dev/null and b/source/manual/how-tos/images/aws_configure_security_group.png differ diff --git a/source/manual/how-tos/images/aws_instances.png b/source/manual/how-tos/images/aws_instances.png new file mode 100644 index 0000000..3a3a54f Binary files /dev/null and b/source/manual/how-tos/images/aws_instances.png differ diff --git a/source/manual/how-tos/images/aws_launch_new_image.png b/source/manual/how-tos/images/aws_launch_new_image.png new file mode 100644 index 0000000..cabf738 Binary files /dev/null and b/source/manual/how-tos/images/aws_launch_new_image.png differ diff --git a/source/manual/how-tos/images/aws_review_settings.png b/source/manual/how-tos/images/aws_review_settings.png new file mode 100644 index 0000000..de5a2b5 Binary files /dev/null and b/source/manual/how-tos/images/aws_review_settings.png differ diff --git a/source/manual/how-tos/images/aws_search_current_ip.png b/source/manual/how-tos/images/aws_search_current_ip.png new file mode 100644 index 0000000..c8ccb62 Binary files /dev/null and b/source/manual/how-tos/images/aws_search_current_ip.png differ diff --git a/source/manual/how-tos/images/aws_ssh_keypair.png b/source/manual/how-tos/images/aws_ssh_keypair.png new file mode 100644 index 0000000..8a7f5be Binary files /dev/null and b/source/manual/how-tos/images/aws_ssh_keypair.png differ diff --git a/source/manual/how-tos/images/aws_status.png b/source/manual/how-tos/images/aws_status.png new file mode 100644 index 0000000..5f1a099 Binary files /dev/null and b/source/manual/how-tos/images/aws_status.png differ diff --git a/source/manual/how-tos/images/block_private_networks.png b/source/manual/how-tos/images/block_private_networks.png new file mode 100644 index 0000000..3cc0363 Binary files /dev/null and b/source/manual/how-tos/images/block_private_networks.png differ diff --git a/source/manual/how-tos/images/btn_download.png b/source/manual/how-tos/images/btn_download.png new file mode 100644 index 0000000..2485708 Binary files /dev/null and b/source/manual/how-tos/images/btn_download.png differ diff --git a/source/manual/how-tos/images/btn_save.png b/source/manual/how-tos/images/btn_save.png new file mode 100644 index 0000000..18125e2 Binary files /dev/null and b/source/manual/how-tos/images/btn_save.png differ diff --git a/source/manual/how-tos/images/btn_upload.png b/source/manual/how-tos/images/btn_upload.png new file mode 100644 index 0000000..d266a84 Binary files /dev/null and b/source/manual/how-tos/images/btn_upload.png differ diff --git a/source/manual/how-tos/images/c-icap_av.png b/source/manual/how-tos/images/c-icap_av.png new file mode 100644 index 0000000..64eeb1f Binary files /dev/null and b/source/manual/how-tos/images/c-icap_av.png differ diff --git a/source/manual/how-tos/images/c-icap_settings.png b/source/manual/how-tos/images/c-icap_settings.png new file mode 100644 index 0000000..202395f Binary files /dev/null and b/source/manual/how-tos/images/c-icap_settings.png differ diff --git a/source/manual/how-tos/images/captiveportal_popup.png b/source/manual/how-tos/images/captiveportal_popup.png new file mode 100644 index 0000000..00f1909 Binary files /dev/null and b/source/manual/how-tos/images/captiveportal_popup.png differ diff --git a/source/manual/how-tos/images/certificate.png b/source/manual/how-tos/images/certificate.png new file mode 100644 index 0000000..b91e4ad Binary files /dev/null and b/source/manual/how-tos/images/certificate.png differ diff --git a/source/manual/how-tos/images/changefilter.png b/source/manual/how-tos/images/changefilter.png new file mode 100644 index 0000000..0e17cee Binary files /dev/null and b/source/manual/how-tos/images/changefilter.png differ diff --git a/source/manual/how-tos/images/clamav_settings.png b/source/manual/how-tos/images/clamav_settings.png new file mode 100644 index 0000000..b4abb5a Binary files /dev/null and b/source/manual/how-tos/images/clamav_settings.png differ diff --git a/source/manual/how-tos/images/cli_list_captiveportalsessions.png b/source/manual/how-tos/images/cli_list_captiveportalsessions.png new file mode 100644 index 0000000..79f1a63 Binary files /dev/null and b/source/manual/how-tos/images/cli_list_captiveportalsessions.png differ diff --git a/source/manual/how-tos/images/cp-traffic-shaping.png b/source/manual/how-tos/images/cp-traffic-shaping.png new file mode 100644 index 0000000..b3c8bcb Binary files /dev/null and b/source/manual/how-tos/images/cp-traffic-shaping.png differ diff --git a/source/manual/how-tos/images/cp_active_sessions.png b/source/manual/how-tos/images/cp_active_sessions.png new file mode 100644 index 0000000..843ec4c Binary files /dev/null and b/source/manual/how-tos/images/cp_active_sessions.png differ diff --git a/source/manual/how-tos/images/cp_active_vouchers.png b/source/manual/how-tos/images/cp_active_vouchers.png new file mode 100644 index 0000000..a6baa8d Binary files /dev/null and b/source/manual/how-tos/images/cp_active_vouchers.png differ diff --git a/source/manual/how-tos/images/cp_royalhotel_voucher.png b/source/manual/how-tos/images/cp_royalhotel_voucher.png new file mode 100644 index 0000000..5832aa6 Binary files /dev/null and b/source/manual/how-tos/images/cp_royalhotel_voucher.png differ diff --git a/source/manual/how-tos/images/cp_voucher_login.png b/source/manual/how-tos/images/cp_voucher_login.png new file mode 100644 index 0000000..4ed79aa Binary files /dev/null and b/source/manual/how-tos/images/cp_voucher_login.png differ diff --git a/source/manual/how-tos/images/create_vouchers.png b/source/manual/how-tos/images/create_vouchers.png new file mode 100644 index 0000000..789b064 Binary files /dev/null and b/source/manual/how-tos/images/create_vouchers.png differ diff --git a/source/manual/how-tos/images/default_login_no_authenticator.png b/source/manual/how-tos/images/default_login_no_authenticator.png new file mode 100644 index 0000000..7409d74 Binary files /dev/null and b/source/manual/how-tos/images/default_login_no_authenticator.png differ diff --git a/source/manual/how-tos/images/disable_offloading.png b/source/manual/how-tos/images/disable_offloading.png new file mode 100644 index 0000000..5833f12 Binary files /dev/null and b/source/manual/how-tos/images/disable_offloading.png differ diff --git a/source/manual/how-tos/images/downloadbtn.png b/source/manual/how-tos/images/downloadbtn.png new file mode 100644 index 0000000..e81c762 Binary files /dev/null and b/source/manual/how-tos/images/downloadbtn.png differ diff --git a/source/manual/how-tos/images/dynamic_routes_howto.png b/source/manual/how-tos/images/dynamic_routes_howto.png new file mode 100644 index 0000000..3378794 Binary files /dev/null and b/source/manual/how-tos/images/dynamic_routes_howto.png differ diff --git a/source/manual/how-tos/images/dynamic_routes_ospf_general.png b/source/manual/how-tos/images/dynamic_routes_ospf_general.png new file mode 100644 index 0000000..29205de Binary files /dev/null and b/source/manual/how-tos/images/dynamic_routes_ospf_general.png differ diff --git a/source/manual/how-tos/images/dynamic_routes_ospf_interface_dialog.png b/source/manual/how-tos/images/dynamic_routes_ospf_interface_dialog.png new file mode 100644 index 0000000..065e671 Binary files /dev/null and b/source/manual/how-tos/images/dynamic_routes_ospf_interface_dialog.png differ diff --git a/source/manual/how-tos/images/dynamic_routes_ospf_interfaces.png b/source/manual/how-tos/images/dynamic_routes_ospf_interfaces.png new file mode 100644 index 0000000..ab63fa1 Binary files /dev/null and b/source/manual/how-tos/images/dynamic_routes_ospf_interfaces.png differ diff --git a/source/manual/how-tos/images/dynamic_routes_ospf_network_dialog.png b/source/manual/how-tos/images/dynamic_routes_ospf_network_dialog.png new file mode 100644 index 0000000..b81b2b6 Binary files /dev/null and b/source/manual/how-tos/images/dynamic_routes_ospf_network_dialog.png differ diff --git a/source/manual/how-tos/images/dynamic_routes_ospf_networks.png b/source/manual/how-tos/images/dynamic_routes_ospf_networks.png new file mode 100644 index 0000000..a0b8b16 Binary files /dev/null and b/source/manual/how-tos/images/dynamic_routes_ospf_networks.png differ diff --git a/source/manual/how-tos/images/dynamic_routes_rip.png b/source/manual/how-tos/images/dynamic_routes_rip.png new file mode 100644 index 0000000..7d234b5 Binary files /dev/null and b/source/manual/how-tos/images/dynamic_routes_rip.png differ diff --git a/source/manual/how-tos/images/dynamic_routes_zebra.png b/source/manual/how-tos/images/dynamic_routes_zebra.png new file mode 100644 index 0000000..7bff2a7 Binary files /dev/null and b/source/manual/how-tos/images/dynamic_routes_zebra.png differ diff --git a/source/manual/how-tos/images/expanded_view.png b/source/manual/how-tos/images/expanded_view.png new file mode 100644 index 0000000..38668c4 Binary files /dev/null and b/source/manual/how-tos/images/expanded_view.png differ diff --git a/source/manual/how-tos/images/export_CA_cert.png b/source/manual/how-tos/images/export_CA_cert.png new file mode 100644 index 0000000..159c77e Binary files /dev/null and b/source/manual/how-tos/images/export_CA_cert.png differ diff --git a/source/manual/how-tos/images/facebook_click.png b/source/manual/how-tos/images/facebook_click.png new file mode 100644 index 0000000..b204aa7 Binary files /dev/null and b/source/manual/how-tos/images/facebook_click.png differ diff --git a/source/manual/how-tos/images/facebook_lock.png b/source/manual/how-tos/images/facebook_lock.png new file mode 100644 index 0000000..5eab2b5 Binary files /dev/null and b/source/manual/how-tos/images/facebook_lock.png differ diff --git a/source/manual/how-tos/images/firmware.png b/source/manual/how-tos/images/firmware.png new file mode 100644 index 0000000..e206636 Binary files /dev/null and b/source/manual/how-tos/images/firmware.png differ diff --git a/source/manual/how-tos/images/freeradius_clients.png b/source/manual/how-tos/images/freeradius_clients.png new file mode 100644 index 0000000..b53be20 Binary files /dev/null and b/source/manual/how-tos/images/freeradius_clients.png differ diff --git a/source/manual/how-tos/images/freeradius_edit_client.png b/source/manual/how-tos/images/freeradius_edit_client.png new file mode 100644 index 0000000..18dfcb6 Binary files /dev/null and b/source/manual/how-tos/images/freeradius_edit_client.png differ diff --git a/source/manual/how-tos/images/freeradius_edit_user.png b/source/manual/how-tos/images/freeradius_edit_user.png new file mode 100644 index 0000000..d63d30b Binary files /dev/null and b/source/manual/how-tos/images/freeradius_edit_user.png differ diff --git a/source/manual/how-tos/images/freeradius_general.png b/source/manual/how-tos/images/freeradius_general.png new file mode 100644 index 0000000..65c0ed7 Binary files /dev/null and b/source/manual/how-tos/images/freeradius_general.png differ diff --git a/source/manual/how-tos/images/freeradius_users.png b/source/manual/how-tos/images/freeradius_users.png new file mode 100644 index 0000000..4a71645 Binary files /dev/null and b/source/manual/how-tos/images/freeradius_users.png differ diff --git a/source/manual/how-tos/images/fw_category_multiselect.png b/source/manual/how-tos/images/fw_category_multiselect.png new file mode 100644 index 0000000..955fb69 Binary files /dev/null and b/source/manual/how-tos/images/fw_category_multiselect.png differ diff --git a/source/manual/how-tos/images/google_token_sample.png b/source/manual/how-tos/images/google_token_sample.png new file mode 100644 index 0000000..4cb19d1 Binary files /dev/null and b/source/manual/how-tos/images/google_token_sample.png differ diff --git a/source/manual/how-tos/images/guestnet_fwrules.png b/source/manual/how-tos/images/guestnet_fwrules.png new file mode 100644 index 0000000..aea1e43 Binary files /dev/null and b/source/manual/how-tos/images/guestnet_fwrules.png differ diff --git a/source/manual/how-tos/images/haproxy_acls.png b/source/manual/how-tos/images/haproxy_acls.png new file mode 100644 index 0000000..7181fd1 Binary files /dev/null and b/source/manual/how-tos/images/haproxy_acls.png differ diff --git a/source/manual/how-tos/images/haproxy_actions.png b/source/manual/how-tos/images/haproxy_actions.png new file mode 100644 index 0000000..4e29171 Binary files /dev/null and b/source/manual/how-tos/images/haproxy_actions.png differ diff --git a/source/manual/how-tos/images/haproxy_backends.png b/source/manual/how-tos/images/haproxy_backends.png new file mode 100644 index 0000000..6acc86e Binary files /dev/null and b/source/manual/how-tos/images/haproxy_backends.png differ diff --git a/source/manual/how-tos/images/haproxy_condition_add_authentication.png b/source/manual/how-tos/images/haproxy_condition_add_authentication.png new file mode 100644 index 0000000..a992f9a Binary files /dev/null and b/source/manual/how-tos/images/haproxy_condition_add_authentication.png differ diff --git a/source/manual/how-tos/images/haproxy_edit_acl.png b/source/manual/how-tos/images/haproxy_edit_acl.png new file mode 100644 index 0000000..578882b Binary files /dev/null and b/source/manual/how-tos/images/haproxy_edit_acl.png differ diff --git a/source/manual/how-tos/images/haproxy_edit_action.png b/source/manual/how-tos/images/haproxy_edit_action.png new file mode 100644 index 0000000..fccd102 Binary files /dev/null and b/source/manual/how-tos/images/haproxy_edit_action.png differ diff --git a/source/manual/how-tos/images/haproxy_edit_backend.png b/source/manual/how-tos/images/haproxy_edit_backend.png new file mode 100644 index 0000000..68c0ff8 Binary files /dev/null and b/source/manual/how-tos/images/haproxy_edit_backend.png differ diff --git a/source/manual/how-tos/images/haproxy_edit_frontend.png b/source/manual/how-tos/images/haproxy_edit_frontend.png new file mode 100644 index 0000000..567ef05 Binary files /dev/null and b/source/manual/how-tos/images/haproxy_edit_frontend.png differ diff --git a/source/manual/how-tos/images/haproxy_edit_rule_authentication.png b/source/manual/how-tos/images/haproxy_edit_rule_authentication.png new file mode 100644 index 0000000..ab5c050 Binary files /dev/null and b/source/manual/how-tos/images/haproxy_edit_rule_authentication.png differ diff --git a/source/manual/how-tos/images/haproxy_edit_server.png b/source/manual/how-tos/images/haproxy_edit_server.png new file mode 100644 index 0000000..e1ee52a Binary files /dev/null and b/source/manual/how-tos/images/haproxy_edit_server.png differ diff --git a/source/manual/how-tos/images/haproxy_forward_to_dir_rule.png b/source/manual/how-tos/images/haproxy_forward_to_dir_rule.png new file mode 100644 index 0000000..99a7cec Binary files /dev/null and b/source/manual/how-tos/images/haproxy_forward_to_dir_rule.png differ diff --git a/source/manual/how-tos/images/haproxy_forward_to_dir_service.png b/source/manual/how-tos/images/haproxy_forward_to_dir_service.png new file mode 100644 index 0000000..2622ee0 Binary files /dev/null and b/source/manual/how-tos/images/haproxy_forward_to_dir_service.png differ diff --git a/source/manual/how-tos/images/haproxy_frontend_add_authentication.png b/source/manual/how-tos/images/haproxy_frontend_add_authentication.png new file mode 100644 index 0000000..d56e2a6 Binary files /dev/null and b/source/manual/how-tos/images/haproxy_frontend_add_authentication.png differ diff --git a/source/manual/how-tos/images/haproxy_frontends.png b/source/manual/how-tos/images/haproxy_frontends.png new file mode 100644 index 0000000..3532f73 Binary files /dev/null and b/source/manual/how-tos/images/haproxy_frontends.png differ diff --git a/source/manual/how-tos/images/haproxy_general.png b/source/manual/how-tos/images/haproxy_general.png new file mode 100644 index 0000000..902d8fd Binary files /dev/null and b/source/manual/how-tos/images/haproxy_general.png differ diff --git a/source/manual/how-tos/images/haproxy_root_path_condition.png b/source/manual/how-tos/images/haproxy_root_path_condition.png new file mode 100644 index 0000000..b176c80 Binary files /dev/null and b/source/manual/how-tos/images/haproxy_root_path_condition.png differ diff --git a/source/manual/how-tos/images/haproxy_servers.png b/source/manual/how-tos/images/haproxy_servers.png new file mode 100644 index 0000000..97732c5 Binary files /dev/null and b/source/manual/how-tos/images/haproxy_servers.png differ diff --git a/source/manual/how-tos/images/haproxy_settings_global_params_auth.png b/source/manual/how-tos/images/haproxy_settings_global_params_auth.png new file mode 100644 index 0000000..78f4482 Binary files /dev/null and b/source/manual/how-tos/images/haproxy_settings_global_params_auth.png differ diff --git a/source/manual/how-tos/images/idps.png b/source/manual/how-tos/images/idps.png new file mode 100644 index 0000000..dfc5a9b Binary files /dev/null and b/source/manual/how-tos/images/idps.png differ diff --git a/source/manual/how-tos/images/ids_menu.png b/source/manual/how-tos/images/ids_menu.png new file mode 100644 index 0000000..8079506 Binary files /dev/null and b/source/manual/how-tos/images/ids_menu.png differ diff --git a/source/manual/how-tos/images/ids_tabs_user.png b/source/manual/how-tos/images/ids_tabs_user.png new file mode 100644 index 0000000..ce74912 Binary files /dev/null and b/source/manual/how-tos/images/ids_tabs_user.png differ diff --git a/source/manual/how-tos/images/ids_tabs_user_add.png b/source/manual/how-tos/images/ids_tabs_user_add.png new file mode 100644 index 0000000..4699e66 Binary files /dev/null and b/source/manual/how-tos/images/ids_tabs_user_add.png differ diff --git a/source/manual/how-tos/images/insight_details_view.png b/source/manual/how-tos/images/insight_details_view.png new file mode 100644 index 0000000..65ab069 Binary files /dev/null and b/source/manual/how-tos/images/insight_details_view.png differ diff --git a/source/manual/how-tos/images/insight_export.png b/source/manual/how-tos/images/insight_export.png new file mode 100644 index 0000000..adbbc38 Binary files /dev/null and b/source/manual/how-tos/images/insight_export.png differ diff --git a/source/manual/how-tos/images/insight_export_view.png b/source/manual/how-tos/images/insight_export_view.png new file mode 100644 index 0000000..ff8c259 Binary files /dev/null and b/source/manual/how-tos/images/insight_export_view.png differ diff --git a/source/manual/how-tos/images/insight_full_details.png b/source/manual/how-tos/images/insight_full_details.png new file mode 100644 index 0000000..9cb01d7 Binary files /dev/null and b/source/manual/how-tos/images/insight_full_details.png differ diff --git a/source/manual/how-tos/images/insight_gui.png b/source/manual/how-tos/images/insight_gui.png new file mode 100644 index 0000000..32fcca5 Binary files /dev/null and b/source/manual/how-tos/images/insight_gui.png differ diff --git a/source/manual/how-tos/images/iphone_qr_scan.png b/source/manual/how-tos/images/iphone_qr_scan.png new file mode 100644 index 0000000..ccc7c36 Binary files /dev/null and b/source/manual/how-tos/images/iphone_qr_scan.png differ diff --git a/source/manual/how-tos/images/ips_action.png b/source/manual/how-tos/images/ips_action.png new file mode 100644 index 0000000..6d54aaa Binary files /dev/null and b/source/manual/how-tos/images/ips_action.png differ diff --git a/source/manual/how-tos/images/ips_description.png b/source/manual/how-tos/images/ips_description.png new file mode 100644 index 0000000..701738d Binary files /dev/null and b/source/manual/how-tos/images/ips_description.png differ diff --git a/source/manual/how-tos/images/ips_description_country.png b/source/manual/how-tos/images/ips_description_country.png new file mode 100644 index 0000000..4f22852 Binary files /dev/null and b/source/manual/how-tos/images/ips_description_country.png differ diff --git a/source/manual/how-tos/images/ips_facebook_alert.png b/source/manual/how-tos/images/ips_facebook_alert.png new file mode 100644 index 0000000..b170703 Binary files /dev/null and b/source/manual/how-tos/images/ips_facebook_alert.png differ diff --git a/source/manual/how-tos/images/ips_geoip_alert.png b/source/manual/how-tos/images/ips_geoip_alert.png new file mode 100644 index 0000000..e3ac8e5 Binary files /dev/null and b/source/manual/how-tos/images/ips_geoip_alert.png differ diff --git a/source/manual/how-tos/images/ips_rule_add_geoip.png b/source/manual/how-tos/images/ips_rule_add_geoip.png new file mode 100644 index 0000000..8882572 Binary files /dev/null and b/source/manual/how-tos/images/ips_rule_add_geoip.png differ diff --git a/source/manual/how-tos/images/ips_rule_details.png b/source/manual/how-tos/images/ips_rule_details.png new file mode 100644 index 0000000..5423c00 Binary files /dev/null and b/source/manual/how-tos/images/ips_rule_details.png differ diff --git a/source/manual/how-tos/images/ips_save.png b/source/manual/how-tos/images/ips_save.png new file mode 100644 index 0000000..bf71392 Binary files /dev/null and b/source/manual/how-tos/images/ips_save.png differ diff --git a/source/manual/how-tos/images/ipsec_ipsec_lan_rule.png b/source/manual/how-tos/images/ipsec_ipsec_lan_rule.png new file mode 100644 index 0000000..adb5324 Binary files /dev/null and b/source/manual/how-tos/images/ipsec_ipsec_lan_rule.png differ diff --git a/source/manual/how-tos/images/ipsec_road_vpn_p1a.png b/source/manual/how-tos/images/ipsec_road_vpn_p1a.png new file mode 100644 index 0000000..a2b2db8 Binary files /dev/null and b/source/manual/how-tos/images/ipsec_road_vpn_p1a.png differ diff --git a/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_4.png b/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_4.png new file mode 100644 index 0000000..ef3e185 Binary files /dev/null and b/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_4.png differ diff --git a/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_apply.png b/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_apply.png new file mode 100644 index 0000000..b6f0043 Binary files /dev/null and b/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_apply.png differ diff --git a/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_enable.png b/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_enable.png new file mode 100644 index 0000000..0f3818f Binary files /dev/null and b/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_enable.png differ diff --git a/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_p2_empty.png b/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_p2_empty.png new file mode 100644 index 0000000..81582c2 Binary files /dev/null and b/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_p2_empty.png differ diff --git a/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_show_p2.png b/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_show_p2.png new file mode 100644 index 0000000..ff424bc Binary files /dev/null and b/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_show_p2.png differ diff --git a/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_success.png b/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_success.png new file mode 100644 index 0000000..c8d4287 Binary files /dev/null and b/source/manual/how-tos/images/ipsec_s2s_vpn_p1a_success.png differ diff --git a/source/manual/how-tos/images/ipsec_s2s_vpn_p1b_4.png b/source/manual/how-tos/images/ipsec_s2s_vpn_p1b_4.png new file mode 100644 index 0000000..a6c78bb Binary files /dev/null and b/source/manual/how-tos/images/ipsec_s2s_vpn_p1b_4.png differ diff --git a/source/manual/how-tos/images/ipsec_status.png b/source/manual/how-tos/images/ipsec_status.png new file mode 100644 index 0000000..83573f5 Binary files /dev/null and b/source/manual/how-tos/images/ipsec_status.png differ diff --git a/source/manual/how-tos/images/ipsec_wan_rules.png b/source/manual/how-tos/images/ipsec_wan_rules.png new file mode 100644 index 0000000..d89a68a Binary files /dev/null and b/source/manual/how-tos/images/ipsec_wan_rules.png differ diff --git a/source/manual/how-tos/images/ldap_mygroup_properties.png b/source/manual/how-tos/images/ldap_mygroup_properties.png new file mode 100644 index 0000000..316a55a Binary files /dev/null and b/source/manual/how-tos/images/ldap_mygroup_properties.png differ diff --git a/source/manual/how-tos/images/ldap_selectcontainer.png b/source/manual/how-tos/images/ldap_selectcontainer.png new file mode 100644 index 0000000..6965186 Binary files /dev/null and b/source/manual/how-tos/images/ldap_selectcontainer.png differ diff --git a/source/manual/how-tos/images/ldap_testfail.png b/source/manual/how-tos/images/ldap_testfail.png new file mode 100644 index 0000000..65b29b6 Binary files /dev/null and b/source/manual/how-tos/images/ldap_testfail.png differ diff --git a/source/manual/how-tos/images/ldap_testok.png b/source/manual/how-tos/images/ldap_testok.png new file mode 100644 index 0000000..bb1e692 Binary files /dev/null and b/source/manual/how-tos/images/ldap_testok.png differ diff --git a/source/manual/how-tos/images/mycompany_login.png b/source/manual/how-tos/images/mycompany_login.png new file mode 100644 index 0000000..4a9d507 Binary files /dev/null and b/source/manual/how-tos/images/mycompany_login.png differ diff --git a/source/manual/how-tos/images/netflow_exporter.png b/source/manual/how-tos/images/netflow_exporter.png new file mode 100644 index 0000000..66a80d4 Binary files /dev/null and b/source/manual/how-tos/images/netflow_exporter.png differ diff --git a/source/manual/how-tos/images/opnsense_add_gif.png b/source/manual/how-tos/images/opnsense_add_gif.png new file mode 100644 index 0000000..a06f466 Binary files /dev/null and b/source/manual/how-tos/images/opnsense_add_gif.png differ diff --git a/source/manual/how-tos/images/opnsense_hotspot_controller.png b/source/manual/how-tos/images/opnsense_hotspot_controller.png new file mode 100644 index 0000000..23bb652 Binary files /dev/null and b/source/manual/how-tos/images/opnsense_hotspot_controller.png differ diff --git a/source/manual/how-tos/images/osx-ipsec-conf1.png b/source/manual/how-tos/images/osx-ipsec-conf1.png new file mode 100644 index 0000000..400222b Binary files /dev/null and b/source/manual/how-tos/images/osx-ipsec-conf1.png differ diff --git a/source/manual/how-tos/images/osx-ipsec-conf2.png b/source/manual/how-tos/images/osx-ipsec-conf2.png new file mode 100644 index 0000000..ef2b2cc Binary files /dev/null and b/source/manual/how-tos/images/osx-ipsec-conf2.png differ diff --git a/source/manual/how-tos/images/osx-ipsec-connected.png b/source/manual/how-tos/images/osx-ipsec-connected.png new file mode 100644 index 0000000..ed077b7 Binary files /dev/null and b/source/manual/how-tos/images/osx-ipsec-connected.png differ diff --git a/source/manual/how-tos/images/osx-ipsec-new.png b/source/manual/how-tos/images/osx-ipsec-new.png new file mode 100644 index 0000000..2b389a4 Binary files /dev/null and b/source/manual/how-tos/images/osx-ipsec-new.png differ diff --git a/source/manual/how-tos/images/otp_qr_code.png b/source/manual/how-tos/images/otp_qr_code.png new file mode 100644 index 0000000..6599ea0 Binary files /dev/null and b/source/manual/how-tos/images/otp_qr_code.png differ diff --git a/source/manual/how-tos/images/pie_details.png b/source/manual/how-tos/images/pie_details.png new file mode 100644 index 0000000..909e410 Binary files /dev/null and b/source/manual/how-tos/images/pie_details.png differ diff --git a/source/manual/how-tos/images/pie_piece.png b/source/manual/how-tos/images/pie_piece.png new file mode 100644 index 0000000..14deafd Binary files /dev/null and b/source/manual/how-tos/images/pie_piece.png differ diff --git a/source/manual/how-tos/images/plugin_mdns_repeater.png b/source/manual/how-tos/images/plugin_mdns_repeater.png new file mode 100644 index 0000000..6ce964e Binary files /dev/null and b/source/manual/how-tos/images/plugin_mdns_repeater.png differ diff --git a/source/manual/how-tos/images/postfix_add_domain_forward.png b/source/manual/how-tos/images/postfix_add_domain_forward.png new file mode 100644 index 0000000..c9906a5 Binary files /dev/null and b/source/manual/how-tos/images/postfix_add_domain_forward.png differ diff --git a/source/manual/how-tos/images/postfix_add_new_domain.png b/source/manual/how-tos/images/postfix_add_new_domain.png new file mode 100644 index 0000000..ca0d3c3 Binary files /dev/null and b/source/manual/how-tos/images/postfix_add_new_domain.png differ diff --git a/source/manual/how-tos/images/postfix_antispam_tab.png b/source/manual/how-tos/images/postfix_antispam_tab.png new file mode 100644 index 0000000..b9b2509 Binary files /dev/null and b/source/manual/how-tos/images/postfix_antispam_tab.png differ diff --git a/source/manual/how-tos/images/postfix_general_tab.png b/source/manual/how-tos/images/postfix_general_tab.png new file mode 100644 index 0000000..d18bd97 Binary files /dev/null and b/source/manual/how-tos/images/postfix_general_tab.png differ diff --git a/source/manual/how-tos/images/ppp_celular_configured.png b/source/manual/how-tos/images/ppp_celular_configured.png new file mode 100644 index 0000000..491d29b Binary files /dev/null and b/source/manual/how-tos/images/ppp_celular_configured.png differ diff --git a/source/manual/how-tos/images/proxy_basics.png b/source/manual/how-tos/images/proxy_basics.png new file mode 100644 index 0000000..d517114 Binary files /dev/null and b/source/manual/how-tos/images/proxy_basics.png differ diff --git a/source/manual/how-tos/images/proxy_blacklist.png b/source/manual/how-tos/images/proxy_blacklist.png new file mode 100644 index 0000000..0809a22 Binary files /dev/null and b/source/manual/how-tos/images/proxy_blacklist.png differ diff --git a/source/manual/how-tos/images/proxy_cache.png b/source/manual/how-tos/images/proxy_cache.png new file mode 100644 index 0000000..6556641 Binary files /dev/null and b/source/manual/how-tos/images/proxy_cache.png differ diff --git a/source/manual/how-tos/images/proxy_categories.png b/source/manual/how-tos/images/proxy_categories.png new file mode 100644 index 0000000..ec2bf6d Binary files /dev/null and b/source/manual/how-tos/images/proxy_categories.png differ diff --git a/source/manual/how-tos/images/proxy_catgegory.png b/source/manual/how-tos/images/proxy_catgegory.png new file mode 100644 index 0000000..1b05031 Binary files /dev/null and b/source/manual/how-tos/images/proxy_catgegory.png differ diff --git a/source/manual/how-tos/images/proxy_firefox.png b/source/manual/how-tos/images/proxy_firefox.png new file mode 100644 index 0000000..be3cdad Binary files /dev/null and b/source/manual/how-tos/images/proxy_firefox.png differ diff --git a/source/manual/how-tos/images/proxy_firewall.png b/source/manual/how-tos/images/proxy_firewall.png new file mode 100644 index 0000000..a181409 Binary files /dev/null and b/source/manual/how-tos/images/proxy_firewall.png differ diff --git a/source/manual/how-tos/images/proxy_tag.png b/source/manual/how-tos/images/proxy_tag.png new file mode 100644 index 0000000..1ca1c1e Binary files /dev/null and b/source/manual/how-tos/images/proxy_tag.png differ diff --git a/source/manual/how-tos/images/proxy_ut1.png b/source/manual/how-tos/images/proxy_ut1.png new file mode 100644 index 0000000..6a3016d Binary files /dev/null and b/source/manual/how-tos/images/proxy_ut1.png differ diff --git a/source/manual/how-tos/images/qs-access_server.png b/source/manual/how-tos/images/qs-access_server.png new file mode 100644 index 0000000..eb20117 Binary files /dev/null and b/source/manual/how-tos/images/qs-access_server.png differ diff --git a/source/manual/how-tos/images/redis_general.png b/source/manual/how-tos/images/redis_general.png new file mode 100644 index 0000000..58e2cc1 Binary files /dev/null and b/source/manual/how-tos/images/redis_general.png differ diff --git a/source/manual/how-tos/images/redis_menu_entry.png b/source/manual/how-tos/images/redis_menu_entry.png new file mode 100644 index 0000000..42def60 Binary files /dev/null and b/source/manual/how-tos/images/redis_menu_entry.png differ diff --git a/source/manual/how-tos/images/rspamd_antispam_menu.png b/source/manual/how-tos/images/rspamd_antispam_menu.png new file mode 100644 index 0000000..dc49873 Binary files /dev/null and b/source/manual/how-tos/images/rspamd_antispam_menu.png differ diff --git a/source/manual/how-tos/images/rspamd_general.png b/source/manual/how-tos/images/rspamd_general.png new file mode 100644 index 0000000..899580e Binary files /dev/null and b/source/manual/how-tos/images/rspamd_general.png differ diff --git a/source/manual/how-tos/images/rspamd_mx_check.png b/source/manual/how-tos/images/rspamd_mx_check.png new file mode 100644 index 0000000..8e9eadf Binary files /dev/null and b/source/manual/how-tos/images/rspamd_mx_check.png differ diff --git a/source/manual/how-tos/images/rulesdrop.png b/source/manual/how-tos/images/rulesdrop.png new file mode 100644 index 0000000..0d8cd03 Binary files /dev/null and b/source/manual/how-tos/images/rulesdrop.png differ diff --git a/source/manual/how-tos/images/rulesets_enable.png b/source/manual/how-tos/images/rulesets_enable.png new file mode 100644 index 0000000..a6bcd85 Binary files /dev/null and b/source/manual/how-tos/images/rulesets_enable.png differ diff --git a/source/manual/how-tos/images/schedule.png b/source/manual/how-tos/images/schedule.png new file mode 100644 index 0000000..1afdce7 Binary files /dev/null and b/source/manual/how-tos/images/schedule.png differ diff --git a/source/manual/how-tos/images/screenshot_enable_transparent_http.png b/source/manual/how-tos/images/screenshot_enable_transparent_http.png new file mode 100644 index 0000000..65c539d Binary files /dev/null and b/source/manual/how-tos/images/screenshot_enable_transparent_http.png differ diff --git a/source/manual/how-tos/images/search_ca.png b/source/manual/how-tos/images/search_ca.png new file mode 100644 index 0000000..941016f Binary files /dev/null and b/source/manual/how-tos/images/search_ca.png differ diff --git a/source/manual/how-tos/images/shaping_rules_s1.png b/source/manual/how-tos/images/shaping_rules_s1.png new file mode 100644 index 0000000..de07ecb Binary files /dev/null and b/source/manual/how-tos/images/shaping_rules_s1.png differ diff --git a/source/manual/how-tos/images/shaping_rules_s2.png b/source/manual/how-tos/images/shaping_rules_s2.png new file mode 100644 index 0000000..7e88cab Binary files /dev/null and b/source/manual/how-tos/images/shaping_rules_s2.png differ diff --git a/source/manual/how-tos/images/shaping_rules_s3.png b/source/manual/how-tos/images/shaping_rules_s3.png new file mode 100644 index 0000000..cd11f59 Binary files /dev/null and b/source/manual/how-tos/images/shaping_rules_s3.png differ diff --git a/source/manual/how-tos/images/shaping_rules_s4.png b/source/manual/how-tos/images/shaping_rules_s4.png new file mode 100644 index 0000000..a662c34 Binary files /dev/null and b/source/manual/how-tos/images/shaping_rules_s4.png differ diff --git a/source/manual/how-tos/images/spamhaus_drop_edrop.png b/source/manual/how-tos/images/spamhaus_drop_edrop.png new file mode 100644 index 0000000..a315fcc Binary files /dev/null and b/source/manual/how-tos/images/spamhaus_drop_edrop.png differ diff --git a/source/manual/how-tos/images/spamhaus_lan.png b/source/manual/how-tos/images/spamhaus_lan.png new file mode 100644 index 0000000..730d1ee Binary files /dev/null and b/source/manual/how-tos/images/spamhaus_lan.png differ diff --git a/source/manual/how-tos/images/spamhaus_pftable.png b/source/manual/how-tos/images/spamhaus_pftable.png new file mode 100644 index 0000000..5ef8ae6 Binary files /dev/null and b/source/manual/how-tos/images/spamhaus_pftable.png differ diff --git a/source/manual/how-tos/images/spamhaus_wan_rules.png b/source/manual/how-tos/images/spamhaus_wan_rules.png new file mode 100644 index 0000000..bd30f5f Binary files /dev/null and b/source/manual/how-tos/images/spamhaus_wan_rules.png differ diff --git a/source/manual/how-tos/images/sslvpn_client_certificate.png b/source/manual/how-tos/images/sslvpn_client_certificate.png new file mode 100644 index 0000000..5b8639e Binary files /dev/null and b/source/manual/how-tos/images/sslvpn_client_certificate.png differ diff --git a/source/manual/how-tos/images/sslvpn_connection_status.png b/source/manual/how-tos/images/sslvpn_connection_status.png new file mode 100644 index 0000000..23f6173 Binary files /dev/null and b/source/manual/how-tos/images/sslvpn_connection_status.png differ diff --git a/source/manual/how-tos/images/sslvpn_firewall_rule_client.png b/source/manual/how-tos/images/sslvpn_firewall_rule_client.png new file mode 100644 index 0000000..e472e6c Binary files /dev/null and b/source/manual/how-tos/images/sslvpn_firewall_rule_client.png differ diff --git a/source/manual/how-tos/images/sslvpn_image_new.png b/source/manual/how-tos/images/sslvpn_image_new.png new file mode 100644 index 0000000..8998ced Binary files /dev/null and b/source/manual/how-tos/images/sslvpn_image_new.png differ diff --git a/source/manual/how-tos/images/sslvpn_openvpn_rule.png b/source/manual/how-tos/images/sslvpn_openvpn_rule.png new file mode 100644 index 0000000..de80b77 Binary files /dev/null and b/source/manual/how-tos/images/sslvpn_openvpn_rule.png differ diff --git a/source/manual/how-tos/images/sslvpn_server.png b/source/manual/how-tos/images/sslvpn_server.png new file mode 100644 index 0000000..c6de7d3 Binary files /dev/null and b/source/manual/how-tos/images/sslvpn_server.png differ diff --git a/source/manual/how-tos/images/sslvpn_wan_rule.png b/source/manual/how-tos/images/sslvpn_wan_rule.png new file mode 100644 index 0000000..31f95b9 Binary files /dev/null and b/source/manual/how-tos/images/sslvpn_wan_rule.png differ diff --git a/source/manual/how-tos/images/stacked_view.png b/source/manual/how-tos/images/stacked_view.png new file mode 100644 index 0000000..c3f76d3 Binary files /dev/null and b/source/manual/how-tos/images/stacked_view.png differ diff --git a/source/manual/how-tos/images/stream_view.png b/source/manual/how-tos/images/stream_view.png new file mode 100644 index 0000000..f761de0 Binary files /dev/null and b/source/manual/how-tos/images/stream_view.png differ diff --git a/source/manual/how-tos/images/system_access_tester.png b/source/manual/how-tos/images/system_access_tester.png new file mode 100644 index 0000000..d3fb7e5 Binary files /dev/null and b/source/manual/how-tos/images/system_access_tester.png differ diff --git a/source/manual/how-tos/images/template_download.png b/source/manual/how-tos/images/template_download.png new file mode 100644 index 0000000..c569bc6 Binary files /dev/null and b/source/manual/how-tos/images/template_download.png differ diff --git a/source/manual/how-tos/images/template_filelisting.png b/source/manual/how-tos/images/template_filelisting.png new file mode 100644 index 0000000..96befbb Binary files /dev/null and b/source/manual/how-tos/images/template_filelisting.png differ diff --git a/source/manual/how-tos/images/tor_exit.png b/source/manual/how-tos/images/tor_exit.png new file mode 100644 index 0000000..b3b26af Binary files /dev/null and b/source/manual/how-tos/images/tor_exit.png differ diff --git a/source/manual/how-tos/images/tor_exit_acl_entry.png b/source/manual/how-tos/images/tor_exit_acl_entry.png new file mode 100644 index 0000000..d45fae0 Binary files /dev/null and b/source/manual/how-tos/images/tor_exit_acl_entry.png differ diff --git a/source/manual/how-tos/images/tor_general.png b/source/manual/how-tos/images/tor_general.png new file mode 100644 index 0000000..c64d1d3 Binary files /dev/null and b/source/manual/how-tos/images/tor_general.png differ diff --git a/source/manual/how-tos/images/tor_hidden_services.png b/source/manual/how-tos/images/tor_hidden_services.png new file mode 100644 index 0000000..6bb8bc1 Binary files /dev/null and b/source/manual/how-tos/images/tor_hidden_services.png differ diff --git a/source/manual/how-tos/images/tor_hidden_services_edit.png b/source/manual/how-tos/images/tor_hidden_services_edit.png new file mode 100644 index 0000000..db3b035 Binary files /dev/null and b/source/manual/how-tos/images/tor_hidden_services_edit.png differ diff --git a/source/manual/how-tos/images/tor_hidden_services_edit_very_hidden.png b/source/manual/how-tos/images/tor_hidden_services_edit_very_hidden.png new file mode 100644 index 0000000..cd6b507 Binary files /dev/null and b/source/manual/how-tos/images/tor_hidden_services_edit_very_hidden.png differ diff --git a/source/manual/how-tos/images/tor_hidden_services_route_edit.png b/source/manual/how-tos/images/tor_hidden_services_route_edit.png new file mode 100644 index 0000000..28f0dce Binary files /dev/null and b/source/manual/how-tos/images/tor_hidden_services_route_edit.png differ diff --git a/source/manual/how-tos/images/tor_hidden_services_routing.png b/source/manual/how-tos/images/tor_hidden_services_routing.png new file mode 100644 index 0000000..3fe79ce Binary files /dev/null and b/source/manual/how-tos/images/tor_hidden_services_routing.png differ diff --git a/source/manual/how-tos/images/tor_hidden_servicesvery_hidden_credentials.png b/source/manual/how-tos/images/tor_hidden_servicesvery_hidden_credentials.png new file mode 100644 index 0000000..6446899 Binary files /dev/null and b/source/manual/how-tos/images/tor_hidden_servicesvery_hidden_credentials.png differ diff --git a/source/manual/how-tos/images/tor_relay.png b/source/manual/how-tos/images/tor_relay.png new file mode 100644 index 0000000..e5a83d5 Binary files /dev/null and b/source/manual/how-tos/images/tor_relay.png differ diff --git a/source/manual/how-tos/images/tor_socks_acl.png b/source/manual/how-tos/images/tor_socks_acl.png new file mode 100644 index 0000000..272ad22 Binary files /dev/null and b/source/manual/how-tos/images/tor_socks_acl.png differ diff --git a/source/manual/how-tos/images/tor_socks_acl_edit.png b/source/manual/how-tos/images/tor_socks_acl_edit.png new file mode 100644 index 0000000..1c746b6 Binary files /dev/null and b/source/manual/how-tos/images/tor_socks_acl_edit.png differ diff --git a/source/manual/how-tos/images/tunnelbroker_configure_lan.png b/source/manual/how-tos/images/tunnelbroker_configure_lan.png new file mode 100644 index 0000000..714d479 Binary files /dev/null and b/source/manual/how-tos/images/tunnelbroker_configure_lan.png differ diff --git a/source/manual/how-tos/images/tunnelbroker_dhcpv6.png b/source/manual/how-tos/images/tunnelbroker_dhcpv6.png new file mode 100644 index 0000000..dffbb5e Binary files /dev/null and b/source/manual/how-tos/images/tunnelbroker_dhcpv6.png differ diff --git a/source/manual/how-tos/images/tunnelbroker_fw_rules.png b/source/manual/how-tos/images/tunnelbroker_fw_rules.png new file mode 100644 index 0000000..c82714a Binary files /dev/null and b/source/manual/how-tos/images/tunnelbroker_fw_rules.png differ diff --git a/source/manual/how-tos/images/tunnelbroker_setup.png b/source/manual/how-tos/images/tunnelbroker_setup.png new file mode 100644 index 0000000..1e22603 Binary files /dev/null and b/source/manual/how-tos/images/tunnelbroker_setup.png differ diff --git a/source/manual/how-tos/images/user_cloudimport.png b/source/manual/how-tos/images/user_cloudimport.png new file mode 100644 index 0000000..6884350 Binary files /dev/null and b/source/manual/how-tos/images/user_cloudimport.png differ diff --git a/source/manual/how-tos/images/user_ldap_distinguishedname.png b/source/manual/how-tos/images/user_ldap_distinguishedname.png new file mode 100644 index 0000000..d0d7b70 Binary files /dev/null and b/source/manual/how-tos/images/user_ldap_distinguishedname.png differ diff --git a/source/manual/how-tos/images/user_privileges.png b/source/manual/how-tos/images/user_privileges.png new file mode 100644 index 0000000..ce62064 Binary files /dev/null and b/source/manual/how-tos/images/user_privileges.png differ diff --git a/source/manual/how-tos/images/user_testresult_ldap.png b/source/manual/how-tos/images/user_testresult_ldap.png new file mode 100644 index 0000000..8598e63 Binary files /dev/null and b/source/manual/how-tos/images/user_testresult_ldap.png differ diff --git a/source/manual/how-tos/images/usermanager_groups.png b/source/manual/how-tos/images/usermanager_groups.png new file mode 100644 index 0000000..7f69b92 Binary files /dev/null and b/source/manual/how-tos/images/usermanager_groups.png differ diff --git a/source/manual/how-tos/images/viscosity_connected.png b/source/manual/how-tos/images/viscosity_connected.png new file mode 100644 index 0000000..ff8bd84 Binary files /dev/null and b/source/manual/how-tos/images/viscosity_connected.png differ diff --git a/source/manual/how-tos/images/viscosity_files.png b/source/manual/how-tos/images/viscosity_files.png new file mode 100644 index 0000000..5d083c0 Binary files /dev/null and b/source/manual/how-tos/images/viscosity_files.png differ diff --git a/source/manual/how-tos/images/viscosity_imported.png b/source/manual/how-tos/images/viscosity_imported.png new file mode 100644 index 0000000..d58b8d4 Binary files /dev/null and b/source/manual/how-tos/images/viscosity_imported.png differ diff --git a/source/manual/how-tos/images/viscosity_login.png b/source/manual/how-tos/images/viscosity_login.png new file mode 100644 index 0000000..bb8239e Binary files /dev/null and b/source/manual/how-tos/images/viscosity_login.png differ diff --git a/source/manual/how-tos/images/zerotier-0.png b/source/manual/how-tos/images/zerotier-0.png new file mode 100644 index 0000000..d675575 Binary files /dev/null and b/source/manual/how-tos/images/zerotier-0.png differ diff --git a/source/manual/how-tos/images/zerotier-1.png b/source/manual/how-tos/images/zerotier-1.png new file mode 100644 index 0000000..c29e7e6 Binary files /dev/null and b/source/manual/how-tos/images/zerotier-1.png differ diff --git a/source/manual/how-tos/images/zerotier-2.png b/source/manual/how-tos/images/zerotier-2.png new file mode 100644 index 0000000..02a0e80 Binary files /dev/null and b/source/manual/how-tos/images/zerotier-2.png differ diff --git a/source/manual/how-tos/images/zerotier-3.png b/source/manual/how-tos/images/zerotier-3.png new file mode 100644 index 0000000..023b606 Binary files /dev/null and b/source/manual/how-tos/images/zerotier-3.png differ diff --git a/source/manual/how-tos/images/zerotier-4.png b/source/manual/how-tos/images/zerotier-4.png new file mode 100644 index 0000000..06fdf60 Binary files /dev/null and b/source/manual/how-tos/images/zerotier-4.png differ diff --git a/source/manual/how-tos/images/zerotier-5.png b/source/manual/how-tos/images/zerotier-5.png new file mode 100644 index 0000000..3e54bf8 Binary files /dev/null and b/source/manual/how-tos/images/zerotier-5.png differ diff --git a/source/manual/how-tos/insight.rst b/source/manual/how-tos/insight.rst new file mode 100644 index 0000000..0384b60 --- /dev/null +++ b/source/manual/how-tos/insight.rst @@ -0,0 +1,137 @@ +================================ +Using Insight - Netflow Analyzer +================================ +OPNsense is equipped with a flexible and fast Netflow Analyzer called Insight. +To use Insight, one needs to configure the Netlfow exporter for local capturing +of Netflow data. To do so take a look at :doc:`netflow_exporter`. + +-------------- +User Interface +-------------- +Insight is a fully integrated part of OPNsense. Its User Interface is simple yet +powerful. + +.. image:: images/insight_gui.png + :scale: 100% + + +Insight offers a full set of analysis tools, ranging from a graphical overview to +a csv exporter for further analysis with you favorite spreadsheet. + + +--------------- +Graphs & Totals +--------------- +The default view of Insight is the Top users and Graphical Overview. +This view allows for quick examination of current and past flows, showing a graph +for in and out going traffic for each configured intertface. + +Select Range & Resolution +------------------------- +In the top right corner a selection can be made for the date range and accuracy +(resolution) of the collected traffic flows. + +View Type +--------- +One can show the traffic flows in a stacked manner (default), as a stream or expanded +to compare usage with different interfaces. + + +**Stacked** + +.. image:: images/stacked_view.png + :scale: 100% + +**Stream** + +.. image:: images/stream_view.png + :scale: 100% + +**Expanded** + +.. image:: images/expanded_view.png + :scale: 100% + +Interfaces +---------- +Clicking on an interface disables or enables the graph view, double clicking select +only that interface. + +Top Users +------------ +The top 25 users are shown for a selected interface, both for ports and ips within +the previously selected date range. + +Interface Top +------------- +Select the interface to see the top 25 users. + +Port Pie Chart +--------------- +The port pie chart shows the percentage per port/application. One can change the +view by clicking or double clicking on one of the shown port names/numbers. + +Clicking on a piece of the pie will open a detailed view for further analysis. + +.. image:: images/pie_piece.png + :scale: 100% + +.. image:: images/pie_details.png + :scale: 100% + + +IP Addresses Pie Chart +---------------------- +The IP addresses pie chart works the same as the ports pie chart and shows the +percentage per ip number. One can change the view by clicking or double clicking +on one of the shown ip numbers. + +Clicking on a piece of the pie will open a detailed view for further analysis. + +Interface Totals +---------------- +Not shown in the screenshot but latest version also includes a Total for the +selected interface, shown are Packets (In, Out, Total) and Bytes (In, Out, Total). + + +------------ +Details View +------------ +One can open the details view by clicking on one of the pieces of a pie chart or +click on the tab **Details**. + +When opening the details view by clicking on the tab one can make a new query. + +.. image:: images/insight_details_view.png + :scale: 100% + +After selecting a valid date range (form/to) and interface one can further limit +the output by filtering on port or ip address. Select the refresh icon to update +the detailed output. Leave Port and Address empty for a full detailed listing. + +.. image:: images/insight_full_details.png + :scale: 100% + + +----------- +Export View +----------- +The **Export** view allows you to export the data for further analysis in your favorite +spreadsheet or other data analysis application. + +.. image:: images/insight_export_view.png + :scale: 100% + +To export data, select a **Collection** : + +* FlowSourceAddrTotals - Totals per source address +* FlowInterfaceTotals - Totals per interface +* FlowDstPortTotals - Totals per destination port +* FlowSourceAddrDetails - Full details per source address + +Select the **Resolution** in seconds (300,3600,86400) + +Then select a date range (from/to) and click the **export** button. + +.. image:: images/insight_export.png + :scale: 100% diff --git a/source/manual/how-tos/installaws.rst b/source/manual/how-tos/installaws.rst new file mode 100644 index 0000000..15329f8 --- /dev/null +++ b/source/manual/how-tos/installaws.rst @@ -0,0 +1,95 @@ +============================= +Installing OPNsense AWS image +============================= +.. image:: images/amazon-web-services.png + :scale: 100% + +To apply for access to the OPNsense Amazon AWS EC2 cloud image, you need: + +* An active support subscription + see: https://opnsense.org/support-overview/commercial-support/) +* Supply your Amazon Account Number + to share the Amazon Machine Image with. + +--------------------- +Step 1 - New Instance +--------------------- +Start a new instance and then go to "instances", followed by "launch instance" +and then "My AMIs", don't forget to select "Shared with me" + + +-------------------- +Step 2 - Select Type +-------------------- +Choose an instance type + +.. image:: images/aws_launch_new_image.png + :scale: 100% + +--------------------------------- +Step 3 - Configure security group +--------------------------------- +To configure security group, make sure you allow https access from your own network. + +.. image:: images/aws_configure_security_group.png + :scale: 100% + + +------------------------- +Step 4 - Configure a disk +------------------------- + +.. image:: images/aws_choose_disc.png + :scale: 100% + + +----------------------------- +Step 5 - Review your settings +----------------------------- + +.. image:: images/aws_review_settings.png + :scale: 100% + +-------------------- +Step 6 - SSH keypair +-------------------- +Select ssh keypair or skip, the ssh key isn’t used for OPNsense, ssh is disabled by default. + +.. image:: images/aws_ssh_keypair.png + :scale: 100% + +--------------------------- +Step 7 - Review status page +--------------------------- + +.. image:: images/aws_status.png + :scale: 100% + +---------------------- +Step 8 - AWS instances +---------------------- +Go to your AWS instances + +.. image:: images/aws_instances.png + :scale: 100% + +Select the image, go to “image settings” then “get system log” to obtain the +initial password + +------------------------------ +Step 9 - Initial root password +------------------------------ +Copy your initial root password (line ** set initial….) + +.. image:: images/aws_capture_initial_password.png + :scale: 100% + +-------------------------------- +Step 10 - Search current address +-------------------------------- + +.. image:: images/aws_search_current_ip.png + :scale: 100% + + +Login to OPNsense using the address provided. diff --git a/source/manual/how-tos/ips-feodo.rst b/source/manual/how-tos/ips-feodo.rst new file mode 100644 index 0000000..cf6966f --- /dev/null +++ b/source/manual/how-tos/ips-feodo.rst @@ -0,0 +1,125 @@ +================================= +IPS SSLBlacklists & Feodo Tracker +================================= + +This tutorial explains how to setup the IPS system to drop SSL certificates +listed on the `abuse.ch `__ SSL Blacklists & Feodo Tracker. + +Feodo (also known as Cridex or Bugat) is a Trojan used to commit e-banking fraud +and steal sensitive information from the victim’s computer, such as credit card +details or credentials. For more information see https://feodotracker.abuse.ch + +------------- +Prerequisites +------------- +* Always upgrade to latest release first. + See :doc:`/manual/install` and/or upgrade to latest release: + **System->Firmware: Fetch updates** + +.. image:: images/firmware.png + :scale: 100% + +* Minimum Advisable Memory is 2 Gigabyte and sufficient free disk space for + logging (>10GB advisable). + +* Disable all Hardware Offloading + Under **Interface-Settings** + +.. image:: images/disable_offloading.png + :scale: 100% + +.. warning:: + + After applying you need to reboot OPNsense otherwise offloading may not + completely be disabled and IPS mode will not function. + +.. Note:: + + Some features described on this page were added in version 16.1.1. + Always keep your system up to date. + + +-------------------------------------- +Setup Intrusion Detection & Prevention +-------------------------------------- +To enable IDS/IPS just go to Services->Intrusion Detection and select **enabled +& IPS mode**. Make sure you have selected the right interface for the intrusion +detection system too run on. For our example we will use the WAN interface, as +that will most likely be you connection with the public Internet. + +.. image:: images/idps.png + :scale: 100% + +------------------- +Apply configuration +------------------- +First apply the configuration by pressing the **Apply** button at the bottom of +the form. + +.. image:: images/applybtn.png + :scale: 100% + +--------------- +Fetch Rule sets +--------------- +For this example we will only fetch the abuse.ch SSL & Dodo Tracker rulesets. +To do so: select Enabled after each one. + +.. image:: images/rulesets_enable.png + :scale: 100% + +To download the rule sets press **Download & Update Rules**. + +.. image:: images/downloadbtn.png + :scale: 100% + +----------------------- +Change default behavior +----------------------- +Now click on the info button right after each rule and change Input Filter +from none to drop actions. + +.. image:: images/changefilter.png + :scale: 100% + +When done it should like this: + +.. image:: images/rulesdrop.png + :scale: 100% + +------------------------ +Apply fraud drop actions +------------------------ +Now press **Download & Update Rules** again to change the behavior to drop. + +.. image:: images/downloadbtn.png + :scale: 100% + +--------------- +Keep up to date +--------------- +Now schedule a regular fetch to keep your server up to date. + +Click on schedule, a popup window will appear: + +.. image:: images/schedule.png + :scale: 100% + +Select **enabled** and choose a time. For the example it is set to each day at 11:12. +Select **Save changes** and wait until you have returned to the IDS screen. + +---- +DONE +---- +Your system has now been fully setup to drop known fraudulent SSL certificates +as well data phishing attempts by utilizing the Feodo tracking list. + + +------------ +Sample alert +------------ +Currently there is no test service available to check your block rules against, +however here is a sample of an actual alert that has been blocked: + +.. image:: images/alerts.jpg + :scale: 100% diff --git a/source/manual/how-tos/ips-geoip.rst b/source/manual/how-tos/ips-geoip.rst new file mode 100644 index 0000000..089e22f --- /dev/null +++ b/source/manual/how-tos/ips-geoip.rst @@ -0,0 +1,111 @@ +================== +IPS GeoIP Blocking +================== + +This tutorial explains how to setup the IPS system to block ip's based on their +geographic location. This option is made possible by the integration of the +Maxmind GeoLite2 Country database. More information can be found here: http://dev.maxmind.com/geoip/geoip2/geolite2/ + +------------- +Prerequisites +------------- +* Always upgrade to latest release first. + See :doc:`/manual/install` and/or upgrade to latest release: + **System->Firmware: Fetch updates** + +.. image:: images/firmware.png + :scale: 100% + +* Minimum Advisable Memory is 2 Gigabyte and sufficient free disk space for + logging (>10GB advisable). + +* Disable all Hardware Offloading + Under **Interface-Settings** + +.. image:: images/disable_offloading.png + :scale: 100% + +.. warning:: + + After applying you need to reboot OPNsense otherwise offloading may not + completely be disabled and IPS mode will not function. + +To start go to **Services->Intrusion Detection** + +|ids_menu| + +------------ +User defined +------------ + +Select the tab **User defined**. + +|ids_tabs_user| + +----------------- +Create a new Rule +----------------- + +Select |add| to add a new rule. + +Select Country: + +.. image:: images/ips_rule_add_geoip.png + :scale: 100% + +We selected **Netherlands(not)** as this server needs to be accessible within +The Netherlands, this will drop all other traffic in both directions. + +Select the Action (Alert or Drop): + +.. image:: images/ips_action.png + :scale: 100% + +Add a description: + +.. image:: images/ips_description_country.png + :scale: 100% + + +And click **Save changes** |save| + + +--------------------------------------- +Enable Intrusion Detection & Prevention +--------------------------------------- +To enable IDS/IPS just go to Services->Intrusion Detection and select **enabled +& IPS mode**. Make sure you have selected the right interface for the intrusion +detection system too run on. For our example we will use the WAN interface, as +that will most likely be you connection with the public Internet. + +.. image:: images/idps.png + :scale: 100% + +------------------- +Apply configuration +------------------- +If this is the first GeoIP rule you add then you need to **Download & Update Rules** + +.. image:: images/downloadbtn.png + :scale: 100% + +Then apply the configuration by pressing the **Apply** button at the bottom of +the form. + +.. image:: images/applybtn.png + :scale: 100% + + +------------ +Sample Alert +------------ +See a sample of an alert message below. + +.. image:: images/ips_geoip_alert.png + :scale: 100% + + +.. |save| image:: images/ips_save.png +.. |ids_menu| image:: images/ids_menu.png +.. |ids_tabs_user| image:: images/ids_tabs_user.png +.. |add| image:: images/ids_tabs_user_add.png diff --git a/source/manual/how-tos/ips-sslfingerprint.rst b/source/manual/how-tos/ips-sslfingerprint.rst new file mode 100644 index 0000000..e14f600 --- /dev/null +++ b/source/manual/how-tos/ips-sslfingerprint.rst @@ -0,0 +1,130 @@ +========================== +IPS Block SSL certificates +========================== + +This tutorial explains how to setup the IPS system to block ssl certificates based on their +SHA1 fingerprint. + +------------- +Prerequisites +------------- +* Always upgrade to latest release first. + See :doc:`/manual/install` and/or upgrade to latest release: + **System->Firmware: Fetch updates** + +.. image:: images/firmware.png + :scale: 100% + +* Minimum Advisable Memory is 2 Gigabyte and sufficient free disk space for + logging (>10GB advisable). + +* Disable all Hardware Offloading + Under **Interface-Settings** + +.. image:: images/disable_offloading.png + :scale: 100% + +.. warning:: + + After applying you need to reboot OPNsense otherwise offloading may not + completely be disabled and IPS mode will not function. + +To start go to **Services->Intrusion Detection** + +|ids_menu| + +------------ +User defined +------------ + +Select the tab **User defined**. + +|ids_tabs_user| + +----------------- +Create a new Rule +----------------- + +Select |add| to add a new rule. + +Get fingerprint of website +-------------------------- +It is relatively easy to find out the SSL fingerprint of a website. +For demonstration we will block facebook and use Firefox to determine the fingerprint. + +Open your browser and go to https://facebook.com when loaded click on the lock +next to the address : |lock|. + +Now you will see something similar to: + +.. image:: images/facebook_click.png + :scale: 100% + +Click on the arrow ( **>** ) and then Select **More Information** +Now open the certificate details and you will see something that looks like this: + +.. image:: images/certificate.png + :scale: 100% + +Copy the SHA1 certificate fingerprint (A0:4E:AF:B3:48:C2:6B:15:A8:C1:AA:87:A3:33:CA:A3:CD:EE:C9:C9). + + +Paste this into the new rule: + +.. image:: images/ips_rule_details.png + :scale: 100% + +Select the Action (Alert or Drop): + +.. image:: images/ips_action.png + :scale: 100% + +Add a description: + +.. image:: images/ips_description.png + :scale: 100% + + +And click **Save changes** |save| + + +--------------------------------------- +Enable Intrusion Detection & Prevention +--------------------------------------- +To enable IDS/IPS just go to Services->Intrusion Detection and select **enabled +& IPS mode**. Make sure you have selected the right interface for the intrusion +detection system too run on. For our example we will use the WAN interface, as +that will most likely be you connection with the public Internet. + +.. image:: images/idps.png + :scale: 100% + +------------------- +Apply configuration +------------------- +First apply the configuration by pressing the **Apply** button at the bottom of +the form. + +.. image:: images/applybtn.png + :scale: 100% + +---------------------------- +Clear Browser Cache and test +---------------------------- +Since your browser has cached the ssl certificate you will need to clear your +cache first. After that you can test and will see the following in **Alerts**: + +.. image:: images/ips_facebook_alert.png + :scale: 100% + +.. Note:: + + If the browser has cached the certificate no SSL certificate exchange will be + done and the website will not be blocked. + + +.. |save| image:: images/ips_save.png +.. |ids_menu| image:: images/ids_menu.png +.. |ids_tabs_user| image:: images/ids_tabs_user.png +.. |add| image:: images/ids_tabs_user_add.png +.. |lock| image:: images/facebook_lock.png diff --git a/source/manual/how-tos/ipsec-road.rst b/source/manual/how-tos/ipsec-road.rst new file mode 100644 index 0000000..0247ddb --- /dev/null +++ b/source/manual/how-tos/ipsec-road.rst @@ -0,0 +1,339 @@ +======================== +Setup IPsec Road-Warrior +======================== +Road Warriors are remote users who need secure access to the companies infrastructure. +IPsec Mobile Clients offer a solution that is easy to setup with OSX (native) +and is know to work with iOS as well as many Android devices. + +For more flexibility use SSL VPN's, OPNsense utilizes OpenVPN for this purpose. + +With this example we'll show you how to configure the Mobile Client Setup in +OPNsense and give you configuration examples for: + +* OSX +* iOS +* Android + +.. Note:: + + For the sample we will use a private ip for our WAN connection. + This requires us to disable the default block rule on wan to allow private traffic. + To do so, go to the **Interfaces->[WAN]** and uncheck "Block private networks". + *(Dont forget to save and apply)* + + .. image:: images/block_private_networks.png + +----------------------------- + +------------ +Sample Setup +------------ +For the sample configuration we configure OPNsense + +**Company Network with Remote Client** + +.. nwdiag:: + :scale: 100% + + nwdiag { + + span_width = 90; + node_width = 180; + Internet [shape = "cisco.cloud"]; + fileserver [label="File Server",shape="cisco.fileserver",address="192.168.1.10"]; + fileserver -- switchlan; + + network LAN { + switchlan [label="",shape = "cisco.workgroup_switch"]; + label = " LAN"; + address ="192.168.1.1.x/24"; + fw1 [address="192.168.1.1/24"]; + } + + network WAN { + label = " WAN"; + fw1 [shape = "cisco.firewall", address="172.18.0.164"]; + Internet; + } + + network Remote { + Internet; + laptop [address="172.10.10.55 (WANIP),10.10.0.1 (IPsec)",label="Remote User",shape="cisco.laptop"]; + } + } + +Company Network +--------------- +==================== ============================= + **Hostname** fw1 + **WAN IP** 172.18.0.164 + **LAN IP** 192.168.1.0/24 + **LAN DHCP Range** 192.168.1.100-192.168.1.200 + **IPsec Clients** 10.10.0.0/24 +==================== ============================= + + +--------------------------- +Firewall Rules Mobile Users +--------------------------- +To allow IPsec Tunnel Connections, the following should be allowed on WAN. + +* Protocol ESP +* UDP Traffic on Port 500 (ISAKMP) +* UDP Traffic on Port 4500 (NAT-T) + +.. image:: images/ipsec_wan_rules.png + :scale: 100% + +To allow traffic passing to your LAN subnet you need to add a rule to the IPsec +interface. + +.. image:: images/ipsec_ipsec_lan_rule.png + :scale: 100% + +----------------------- +Step 1 - Mobile Clients +----------------------- +First we will need to setup the mobile clients network and authentication methods. +Go to **VPN->IPsec->Mobile Clients** + +For our example will use the following settings: + +IKE Extensions +-------------- +========================= ================ ================================================ +**Enable** checked *check to enable mobile clients* +**User Authentication** Local Database *For the example we use the Local Database* +**Group Authentication** none *Leave on none* +**Virtual Address Pool** 10.0.0.0/24 *Enter the IP range for the remote clients* +========================= ================ ================================================ + +You can select other options, but we will leave them all unchecked for this +example. + +**Save** your settings and select **Create Phase1** when it appears. +Then enter the Mobile Client Phase 1 setting. + +------------------------------- +Step 2 - Phase 1 Mobile Clients +------------------------------- + +Phase 1 General information +--------------------------- +========================= ============= ================================================ +**Connection method** default *default is 'Start on traffic'* +**Key Exchange version** V1 *only V1 is supported for mobile clients* +**Internet Protocol** IPv4 +**Interface** WAN *choose the interface connected to the internet* +**Description** MobileIPsec *freely chosen description* +========================= ============= ================================================ + +Phase 1 proposal (Authentication) +--------------------------------- +=========================== ====================== ====================================== + **Authentication method** Mutual PSK +Xauth *Using a Pre-shared Key and Login* + **Negotiation mode** Agressive *Select Aggressive* + **My identifier** My IP address *Simple identification for fixed ip* + **Peer identifier** User distinguished *Identification for peer* + *Peer identifier* vpnuser@example.com *Our freely chosen identifier* + **Pre-Shared Key** At4aDMOAOub2NwT6gMHA *Random key*. **CREATE YOUR OWN!** +=========================== ====================== ====================================== + + +Phase 1 proposal (Algorithms) +----------------------------- +========================== ============= =========================================================== + **Encryption algorithm** AES *For our sample we will Use AES/256 bits* + **Hash algoritm** SHA1 *SHA1 for compatibility, you can try a stronger hash* + **DH key group** 1024 bit *1024 bit for compatibility, you can try stronger group* + **Lifetime** 28800 sec *lifetime before renegotiation* +========================== ============= =========================================================== + + +Advanced Options +---------------- +======================= =========== =================================================== +**Disable Rekey** Unchecked *Renegotiate when connection is about to expire* +**Disable Reauth** Unchecked *For IKEv2 only re-authenticate peer on rekeying* +**NAT Traversal** Enabled *Enable for IKEv1* +**Dead Peer Detection** Unchecked +======================= =========== =================================================== + + +Save your setting by pressing: + +.. image:: images/btn_save.png + :scale: 100% + +Now you should see the following screen: + +.. image:: images/ipsec_road_vpn_p1a.png + :scale: 100% + + +------------------------------- +Step 3 - Phase 2 Mobile Clients +------------------------------- +Press the button that says '+ Show 0 Phase-2 entries' + +.. image:: images/ipsec_s2s_vpn_p1a_show_p2.png + :scale: 100% + +You will see an empty list: + +.. image:: images/ipsec_s2s_vpn_p1a_p2_empty.png + :scale: 100% + +Now press the *+* at the right of this list to add a Phase 2 entry. + +General information +------------------- +======================= ================== ============================= + **Mode** Tunnel IPv4 *Select Tunnel mode* + **Description** MobileIPsecP2 *Freely chosen description* +======================= ================== ============================= + +Local Network +------------- +======================= ================== ============================== + **Local Network** LAN subnet *Route the local LAN subnet* +======================= ================== ============================== + +Phase 2 proposal (SA/Key Exchange) +---------------------------------- +=========================== ============ ========================================== +**Protocol** ESP *Choose ESP for encryption* +**Encryption algorithms** AES / 256 *For the sample we use AES 256* +**Hash algorithms** SHA1 *You may also try stronger SHA512* +**PFS Key group** off *Enable a group fro stronger security* +**Lifetime** 3600 sec +=========================== ============ ========================================== + +Save your setting by pressing: + +.. image:: images/btn_save.png + :scale: 100% + +----------------------------- + +Enable IPsec, Select: + +.. image:: images/ipsec_s2s_vpn_p1a_enable.png + :scale: 100% + +Save: + +.. image:: images/btn_save.png + :scale: 100% + +And Apply changes: + +.. image:: images/ipsec_s2s_vpn_p1a_apply.png + :scale: 100% + +------------------ + +.. image:: images/ipsec_s2s_vpn_p1a_success.png + :scale: 100% + +----------------------------- + +------------------------ +Step 4 - Add IPsec Users +------------------------ +For this example we will create a new user who may access the mobile IPsec vpn. + +Go to **System->Access->Users** and press the **+** sign in the lower right corner +to add a new user. + +Enter the following into the form: + +=============== ========== + **User Name** expert + **Password** &test!9T +=============== ========== + +**Save** this user and reopen in edit mode to add privileges. + +Add privilege **User - VPN - IPsec xauth Dialin** by pressing the **+** under +**Effective Privileges**. + +**Save** to apply. + +---------------------- + +------------------------- +Step 5 - Configure Client +------------------------- +To illustrate the client setup we will look at the configuration under OSX, including +some screenshots. The configurations for Android and iOS will be settings only. + +.. Note:: + Configuration samples listed here where created using latest OSX, iOS and + Android devices on time of publication in February 2016. + +-------------------- +Configure OSX Client +-------------------- + +Start with opening your network settings (System Preferences -> Network) and +Add a new network by pressing the + in the lower left corner. + +Now select **VPN** and **Cisco IPSec**, give your connection a name and press **Create**. + +.. image:: images/osx-ipsec-new.png + :scale: 100% + +Now enter the details for our connection: + +.. image:: images/osx-ipsec-conf1.png + :scale: 100% + +Next press **Authentication Settings** to add the group name and pre-shared key. + +.. image:: images/osx-ipsec-conf2.png + :scale: 100% + +Press **OK** to save these settings and then **Apply** to apply them. + +Now test the connection by selecting it from the list and hit **Connect**. + +.. image:: images/osx-ipsec-connected.png + :scale: 100% + +**Done** + +-------------------- +Configure iOS Client +-------------------- +To add a VPN connection on an iOS device go to **Setting->General->VPN**. +Select **Add VPN Configuration** chose **IPsec** and use the Following Settings: + +========================== ======================= ======================================== + **Description** IPsec OPNsense *Freely chosen description* + **Server** 172.18.0.164 *Our server address* + **Account** expert *Username of the remote account* + **Password** &test!9T *Leave blank to be prompted every time* + **IPsec-id** vpnuser@example.com *The peer identity we chose* + **Preshared IPsec-key** At4aDMOAOub2NwT6gMHA *Our PSK* +========================== ======================= ======================================== + +------------------------ +Configure Android Client +------------------------ +To add a VPN connection on an Android device go to **Settings -> Connections -> +more networks** , select **VPN**. Press the **+** in the top right corner to add +a new vpn connection. + +Use the Following Settings: + +========================== ======================= ============================= + **Name** IPsec OPNsense *Freely chosen name* + **Type** IPSec Xauth PSK *As configured in OPNsense* + **Server address** 172.18.0.164 *Our server address* + **IPsec-id** vpnuser@example.com *The peer identity we chose* + **Preshared IPsec-key** At4aDMOAOub2NwT6gMHA *Our PSK* +========================== ======================= ============================= + +**Save** and try connecting. To connect enter Username and Password for the user +*expert* we created in this example. diff --git a/source/manual/how-tos/ipsec-s2s.rst b/source/manual/how-tos/ipsec-s2s.rst new file mode 100644 index 0000000..1e2a36c --- /dev/null +++ b/source/manual/how-tos/ipsec-s2s.rst @@ -0,0 +1,533 @@ +================================ +Setup IPsec site to site tunnel +================================ + +Site to site VPN's connect two locations with static public IP addresses and allow +traffic to be routed between the two networks. This is most commonly used to +connect an organization's branch offices back to its main office, so branch users +can access network resources in the main office. + +---------------- +Before you start +---------------- +Before starting with the configuration of an IPsec tunnel you need to have a +working OPNsense installation wit a unique LAN IP subnet for each side of your +connection (you local network need to different than that of the remote network). + +.. Note:: + + For the sample we will use a private ip for our WAN connection. + This requires us to disable the default block rule on wan to allow private traffic. + To do so, go to the **Interfaces->[WAN]** and uncheck "Block private networks". + *(Dont forget to save and apply)* + + .. image:: images/block_private_networks.png + +----------------------------- + +------------ +Sample Setup +------------ +For the sample configuration we use two OPNsense boxes to simulate a site to site +tunnel, with the following configuration: + +.. sidebar:: Network Site A + + .. nwdiag:: + :scale: 100% + + nwdiag { + + span_width = 90; + node_width = 180; + Internet [shape = "cisco.cloud"]; + pclana [label="PC Site A",shape="cisco.pc"]; + pclana -- switchlana; + + network LANA { + switchlana [label="",shape = "cisco.workgroup_switch"]; + label = " LAN Site A"; + address ="192.168.1.1.x/24"; + fw1 [address="192.168.1.1/24"]; + tunnel [label=" IPsec Tunnel",shape = cisco.cloud]; + } + + network WANA { + label = " WAN Site A"; + fw1 [shape = "cisco.firewall", address="172.10.1.1/24"]; + Internet; + } + + } + +Site A +------ +==================== ============================= + **Hostname** fw1 + **WAN IP** 172.10.1.1/24 + **LAN IP** 192.168.1.1/24 + **LAN DHCP Range** 192.168.1.100-192.168.1.200 +==================== ============================= + +| +| +| +| + +----------------------------- + +.. sidebar:: Network Site B + + .. nwdiag:: + :scale: 100% + + nwdiag { + + span_width = 90; + node_width = 180; + Internet [shape = "cisco.cloud"]; + pclanb [label="PC Site B",shape="cisco.pc"]; + pclanb -- switchlanb; + + network LANB { + label = " LAN Site B"; + address ="192.168.2.1.x/24"; + fw2 [address="192.168.2.1/24"]; + tunnel [label=" IPsec Tunnel",shape = cisco.cloud]; + switchlanb [label="",shape = "cisco.workgroup_switch"]; + } + + network WANB { + label = " WAN Site B"; + fw2 [shape = "cisco.firewall", address="172.10.2.1/24"]; + Internet; + } + + } + +Site B +------ + +==================== ============================= + **Hostname** fw2 + **WAN IP** 172.10.2.1/24 + **LAN Net** 192.168.2.0/24 + **LAN DHCP Range** 192.168.2.100-192.168.2.200 +==================== ============================= + +| +| +| +| + +----------------------------- + + +Full Network Diagram Including IPsec Tunnel +------------------------------------------- + +.. nwdiag:: + :scale: 100% + :caption: IPsec Site-to-Site tunnel network + + nwdiag { + + span_width = 90; + node_width = 180; + Internet [shape = "cisco.cloud"]; + pclana [label="PC Site A",shape="cisco.pc"]; + pclana -- switchlana; + + network LANA { + switchlana [label="",shape = "cisco.workgroup_switch"]; + label = " LAN Site A"; + address ="192.168.1.1.x/24"; + fw1 [address="192.168.1.1/24"]; + tunnel [label=" IPsec Tunnel",shape = cisco.cloud]; + } + + network WANA { + label = " WAN Site A"; + fw1 [shape = "cisco.firewall", address="172.10.1.1/24"]; + Internet; + } + + network WANB { + label = " WAN Site B"; + fw2 [shape = "cisco.firewall", address="172.10.2.1/24"]; + Internet; + } + + network LANB { + label = " LAN Site B"; + address ="192.168.2.1.x/24"; + fw2 [address="192.168.2.1/24"]; + tunnel; + switchlanb [label="",shape = "cisco.workgroup_switch"]; + } + pclanb [label="PC Site B",shape="cisco.pc"]; + pclanb -- switchlanb; + + } + +------------------------------ +Firewall Rules Site A & Site B +------------------------------ +To allow IPsec Tunnel Connections, the following should be allowed on WAN for on +sites: + +* Protocol ESP +* UDP Traffic on Port 500 (ISAKMP) +* UDP Traffic on Port 4500 (NAT-T) + +.. image:: images/ipsec_wan_rules.png + :scale: 100% + +.. Note:: + + You can further limit the traffic by the source ip of the remote host. + +To allow traffic passing to your LAN subnet you need to add a rule to the IPsec +interface. + +.. image:: images/ipsec_ipsec_lan_rule.png + :scale: 100% + +----------------------- +Step 1 - Phase 1 Site A +----------------------- +(Under **VPN->IPsec->Tunnel Settings** Press **+**) +We will use the following settings: + +General information +------------------- +========================= ============= ================================================ +**Connection method** default *default is 'Start on traffic'* +**Key Exchange version** V2 *both V1 and V2 are supported* +**Internet Protocol** IPv4 +**Interface** WAN *choose the interface connected to the internet* +**Remote gateway** 172.10.2.1 *the public ip address of your remote OPNsense* +**Description** Site B *freely chosen description* +========================= ============= ================================================ + + +Phase 1 proposal (Authentication) +--------------------------------- +=========================== ====================== ====================================== + **Authentication method** Mutual PSK *Using a Pre-shared Key* + **Negotiation mode** Main *Use Main. Aggressive is insecure* + **My identifier** My IP address *Simple identification for fixed ip* + **Peer identifier** Peer IP address *Simple identification for fixed ip* + **Pre-Shared Key** At4aDMOAOub2NwT6gMHA *Random key*. **CREATE YOUR OWN!** +=========================== ====================== ====================================== + + +Phase 1 proposal (Algorithms) +----------------------------- +========================== ============= =========================================== + **Encryption algorithm** AES *For our sample we will Use AES/256 bits* + **Hash algoritm** SHA512 *Use a strong hash like SHA512* + **DH key group** 2048 bit *2048 bit should be sufficient* + **Lifetime** 28800 sec *lifetime before renegotiation* +========================== ============= =========================================== + + +Advanced Options +---------------- +======================= =========== =================================================== +**Disable Rekey** Unchecked *Renegotiate when connection is about to expire* +**Disable Reauth** Unchecked *For IKEv2 only re-authenticate peer on rekeying* +**NAT Traversal** Disabled *For IKEv2 NAT traversal is always enabled* +**Dead Peer Detection** Unchecked +======================= =========== =================================================== + + +Save your setting by pressing: + +.. image:: images/btn_save.png + :scale: 100% + +Now you should see the following screen: + +.. image:: images/ipsec_s2s_vpn_p1a_4.png + :scale: 100% + + +----------------------- +Step 2 - Phase 2 Site A +----------------------- +Press the button that says '+ Show 0 Phase-2 entries' + +.. image:: images/ipsec_s2s_vpn_p1a_show_p2.png + :scale: 100% + +You will see an empty list: + +.. image:: images/ipsec_s2s_vpn_p1a_p2_empty.png + :scale: 100% + +Now press the *+* at the right of this list to add a Phase 2 entry. + +General information +------------------- +======================= ================== ============================= + **Mode** Tunnel IPv4 *Select Tunnel mode* + **Description** Local LAN Site B *Freely chosen description* +======================= ================== ============================= + +Local Network +------------- +======================= ================== ============================== + **Local Network** LAN subnet *Route the local LAN subnet* +======================= ================== ============================== + +Remote Network +-------------- +============== =============== ========================== + **Type** Network *Route a remote network* + **Address** 192.168.2.1/24 *The remote LAN subnet* +============== =============== ========================== + + +Phase 2 proposal (SA/Key Exchange) +---------------------------------- +=========================== ============ ======================================= +**Protocol** ESP *Choose ESP for encryption* +**Encryption algorithms** AES / 256 *For the sample we use AES 256* +**Hash algortihms** SHA512 *Choose a strong hash like SHA512* +**PFS Key group** 2048 bit *Not required but enhanced security* +**Lifetime** 3600 sec +=========================== ============ ======================================= + +Save your setting by pressing: + +.. image:: images/btn_save.png + :scale: 100% + +----------------------------- + +Enable IPsec for Site A, Select: + +.. image:: images/ipsec_s2s_vpn_p1a_enable.png + :scale: 100% + +Save: + +.. image:: images/btn_save.png + :scale: 100% + +And Apply changes: + +.. image:: images/ipsec_s2s_vpn_p1a_apply.png + :scale: 100% + +------------------ + +.. image:: images/ipsec_s2s_vpn_p1a_success.png + :scale: 100% + +**You are done configuring Site A.** + +----------------------------- + +----------------------- +Step 3 - Phase 1 Site B +----------------------- +(Under **VPN->IPsec->Tunnel Settings** Press **+**) +We will use the following settings: + +General information +------------------- +========================= ============= ================================================ +**Connection method** default *default is 'Start on traffic'* +**Key Exchange version** V2 *both V1 and V2 are supported* +**Internet Protocol** IPv4 +**Interface** WAN *choose the interface connected to the internet* +**Remote gateway** 172.10.1.1 *the public ip address of your remote OPNsense* +**Description** Site A *freely chosen description* +========================= ============= ================================================ + + +Phase 1 proposal (Authentication) +--------------------------------- +=========================== ====================== ====================================== + **Authentication method** Mutual PSK *Using a Pre-shared Key* + **Negotiation mode** Main *Use Main. Aggressive is insecure* + **My identifier** My IP address *Simple identification for fixed ip* + **Peer identifier** Peer IP address *Simple identification for fixed ip* + **Pre-Shared Key** At4aDMOAOub2NwT6gMHA *Random key*. **CREATE YOUR OWN!** +=========================== ====================== ====================================== + + +Phase 1 proposal (Algorithms) +----------------------------- +========================== ============= =========================================== + **Encryption algorithm** AES *For our sample we will Use AES/256 bits* + **Hash algoritm** SHA512 *Use a strong hash like SHA512* + **DH key group** 2048 bit *2048 bit should be sufficient* + **Lifetime** 28800 sec *lifetime before renegotiation* +========================== ============= =========================================== + + +Advanced Options +---------------- +======================= =========== =================================================== +**Disable Rekey** Unchecked *Renegotiate when connection is about to expired* +**Disable Reauth** Unchecked *For IKEv2 only re-authenticate peer on rekeying* +**NAT Traversal** Disable *For IKEv2 NAT traversal is always enabled* +**Dead Peer Detection** Unchecked +======================= =========== =================================================== + + +Save your setting by pressing: + +.. image:: images/btn_save.png + :scale: 100% + +Now you should see the following screen: + +.. image:: images/ipsec_s2s_vpn_p1b_4.png + :scale: 100% + + +----------------------- +Step 4 - Phase 2 Site B +----------------------- + +Press the button that says '+ Show 0 Phase-2 entries' + +.. image:: images/ipsec_s2s_vpn_p1a_show_p2.png + +You will see an empty list: + +.. image:: images/ipsec_s2s_vpn_p1a_p2_empty.png + :scale: 100% + +Now press the *+* at the right of this list to add a Phase 2 entry. + +General information +------------------- +======================= ================== ============================= + **Mode** Tunnel IPv4 *Select Tunnel mode* + **Description** Local LAN Site A *Freely chosen description* +======================= ================== ============================= + + +Local Network +------------- +======================= ================== ============================== + **Local Network** LAN subnet *Route the local LAN subnet* +======================= ================== ============================== + +Remote Network +-------------- +============== =============== ========================== + **Type** Network *Route a remote network* + **Address** 192.168.1.1/24 *The remote LAN subnet* +============== =============== ========================== + + +Phase 2 proposal (SA/Key Exchange) +---------------------------------- +=========================== ============ ======================================= +**Protocol** ESP *Choose ESP for encryption* +**Encryption algorithms** AES / 256 *For the sample we use AES 256* +**Hash algortihms** SHA512 *Choose a strong hash like SHA512* +**PFS Key group** 2048 bit *Not required but enhanced security* +**Lifetime** 3600 sec +=========================== ============ ======================================= + + +Save your setting by pressing: + +.. image:: images/btn_save.png + :scale: 100% + +----------------------------- + +Enable IPsec for Site B, Select: + +.. image:: images/ipsec_s2s_vpn_p1a_enable.png + :scale: 100% + +Save: + +.. image:: images/btn_save.png + :scale: 100% + +And Apply changes: + +.. image:: images/ipsec_s2s_vpn_p1a_apply.png + :scale: 100% + +----------------------------- + +.. image:: images/ipsec_s2s_vpn_p1a_success.png + :scale: 100% + +**You are done configuring Site B.** + + +------------------ +IPsec Tunnel Ready +------------------ + +The tunnel should now be up and routing the both networks. +Go to **VPN->IPsec->Status Overview** to see current status. +Press on the **(i)** to see the details of the phase 2 tunnel(s), like this: + +.. image:: images/ipsec_status.png + :scale: 100% + +.. Note:: + + If the tunnel did not come up, try to restart the service on both ends. + +-------------------- +Sample configuration +-------------------- +For test purposes we used two OPNsense boxes integrated into one unit and a +cross-cable between the WAN ports. + +.. image:: images/OPN20322R_870px.png + :target: https://www.deciso.com/product-catalog/opn20322r/ + :scale: 100% + +To route traffic the WAN interfaces have been configured to use a /16 segment and +they are each others default gateway. Other than that the sample is equal to this +how-to. + +Configuration Site A + :download:`Config.xml Site A ` + +Configuration Site B + :download:`Config.xml Site B ` + +---------------- +Trouble shooting +---------------- + +Phase 1 won't come up +--------------------- +That is a difficult one. First check you firewall rules to see if you allow the +right ports and protocols (ESP, UDP 500 & UDP 4500) for the WAN interface. + +Check your ipsec log to see if that reviels a possible cause. + +Common issues are unequal settings. Both ends must use the +same PSK and encryption standard. + +Phase 1 works but no phase 2 tunnels are connected +--------------------------------------------------- + +Did you set the correct local and remote networks. A common mistake is to fill in +the ip address of the remote host in stead of its network ending with **x.x.x.0** + +Common issues are unequal settings. Both ends must use the same encryption standard. + + +.. Note:: + + If you are testing locally with your pc connected to one of the two test boxes + as in the sample configuration, then make sure you have no other network + connections (f.i. wifi). diff --git a/source/manual/how-tos/ipv6_tunnelbroker.rst b/source/manual/how-tos/ipv6_tunnelbroker.rst new file mode 100644 index 0000000..27425e3 --- /dev/null +++ b/source/manual/how-tos/ipv6_tunnelbroker.rst @@ -0,0 +1,129 @@ +============================ +Configure IPv6 Tunnel Broker +============================ +**Original Author:** Shawn Webb + +------------ +Introduction +------------ + +OPNsense supports native IPv6 as well as tunneled IPv6. This article shows how +to set up TunnelBroker, Hurricane Electric's IPv6-in-IPv4 tunnel, with OPNsense. +If you're based in the US and you use Netflix, you might not want to follow these +instructions. Netflix now blocks TunnelBroker. + +If you use IRC or need access to SMTP over the TunnelBroker connection, +Hurricane Electric requires you to go through their free IPv6 certification process. +Their "sage" level is the highest level and will allow you to enable IRC and SMTP. +Note that your OPNsense firewall must be directly connected to the Internet. +Being behind a NAT will not work. + +The rest of this article assumes you already have a TunnelBroker account. If not, +sign up and go through the free IPv6 certification process. Screenshots are provided +throughout this article. + +---------- +Background +---------- + +Enable ICMP on the WAN side of your OPNsense firewall. TunnelBroker's UI will +tell you an IP to use when you're setting up your tunnel on their end. + +Now add a tunnel. Make sure to add a routed /48 as we will need that to dish out +individual /64 slices to each network. Once configured, your tunnel settings +should look like this: + +.. image:: images/tunnelbroker_setup.png + :scale: 100% + +----------------------- +Step 1 - Add GIF tunnel +----------------------- + +To configure OPNsense start with adding a new gif interface. +Go to **Interfaces->Other Types->GIF** and click on **Add** in the upper tight corner +of the form. + +Use the following settings and copy in the IPv4&6 addresses from your TunnelBroker's UI. + +============================== ============================ + **Parent interface** *WAN* + **GIF remote address** *Server IPv4 Address* + **GIF tunnel local address** *Client IPv6 Address* + **GIF tunnel remote address** *Server IPv6 Address/64* + **Route caching** *disabled* + **ECN friendly behavior** *disabled* + **Description** *Tunnel Broker* +============================== ============================ + +.. Note:: + + Make sure to include the **/64** prefixes! + +.. image:: images/opnsense_add_gif.png + :scale: 100% + +---------------------------------------------------- +Step 2 - Configure the GIF tunnel as a new interface +---------------------------------------------------- + +The newly created GIF tunnel must now be assigned as a new interface. +Go to **Interfaces->Assignments**, select the GIF tunnel for **New interface** +and click the **+** sign next to it. + +Then under **Interfaces->[OPTX]** check **Enable Interface** and change the +description to e.g. TUNNELBROKER before hitting **Save**. + +The newly created interface must now be set as the default IPv6 gateway +under **System->Gateways->All** by editing the new gateway entry +TUNNELBROKER_TUNNELV6 and checking **Default Gateway** before saving. + +----------------------------- +Step 3 - Basic Firewall Rules +----------------------------- + +Now add basic firewall rules. Since I have a LAN network and a WLAN network, I +allow WLAN to initiate connections to LAN, but not the other way around. I only +have servers on LAN whereas most of my clients are on WLAN (Wireless LAN). +I block all incoming to LAN and WLAN. Of course, outbound connections are fine. + +.. image:: images/tunnelbroker_fw_rules.png + :scale: 100% + +-------------------------------- +Step 4 - Configure LAN interface +-------------------------------- + +Now configure your LAN interface. The static IPv6 address we'll give it is a +**/64** address from your assigned **/48**. I won't show the WLAN settings simply +because it's the very same. You'll repeat the same process for further networks, +but assigning the next interface a separate **/64** address. + +.. image:: images/tunnelbroker_configure_lan.png + :scale: 100% + +------------------------------- +Step 5 - Configure DHCPv6 SLAAC +------------------------------- + +We'll next configure OPNsense for Stateless Address Auto Configuration (SLAAC). +We're going to set up the DHCPv6 service. Go to **Services->DHCPv6->Server**. + +Simply choose a range for clients to use. Save your settings. Next go to the +Router Advertisements sub tab on that same page. Set the **Router Advertisements** +setting to *Assisted* and the **Router Priority** setting to *Normal*. + +.. image:: images/tunnelbroker_dhcpv6.png + :scale: 100% + +Save your settings. + +-------------------------------- +Step 6 - Test your Configuration +-------------------------------- + +You should now be set up for IPv6. To test your configuration, bring online an +IPv6 machine, use your favorite tool to determine you have an IPv6 address. If +you're using SLAAC, it may take up to 30 seconds or more to get an IPv6 address. +If you see that your interface has an IPv6 address, you can try going to an +IPv6 only test site, such as http://6.ifconfig.pro/ diff --git a/source/manual/how-tos/mailgateway.rst b/source/manual/how-tos/mailgateway.rst new file mode 100644 index 0000000..a712c9f --- /dev/null +++ b/source/manual/how-tos/mailgateway.rst @@ -0,0 +1,112 @@ +================================= +How To: Setting Up A Mail Gateway +================================= + +.. Warning:: + A mail gateway under high load may need a lot of memory and CPU power. + Keep in mind that the components have some hardware requirements like the + ClamAV- and the Redis plugin. + It is not recommended to run this software on weak hardware. + +------------ +Installation +------------ + +First of all, you have to install the required plugins from the plugins view. + +.. image:: ../images/menu_plugins.png + +The required plugins are: + +* ClamAV +* Postfix +* Redis +* Rspamd + +After a page reload you will get some new menu entry under services for all installed plugins. + +---------------------------- +Configuration Of The Plugins +---------------------------- + +1. ClamAV +--------- + +For ClamAV, you can follow the instructions in :doc:`clamav`. + +2. Redis (optional but recommended) +----------------------------------- + +In the next step, we need to install the Redis database. Redis is required for caching and for +some features of the rspamd plugin. + +.. Warning:: + If you don't set up a Redis instance, some components of rspamd will automatically disable + themself silently and it will not be visible in the GUI. + +.. Image:: images/redis_general.png + +For a basic Redis instance, you can just check `Enable Redis` and click `Apply` to start the servers. + + +3. Rspamd +--------- + +First of all, you will need to activate the plugin by checking the `Enable rspamd` checkbox. +If you have installed and configured the Redis plugin, you should check the second checkbox as well. + +.. Image:: images/rspamd_general.png + +If you are ready, rspamd should be up and running. + +Now you should configure the rspamd modules you need. + +.. Note:: + The ClamAV component does enable or disable itself automatically if it has been configured + depending on the ClamAV (clamd) configuration. + +For example, if the MX should be checked, the menu for the `Spam Protection`: + +.. Image:: images/rspamd_antispam_menu.png + +After a click, you will see the form: + +.. Image:: images/rspamd_mx_check.png + +In this case the configuration is quite simple: Check `Enabled`, add a cache expiration time (in +Seconds) as well as clicking at the `Apply` button. + +Postfix +------- + +First of all, you need to configure the domains you want to forward in the `Domains` menu. +.. Image:: images/postfix_add_new_domain.png + +Enter the values for your mail server in the dialog after clicking `+`: + +.. Image:: images/postfix_add_domain_forward.png + +After saving usually the apply button needs to be hit but the server is not running anyway as it +needs to be configured first. If you add new domains, you have to hit this button to apply changes. + +.. Image:: images/postfix_general_tab.png + +In the `General` tab, the Postfix service must be enabled. +If your system settings differ from your system settings, you may override them here. +For example overriding the hostname makes sense because you may want to use the hostname +which has been configured as the MX host in the DNS. + +You shhould keep the checkboxes at the bottom enabled as they enable restrictions, which provide an additional layer of security. + +Save the changes and switch to `Antispam` tab. + +.. Image:: images/postfix_antispam_tab.png + +Enable the Checkbox and click `Save`. + +--------------- +Follow Up Tasks +--------------- + +In the next step, you should go to the `Firewall` menu. +Create a new rule to pass port TCP/25 traffic from `Any` to `This Firewall`. diff --git a/source/manual/how-tos/multicast-dns.rst b/source/manual/how-tos/multicast-dns.rst new file mode 100644 index 0000000..711e0d7 --- /dev/null +++ b/source/manual/how-tos/multicast-dns.rst @@ -0,0 +1,37 @@ +=================== +Multicast DNS Proxy +=================== + +If you want to connect multicast DNS of multiple networks, you will need to proxy between them. + +------------ +Installation +------------ + +First of all, you have to install the mdns-repeater plugin (os-mdns-repeater) from the plugins view. + +.. image:: ../images/menu_plugins.png + + +After a page reload you will get a new menu entry under services for MDNS Repeater. +Select it and you will get to the following screen: + +.. image:: images/plugin_mdns_repeater.png + +------------- +Configuration +------------- + +.. Warning:: + mdns-repeater requires at least 2 interfaces to work. + +The configuration is fairly simple. Just enable the service and add the interfaces. +For example: + +========== ================== +Property Value +========== ================== +Enabled checked +Interfaces LAN, OPT1, OPT2 +========== ================== + diff --git a/source/manual/how-tos/multiwan.rst b/source/manual/how-tos/multiwan.rst new file mode 100644 index 0000000..98368bb --- /dev/null +++ b/source/manual/how-tos/multiwan.rst @@ -0,0 +1,211 @@ +=============== +Setup Multi WAN +=============== +Multi WAN scenario's are commonly used for failover or load balancing, but combinations +are also possible with OPNsense. + +.. blockdiag:: + :desctable: + + blockdiag { + WAN_primary -- OPNsense; + OPNsense -- WAN_backup; + internet -- WAN_primary; + WAN_backup -- internet; + internet [shape="cloud"]; + WAN_primary [shape="cisco.modem",label=""]; + WAN_backup [shape="cisco.modem",label=""]; + + } + + +------------------ +Configure Failover +------------------ +To setup Failover the following step will be taken: + +#. Add monitor IP's to the gateways +#. Add a gateway group +#. Configure DNS for each gateway +#. Use policy based routing to utilize our gateway group +#. Add a firewall rule for DNS traffic that is intended for the firewall itself + +.. TIP:: + Did you know you can browse quick and easy to the right page by using the + search box in the top right corner of your screen? Like this: + + .. image:: /manual/images/quick-navigation.png + + +Example configuration +--------------------- +Our example utilized two previous configured WAN gateways that both are confirmed +to function separately. As DNS's and monitor ip's we will utilize google's DNS +services 8.8.8.8 and 8.8.4.4, of course you can use your own 'known good' setting. + +We defined WAN and WAN2, where WAN will be our primary (default) gateway. + +Step 1 - Add monitor IP's +------------------------- +You may skip this step if you already have setup the monitoring ip and both gateways +are shown as online. + +To add a monitoring ip go to **System->Gateways->All** and click on the first pencil +symbol to edit the first gateway. + +Now make sure the following is configured: + +================================= ============= =================================== + **Disable Gateway Monitoring** Unchecked *Make sure monitoring is enabled* + **Monitor IP** 8.8.8.8 *We use Google's DNS* + **Mark Gateway as Down** Unchecked +================================= ============= =================================== + +Then click on the second pencil symbol to edit the second gateway. + +Now make sure the following is configured: + +================================= ============= =================================== + **Disable Gateway Monitoring** Unchecked *Make sure monitoring is enabled* + **Monitor IP** 8.8.4.4 *We use Google's second DNS* + **Mark Gateway as Down** Unchecked +================================= ============= =================================== + +Step 2 - Add Gateway Group +-------------------------- +Go to **System->Gateways->Group** and press **+ Add Group** in the upper right +corner. + +Use the following settings: + +======================= ================== ============================================ + **Group Name** WANGWGROUP *Enter a name for the gw routing later on* + **Gateway Priority** WANGW / Tier 1 *Select the first gateway and Tier 1* + *..* WAN2GW / Tier 2 *Select the second gateway and Tier 2* + **Trigger Level** Packet Loss *Select the trigger you want to use* + **Description** Failover Group *Freely chosen description* +======================= ================== ============================================ + +.. Tip:: + **Trigger Level Explained** + + * Member Down + *Triggers when the gateway has 100% packet loss.* + * Packet Loss + *Triggers when the packet loss to a gateway is higher then the defined threshold.* + * High Latency + *Triggers when the latency to a gateway higher than its defined threshold.* + * Packet Loss or High Latency + *Triggers for either of the above conditions.* + +Step 3 - Configure DNS for each gateway +--------------------------------------- +Go to **System->Settings->General** and make sure each gateway has its own DNS +setup: like this: + +DNS servers + +================= ========= + **8.8.8.8** WANGW + **8.8.4.4** WAN2GW +================= ========= + +Step 4 - Policy based routing +----------------------------- +Go to **Firewall->Rules** + +For our example we will update the default LAN pass rule. Click on the pencil +next to this rule (*Default allow LAN to any rule*). + +Now under **Gateway** change selection to *WANGWGROUP*. + +**Save** and **Apply changes** + +.. Note:: + This rule will utilize the gateway group for all traffic coming from our LAN + network. This also means that traffic intended for the firewall itself will + be routed in this (wrong) direction. That is why Step 5 is needed for our DNS + traffic going to and coming from our DNS forwarder on the firewall itself. + +Step 5 - Add allow rule for DNS traffic +--------------------------------------- +Add a rule just above the default LAN allow rule to make sure traffic to and from +the firewall on port 53 (DNS) is not going to be routed to the Gateway Group that +we just defined. + +Start with pressing the *+* icon in the bottom left corner. + +Enter the following details: + +============================= ======================== ====================================== + **Action** Pass *Allow this traffic to pass* + **Interface** LAN + **TCP/IP Version** IPv4 *For our example we use IPv4* + **Protocol** TCP/UDP *Select the right protocol* + **Source** any + **Destination** Single host or Network + **Destination** 192.168.1.1/32 *IP of the firewall only hence /32* + **Destination port range** DNS - DNS *Only DNS* + **Category** DNS *See* :doc:`fwcategory` + **Description** Local Route DNS *Freely chosen description* + **Gateway** default *Select default* +============================= ======================== ====================================== + +Advanced Options +---------------- +For each gateway there are several advanced options you can use to change the +default behavior/thresholds. These option can be changed under +**System->Gateways->All**, press the pencil icon next to the Gateway you want +to update. + +The current options are: + * Latency thresholds + Low and high thresholds for latency in milliseconds. + * Packet Loss thresholds + Low and high thresholds for packet loss in %. + * Probe Interval + How often that an ICMP probe will be sent in seconds. + * Down + The number of seconds of failed probes before the alarm will fire. + * Avg Delay Replies Qty + How many replies should be used to compute average delay for controlling "delay" alarms? + * Avg Packet Loss Probes Qty + How many probes should be used to compute average packet loss. + * Lost Probe Delay + The delay (in qty of probe samples) after which loss is computed. + +------------------------ +Configure Load Balancing +------------------------ +To setup load balancing follow the same configuration procedure as for Failover, +but in step 2 choose same **Tier** for both Gateways. + +This will change the behavior from failover to equal balancing between the two +gateways. + +Sticky Connection +----------------- +Some web sites don't like changing request ip's for the same session, this may +lead to unexpected behavior. To solve this you can use the option **Sticky Connections**, +this will make sure each subsequent request from the same user to the same website +is send through the same gateway. + +To set this option can be set under **Firewall->Settings->Advanced**. + +Unequal Balancing (Weight) +-------------------------- +If you have a non symmetric setup with one IPS having a much higher +bandwidth that the other then you can set a weight on each gateway to change the +load balance. For instance if you have one line of 10Mbps and one of 20Mbps then +set the weight of the first one to 1 and the second one to 2. This way the second +gateway will get twice as many traffic to handle than the first. + +To do so, go to **System->Gateways->All** and press the pencil icon next to the +Gateway you want to update. The weight is defined under the advanced section. + +------------------------------ +Combining Balancing & Failover +------------------------------ +To combine Load Balancing with Failover you will have 2 or more WAN connections +for Balancing purposes and 1 or more for Failover. OPNsense offers 5 tiers +(Failover groups) each tier can hold multiple ISP's/WAN gateways. diff --git a/source/manual/how-tos/netflow_exporter.rst b/source/manual/how-tos/netflow_exporter.rst new file mode 100644 index 0000000..a798637 --- /dev/null +++ b/source/manual/how-tos/netflow_exporter.rst @@ -0,0 +1,22 @@ +-------------------------- +Configure Netflow Exporter +-------------------------- + +.. image:: images/netflow_exporter.png + +Configuring the Netflow Exporter is a simple task. Go to **Reporting->NetFlow**. + +Select all **Interfaces** you want to collect/export data from, usually one would +select all available interfaces here. + +If you do not want to record traffic originating or going to the firewall itself +then add the interfaces to **Egress only** to prevent double counting of the same traffic +flow (See also :doc:`/manual/netflow` for more information). + +For local analysis using Insight also enable **Capture local**. + +Depending on the application you would like to use select **Version** 5 or 9. +Remember that version 5 does not support IPv6. + +Add your **Destinations** (ip:port then enter) local ip will be added automatic +if Capture local is selected. diff --git a/source/manual/how-tos/proxyicapantivirus.rst b/source/manual/how-tos/proxyicapantivirus.rst new file mode 100644 index 0000000..24aacce --- /dev/null +++ b/source/manual/how-tos/proxyicapantivirus.rst @@ -0,0 +1,89 @@ +=========================== +Setup Anti Virus Protection +=========================== +OPNsense can offer http and https protection by utilizing its highly flexible +proxy and the industry standard ICAP. An external engine from one of the known +vendors is used to offer maximum protection against malware, such as ransomware, +trojans and viruses. This protection can be further enhanced by the build-in Intrusion +Prevention System and Category Based Web filtering. + +This How To will utilize Symantec's Protection Engine, but any other vendor that +support ICAP will work just as well. + +.. Note:: + The Anti Virus Engine can protect you against malicious websites and infected + file downloads, it does not protect the local clients. Therefore it is always + a good idea to install a client based solution as well to protect against other + forms of infection such as through emails or usb stick. + +.. image:: images/SPE_home.png + :scale: 100% + +Step 1 - Setup the Proxy +------------------------ +Start with setting up the proxy with its basic configuration, see :doc:`cachingproxy`. + +Step 2 - Setup Transparent Mode +------------------------------- +To setup the transparent mode, see: :doc:`proxytransparent`. + +Step 3 - Configure the Engine +----------------------------- +For this example we have used Symantecs Protection Engine. +The installation is straight forward, please refer to Symantecs documentation for +full installation and configuration instructions. + +We installed the Engine for Web Proxy purpose and enabled ICAP with its default settings. + +.. image:: images/SPE_ICAP.png + :scale: 100% + +Step 4 - Connect the Engine +--------------------------- +Now connect the server that the engine is installed on to OPNsense trough either +a switch or a direct cable connection. Preferable use a separate network for this +traffic to make sure the unencrypted ICAP traffic can's be tapped. + +.. Note:: + ICAP traffic is not encrypted, meaning you have to make sure the traffic is not + visible to anyone else. When using transparent https mode it is best to configure + a separate interface for ICAP traffic and connect the Server (Engine) directly + with a crosslink cable. Alternatively one may use a VLAN for this purpose. + +Step 5 - Configure ICAP +----------------------- +To configure ICAP go to **Services->Proxy->Administration** And select **ICAP Settings** +for the **Forward Proxy** tab. + +Select enable ICAP and filling the Request and Response URL's. +For Symantecs Protection Engine the look like this: + +======================== =================================== + **Request Modify URL** icap://192.168.2.1:1344/avscanreq + **Response Modify URL** icap://191.168.2.1:1344/avscan +======================== =================================== + +Now click on **Apply** + +Step 6 - Test using EICAR +------------------------- +To test if the engine is operational and functional go to http://www.eicar.org/85-0-Download.html +on this page you will find several files you can test. + +First test the http protocol version and if that works the https version if you +have also configured the transparent ssl proxy mode. + +.. Warning:: + **IMPORTANT NOTE** : + YOU DOWNLOAD THESE FILES AT YOUR OWN RISK! + + +If everything went well you should see something similar to this in you browser: + +.. code-block:: guess + + The content you just requested contains EICAR Test String and was blocked by the + Symantec Protection Engine based on local administrator settings. Contact your + local administrator for further information. + +**DONE** diff --git a/source/manual/how-tos/proxyicapantivirusinternal.rst b/source/manual/how-tos/proxyicapantivirusinternal.rst new file mode 100644 index 0000000..d28b042 --- /dev/null +++ b/source/manual/how-tos/proxyicapantivirusinternal.rst @@ -0,0 +1,73 @@ +================================================== +Setup Anti Virus Protection using OPNsense Plugins +================================================== +OPNsense can offer http and https protection by utilizing its highly flexible +proxy and the industry standard ICAP. An external engine from one of the known +vendors is used to offer maximum protection against malware, such as ransomware, +trojans and viruses. This protection can be further enhanced by the build-in Intrusion +Prevention System and Category Based Web filtering. + +This How To will use the Plugins C-ICAP and ClamAV. + +.. Note:: + The Anti Virus Engine can protect you against malicious websites and infected + file downloads, it does not protect the local clients. Therefore it is always + a good idea to install a client based solution as well to protect against other + forms of infection such as through emails or usb stick if they are not analyzed + as well. + +.. Note:: + Note that there is still another attack vector called social engineering. + Most attacks would fail without the help of an internal human whose trust + is exploited. An active scanner is only a part of the security concept. + +Step 1 - Setup the Proxy +------------------------ +Start with setting up the proxy with its basic configuration, see :doc:`cachingproxy`. + +Step 2 - Setup Transparent Mode +------------------------------- +To setup the transparent mode, see: :doc:`proxytransparent`. + +Step 3 - Install and Configure the ClamAV and the C-ICAP plugins +---------------------------------------------------------------- + +.. Note:: + The defaults from c-icap and ClamAV (vendor defaults) are used. + Please keep in mind that changing may affect security or performance. + If you don't know how a setting is affecting your network, + you should keep it at the default. + +- :doc:`clamav` +- :doc:`c-icap` + + +Step 4 - Configure ICAP +----------------------- +To configure ICAP go to **Services->Proxy->Administration** And select **ICAP Settings** +for the **Forward Proxy** tab. + +Select enable ICAP and filling the Request and Response URL's. +For the C-ICAP plugin, the default URLs will be: + +======================== ========================= + **Request Modify URL** icap://[::1]:1344/avscan + **Response Modify URL** icap://[::1]:1344/avscan +======================== ========================= + +Now click on **Apply** + +Step 5 - Test using EICAR +------------------------- +To test if the engine is operational and functional go to http://www.eicar.org/85-0-Download.html +on this page you will find several files you can test. + +First test the http protocol version and if that works the https version if you +have also configured the transparent ssl proxy mode. + +.. Warning:: + **IMPORTANT NOTE** : + YOU DOWNLOAD THESE FILES AT YOUR OWN RISK! + + +**DONE** diff --git a/source/manual/how-tos/proxytransparent.rst b/source/manual/how-tos/proxytransparent.rst new file mode 100644 index 0000000..fc04c70 --- /dev/null +++ b/source/manual/how-tos/proxytransparent.rst @@ -0,0 +1,168 @@ +======================= +Setup Transparent Proxy +======================= +OPNsense offers a powerful proxy that can be used in combination with category +based web filtering and any ICAP capable anti virus/malware engine. The proxy +can be configured to run in transparent mode, this mean the clients browser does +not have to be configured for the web proxy, but all traffic is diverted to the +proxy automatically by utilizing Network Address Translation. + +In this How To, we will explain the basic http as well as https (ssl bump) transparent +proxy modes. + +.. Warning:: + The Transparent SSL/HTTPS proxy mode uses a technique also called man-in-the-middle, + only configure and use this if your know what you are doing. When configured wrong + you may end up in lessing your security defenses significantly instead of enhancing + them. Using a transparent https proxy can be a dangerous practice and may not be + allowed by the services you use, for instance e-banking. + +Step 1 - Basic Proxy Setup +-------------------------- +To setup the transparent mode(s) a functional basic proxy setup is required. +For basic configuration please refer to :doc:`cachingproxy`. + +Step 2 - Transparent HTTP +-------------------------------- +Go to **Services->Proxy->Administration** + +Then select **General Forward Settings** under the **Forward Proxy Tab**. + +Select **Enable Transparent HTTP proxy** +And Click **Apply**. + +Step 3 - NAT/Firewall Rule +--------------------------------- +A simple way to add the NAT/Firewall Rule is to click on the **(i)** icon on the +left of the **Enable Transparent HTTP proxy** option and click on **add a new firewall rule**. + +.. image:: images/screenshot_enable_transparent_http.png + :scale: 100% + +**For reference, these are the default settings:** + +============================ ================================= + **Interface** LAN + **Protocol** TCP + **Source** LAN net + **Source port range** any - any + **Destination** any + **Destination port range** HTTP - HTTP + **Redirect target IP** 127.0.0.1 + **Redirect target port** other/3128 + **Description** redirect traffic to proxy + **NAT reflection** Enable + **Filter rule association** Add associated filter rule +============================ ================================= + +The defaults should be alright, just press **Save** and **Apply Changes**. + + +Step 4 - CA for Transparent SSL +-------------------------------------- +Before we can setup transparent SSL/HTTPS proxy we need to create a Certificate +Authority. Go to **System->Trust->Authorities** or use the search box to get there +fast. + +.. image:: images/search_ca.png + :scale: 100% + +Click on **add or import ca** in the upper right corner of the screen to create +a new CA. + +For our example we use the following data: + +======================== =========================================== + **Descriptive name** OPNsense-SSL + **Method** Create an internal Certificate Authority + **Key length (bits)** 2048 + **Digest Algorithm** SHA256 + **Lifetime (days)** 356 + **Country Code** NL (Netherlands) + **State or Province** Zuid Holland + **City** Middelharnis + **Organization** OPNsense + **Email Address** spam@opnsense.org + **Common Name** opnsense-ssl-ca +======================== =========================================== + +**Save** + +Step 5 - Transparent SSL +------------------------------------- +Go to **Services->Proxy->Administration** +Then select **General Forward Settings** under the **Forward Proxy Tab**. + +Select **Enable SSL mode** and set **CA to use** to the CA you have just created. +Then Click **Apply**. + +Step 6 - Configure No SSL Bump +------------------------------ +This step is very important and requires careful consideration! +To make sure that known sites are not bumped and keep their original security layer +intact, one needs to add those including all subdomain to the **SSL no bump sites** +field. + +To enter a new item type in the field and hit enter to accept. start with a . (dot) +to add all subdomains as well. Example: To add all of paypal.com , type .paypal.com +and hit enter. + +.. Note:: + Make sure that all banking sites and sites that you provide personal or login + information for are added to this field. If you are not sure what to add, please + reconsider using transparent SSL as its clearly not intended for you! + + + + +Step 7 - SSL NAT/Firewall Rule +------------------------------------- +A simple way to add the NAT/Firewall Rule is to click on the **(i)** icon on the +left of the **Enable SSL mode** option and click on **add a new firewall rule**. + +.. image:: images/screenshot_enable_transparent_http.png + :scale: 100% + +**For reference, these are the default settings:** + +============================ ================================= + **Interface** LAN + **Protocol** TCP + **Source** LAN net + **Source port range** any - any + **Destination** any + **Destination port range** HTTPS - HTTPS + **Redirect target IP** 127.0.0.1 + **Redirect target port** other/3129 + **Description** redirect traffic to proxy + **NAT reflection** Enable + **Filter rule association** Add associated filter rule +============================ ================================= + +The defaults should be alright, just press **Save** and **Apply Changes**. + +Step 8 - Configure OS/Browser +----------------------------- +Since the CA is not trusted by your browser, you will get a message about this +for each page you visit. To solve this you can import the Key into your OS and +set as trusted. To export the Key go to **System->Trust->Authorities** and click +on the icon to export the CA certificate. Of course one may choose to accept the +certificate for each page manually, but for some pages that may not work well unless +not bumped. + +.. image:: images/export_CA_cert.png + :scale: 100% + +Import and change trust settings on your favorite OS. Per example on OSX it looks +like this: + +.. image:: images/Trust_Settings_OSX.png + :scale: 100% + +.. Warning:: + Again be very careful with this as your system will accept any page signed with + this CA certificate. As long as no-one gains access to the private key that + is no problem, but if any one can get a get a hold of it then all traffic + can be decrypted except those in the *do not bump* list. You have been warned! + +**DONE** diff --git a/source/manual/how-tos/proxywebfilter.rst b/source/manual/how-tos/proxywebfilter.rst new file mode 100644 index 0000000..24479fa --- /dev/null +++ b/source/manual/how-tos/proxywebfilter.rst @@ -0,0 +1,131 @@ +==================== +Setup Web Filtering +==================== +Category based web filtering in OPNsense is done by utilizing the build-in proxy +and one of the freely available or commercial blacklists. + +For this this How-to we will utilize the `UT1 "web categorization list" `__ from the +Université Toulouse managed by Fabrice Prigent. This list is supplied for free +under the `Creative Commons license `__. + +Other popular lists that are expected to work well with OPNsense are: + +* Shallalist.de + Free for personal usage and partly for commercial usage +* URLBlacklist.com + Commercial paid service +* Squidblacklist.org + Commercial paid service + +For this tutorial we will assume: + +* Proxy has his default settings / is not configured +* We only want web filtering and nothing else (no caching, no authentication) + +.. Note:: + For other general/basic setup item of the proxy see :doc:`cachingproxy` + +------------------------------- +Step 1 - Disable Authentication +------------------------------- +To start go to **Services->Proxy->Administration**. + +Click on the arrow next to the **Forward Proxy** tab to show the drop down menu. +Now select **Authentication Settings** and click on **Clear All** to disable user +authentication. And click **Apply** to save the change. + +---------------------------- +Step 2 - Configure Blacklist +---------------------------- +Click on the tab **Remote Access Control Lists**. +Now click on the **+** in the lower right corner of the from to add a new list. + +A screen will popup, enter the following details: + +================= ======================= =========================================== + **Enabled** Checked *Enable/Disable* + **Filename** UT1 *Choose a unique filename* + **URL** (copy/paste the URL) *The URL of the blacklist* + **categories** (Leave blank) *If left blank the full list will be fetched* + **Description** UT1 web filter *Your description* +================= ======================= =========================================== + +The URL of the full compressed UT1 category based list is: + ftp://ftp.ut-capitole.fr/pub/reseau/cache/squidguard_contrib/blacklists.tar.gz + +.. image:: images/proxy_ut1.png + :scale: 100% + +Press **Save Changes**. + +-------------------------------- +Step 3 - Download the Categories +-------------------------------- +Now press Download ACL's, please note that this will take a while (can be several +minutes) as the full list (>19MB) will be converted to squid acl's. + +------------------------- +Step 4 - Setup Categories +------------------------- +Now we can select the categories we want to use by clicking on the pencil icon next +to the description of the list. This will open the edit window again, but now you +will see all available categories extracted from the list. + +.. image:: images/proxy_categories.png + :scale: 100% + +For our example we will filter ads and adult content. The easiest way to do so is +clear the list and select the following from the drop down list: + +.. image:: images/proxy_catgegory.png + :scale: 100% + +Now **Save changes** and press **Download ACLs** again to download and reconstruct +the list with only the selected categories. This will take roughly the same amount +of time as the first fetch as the adult alone section is ~15MB. + +--------------------- +Step 5 - Enable Proxy +--------------------- +To enable the proxy just go to **Services->Proxy Server->Administration** and +check **Enable proxy** en click on **Apply**. The proxy will bind to LAN and port 3128. + +It may take a while for the proxy to start and the play icon on the top right corner +of the screen will turn red. Refresh the page to see if the proxy is done loading +(play icon will turn green). + +----------------------------- +Step 6 - Disable Proxy Bypass +----------------------------- +To make sure no-one can bypass the proxy you need to add a firewall rule. +Go to **Firewall->Rules** and add the following to the top of the list rule on the +LAN interface (if LAN is where your clients and proxy are on). + +============================ ===================== + **Action** Block + **Interface** LAN + **Protocol** TCP/UDP + **Source** LAN net + **Destination Port Range** HTTP + **Category** Block Proxy Bypass + **Description** Block http bypass +============================ ===================== + +**Save** + +And one more rule to block HTTPS access: + +============================ ===================== + **Action** Block + **Interface** LAN + **Protocol** TCP/UDP + **Source** LAN net + **Destination Port Range** HTTPS + **Category** Block Proxy Bypass + **Description** Block https bypass +============================ ===================== + +**Save** & **Apply changes** + +.. image:: images/proxy_firewall.png + :scale: 100% diff --git a/source/manual/how-tos/resources/Carp_example_backup.xml b/source/manual/how-tos/resources/Carp_example_backup.xml new file mode 100644 index 0000000..1e81201 --- /dev/null +++ b/source/manual/how-tos/resources/Carp_example_backup.xml @@ -0,0 +1,701 @@ + + + 11.2 + + opnsense + + + Disable the pf ftp proxy handler. + debug.pfftpproxy + default + + + Increase UFS read-ahead speeds to match current state of hard drives and NCQ. More information here: http://ivoras.sharanet.org/blog/tree/2010-11-19.ufs-read-ahead.html + vfs.read_max + default + + + Set the ephemeral port range to be lower. + net.inet.ip.portrange.first + default + + + Drop packets to closed TCP ports without returning a RST + net.inet.tcp.blackhole + default + + + Do not send ICMP port unreachable messages for closed UDP ports + net.inet.udp.blackhole + default + + + Randomize the ID field in IP packets (default is 0: sequential IP IDs) + net.inet.ip.random_id + default + + + Drop SYN-FIN packets (breaks RFC1379, but nobody uses it anyway) + net.inet.tcp.drop_synfin + default + + + Enable sending IPv4 redirects + net.inet.ip.redirect + default + + + Enable sending IPv6 redirects + net.inet6.ip6.redirect + default + + + Enable privacy settings for IPv6 (RFC 4941) + net.inet6.ip6.use_tempaddr + default + + + Prefer privacy addresses and use them over the normal addresses + net.inet6.ip6.prefer_tempaddr + default + + + Generate SYN cookies for outbound SYN-ACK packets + net.inet.tcp.syncookies + default + + + Maximum incoming/outgoing TCP datagram size (receive) + net.inet.tcp.recvspace + default + + + Maximum incoming/outgoing TCP datagram size (send) + net.inet.tcp.sendspace + default + + + IP Fastforwarding + net.inet.ip.fastforwarding + default + + + Do not delay ACK to try and piggyback it onto a data packet + net.inet.tcp.delayed_ack + default + + + Maximum outgoing UDP datagram size + net.inet.udp.maxdgram + default + + + Handling of non-IP packets which are not passed to pfil (see if_bridge(4)) + net.link.bridge.pfil_onlyip + default + + + Set to 0 to disable filtering on the incoming and outgoing member interfaces. + net.link.bridge.pfil_member + default + + + Set to 1 to enable filtering on the bridge interface + net.link.bridge.pfil_bridge + default + + + Allow unprivileged access to tap(4) device nodes + net.link.tap.user_open + default + + + Randomize PID's (see src/sys/kern/kern_fork.c: sysctl_kern_randompid()) + kern.randompid + default + + + Maximum size of the IP input queue + net.inet.ip.intr_queue_maxlen + default + + + Disable CTRL+ALT+Delete reboot from keyboard. + hw.syscons.kbd_reboot + default + + + Enable TCP extended debugging + net.inet.tcp.log_debug + default + + + Set ICMP Limits + net.inet.icmp.icmplim + default + + + TCP Offload Engine + net.inet.tcp.tso + default + + + UDP Checksums + net.inet.udp.checksum + default + + + Maximum socket buffer size + kern.ipc.maxsockbuf + default + + + + normal + OPNsense + localdomain + + all + All Users + system + 1998 + 0 + + + admins + System Administrators + system + 1999 + 0 + page-all + + + root + System Administrator + system + admins + $6$$Y8Et6wWDdXO2tJZRabvSfQvG2Lc8bAS6D9COIsMXEJ2KjA27wqDuAyd/CdazBQc3H3xQX.JXMKxJeRz2OqTkl. + 0 + user-shell-access + 6236393534643264633361623266386435346633383365643836616631626133 + + 2000 + 2000 + Africa/Abidjan + + 0.nl.pool.ntp.org + + https + 1 + 549a859fe5a0a + + 2 + + yes + 1 + + + + hadp + hadp + hadp + + monthly + + + 1 + + 1 + enabled + enabled + + 115200 + serial + en_US + 8.8.8.8 + 1 + none + none + none + none + + + + 1 + em1 + 172.18.0.102 + dhcpv6 + 24 + WANGW + + + + 0 + + + 1 + em0 + 192.168.1.20 + 24 + track6 + 64 + + + wan + 0 + + + PFSYNC + em2 + 1 + 10.0.0.2 + 24 + + + + + + 1 + + 192.168.1.10 + 192.168.1.245 + + 192.168.1.10 + + + + + 192.168.1.1 + + + + + + + + + + + + + + + + 192.168.1.1 + + + + + + + + + + + + + + + public + + + + + + + + + + + + + + + advanced + + wan + + 127.0.0.0/8 + + 500 + + + 1 + + 1 + Auto created rule for ISAKMP - localhost to WAN + + + Manual Outbound NAT Switch + + + + wan + + 127.0.0.0/8 + + + + + 1 + + + Auto created rule - localhost to WAN + + + Manual Outbound NAT Switch + + + + + 192.168.1.0/24 + + + Auto created rule for ISAKMP - LAN to WAN + 172.18.0.100 + + 0 + wan + + 1 + + 1 + + 500 + + + Manual Outbound NAT Switch + + + + root@192.168.1.127 + + + + + 192.168.1.0/24 + + + Auto created rule - LAN to WAN + 172.18.0.100 + + 0 + wan + + + 1 + + + + Manual Outbound NAT Switch + + + + root@192.168.1.100 + + + + wan + + 10.0.0.1/32 + + 500 + + + 1 + + 1 + Auto created rule for ISAKMP - PFSYNC to WAN + + + Manual Outbound NAT Switch + + + + wan + + 10.0.0.1/32 + + + + + 1 + + + Auto created rule - PFSYNC to WAN + + + Manual Outbound NAT Switch + + + + + + + + pass + wan + inet + + + + + + + + keep state + + carp + + 1 + + + 1 + + + + + root@192.168.1.127 + + + + root@192.168.1.127 + + + + pass + inet + Default allow LAN to any rule + lan + + lan + + + + + + + pass + inet6 + Default allow LAN IPv6 to any rule + lan + + lan + + + + + + + + pass + opt1 + inet + + + + + + + + keep state + + + 1 + + + 1 + + + + + root@192.168.1.100 + + + + root@192.168.1.100 + + + + + + + + + + + + + + + + 1,31 + 0-5 + * + * + * + root + adjkerntz -a + + + 1 + 3 + 1 + * + * + root + /usr/local/etc/rc.update_bogons + + + */60 + * + * + * + * + root + /usr/local/sbin/expiretable -v -t 3600 sshlockout + + + 1 + 1 + * + * + * + root + /usr/local/etc/rc.dyndns.update + + + */60 + * + * + * + * + root + /usr/local/sbin/expiretable -v -t 3600 virusprot + + + 30 + 12 + * + * + * + root + /usr/local/etc/rc.update_urltables + + + + + + + + + + + ICMP + icmp + ICMP + + + + TCP + tcp + Generic TCP + + + + HTTP + http + Generic HTTP + + / + + 200 + + + + HTTPS + https + Generic HTTPS + + / + + 200 + + + + SMTP + send + Generic SMTP + + + 220 * + + + + + system_information-container:col1:show,captive_portal_status-container:col1:close,carp_status-container:col1:close,cpu_graphs-container:col1:close,gateways-container:col1:close,gmirror_status-container:col1:close,installed_packages-container:col1:close,interface_statistics-container:col1:close,interface_list-container:col2:show,ipsec-container:col2:close,load_balancer_status-container:col2:close,log-container:col2:close,picture-container:col2:close,rss-container:col2:close,services_status-container:col2:close,traffic_graphs-container:col2:close + + + + (system)@10.0.0.1: Merged in config (staticroutes,gateways,virtualip,schedules,filter,nat,dhcpd sections) from XMLRPC client. + (system)@10.0.0.1 + + + 549a859fe5a0a + webConfigurator default + LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZiekNDQTFlZ0F3SUJBZ0lKQUo0Y2VGS2U1RGF0TUEwR0NTcUdTSWIzRFFFQkN3VUFNRTR4Q3pBSkJnTlYKQkFZVEFrNU1NUlV3RXdZRFZRUUlEQXhhZFdsa0xVaHZiR3hoYm1ReEZUQVRCZ05WQkFjTURFMXBaR1JsYkdoaApjbTVwY3pFUk1BOEdBMVVFQ2d3SVQxQk9jMlZ1YzJVd0hoY05NVFF4TWpJME1Ea3lNVE00V2hjTk1UVXhNakkwCk1Ea3lNVE00V2pCT01Rc3dDUVlEVlFRR0V3Sk9UREVWTUJNR0ExVUVDQXdNV25WcFpDMUliMnhzWVc1a01SVXcKRXdZRFZRUUhEQXhOYVdSa1pXeG9ZWEp1YVhNeEVUQVBCZ05WQkFvTUNFOVFUbk5sYm5ObE1JSUNJakFOQmdrcQpoa2lHOXcwQkFRRUZBQU9DQWc4QU1JSUNDZ0tDQWdFQXovalZKNlRSZUJDUDV5UFo4aU5IL0h6aSt0UUh5UEd1CmVMUVkxb2c4TWJVa1JYZm94bGtKN0VxQTQzR2ZRRXphZzdsQ3c0Q1dBMVRqYnNNdmFpUnZFaFBta3IwYTZlUUgKOU1HdDl2cjdUZGlTdmxSei9zZUc5bkR4Q2JRSnh6OUs5NEtpQWl3aE1rcUhyYmpBNVBGTFlrNGVVRW13NU9WSAp5ajZjSU55eit2alFGKy9rY3MwZ3k1VGF4V0tvcnZVM1RtNFJOTm9rblE3Mmd5R2Z2T3Bydi9ibnEvQ3pYRWovCmsrNmM5bzQ5MTRhZ2Z6RmJYQ0s5c3M2Z1VRZFlDNHBBcTAzSHllMk9EUHhWRnVCS3JuN01kd3RNdUFTc1ViUmIKL1A1UTRmdjNzSmhhZGhrd05MaE15LzNUNkpvZ0pzN29DUVI1WEZPUXFJMVpKcWlkRWp2MFB5aW02bGhHVXVEZQpTa2wrekhnMzAvZFY5Y05HblhlRzBkdGNLN3p5OVdIc3Z3bzNqUU12aXY2bDVjekEySGFGQzQvWmJQU21GRVdaCnpIZ2Fmam9KSjhMMVNoUWtDU1JGV2s4SHFqdG92ajRoR0lBSTBtb1h0eUtQNTQwT1EvQ2wzelJMM1MydmMrb0gKamtnQmRrWWIvTjIzbkUxb1UvbkhnRHgvalhmOHQ1Zm9XNXpJZ1RMdm1QN01RSWhhVWIxbk01ZjRzVU1hVk00cQpZN2g4UURRUElsT3NrUk9lYXRsNkZFSnVMQWRpVkcrNGY0b21DK1Azc1JOK2RxRTZUSVF4NENJSG5GMXZTZ2Q3ClYrOHptL0M3SnhQdXNRR1R6L3JraG5LeFB6T2VxMzNKSU90a2s2REwwOXNrbGs3RmlxWnhNaFVwVjRSM2FTSFIKVW1GOTJQb2FVeEVDQXdFQUFhTlFNRTR3SFFZRFZSME9CQllFRkNkeG1Pdytya1c3UFg3RXBOQWxidENjaWNnMgpNQjhHQTFVZEl3UVlNQmFBRkNkeG1Pdytya1c3UFg3RXBOQWxidENjaWNnMk1Bd0dBMVVkRXdRRk1BTUJBZjh3CkRRWUpLb1pJaHZjTkFRRUxCUUFEZ2dJQkFNSUtMd2tjalcrRWxNVS82VXZORFh0ZnppOTVualQ1ZmJsby94RGoKdDFXUDlVbkd4bmF6aFl2eUs5bEdLdFJUSGRaRER3bSthemJicklmOXFSdUo4ZzdSZ1VxSTZoWHQ2VjkremlDYgpNdVcvZnBvMmxDVlNPYUZsV2dnMzVHblZyeTJDNU5iZi9ZeXJFSi9VaU1Ed2Q4QUZyaStITHNkMU4xWGh3M1grCk53M0JlTEx6QmcvaFF5Wi9ZZ08wVW9ma0h6SFQ1T2UyeHM3a2xMUFZab2dGT3JCM0lJYmkrdFBWN1RuK3RGUmYKWFJ4ZkR6R0xwcTlIb1dxVDFtU0xjVjRGem5iUUhnSmoveitsVGxMRFc0OG83WGpWSUIyTnRNUjJVc1BEN24wOAo0aGZJcUNWbWFmT1lFUFplYk45VUNJdG54SXJ4NUFzRjZVRGVGK2Y1Tnh4ZnNkdENxMmd2SXM5WUsxN3BiZXZlCkZ2QkZYWUt0dnVJRTRwSDU2OGhGT0dtdDVSM3RDcTByeGVQanQ2cERTc1Q2cFRmUE9qMlZUSUNMaEU3MFBXQUkKTVZkOWRMd2I1bm9FaHYvK20zU083aGZlVll4MHZURGlNOGNvV3hoZ3VacUdhVUZmQjNwNjQyNEFMaGtTVXd3eApuSGxTbHZjYW1KRTB3bmdkT1pXM243TnU2YUM5QTRWaStlTkNONUZ3UWVma0VMVTVDcmlVNkttOUg1elJoaFZECmZBMUN2N1NZNEYreWxBZ0pjc2s0aGpoMWxYc2x1YWY1SzNwSHZFYVREZng3R0JvRXhxZWgvYitiZEZNMU5PZnUKb1FKU3NmT3poS2ZrMTB5QWNZa0dBcFVjRkVrb1Y4MFp3dk5uVW5tenB6WlBncGxON0MrOHI2M1hFQ3JWSGs4OApUNlJ6Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRZ0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1N3d2dna29BZ0VBQW9JQ0FRRFArTlVucE5GNEVJL24KSTlueUkwZjhmT0w2MUFmSThhNTR0QmpXaUR3eHRTUkZkK2pHV1Fuc1NvRGpjWjlBVE5xRHVVTERnSllEVk9OdQp3eTlxSkc4U0UrYVN2UnJwNUFmMHdhMzIrdnROMkpLK1ZIUCt4NGIyY1BFSnRBbkhQMHIzZ3FJQ0xDRXlTb2V0CnVNRGs4VXRpVGg1UVNiRGs1VWZLUHB3ZzNMUDYrTkFYNytSeXpTRExsTnJGWXFpdTlUZE9iaEUwMmlTZER2YUQKSVorODZtdS85dWVyOExOY1NQK1Q3cHoyamozWGhxQi9NVnRjSXIyeXpxQlJCMWdMaWtDclRjZko3WTRNL0ZVVwo0RXF1ZnN4M0MweTRCS3hSdEZ2OC9sRGgrL2V3bUZwMkdUQTB1RXpML2RQb21pQW16dWdKQkhsY1U1Q29qVmttCnFKMFNPL1EvS0ticVdFWlM0TjVLU1g3TWVEZlQ5MVgxdzBhZGQ0YlIyMXdydlBMMVlleS9DamVOQXkrSy9xWGwKek1EWWRvVUxqOWxzOUtZVVJabk1lQnArT2drbnd2VktGQ1FKSkVWYVR3ZXFPMmkrUGlFWWdBalNhaGUzSW8vbgpqUTVEOEtYZk5FdmRMYTl6NmdlT1NBRjJSaHY4M2JlY1RXaFQrY2VBUEgrTmQveTNsK2hibk1pQk11K1kvc3hBCmlGcFJ2V2N6bC9peFF4cFV6aXBqdUh4QU5BOGlVNnlSRTU1cTJYb1VRbTRzQjJKVWI3aC9paVlMNC9leEUzNTIKb1RwTWhESGdJZ2VjWFc5S0IzdFg3ek9iOExzbkUrNnhBWlBQK3VTR2NyRS9NNTZyZmNrZzYyU1RvTXZUMnlTVwpUc1dLcG5FeUZTbFhoSGRwSWRGU1lYM1kraHBURVFJREFRQUJBb0lDQUNwaUg2NlFuRS9Ic0V2K3RtL3VXTUZRCkFrSHo3Qkk3anI3eWxRMURmbUR5OVkxaXZvR05xOFFIK3ZSZk40RTNLR0VuNUQ5TGVVYjhpYzBNNGlEVGcvOC8KSndKSW42K0MxVXhBSEYvMURqbnpKUlM4eVZibStzNUdmaGpvSkFZREZCZ1UrMGRPRHdYY3dvSFk0UmJIUmdHbQp3ZTdDMWRZUUUrMVhqU0gxV0lpUkpIZDhZQ1kxUDdXOWhFZ3Ryd3JZMW9pWlRkQmpsSXFkZmdlRFZyWjlYN0FqCmRWdEpGb1I4Sy9uTjZ4Y2tMZDQ2aFlMbVlDUUt3SFlzUGVmRmcxLzJzTzg0VHJzTU9xTFMyZFJycVV5ZWNyVGcKREthRDdVcEpZMlhQdmxRUHNZNi92Yy9MbWxOa0srSjJ2RFR2RkJaVW5GMGFHRkdFaGpxVGM5TzVFU21pSmtoSwp4N0ZMME9sTGxmbXlLV0lzSWhhbW9sZTVYWm9VZWxqckxDSGJXdUhsOG5tb2puMTl4cDN1TVA5WHY2MUtmelJTCm1HdjNGbkRGWC9pNVRkZExxUGVMUThpaUYxZXE4OGkrTWRVZDFVb2lteXlQdXZhcWFndjhBM3VaektwYzd3clMKMHZWSGc2ekRmTmNsL0NIMGh6SXZYNXU5QzFiMmdiTXdJbFpwV3JnL2JvaE9SMGNPTVdlZGh4STFOTmFmbDZYNwpMZGNXbzZvRElKT0FHWWpua0R1OGI4OXdVem85WUZRQkpvMU03WFRTdnh0cmF4TnBHUnIxR2VHeXd3MGJ4Z3dsCkV4UkxZM0hhU0dnSlcxanpNMzZhWFkvdi84RU1TVGZsWEFLSWxSWHF3QndUVWcvV1ZTNDJyb0VyRzZ5bjZjbi8KckF5bS9IWS9IR2lXVmdKdjY1Y0JBb0lCQVFEb2N4citOL01JQ281RkJTdUtmcmtSREYzdE9vVUlkQ1p1TGoxMwpKVzREOVgxNkY0NHlqcHowaHcrMENGVURwK1dJTTNGS3VhOWMwT2tNRXhoaCtqRDcvNFlYdkpMbE00dnlxWkRqCm0wOVY4cUxhb1NCbHBlTjRwbzVTcnhSNGovTHNYdk4ySFg2OFJ5a1hLNzR0UVZXU1JtNThuMVRVcm9ORktYNnQKekVPdmtCZ0RKd09GNnF0ZmlwcGl3cVozZXIrL0VOaTJydzVmYkh3YXRmMjROTXFOTmhJRDhwN1dEVDlCL0NBSQo2RXdJWDVrUTdOZFduVU5PR0RnTlBDRndPWXFrdlVmMlAyRzFqRE5EZGh5alBJczVhVUQwS01XZVh4Ym5veDMrClo2NkNmeUlzWUowQU5zeWJOVFhCY3dMcE5nRmJTNnZmNjR1Wm0xSDZ0WW5kZU9pNUFvSUJBUURsQ3QzdHJmcTEKelpPSWhKWURMNEdmZ0pqREFmeFZPaUN6c2dOS1BFcmIyYXRQR3pQZGdjNitLVStHNmZJS2xXaUxiZU55RDlGNgpJdHU3QnJKQlBvT3hDNTVPSW16czQrTUdFSmxqUWIzZzh3NTRRWGZNZGszcGpydCtjd290VGtlaXF3MCtrUytLClZuYkZSL1ZFVGNKaThnQkM0eVFRZGZTNk00SDBHeHVlbktpTysxSjdqdm5Cb1M4NkZOKzArWFRLTUVGWXhJR1IKYkc1amZGUzF5eGxhY2Fza3grS3lMc2VpQkNIYTJXQlhCSmxMb2tQaC9KV0ZOZmN2c2M3S1RvTWY2K3hRcHJqQQpjdEU0Y053dGNDa0xJR3RzSEc4YXhaclA2QWJtR1ZpSFA3NXVaUXNYSzZ4NXV2QWZsNG1XVUJXaU5sNzkyRnVwCmIwZVRNM3A0U2VFWkFvSUJBSGJKazhyRUpzTStPYlFWejBsb053VDZUK21TVlRlYnU2UGtwMjZDeHpUb3VDV3oKY2V4dUt0RmZUK3dOc2Z3N1NiWVBxOTZuQTNHb0pPQVJ4ZzBUd1FLV2N4MGdOZVZCTVV4aDBQUXZneHlGOFNsTwoyL0oyRXNldVBkOE5MNlhvMGhodThYV3ozdmN5V2xKSC9WaTlJWkN0dzNxV0pkREdHYmszV2xCUXFXcEhkYTN1CnV3TXRpRVE3M1dlSTEyOEpZSUd3aHo3Y09Ma1ZCRnJXRkFHVm9Na0hENi9LeGRiWFVETlZONzIxa0YxYkZTcXMKRGVOcVhHSEZTS2VpeWVmQzBCSWQxRytIdGxRRGdKTUNBZUo5Wnh5QXFEdmR0aGVYdW1uSFZ1V1NjSUNwblhvVwpLVVZadTdlNU9tNVFhdlZvcnNyTDRkcDlVWXErNytieDdMRXNQNmtDZ2dFQVJRdGRrMFNiQ3lzSmltSE5odkJQCk52SGhHd2dDTlA3czFMNlkxMHdObFBDcy80L0h0c0ptdkZSZnNOL2RJdXVmTkVqUUE1WlpJMlJXc0s1NEZjcnUKai9SY3FGa2dWTmp0bXVwdUVzbkNuNGtsbDRMRXhsSHpjckNnUEtJWk0wY2h1UnV2Um1rbDE2SHc4OCtaVkJuTQp1MThRVFJtRHlhS0ZQNHcvWklLM2RMenM0dzFIOUE5Sm91RWdCM1k3YWFhNVdpbnB5UVNUdW03aGFBUVcxU2FBCllnOVo5Q0I5YWhGSUJNTVNJWkxkdzkyVENJWEZ5TjRIaEx5YjR6aktpWm5aVlVvZFZzS3Jkdmdsc2NuejFZNjIKRUxDWk1XSHc3RFVkVWdjejdURSt5cWFnbFU3SVpSZTVTb2piMGVvd2c2dG9taG1oMFF2anRkUGgwN0gwL1VYbwpJUUtDQVFFQTRlaHM3M2IzUnlxNGw1RWZOTVhxNmlkeEEraXMzbi9vbnpMN2RZdXhNaG04RG1nYVg4V3hDckNLCmQzY3ZtMDNYWld4QUlsdEhNRk52Rzh5Sk0yb1hEQ3VmclNhOGhHYkdCM2hBclZXNWdXRUdvdCtvSS82Z1grV2EKcEE0TWZ0THRCbFFYVE1va3FvdktMbnZDQ3JqWEtuUW5YV1ZBNENlYUp4alNPNkhlNWxLaXlqZHhod3hYWTJPbAowV1ltN0xTM01pUkVHc1VvMFdTeHNwSmtkMVpwcGRleThkWDloVmVrV0t1UDZwcVJZZXQvZkV4b205U1ZxcmJkCkFINUVZbzNRM3l5VURzY2NOQXRJK0xHY3hFQmp0c21UVEFFV2ZWZ3hXNE5XZnJIQVNWbmFiWDdrSy9EOFQ5TG0KNXIrMGFXaG1La0xpUXdNcmRQSlNZT1VFTkh1S25nPT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo= + + + + + wan + 172.18.0.250 + WANGW + 1 + inet + + + + + WAN Gateway + 1 + 1 + + + + + carp + wan + 1 + 100 + 1 + opnsense + VIP WANx + single + 24 + 172.18.0.100 + + + carp + lan + 3 + 100 + 1 + opnsense + VIP LAN + single + 24 + 192.168.1.1 + + + + 10.0.0.1 + opt1 + + + + on + + + diff --git a/source/manual/how-tos/resources/Carp_example_master.xml b/source/manual/how-tos/resources/Carp_example_master.xml new file mode 100644 index 0000000..e0bba7e --- /dev/null +++ b/source/manual/how-tos/resources/Carp_example_master.xml @@ -0,0 +1,704 @@ + + + 11.2 + + opnsense + + + Disable the pf ftp proxy handler. + debug.pfftpproxy + default + + + Increase UFS read-ahead speeds to match current state of hard drives and NCQ. More information here: http://ivoras.sharanet.org/blog/tree/2010-11-19.ufs-read-ahead.html + vfs.read_max + default + + + Set the ephemeral port range to be lower. + net.inet.ip.portrange.first + default + + + Drop packets to closed TCP ports without returning a RST + net.inet.tcp.blackhole + default + + + Do not send ICMP port unreachable messages for closed UDP ports + net.inet.udp.blackhole + default + + + Randomize the ID field in IP packets (default is 0: sequential IP IDs) + net.inet.ip.random_id + default + + + Drop SYN-FIN packets (breaks RFC1379, but nobody uses it anyway) + net.inet.tcp.drop_synfin + default + + + Enable sending IPv4 redirects + net.inet.ip.redirect + default + + + Enable sending IPv6 redirects + net.inet6.ip6.redirect + default + + + Enable privacy settings for IPv6 (RFC 4941) + net.inet6.ip6.use_tempaddr + default + + + Prefer privacy addresses and use them over the normal addresses + net.inet6.ip6.prefer_tempaddr + default + + + Generate SYN cookies for outbound SYN-ACK packets + net.inet.tcp.syncookies + default + + + Maximum incoming/outgoing TCP datagram size (receive) + net.inet.tcp.recvspace + default + + + Maximum incoming/outgoing TCP datagram size (send) + net.inet.tcp.sendspace + default + + + IP Fastforwarding + net.inet.ip.fastforwarding + default + + + Do not delay ACK to try and piggyback it onto a data packet + net.inet.tcp.delayed_ack + default + + + Maximum outgoing UDP datagram size + net.inet.udp.maxdgram + default + + + Handling of non-IP packets which are not passed to pfil (see if_bridge(4)) + net.link.bridge.pfil_onlyip + default + + + Set to 0 to disable filtering on the incoming and outgoing member interfaces. + net.link.bridge.pfil_member + default + + + Set to 1 to enable filtering on the bridge interface + net.link.bridge.pfil_bridge + default + + + Allow unprivileged access to tap(4) device nodes + net.link.tap.user_open + default + + + Randomize PID's (see src/sys/kern/kern_fork.c: sysctl_kern_randompid()) + kern.randompid + default + + + Maximum size of the IP input queue + net.inet.ip.intr_queue_maxlen + default + + + Disable CTRL+ALT+Delete reboot from keyboard. + hw.syscons.kbd_reboot + default + + + Enable TCP extended debugging + net.inet.tcp.log_debug + default + + + Set ICMP Limits + net.inet.icmp.icmplim + default + + + TCP Offload Engine + net.inet.tcp.tso + default + + + UDP Checksums + net.inet.udp.checksum + default + + + Maximum socket buffer size + kern.ipc.maxsockbuf + default + + + + normal + OPNsense + localdomain + + all + All Users + system + 1998 + 0 + + + admins + System Administrators + system + 1999 + 0 + page-all + + + root + System Administrator + system + admins + $6$$Y8Et6wWDdXO2tJZRabvSfQvG2Lc8bAS6D9COIsMXEJ2KjA27wqDuAyd/CdazBQc3H3xQX.JXMKxJeRz2OqTkl. + 0 + user-shell-access + 6236393534643264633361623266386435346633383365643836616631626133 + + 2000 + 2000 + Africa/Abidjan + + 0.nl.pool.ntp.org + + https + 1 + 55a674a3abc80 + + 2 + + yes + 1 + + + + hadp + hadp + hadp + + monthly + + + 1 + en_US + none + none + none + none + + 1 + enabled + enabled + + 115200 + serial + 8.8.8.8 + 1 + + + + 1 + em1 + 172.18.0.101 + dhcpv6 + 24 + WANGW + + + + 0 + + + 1 + em0 + 192.168.1.10 + 24 + track6 + 64 + + + wan + 0 + + + PFSYNC + em2 + 1 + + 10.0.0.1 + 24 + + + + + + 1 + + 192.168.1.10 + 192.168.1.245 + + 192.168.1.20 + + + + + 192.168.1.1 + + + + + + + + + + + + + + + + 192.168.1.1 + + + + + + + + + + + + + + + public + + + + + + + + + + + + + + + advanced + + wan + + 127.0.0.0/8 + + 500 + + + 1 + + 1 + Auto created rule for ISAKMP - localhost to WAN + + + Manual Outbound NAT Switch + + + + wan + + 127.0.0.0/8 + + + + + 1 + + + Auto created rule - localhost to WAN + + + Manual Outbound NAT Switch + + + + + 192.168.1.0/24 + + + Auto created rule for ISAKMP - LAN to WAN + 172.18.0.100 + + 0 + wan + + 1 + + 1 + + 500 + + + Manual Outbound NAT Switch + + + + root@192.168.1.127 + + + + + 192.168.1.0/24 + + + Auto created rule - LAN to WAN + 172.18.0.100 + + 0 + wan + + + 1 + + + + Manual Outbound NAT Switch + + + + root@192.168.1.100 + + + + wan + + 10.0.0.1/32 + + 500 + + + 1 + + 1 + Auto created rule for ISAKMP - PFSYNC to WAN + + + Manual Outbound NAT Switch + + + + wan + + 10.0.0.1/32 + + + + + 1 + + + Auto created rule - PFSYNC to WAN + + + Manual Outbound NAT Switch + + + + + + + + pass + wan + inet + + + + + + + + keep state + + carp + + 1 + + + 1 + + + + + root@192.168.1.127 + + + + root@192.168.1.127 + + + + pass + inet + Default allow LAN to any rule + lan + + lan + + + + + + + pass + inet6 + Default allow LAN IPv6 to any rule + lan + + lan + + + + + + + + pass + opt1 + inet + + + + + + + + keep state + + + 1 + + + 1 + + + + + root@192.168.1.100 + + + + root@192.168.1.100 + + + + + + + + + + + + + + 1,31 + 0-5 + * + * + * + root + adjkerntz -a + + + 1 + 3 + 1 + * + * + root + /usr/local/etc/rc.update_bogons + + + */60 + * + * + * + * + root + /usr/local/sbin/expiretable -v -t 3600 sshlockout + + + 1 + 1 + * + * + * + root + /usr/local/etc/rc.dyndns.update + + + */60 + * + * + * + * + root + /usr/local/sbin/expiretable -v -t 3600 virusprot + + + 30 + 12 + * + * + * + root + /usr/local/etc/rc.update_urltables + + + + + + + + + + + ICMP + icmp + ICMP + + + + TCP + tcp + Generic TCP + + + + HTTP + http + Generic HTTP + + / + + 200 + + + + HTTPS + https + Generic HTTPS + + / + + 200 + + + + SMTP + send + Generic SMTP + + + 220 * + + + + + system_information-container:col1:show,captive_portal_status-container:col1:close,carp_status-container:col1:close,cpu_graphs-container:col1:close,gateways-container:col1:close,gmirror_status-container:col1:close,installed_packages-container:col1:close,interface_statistics-container:col1:close,interface_list-container:col2:show,ipsec-container:col2:close,load_balancer_status-container:col2:close,log-container:col2:close,picture-container:col2:close,rss-container:col2:close,services_status-container:col2:close,traffic_graphs-container:col2:close + + + + root@192.168.1.127: Updated High Availability configuration + root@192.168.1.127 + + + 55a674a3abc80 + webConfigurator default + LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZiekNDQTFlZ0F3SUJBZ0lKQU40cUlaTHV4VXcrTUEwR0NTcUdTSWIzRFFFQkN3VUFNRTR4Q3pBSkJnTlYKQkFZVEFrNU1NUlV3RXdZRFZRUUlEQXhhZFdsa0xVaHZiR3hoYm1ReEZUQVRCZ05WQkFjTURFMXBaR1JsYkdoaApjbTVwY3pFUk1BOEdBMVVFQ2d3SVQxQk9jMlZ1YzJVd0hoY05NVFV3TnpFMU1UUTFOak01V2hjTk1UWXdOekUwCk1UUTFOak01V2pCT01Rc3dDUVlEVlFRR0V3Sk9UREVWTUJNR0ExVUVDQXdNV25WcFpDMUliMnhzWVc1a01SVXcKRXdZRFZRUUhEQXhOYVdSa1pXeG9ZWEp1YVhNeEVUQVBCZ05WQkFvTUNFOVFUbk5sYm5ObE1JSUNJakFOQmdrcQpoa2lHOXcwQkFRRUZBQU9DQWc4QU1JSUNDZ0tDQWdFQW4wUlorR05lVGg2Qk1YckNPQ04rc0kzZXJYWWhuWDRSCm8yallCQ3VzeVZoSjFQK2p6VHNzcEhnUkhRNWpLZVhyc21iL3drQ2dxVzVFSUx3QWx2eUVLL0VQTm1hMlE2Q3QKSVBMckZzdEFYV0hRWTVYdWQwMDNySjFyWVFKem8wY1p6ak1rM3dCNzkyZDBGaUREbk5sMDY5allDb0wyd1BaRgplZlVjVm9nMDh5MGxXemNPTkY2TldjcmNNZzdBNHBEZTdacXJQMm9Ud1Arcy9sOFMySlZVbU90OGh3Z3NsYmo1CmRFbHlnS0RXWXZyeTR3YzFzbWo3Yk00OXV0VW9JQmI1OUk0VmlrNzdUSklzN1FscjdpUGE1akJRclhiSElldHYKSnUvQXZpaTcwUjR5cmZFUy9yMm5uQkZOQ2FhS3dnbmgyYjBOZUwzTFBtUHN2Y1pEZm92a2l3dWwwWTVXR0FzVQpvN3lHZ0Fmd0t5SjdKSEJLZjVmTm1MdXRlb2w2cU9xblROTlFoMDNHNVFyWXVPWlU5blJLMDdRN1JiUC9taXhMClJEMEhwd3ZRbjBRR21yS3kxeWRwOFJtZnlxOWhvRWVuamVBV0xtT1p6eVZncHRrQzJod0RmalNLcWdkK3lWOXEKemJiSHpscy9ueFEvazVWZGRJZXBHOTRad0RFTFNqZFNzaXlnazNOQ2N5QXk4VXJRNnV0dWZLMTBGaXhKK2JFWQpMZW8veEhJcC8yWFJQYmVRSUpxRllrSm81WmRMSVk4dXNvQ0ZOcEtBeTRRTkoyRnZBSDUxK0JZQTRzK1hHSnZDCmw3SWdaVHI3a0F1WU9ncGZHWVZTWFFyT1FZMVFBYmE4eUZSYi8vcG1RMko3K3NxSDRlZ2puZ0lWZEltUTJlR2UKdzZRNVlURmtMRzBDQXdFQUFhTlFNRTR3SFFZRFZSME9CQllFRkVyY0tCaDBhVE1aVjRiUzRKNCtMWWZTejVRTwpNQjhHQTFVZEl3UVlNQmFBRkVyY0tCaDBhVE1aVjRiUzRKNCtMWWZTejVRT01Bd0dBMVVkRXdRRk1BTUJBZjh3CkRRWUpLb1pJaHZjTkFRRUxCUUFEZ2dJQkFBYzZKYU5pbTUyclh0c0lnekR4WVBjZjRiaWgwZlR6SHFqM0hTM1UKb0RvRmFOcG9ISTVFWjRCdTFlS2VnVVpqSEpMdTc2cWFkSnJvTkZ0cy83Zy8wdmliRW1venhqUzAxZUE2eUZRbAp0ZkRSSU5GU0puV05ZcnN4RHh6dHp4NGtYZ2QxcFlwbkNoUitDemord1ppNjhSWC9TTlpEOE1HSmIzVHJLT2FICnMyUGVoVTFRcTNqL25IT05TbEdwOHl3ZzRwVlBUUlZ6Y240anQ0NHc0RVNlWWtRTE1vZlhVeVluSzBxOWpaM0UKekE2UEtoWlhwNzFIYnJwYkNLRk5IaG14WDNFakFDS0VSRlN3QlFnRWs5QlBOdTI4YTgzS0FqVXhnNmIvbnJRMwpIbTIvdmdBQmJKQ3lWNUVvTU1NYlZOcUI3QXZ3MGJzQ2hYczk4dW9zcURtaWdld3dpaUJ5aGtBOWVjUnVOTW9hCmk2bDRacy9hTUhlYnRtRlI5Nmp0ZVoxY1RQazAvNEM3T2x2WE02VnhoWmhWMHZOb1ZyWExGZkw4eXI2TGlnUW4KWVRzUStMTlUrUUNyR1p6Mkl0ai9VNU5YZjZodFJQcTltVlh0ZmJQUDVPUmJYd3E3dmMrU3I0TDhCaXJkVE4rTApZWkd2bklSclBjVlBzTWZnOUp1cnFQRFpheG1KNEVUOHNxbEl1eEpySnY1SXNIbXJpRGNyUkx0NWlzQ1Zkbkc0CkNya1NPd1RLWmhPMUV2a1N1R0NVREJhT1BBdi82WUFRK3ZiQzdycnBtTit4TmM1R2xUcGRKS3c2YnNhVit5QzMKczJOeUJiNE5PS0VwamhubzZvZ0swMDBuL1FnMk9IMzB6VDlEWXQvZHg2UTA5Njd3QUIzZjFWWHphZFV2Z24xcQpESkZZCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRUUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1Nzd2dna25BZ0VBQW9JQ0FRQ2ZSRm40WTE1T0hvRXgKZXNJNEkzNndqZDZ0ZGlHZGZoR2phTmdFSzZ6SldFblUvNlBOT3l5a2VCRWREbU1wNWV1eVp2L0NRS0NwYmtRZwp2QUNXL0lRcjhRODJaclpEb0swZzh1c1d5MEJkWWRCamxlNTNUVGVzbld0aEFuT2pSeG5PTXlUZkFIdjNaM1FXCklNT2MyWFRyMk5nS2d2YkE5a1Y1OVJ4V2lEVHpMU1ZiTnc0MFhvMVp5dHd5RHNEaWtON3RtcXMvYWhQQS82eisKWHhMWWxWU1k2M3lIQ0N5VnVQbDBTWEtBb05aaSt2TGpCeld5YVB0c3pqMjYxU2dnRnZuMGpoV0tUdnRNa2l6dApDV3Z1STlybU1GQ3Rkc2NoNjI4bTc4QytLTHZSSGpLdDhSTCt2YWVjRVUwSnBvckNDZUhadlExNHZjcytZK3k5CnhrTitpK1NMQzZYUmpsWVlDeFNqdklhQUIvQXJJbnNrY0VwL2w4Mll1NjE2aVhxbzZxZE0wMUNIVGNibEN0aTQKNWxUMmRFclR0RHRGcy8rYUxFdEVQUWVuQzlDZlJBYWFzckxYSjJueEdaL0tyMkdnUjZlTjRCWXVZNW5QSldDbQoyUUxhSEFOK05JcXFCMzdKWDJyTnRzZk9XeitmRkQrVGxWMTBoNmtiM2huQU1RdEtOMUt5TEtDVGMwSnpJREx4ClN0RHE2MjU4clhRV0xFbjVzUmd0NmovRWNpbi9aZEU5dDVBZ21vVmlRbWpsbDBzaGp5NnlnSVUya29ETGhBMG4KWVc4QWZuWDRGZ0RpejVjWW04S1hzaUJsT3Z1UUM1ZzZDbDhaaFZKZENzNUJqVkFCdHJ6SVZGdi8rbVpEWW52Ngp5b2ZoNkNPZUFoVjBpWkRaNFo3RHBEbGhNV1FzYlFJREFRQUJBb0lDQUFDWnFsa2tUcnV1bzhBQy9XNW11OWlBCmdHRlkrNkZ6VXkreGVuYnhqekluRWdncWVueVFoNGVMS0UxYXU0Yng1ZVNEUE4ySGp0TjBwZThWcGs3clhyZ24Kclc0QUR4bk1KanJrajN4RGdkZVlRY2ZPVGRySFFMbDIwbXZJTFpWazlEVHh2bWJVd3FMWkVmZnZZYTFhcUhVbgpHUkZaRXdNQktwdmVENkJIM1NNNWZWV05ySkVIOWpKcmNFOEQvVGdkWWFtMWxvV2pxYlZsZ1Vwb0kxTUxwUWo2CmdqcWtEajcyTm9KNHNHVEp0bVVqR3YwK0RyYkFiSW9wY05RZWI0dEhhdVBBRVZhM0czMWJZNjMxQmlJY29udVIKblF3NlVWL1FXbGZrT1c2K0NvOHNOUGF3M09oMjRJWFhEdHBGZFdwcnpSMGIrRXdITXhmbUdvTlFsdnFJSG5GaQpNUnlQbk15bmpvV2RBbjN4MjBmQTByNVduUHZ6bC9CQUVTR2JhbzJFaTVWeUFId3NKWlpIMCt3MzNjM3hWTmRUCkJOc3l4ekp2YUxwYk4wbEVYSWxORTVaZDVGYTFKNnpYM0RFVk5wQVdqWU1BcFc4U01KUnRGOXA1eW40b3kyQmYKb3R0T2hyK09aUWRpNlcwUFV6T2lzYkViTjVCc2lwSUpySFpxOXZBSVlxaTlaTGwvMHJETkVobmEzYk9kMDI5WAo2ekV3VnMwTkwrQ1A2OW4ybWxYNlhuS3ZMT0NsNGc4ZTRaMEJ5VDhvY09lVGVRMFY4Vm1nVVBnUjQ5ZkdRREo1Ck1wMUZOL0MxTlprdDlXNFF5cXh1TFJTdHdoRmFycm5jY3hQZWpvZWVPdlJySTJJNE0yUFJtaDF5ZlpWNERQZEMKZjVwNVBRWDZ0MUhuVm1jM29USkJBb0lCQVFET2ZPNDBUSjZ3YmgzSllYMXB4T3V1UkM2TGRyQ3c4R24yd2JWTQp6THVKaElNbS81ME5TMmlPYmNoQXI1WkpSV29ndCtJMUt0Mm9PM09PMmEyQU56eVo0SzNySG5sYUVuYkZIVldGCm9rL1Z1L3NxeUpzVWJWaGszUEMvMUhhWGNWdlFVNWs2MVMyaisvRGJKR1RKck13U3pucUg1Y3VJZS9mYVBZTVAKY0w2a2hmWExoMWtTZFZNMmY1V0lpNDFOTXhnSHRQNW4rQnlrU1JBaEVtNEQvV1RObW9MWGxQYk9sZTVvTkd0VgpWeEduTk53d3c2RW5aamd6UHg5OGV1bi9GSmJZR2pBWFpWQUluRlo5YTVSTW1WUllObjJaUVVXWjBLWjk1dHc2CmIrL3dTRTdUR3M3dXhkODBIbkRmVVlmVy9ZMjRHSnBvUHhKdnU1RUQ0NFV4U25DUkFvSUJBUURGZE0zZlhTWVIKNnNCNXhiU0dHUDhXYTZiQlFSWFJObnBzYmFtNDR0cWZONGE3NzA4cTkycHZ4US8xYlpzYXFZYTkwZTdCeWlhawpCYkdsT04vLzRra25yRFBNQjlOeHZRenpERnpueUZSNGpiZmJNdXZMNkhVRW9TMm9QZnljNDlhMzdZbXFaekRVCnZOS09HWmgzWkRtNGpVbmNEMW9lUm5PUlZXZzRDWEpkT1c2WGpHSTdTdXhXb01lVklKY2NuOENHR1NiRFN6MXoKZlg5cmVCU3Ara0M3QXRwYnhYT2h2cngyKzViZEovRWkvTzNDSnBOYUViRzMxT0s2ak1xOW1Kak0xcXFaNjJIUAorMXVUYlViYTlqYXNvaVZKL3A1SXMrOWZYVGdaZFNLYlhnbDVLdzQ4dm0yRWRWTmxlc3gwTWkzZFRia2d6ZTBHCjB3SkV6NVY5Rkt3ZEFvSUJBRm5KSndia3ZpZjNhY3BVTXVWWDlDY3RqSk9tQTRTY3RXYlBxaGIvK3hmNzM4K0kKWEhFWWRobGdrUy9YYWVEb1p4SmRBdWFkZ2c2UjgxaU5QSTFBOTMvdG01SmVDT1Jxbk94dktlM1d1eUkwQUM0RgpWckdXTGxhRlg4WDZDNnNrWm9qNm9PbGRJdUJvUDczNllEejFmek02Unp0cVo0c3NaSVNvTktIMUkyQ0V3M0ZCCnBEQ0xoYWh2NThTYzhjODh4Vmtza1djQ0V1bzR2dU95a05YNVMraS9JOSs3N1dtODloS25vSGhXU04zTTlXWGEKMnVzMzNuNGlGMzNZTUlGeklYaE1RdGNaZmFpUTJtYms3WEkxUmVDcHFRbUh3VXoxMWo5dXNCcFU3Qjh1UWVBMwppdjEyV3V6ZHc3VEhUZXJsQzhlZUl4M3JOd2dRcGlqcnVOSExEWkVDZ2dFQUNXNHNydkJKOHkwZENEUFREVnlBClFsZmQzUGo0eThjb1RhbG5JN2RoN1p5L1NKYURWMi85bTF6MENDcTE3NjROQzEvTllXQUFQSEV4TE16c2xkSCsKNEhBdkFSMldrYVlQeWtQYTVBOERTY2FxODBNWlUrSEVSUFpWc2VWVC9VSThiUWhoUE13MDN0UXQwaStTd3BEOAoyTDJXdTNYWVBmM3JZeE9MS0xINnprMEI1U2NGUWdPd0Nlc2YzUlZ6WWlDWEYxQjRNM2VTZGNPV3BGRlYyMUJpCmF3d1YxYkEyZDVFZWV5aEU2a2NRRXpXMVBVS09Zd3paU2doVzA4WUpvTWg2ODcyRTVGa0RrT1ZXV0ZJdHdpTmsKTlJhQlpXbE5zZmMyQlgzMFFmTUFOaDlsb0czWC9qcXlERk4yS2pDVk55OTJWVTF5L0FnWnUrdXovZ2xVQUdkTwpXUUtDQVFBNFB1d09oRzlKTjlUUlJrVTVpcG85a2V0MUpJQUgyUjFaR2dBMElWZWp3Z3FjOUhnc0VnbjZPZ0ZjClRoSElQNm5nZTFCMHh6d3plVXNnUGx3ZVN1L0FTQ0xXbHd6bmhFcVpZcnZaRDNJSXBqdDRybmZLMUQ3Q2dRUTkKSmlNcm9aOWhianMxckVqb0U0Wm52VUgxSm1KVk55S3VwMkkwbmlaZ3BLanM5SFhXTDhySEFGdXVac2QzNVhPNwpvZXZCWVJsVG9jZnduUGRZT1pTN3BsWVFPUmc1TVZYN2dzeU11elllSXRxUEgrdGRGZ0REL0EzYzBRd1FPMTJ4CmFnSXVWa00rOUxrdzFoQ25QOGRGTHc5Y21lc2NTejRBcUEyREtOMGtQcjhNY3l5dFdQa3NZTGpkVC9VNWlQaTQKYm55a3UrckY3ZEpkcGw3L1dMY1RjS05lQXozbwotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg== + + + + + wan + 172.18.0.250 + WANGW + 1 + inet + + + + + WAN Gateway + 1 + 1 + + + + + carp + wan + 1 + 0 + 1 + opnsense + VIP WANx + single + 24 + 172.18.0.100 + + + carp + lan + 3 + 0 + 1 + opnsense + VIP LAN + single + 24 + 192.168.1.1 + + + + on + on + on + 10.0.0.2 + opt1 + 10.0.0.2 + root + opnsense + on + on + on + + diff --git a/source/manual/how-tos/resources/config-OPNsense-ipsec-Site-A.xml b/source/manual/how-tos/resources/config-OPNsense-ipsec-Site-A.xml new file mode 100644 index 0000000..c6c93e3 --- /dev/null +++ b/source/manual/how-tos/resources/config-OPNsense-ipsec-Site-A.xml @@ -0,0 +1,618 @@ + + + 11.2 + opnsense + + + Disable the pf ftp proxy handler. + debug.pfftpproxy + default + + + Increase UFS read-ahead speeds to match current state of hard drives and NCQ. More information here: http://ivoras.sharanet.org/blog/tree/2010-11-19.ufs-read-ahead.html + vfs.read_max + default + + + Set the ephemeral port range to be lower. + net.inet.ip.portrange.first + default + + + Drop packets to closed TCP ports without returning a RST + net.inet.tcp.blackhole + default + + + Do not send ICMP port unreachable messages for closed UDP ports + net.inet.udp.blackhole + default + + + Randomize the ID field in IP packets (default is 0: sequential IP IDs) + net.inet.ip.random_id + default + + + + Source routing is another way for an attacker to try to reach non-routable addresses behind your box. + It can also be used to probe for information about your internal networks. These functions come enabled + as part of the standard FreeBSD core system. + + net.inet.ip.sourceroute + default + + + + Source routing is another way for an attacker to try to reach non-routable addresses behind your box. + It can also be used to probe for information about your internal networks. These functions come enabled + as part of the standard FreeBSD core system. + + net.inet.ip.accept_sourceroute + default + + + + Redirect attacks are the purposeful mass-issuing of ICMP type 5 packets. In a normal network, redirects + to the end stations should not be required. This option enables the NIC to drop all inbound ICMP redirect + packets without returning a response. + + net.inet.icmp.drop_redirect + default + + + + This option turns off the logging of redirect packets because there is no limit and this could fill + up your logs consuming your whole hard drive. + + net.inet.icmp.log_redirect + default + + + Drop SYN-FIN packets (breaks RFC1379, but nobody uses it anyway) + net.inet.tcp.drop_synfin + default + + + Enable sending IPv4 redirects + net.inet.ip.redirect + default + + + Enable sending IPv6 redirects + net.inet6.ip6.redirect + default + + + Enable privacy settings for IPv6 (RFC 4941) + net.inet6.ip6.use_tempaddr + default + + + Prefer privacy addresses and use them over the normal addresses + net.inet6.ip6.prefer_tempaddr + default + + + Generate SYN cookies for outbound SYN-ACK packets + net.inet.tcp.syncookies + default + + + Maximum incoming/outgoing TCP datagram size (receive) + net.inet.tcp.recvspace + default + + + Maximum incoming/outgoing TCP datagram size (send) + net.inet.tcp.sendspace + default + + + IP Fastforwarding + net.inet.ip.fastforwarding + default + + + Do not delay ACK to try and piggyback it onto a data packet + net.inet.tcp.delayed_ack + default + + + Maximum outgoing UDP datagram size + net.inet.udp.maxdgram + default + + + Handling of non-IP packets which are not passed to pfil (see if_bridge(4)) + net.link.bridge.pfil_onlyip + default + + + Set to 0 to disable filtering on the incoming and outgoing member interfaces. + net.link.bridge.pfil_member + default + + + Set to 1 to enable filtering on the bridge interface + net.link.bridge.pfil_bridge + default + + + Allow unprivileged access to tap(4) device nodes + net.link.tap.user_open + default + + + Randomize PID's (see src/sys/kern/kern_fork.c: sysctl_kern_randompid()) + kern.randompid + default + + + Maximum size of the IP input queue + net.inet.ip.intr_queue_maxlen + default + + + Disable CTRL+ALT+Delete reboot from keyboard. + hw.syscons.kbd_reboot + default + + + Enable TCP extended debugging + net.inet.tcp.log_debug + default + + + Set ICMP Limits + net.inet.icmp.icmplim + default + + + TCP Offload Engine + net.inet.tcp.tso + default + + + UDP Checksums + net.inet.udp.checksum + default + + + Maximum socket buffer size + kern.ipc.maxsockbuf + default + + + + normal + OPNsense + localdomain + + + admins + System Administrators + system + 1999 + 0 + page-all + + + root + System Administrator + system + admins + $6$$Y8Et6wWDdXO2tJZRabvSfQvG2Lc8bAS6D9COIsMXEJ2KjA27wqDuAyd/CdazBQc3H3xQX.JXMKxJeRz2OqTkl. + 0 + user-shell-access + + 2000 + 2000 + Europe/Amsterdam + 300 + 0.nl.pool.ntp.org + + https + 56b9fb5b8286f + + + yes + 1 + + + + hadp + hadp + hadp + + monthly + + + 115200 + serial + + enabled + 1 + 1 + + 1 + + + + em1 + + 1 + + 1 + 172.10.1.1 + 16 + GW + + + 1 + em0 + 192.168.1.1 + 24 + track6 + 64 + + + wan + 0 + + + + + + + + + + 192.168.1.100 + 192.168.1.199 + + + + + + + + + + + + + + + + public + + + + + + + + + + + + + + + automatic + + + + + pass + wan + inet + keep state + IPsec ESP + IPsec Tunnels + esp + + 1 + + + wanip + + + root@192.168.2.100 + + /firewall_rules_edit.php made changes + + + root@192.168.1.100 + + /firewall_rules_edit.php made changes + + + + pass + wan + inet + keep state + IPsec ISAKMP + IPsec Tunnels + tcp/udp + + 1 + + + wanip + 500 + + + root@192.168.1.100 + + /firewall_rules_edit.php made changes + + + root@192.168.1.100 + + /firewall_rules_edit.php made changes + + + + pass + wan + inet + keep state + IPsec NAT-T + IPsec Tunnels + tcp/udp + + 1 + + + wanip + 4500 + + + root@192.168.1.100 + + /firewall_rules_edit.php made changes + + + root@192.168.1.100 + + /firewall_rules_edit.php made changes + + + + pass + inet + Default allow LAN to any rule + lan + + lan + + + + + + + pass + inet6 + Default allow LAN IPv6 to any rule + lan + + lan + + + + + + + pass + enc0 + inet + keep state + Allow IPsec traffic to LAN net + IPsec Tunnels + + 1 + + + lan + + + root@192.168.2.100 + + /firewall_rules_edit.php made changes + + + root@192.168.1.100 + + /firewall_rules_edit.php made changes + + + + + + + + + 1,31 + 0-5 + * + * + * + root + adjkerntz -a + + + 1 + 3 + 1 + * + * + root + /usr/local/etc/rc.update_bogons + + + */60 + * + * + * + * + root + /usr/local/sbin/expiretable -v -t 3600 sshlockout + + + 1 + 1 + * + * + * + root + /usr/local/etc/rc.dyndns.update + + + */60 + * + * + * + * + root + /usr/local/sbin/expiretable -v -t 3600 virusprot + + + 30 + 12 + * + * + * + root + /usr/local/etc/rc.update_urltables + + + + + + + + + + + ICMP + icmp + ICMP + + + + TCP + tcp + Generic TCP + + + + HTTP + http + Generic HTTP + + / + + 200 + + + + HTTPS + https + Generic HTTPS + + / + + 200 + + + + SMTP + send + Generic SMTP + + + 220 * + + + + + system_information-container:col1:show,captive_portal_status-container:col1:close,carp_status-container:col1:close,cpu_graphs-container:col1:close,gateways-container:col1:close,interface_statistics-container:col1:close,interface_list-container:col2:show,ipsec-container:col2:close,load_balancer_status-container:col2:close,log-container:col2:close,picture-container:col2:close,rss-container:col2:close,services_status-container:col2:close,traffic_graphs-container:col2:close + + + root@192.168.2.100 + + /firewall_rules_edit.php made changes + + + 56b9fb5b8286f + webConfigurator default + LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZiekNDQTFlZ0F3SUJBZ0lKQVB5WVgzRGRzUUJTTUEwR0NTcUdTSWIzRFFFQkN3VUFNRTR4Q3pBSkJnTlYKQkFZVEFrNU1NUlV3RXdZRFZRUUlEQXhhZFdsa0xVaHZiR3hoYm1ReEZUQVRCZ05WQkFjTURFMXBaR1JsYkdoaApjbTVwY3pFUk1BOEdBMVVFQ2d3SVQxQk9jMlZ1YzJVd0hoY05NVFl3TWpBNU1UUTBORFE1V2hjTk1UY3dNakE0Ck1UUTBORFE1V2pCT01Rc3dDUVlEVlFRR0V3Sk9UREVWTUJNR0ExVUVDQXdNV25WcFpDMUliMnhzWVc1a01SVXcKRXdZRFZRUUhEQXhOYVdSa1pXeG9ZWEp1YVhNeEVUQVBCZ05WQkFvTUNFOVFUbk5sYm5ObE1JSUNJakFOQmdrcQpoa2lHOXcwQkFRRUZBQU9DQWc4QU1JSUNDZ0tDQWdFQTNTR2Yvd29vWHQzSDhvUVNLaHNLMis5QTNISHVRWUNzCjB0eS9HaWFNVTN2Z3pKTVVrdWtlelk4YStEQzFnS2pRVkoyMUpFQmVHL2g4eE9VOHM5aWQvTSs5VE5LSEVFRGQKb0poMnZjYjBzZmJtdDgycEFHVDJEanNkRVNEeDErYnNoMktMNEJ2MzQ3N3ZaS0d2UUJWRktncjlVNEtxbS94awpNU09EYUl3ZHgxTVcvVEtNeE53aDhSMkpZVUUzMWN6bkFhcXE0eG5BMGVXWjhyWXAyMmhCbkQxaXdMN1cvWVNuCnprWnhLaVorbjdjUENwVTBod09SblFvOFduYWpvcmFxT0ZkMFJGSTl1bktOQ1k2aEhZUmZ5UHV5WnJxM3dhcEgKTU8xL0EwMWsrK2dBQTNsUW5NdGNVbUpZckRySFpPUGlGQmFaaVkxN0szaTJuNlYrVG9qU1R3L283cjlNMTJTOApaQW9IWCt1d2lvOUwyOW1EYXl0SWpjakl5SzZ6R3hzSWI5QkpxM3JOSFJ4WjBpZUlrVloxN3p0clduaWlMQTB6CnJiMmFWNnJNR3lKQm45WHNST0lHZDF2ajlKdkdFd3hScjhtYXJsSGh1bDZQQ0pFT29VYTBvZkd4bzVhaGZLV1oKNjVkNmhMREVJZHZvU1NCcXNzZ1N3Y2d6a1NOUDdlWmFNYjRBdGlTWFBWa3J3SG5yOHlWVU5jejhYVGhGbk14NwpQb2szNHk0SHZOV091bDdaZzJYUFN3dElUNmxUcFFrajQ4MFJ3UW55aXZJcUFGOEwrM2hMMTRHYXVHVWdzQ2ZaCnlTeFNiMXRMSUhnL0oyYlhESUdsVWdONjh5ZXFjR1FyS3FoQWhvQVVQSUpab0p0cldMZ1FEYm5XYWRlV3IyNzcKTUdNdTlGb3JtM2tDQXdFQUFhTlFNRTR3SFFZRFZSME9CQllFRk13RXRIU0VjRTBWOW80YmYyRTZWbjVtaTFvcQpNQjhHQTFVZEl3UVlNQmFBRk13RXRIU0VjRTBWOW80YmYyRTZWbjVtaTFvcU1Bd0dBMVVkRXdRRk1BTUJBZjh3CkRRWUpLb1pJaHZjTkFRRUxCUUFEZ2dJQkFEaWVpNnMzRElPcnd3NERldXlzYlJValNRSFlyQUl6SHhmNW9ETU4KOGVpYkwyR25DVTZDZENPamJIMVQwMVg4dVVNVTNVaDZIWGJnQ3RESnE1QjduMzNXaDZ1WkxCRkZ1Rkl6L29lWAptTWIxbGZJVEhnTXZuc3FzM3RiU09VQkpiU1RwSGtGeWVnbWFUUE5Nd1ltcWw1VEVlbXNjakMyTTkzL0NIWSt3ClFGU2hpTWVUbUhkdnBQcW0xMkI1SUZOL2x3Qk04REE1dGFVRHJxVytObXVWaE9sdVhKdGlmZlZmSllLNm1LVzcKSFBXYjAzODdzaGpmNDFNeXJodjJMRlU5ZWFsd2t6QmRFNXVpU0ljT1VURFVyQlJaaFpuNDVtVHA3ZnJEeHM2NwplaWE2dzVtZ1VQTElvNndkUlFUbEZtdEU2MmlQdjRsTFFKUFZ0aUFEb1hFTXhVVHBRR2JlRGtZZHU0RFRodGtKCkU5TGV3SjlyOElBUmE0VDMxVUdoRkxzNDJnTTU2bzNWWWJCNDhIc0RVTElRVW83YmxGNENPejRsMmwvRUZpRVUKVlRVMWIrZ3pFMUZLYTdlcUJFNTYvWHczSUQ2d1Vrc1hmYWZsQlI1Y3huUVV1S3dhMnZsdEtNL3o3bFZhc2ZZUQpZRnhTYTlLWnc1MDRyODVLUW9PTmxHMktFeWhZWXhsQ3N6NWR4MlpxMGdUL1cvL1BnbmVFSGpTWE9CR1NvL1dLCnJSejQ2QU4zSUlqMTBIdEx6K1JQQ1VTODAyalJybmRVbjlOeVlsY243cWVEUmFhcm4rWkFjdFludU90ZjdiOUcKaUhJSW9PYTJ6MHZMSnErZW5pOVErbFQxcmc1SXA1S0JwRE0xRWlTU3FyKytZNWhCeGcvSkFlS0Qvc1d4eTZTVAptSkVQCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRZ0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1N3d2dna29BZ0VBQW9JQ0FRRGRJWi8vQ2loZTNjZnkKaEJJcUd3cmI3MERjY2U1QmdLelMzTDhhSm94VGUrRE1reFNTNlI3Tmp4cjRNTFdBcU5CVW5iVWtRRjRiK0h6RQo1VHl6MkozOHo3MU0wb2NRUU4yZ21IYTl4dlN4OXVhM3pha0FaUFlPT3gwUklQSFg1dXlIWW92Z0cvZmp2dTlrCm9hOUFGVVVxQ3YxVGdxcWIvR1F4STROb2pCM0hVeGI5TW96RTNDSHhIWWxoUVRmVnpPY0JxcXJqR2NEUjVabnkKdGluYmFFR2NQV0xBdnRiOWhLZk9SbkVxSm42ZnR3OEtsVFNIQTVHZENqeGFkcU9pdHFvNFYzUkVVajI2Y28wSgpqcUVkaEYvSSs3Sm11cmZCcWtjdzdYOERUV1Q3NkFBRGVWQ2N5MXhTWWxpc09zZGs0K0lVRnBtSmpYc3JlTGFmCnBYNU9pTkpQRCtqdXYwelhaTHhrQ2dkZjY3Q0tqMHZiMllOckswaU55TWpJcnJNYkd3aHYwRW1yZXMwZEhGblMKSjRpUlZuWHZPMnRhZUtJc0RUT3R2WnBYcXN3YklrR2YxZXhFNGdaM1crUDBtOFlUREZHdnlacXVVZUc2WG84SQprUTZoUnJTaDhiR2pscUY4cFpucmwzcUVzTVFoMitoSklHcXl5QkxCeURPUkkwL3Q1bG94dmdDMkpKYzlXU3ZBCmVldnpKVlExelB4ZE9FV2N6SHMraVRmakxnZTgxWTY2WHRtRFpjOUxDMGhQcVZPbENTUGp6UkhCQ2ZLSzhpb0EKWHd2N2VFdlhnWnE0WlNDd0o5bkpMRkp2VzBzZ2VEOG5adGNNZ2FWU0EzcnpKNnB3WkNzcXFFQ0dnQlE4Z2xtZwptMnRZdUJBTnVkWnAxNWF2YnZzd1l5NzBXaXViZVFJREFRQUJBb0lDQUdoV3RGSzNyVUxON01sT2JlKzJJTktUCnVvd0pxZno0UlJPZG13SXd6Q2VjSFA4S0t6d0NpVWsreTkvdHc4WjRZUXg3K1h1b2IzOU5LVG9TWENrVC9iL0wKR2F3RTdqdktENGoyUjVqV0pxRk9PYURpaG1xc09MbVFSTy9QRnEzanhSbEFjM1dFWE52MlBLakQ3WmdVTVRWYwpTQm0rWHRnSktCRlRpMjZxSm1ibG1zUlB0TUl5aUVWbnhXbkJSeUkzYzR5Q3hlMHdPcDRQY3l0bHJxeGJMaElWCm1PSVBhZ3ZuS3ZLV3BGRGFKd2NmYmhaMVBucXlRV1BTNzVWVHczUkVNbDh4VEtmc0VqcEdVS3dBdzU3VTFnbFUKVWVKTkdlVmtmZ0RsSHZnazdaQTY4TDZ5NEVtTFh2MTBjQmljQjNkZ1cwMVZPSThCMWVzMkl4MkREZXpxZkNoMwpLMEdseitDWGVzMFhIL014UnYrUXR6L3lNVHdTUTd0Zys3Z3gyekh0ejVMaXFrTXNIRDR0K1dBSkVYcFlSRjB4CnhZMmJ2V3hDY2JBdmhuL0ZReStHRlY3NjhBODh6ODE2Wk1NV3Q0NUdQZHNmeU1ZK1ZPOG92eTJpdW4rNEVaNy8KY2JmaHpIWmMxdWVOd2xrcFZaUjdtZ2lpeWNmVXFjNU1PUklxckJ0R3JUVVlKNnBSUHphUG9DdHBXeGozcUNzUApDaWpVM2RIcUE1K0gxRkFaQldWY3dQK1J4aFJ1aW9qblJtRVdIeW85SWYzaDIwVHVKdlNRWFJmTHMxakRzR01kCmdhbURTcnZsenNLVWkyRTFKeTRzSk8rL0ZFanduWHV0R2lFV01WcjN3MmJzMW1sNUdGdHdYZXVhV0o3cXdhblUKbDBtZG9MMk9RMGNNbHJra1g3eHhBb0lCQVFENlp6UUk3azlIdGJXMDFWaC9FWEtiWEdwck96SVR6NWJhc0dwTwoyRHNNSEoxWUs1TU1LeUQ2YXFWUDNrNTMveWI1cGdZTmlqMzZlWnNQd1QyRmc2VmMrQXFrUnQ3RnZBM3B5R1ZlCkp1K3BOSWp0S1BIRTNIMWowb0xML1l4bWdIenpUT3B5eTlHRS9PRmMwK043c1dRUlJCcnFBbHlBcDJLYkEwaVgKSlhRd1p5VGNsNTg4VHNzdE01TFpZRFpKZGhzcURvaDN2Ty9YTWp5Ry9DTUFRakZDMWIrb093dWpJOGdYeU4zMQpVOXN4UDBLVmZNL0ZGS0lodDZKRVdQWnh3Um12anZCcmtLV3AzSllQdENlckxvbWxNRzJQMXA0ZWFMemJWdUFoCmNiSDQ1WWZWSmFGbTJvcEtPS1dIMXdWY2hLeGJ4WnNNSThOZFJqQ3MyVEtQQWxDdEFvSUJBUURpRXU0QmxhT2cKNnY0Vzl2TTQrbEVyT0xZMHVrUm5pV2lzSjdVYzlkK2s4VHNJMmdGTWNFY1JveWtsZ1RoN1B6N1NnaFpzOEhsYQptQk5oaWN4NElLeTY4S1VjZGZQZDAvMzBWQmNkSmNQdGtJY3JXMlJzaXJ3N25QeHZ1S01qcWRVNmhnSkU0MnI5CmlPRFVtZDk5ZEpSbnUzZGhhVjNpSkVaMjdudE1NZGdGelJIaTFoK1Zob012aUE5NjlPZ2YvK1E0SkNYd3ZDVksKRkNjUFk3SVlGZm9vWmExWDIwR09HL2I0TEVRSzF3Tml0eW5WRUp4QWxuVjloY2VYbjJNY291aU9Qdk9CRnd3YQpIRG1Ja21rWWw5Qlhkd21jMGJrWVJTcElmTFFvSnU5bkZwZFhGcU1hKzFxSzUyTDRsdGNUWWhUcGhzU3JzR3dzCk1SV3JFL1BTRHZOOUFvSUJBR0pNSnpvbVN3c01neE5FK1NPUXR0dlVVSlpkdTQvWld3L29WeU15Y1NPVkRCTnoKcjVzRVIwTG1vSlNVNFZycjErSUMwYmQ1QUZHV2NVK2kvVUt2WmpmenkwR243SVhWQitVeFhORzBHVHJrTzZoVgovV3JaWDRQVFBMTlZpa3NtdjJaSFdIWE9HeWJJbXJOMUhvVU5Jd3BBSVF5aDlxd3VpVi91encwK2o3ajhsSlRnCkZJdDVKdnRNbHFZc3hjTGEwVmtXTVc1SHhpTkZQa3VES1Q1TnZjYk40Qm5yYStzVC9kV1FiY21EckxWTmJ4YjkKMHhZN3ZsWGNINkFUQ0ZPcGlTckl3d3FHMHZHMmZWWVcwOGU0VWlKOXUxVE8zRzExa2tYTWVkbkhKeVZjL1pDbgo0QTlmVlJCRDRuOUw0bmZxUVRzWmZIOHNmdUhienZuYm5hUlVOVlVDZ2dFQkFLckZROVljay9LOUw5eG5CSWtZCnhQR1NNRWlhSDR2YVJ5QXNDbXBxN0ZvckFyNEg5NDBuRHZncXVLMGs5R1pjK3ZhRzM2dkE1dHBoSDlyQS9ad00KaW8zWHM5RlE1RHEvcFFqSDhJSExBanBVdjFZbi9pN2ppWmE2V2hHR2RtMDlIOTNLVnJKMDIxL1M0b3FXQlRVKwpOOUEzMHREWmg5cUlMbFl1aFNLa1VCcnBza1lZR3RtWE4wZFRUdVpCVTRyQWdFTk1Rd0NiRHN2cmR5bnYxQnJQCmx4eW0yWThSQjI3eWZ0Y3VrT05qVWFKaTI0MmZzM2d5YjJPM0IzTG9LalQ2ZGhMbFNJbE53STJFbm8wa2s1REoKTk02dEU2eksyemVUSDRLTCtJYVFDcTFqYWtTVnkvVll3eWREN0FYOTQwODMrcllBWUZXVXVkR1Q3bHRCZ2g4OQp2ZjBDZ2dFQURhdXJSNDlLR3k0bDR2bDVQYnQweFE4bGRvc25GYlFhVHhrVDJiNU9EL3RYUVJVM3ZZbXE0ejVBCjR5ejFTbkFmc0lDWWNMazBUYTdHLzkwdjNQTFJjQW5wQWU0eERiRGRJQTQ1anpLWG1RYy9mNTBER2l4WDBuUWQKK3RTNXVyWHVtK01PQi84RnA1Q01kaWxSTDdBSDE3czNvait0QWxxcHV4MHo0cXNQR2dWdlRFbTZJSnh4RmVXMAo0cnVad0QvZVUrN1FaNWx6cVphUEcwTkhzblgrem1odHlMS1ozRmtWZStkVXVUQ3ZVSjJkVXl4OVdJUEhpWS9iCjBhTHV0Sk1DT1lxT1J4a0JqZDNiU3dmNk9zZ1RYUDcyRTN1ZzZzQVRtdGtkZ3lPOHRKc001QlgxUE42RWdOU2gKUFM2dFVvanZKbzJtMDlORkx2ZFdHWlU4QVAxaVZBPT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo= + + + + + ikev2 + wan + main + inet + myaddress + peeraddress + + aes + 256 + + sha512 + 14 + 28800 + At4aDMOAOub2NwT6gMHA + pre_shared_key + Site B + off + + 172.10.2.1 + 1 + + + 1 + 56ba1241e5d1c + tunnel + 14 + 3600 + Local LAN Site B + esp + + lan + + + network +
192.168.2.0
+ 24 +
+ + aes + 256 + + hmac_sha512 +
+ 1 +
+ + + wan + 172.10.2.1 + GW + 1 + inet + + Remote Gateway + + + + 1 + + +
diff --git a/source/manual/how-tos/resources/config-OPNsense-ipsec-Site-B.xml b/source/manual/how-tos/resources/config-OPNsense-ipsec-Site-B.xml new file mode 100644 index 0000000..21533dc --- /dev/null +++ b/source/manual/how-tos/resources/config-OPNsense-ipsec-Site-B.xml @@ -0,0 +1,642 @@ + + + 11.2 + opnsense + + + Disable the pf ftp proxy handler. + debug.pfftpproxy + default + + + Increase UFS read-ahead speeds to match current state of hard drives and NCQ. More information here: http://ivoras.sharanet.org/blog/tree/2010-11-19.ufs-read-ahead.html + vfs.read_max + default + + + Set the ephemeral port range to be lower. + net.inet.ip.portrange.first + default + + + Drop packets to closed TCP ports without returning a RST + net.inet.tcp.blackhole + default + + + Do not send ICMP port unreachable messages for closed UDP ports + net.inet.udp.blackhole + default + + + Randomize the ID field in IP packets (default is 0: sequential IP IDs) + net.inet.ip.random_id + default + + + + Source routing is another way for an attacker to try to reach non-routable addresses behind your box. + It can also be used to probe for information about your internal networks. These functions come enabled + as part of the standard FreeBSD core system. + + net.inet.ip.sourceroute + default + + + + Source routing is another way for an attacker to try to reach non-routable addresses behind your box. + It can also be used to probe for information about your internal networks. These functions come enabled + as part of the standard FreeBSD core system. + + net.inet.ip.accept_sourceroute + default + + + + Redirect attacks are the purposeful mass-issuing of ICMP type 5 packets. In a normal network, redirects + to the end stations should not be required. This option enables the NIC to drop all inbound ICMP redirect + packets without returning a response. + + net.inet.icmp.drop_redirect + default + + + + This option turns off the logging of redirect packets because there is no limit and this could fill + up your logs consuming your whole hard drive. + + net.inet.icmp.log_redirect + default + + + Drop SYN-FIN packets (breaks RFC1379, but nobody uses it anyway) + net.inet.tcp.drop_synfin + default + + + Enable sending IPv4 redirects + net.inet.ip.redirect + default + + + Enable sending IPv6 redirects + net.inet6.ip6.redirect + default + + + Enable privacy settings for IPv6 (RFC 4941) + net.inet6.ip6.use_tempaddr + default + + + Prefer privacy addresses and use them over the normal addresses + net.inet6.ip6.prefer_tempaddr + default + + + Generate SYN cookies for outbound SYN-ACK packets + net.inet.tcp.syncookies + default + + + Maximum incoming/outgoing TCP datagram size (receive) + net.inet.tcp.recvspace + default + + + Maximum incoming/outgoing TCP datagram size (send) + net.inet.tcp.sendspace + default + + + IP Fastforwarding + net.inet.ip.fastforwarding + default + + + Do not delay ACK to try and piggyback it onto a data packet + net.inet.tcp.delayed_ack + default + + + Maximum outgoing UDP datagram size + net.inet.udp.maxdgram + default + + + Handling of non-IP packets which are not passed to pfil (see if_bridge(4)) + net.link.bridge.pfil_onlyip + default + + + Set to 0 to disable filtering on the incoming and outgoing member interfaces. + net.link.bridge.pfil_member + default + + + Set to 1 to enable filtering on the bridge interface + net.link.bridge.pfil_bridge + default + + + Allow unprivileged access to tap(4) device nodes + net.link.tap.user_open + default + + + Randomize PID's (see src/sys/kern/kern_fork.c: sysctl_kern_randompid()) + kern.randompid + default + + + Maximum size of the IP input queue + net.inet.ip.intr_queue_maxlen + default + + + Disable CTRL+ALT+Delete reboot from keyboard. + hw.syscons.kbd_reboot + default + + + Enable TCP extended debugging + net.inet.tcp.log_debug + default + + + Set ICMP Limits + net.inet.icmp.icmplim + default + + + TCP Offload Engine + net.inet.tcp.tso + default + + + UDP Checksums + net.inet.udp.checksum + default + + + Maximum socket buffer size + kern.ipc.maxsockbuf + default + + + + normal + OPNsense + localdomain + + admins + System Administrators + system + 1999 + 0 + page-all + + + root + System Administrator + system + admins + $6$$Y8Et6wWDdXO2tJZRabvSfQvG2Lc8bAS6D9COIsMXEJ2KjA27wqDuAyd/CdazBQc3H3xQX.JXMKxJeRz2OqTkl. + 0 + user-shell-access + + 2000 + 2000 + Europe/Amsterdam + + 0.nl.pool.ntp.org + + https + 56b0bd0633772 + + + yes + 1 + + + + hadp + hadp + hadp + + monthly + + + 115200 + serial + + enabled + 1 + 1 + + en_US + none + none + none + none + 1 + + + + em1 + WAN + 1 + + 1 + 172.10.2.1 + 16 + WANGW + + + 1 + em0 + LAN + 192.168.2.1 + 24 + track6 + + 0 + + + + + + + + + 1 + + 192.168.2.100 + 192.168.2.199 + + + + + + + 192.168.2.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public + + + + + + + + + + + + + + + automatic + + + + + pass + wan + inet + keep state + IPsec ESP + IPsec Tunnels + esp + + 1 + + + wanip + + + root@192.168.2.100 + + /firewall_rules_edit.php made changes + + + root@192.168.2.100 + + /firewall_rules_edit.php made changes + + + + pass + wan + inet + keep state + IPsec ISAKMP + IPsec Tunnels + udp + + 1 + + + wanip + 500 + + + root@192.168.2.100 + + /firewall_rules_edit.php made changes + + + root@192.168.2.100 + + /firewall_rules_edit.php made changes + + + + pass + wan + inet + keep state + IPsec NAT-T + IPsec Tunnels + udp + + 1 + + + wanip + 4500 + + + root@192.168.2.100 + + /firewall_rules_edit.php made changes + + + root@192.168.2.100 + + /firewall_rules_edit.php made changes + + + + pass + inet + Default allow LAN to any rule + lan + + lan + + + + + + + pass + inet6 + Default allow LAN IPv6 to any rule + lan + + lan + + + + + + + pass + enc0 + inet + keep state + IPSec Allow Access to LAN Net + IPsec Tunnels + + 1 + + + lan + + + root@192.168.2.100 + + /firewall_rules_edit.php made changes + + + root@192.168.2.100 + + /firewall_rules_edit.php made changes + + + + + + + + + 1,31 + 0-5 + * + * + * + root + adjkerntz -a + + + 1 + 3 + 1 + * + * + root + /usr/local/etc/rc.update_bogons + + + */60 + * + * + * + * + root + /usr/local/sbin/expiretable -v -t 3600 sshlockout + + + 1 + 1 + * + * + * + root + /usr/local/etc/rc.dyndns.update + + + */60 + * + * + * + * + root + /usr/local/sbin/expiretable -v -t 3600 virusprot + + + 30 + 12 + * + * + * + root + /usr/local/etc/rc.update_urltables + + + + + + + + + + + ICMP + icmp + ICMP + + + + TCP + tcp + Generic TCP + + + + HTTP + http + Generic HTTP + + / + + 200 + + + + HTTPS + https + Generic HTTPS + + / + + 200 + + + + SMTP + send + Generic SMTP + + + 220 * + + + + + system_information-container:col1:show,captive_portal_status-container:col1:close,carp_status-container:col1:close,cpu_graphs-container:col1:close,gateways-container:col1:close,interface_statistics-container:col1:close,interface_list-container:col2:show,ipsec-container:col2:close,load_balancer_status-container:col2:close,log-container:col2:close,picture-container:col2:close,rss-container:col2:close,services_status-container:col2:close,traffic_graphs-container:col2:close + + + root@192.168.2.100 + + /system_gateways_edit.php made changes + + + 56b0bd0633772 + webConfigurator default + LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZiekNDQTFlZ0F3SUJBZ0lKQUtFRFdCN2RacjdsTUEwR0NTcUdTSWIzRFFFQkN3VUFNRTR4Q3pBSkJnTlYKQkFZVEFrNU1NUlV3RXdZRFZRUUlEQXhhZFdsa0xVaHZiR3hoYm1ReEZUQVRCZ05WQkFjTURFMXBaR1JsYkdoaApjbTVwY3pFUk1BOEdBMVVFQ2d3SVQxQk9jMlZ1YzJVd0hoY05NVFl3TWpBeU1UUXlPRE13V2hjTk1UY3dNakF4Ck1UUXlPRE13V2pCT01Rc3dDUVlEVlFRR0V3Sk9UREVWTUJNR0ExVUVDQXdNV25WcFpDMUliMnhzWVc1a01SVXcKRXdZRFZRUUhEQXhOYVdSa1pXeG9ZWEp1YVhNeEVUQVBCZ05WQkFvTUNFOVFUbk5sYm5ObE1JSUNJakFOQmdrcQpoa2lHOXcwQkFRRUZBQU9DQWc4QU1JSUNDZ0tDQWdFQXJOcG93a3ZIUnhrZ1hTbHQxRmhOL3RCZnRRRW05OElnClU3ZG5SdjhQVk5IVWVnaHRnZjlGL3ZyV3V0cEJ0MzkvQWY2bk45WG5tRjdqUGVBZU5PRXN4VVhBKzFwZ0FsNFgKYlJQdm1seHZJU2lnZDRKR21KMnJHNE14cGM1T1pMbzZaTzgzNDIwZzRLVGFMSUs2L0ptY1YrUFc4dWJxLzJzTQpVcy9Cc0lERUxWUGlzRUJzc08vczE0UmRWZ1RvVG03Q1dzRVFEUlRBd3RpOVVCbVZEWmFKVDd6NDJpTXdaQm9uClNVc05MRTkvVWg5aVYzWlRrSXM0UDdNOVBUc3ZtM2M3QzFhNUZIbkozaVNQR09NaUNjSERzVnRvbUc5ckR2ejAKNFk1Nkd2akorTnJzVG5WcE9yTTBMUEdUYzUvVkdLWkd6R1lOcFR1NG1zS0hIYXFzeEowd2Z0L2JYNWVZSTVBcQpBWEVGcFNJZldpVnQ5eTZ0Wlg2V3JuZFRrdGY0MHJHU2VleFBhdUNycW1nNjhaTTQ3T0lubEJZa2Y1SnRTT1BjCmtKd0dSWjgyL1ZBcG9LY2Izb2M2dlJ6OThnUk9jcXp6anV4WjhJN2lUemRzdFNFQ2NtT0xMR29ObGM1TkFyNVUKNGJndzVLRURSVFV1OGxtYUQ5bFVKUkFrdG93SGYvRUsyVDNrMTNJR2tJZGNDWTN5TWpEcU9KdktKWWZMdU5CMQpvVGJWWUI2ajlxMzc3MjVxYVhubG9SaXV0N3cxWktKVXZJUGFXMXlsK3p6RndMU3ZtbndvcFdLVFlqamlOZmVJCm5Pazdob0ZVYzg3Q1o2MXluMk9FS2JaWlZ6L1k5TElFM2E0UHNZT0FrYVdnekhKQVlyMTNucVYxWW9WYkdqeHEKY25SMUZUSTNCSWtDQXdFQUFhTlFNRTR3SFFZRFZSME9CQllFRkZBK0o5UlNIZ1JKeW1XMmFnVUQvUmhPWnhFNQpNQjhHQTFVZEl3UVlNQmFBRkZBK0o5UlNIZ1JKeW1XMmFnVUQvUmhPWnhFNU1Bd0dBMVVkRXdRRk1BTUJBZjh3CkRRWUpLb1pJaHZjTkFRRUxCUUFEZ2dJQkFJelFDSDJES1luM0puaDBUVWFNejZBbmZtcHFKbDNra0VsKzhqYXYKelFqZ1RIQmJSSzRiQTZWNmRwUXZKOWhlS1pDRGVubVM3QWxaMlB4MWp5UFdTQllCRkc1MTNIQWF1NjVjWXdJUApPb2Myb0NzZzg3eFlnbXRMZ1ZJbk1VYkdtenFuUmdXQTdzclBJZ3ZKNDJCZWhuU29nRlBpVW1hbnRaYTNkYVVVCkg1OTNsME0xRkpTWm9WbUxMZkx2aEtXdUN6ZWp0RWFaYmdtS1dhNHBnZ3Y5NG93NEt3YjlsRVdVNnl4emNjU0QKbTc2K2JzTHRia2lVYTFKdTJjbFRyaG1WWVZkZ1loamlsV0tEdUx6UHJXNnorZHF6Tkk1d3YzRHJ2SHF0Tm5aTgpaNjBBWmsrUlpHZHhYM0lFazRWeUVKeG9hUXI2UkxhU0J2cTYxMk9NYmFMaERteWJvbHBNRW9sR28zRFRURmt4CkN3cE8ybkx4ZStYTjNNc3VMZWMwUWRaeGE2OE1Ca2ZuUFVEcENYSWdvSHhJNzBtUUt0QmVkUUg4RjJwNkNsUG4KeDFpREpWOGhJM2Z4TWpGOUR3OE12TC9XWkxRMUVOWXlzQjZoeHFtVWJpcXlNcDhuT1NtdmQrb3dmOW9Ub1FGcwpOdTQxOVEwejNER1NlSXlxZGdDdWdzZnE2eGtwbTQ1bnBKbnlRN1FuY3EvdFgyNjY2UTc3eVlLdTd2ZmFiMUxrCkljZ0dkRGl2cVFyZDVpa1FCVHZYSmFiVkE2cFlZaFdxcENKUVRGL3N6cW9vNzNTbVFGbWJrdWRBMG42dHpLb1MKK1A2ZEJBV0gybml6bkI3RFJKWno5L2R2aU9LWHVHN010K09GN2lGWk9Na0xqZGtVbC9QS0lQZ25XZ1JSUDM3QQozU3FlCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpSQUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1M0d2dna3FBZ0VBQW9JQ0FRQ3MybWpDUzhkSEdTQmQKS1czVVdFMyswRisxQVNiM3dpQlR0MmRHL3c5VTBkUjZDRzJCLzBYKyt0YTYya0czZjM4Qi9xYzMxZWVZWHVNOQo0QjQwNFN6RlJjRDdXbUFDWGhkdEUrK2FYRzhoS0tCM2drYVluYXNiZ3pHbHprNWt1anBrN3pmamJTRGdwTm9zCmdycjhtWnhYNDlieTV1ci9hd3hTejhHd2dNUXRVK0t3UUd5dzcrelhoRjFXQk9oT2JzSmF3UkFORk1EQzJMMVEKR1pVTmxvbFB2UGphSXpCa0dpZEpTdzBzVDM5U0gySlhkbE9RaXpnL3N6MDlPeStiZHpzTFZya1VlY25lSkk4WQo0eUlKd2NPeFcyaVliMnNPL1BUaGpub2ErTW40MnV4T2RXazZzelFzOFpOem45VVlwa2JNWmcybE83aWF3b2NkCnFxekVuVEIrMzl0Zmw1Z2prQ29CY1FXbEloOWFKVzMzTHExbGZwYXVkMU9TMS9qU3NaSjU3RTlxNEt1cWFEcngKa3pqczRpZVVGaVIva20xSTQ5eVFuQVpGbnpiOVVDbWdweHZlaHpxOUhQM3lCRTV5clBPTzdGbndqdUpQTjJ5MQpJUUp5WTRzc2FnMlZ6azBDdmxUaHVERGtvUU5GTlM3eVdab1AyVlFsRUNTMmpBZC84UXJaUGVUWGNnYVFoMXdKCmpmSXlNT280bThvbGg4dTQwSFdoTnRWZ0hxUDJyZnZ2Ym1wcGVlV2hHSzYzdkRWa29sUzhnOXBiWEtYN1BNWEEKdEsrYWZDaWxZcE5pT09JMTk0aWM2VHVHZ1ZSenpzSm5yWEtmWTRRcHRsbFhQOWowc2dUZHJnK3hnNENScGFETQpja0JpdlhlZXBYVmloVnNhUEdweWRIVVZNamNFaVFJREFRQUJBb0lDQVFDWENvYnQrTythVmY5c3lNM2E5b3E0CjlmWWJvWFVlbkRoSlR3TGxDKzJtclhBZ2JvcmFSR2t5cEpmTVVQbUowZFAydDBJQlRWNEJUREQvbVg1cnNMUEIKY2ZGdThncmhKcjBMcUpiL2FIUUhJb3dOd2YzVVVEbjdZWW1abkF2dWdyaVNDR0xxelNva2dvak95akdBbHU0Qgo4dXFaK0dReWFxVXJHN1hoZUxOejlGQXF1VEVBNzdZaW9OdzZWVEYxajkwdkZuTGpLMVpCTE1sSVhBSmVERVBTCk5JdXplWHBJam4zejBxd2hJeHBiZFdjbWpCUDdRMXdVZFpnMmtDaEtqa1krNHpuNUJXNzdPVEQ5aTBQc0NLL3EKbzdoak0wRDJxTjJHMTB3bGsyNVJrV05hTDhpUzdaTFREd2xNeU1hWnNubzlFNVFxNVdPcmYvNDNVek9DM3VSSApHWlhLNHB6eUZBQU5tSkdlRTUvNm5yM3Ntd0EvbnhMcGNDSUJMbDlvTDg4clVaYXhZeXdCWm41VjZSbzFSVUN6CkRzZytmaE5xbjlVc1pUdXZwQUQ4ekxkVXVuUTQvK09aS3pEbHRwOWhTNEU4MHpXNDMyVUcxb2lKMG5TYXdJOWUKTFJGNWt5bE55SUhaSG5BRWVxZlVacTR2MWhFbmhVUEFKc0tRVjhvNmQ3cDJDdGFoZUYxdnVrM0QzV3RNdWs2NQpQN1h0bktCL2xCUjE3ai9neUdYS0pUc1BIWENURGZuVGxZZU5IZktiMmxZRHZjMnh5N29aZjZ5bWlRbUZ3bVJTCmt6OTFndDFSbVZaVHQ0Z2VRN0VpaVZScjVxdTc3enZxcjlTOXg5NUNOK0NZZFVoWGdXREMxVEZXdVRCaGxPclMKOENHQ3EzMW12Q25WS1NBQlh3ak1BUUtDQVFFQTJiMGo5dG45MXR2VnRCb0NXd3FDL216N3FCTWFkM0ZPTXFvMAprSCtmeFRWYk1ocC8wOEhWYXFmL2F3VTREVXNhNitFa0RJSm9vZkg4NG1BWmVvZXFyRlZJc2xQdkZiNDEzZSt1CmtNOXJxSjZ6Yk5LQ2YyVU5WTTF0ZjRMRkdjNnNuOTBXdGJzY2U3V2VuRFI2Um9ITjgzbHRvMmY4YWEyVW5EaGUKT2dJUEZhb0lJblBJeG8xQ1NSWDloc0dZZ0VObVUydmtVSzNyRXJSMnVlTy8xQ3ZrMjRLUVJVUEdwaDA2cU8zNQp6dGZKZi9naUJ2QThWdHdkYzkzUHVkTE90STBNNVVKNDNSMWpkdjFUN0lHelR4TFZiL2tJcWdXdkk4Mm04TEpTClE0L0hsK1l6Mk1pNUZ2cUJXeFdXN05jT2xsU1hmYTllUkQ1TE1rT3g5MFdZRDRMZ0NRS0NBUUVBeXpvY3JIN3oKeURNa0RQN3E5QysxMHJrYWE1Z0laWlpmcTBMOUExSStDUlJNWitaVGZZcGlZaTNVcHJPZ1lMdHlCMEpvbU9jNApmSWdabk93MFhHOTd4dUZpeWVTdFlGelEyYjJsa0E1ejE1WUNxUTBUNkYyalVsVkFFQXdNS1FTTEpITlo2ZXNsCkFHZkhVa0FPUllNS0JMZmhnVHRQRk5GUTlZT0F2QlNzcC92TmdMZXNUanpLZW10Tk5vZUsxa2ZQMkMwemFiekwKQkNndDR3UEo3UW1WZ2dEbnBCRStWbE1meE1TckhBcUpGNmJKblZKNk5jdWhqK1FzQkJXZFFmL2NJc1pSL2psdQpvT1EwRC9ycThxTkxIUkNLcEpwNWZ1Mk55SlZBZHVScmd0aVhFNHBROVpCTGtVSXRwOUdic0llQjNFcHAvbDd0Cmd0WnlPbFRqdGVzZ2dRS0NBUUVBb0FuL1p5OHUvait5d1ova1gxcElrZzAwbzRMM0R4ZSs3RXBpUEZzeDZkZWYKNGlITUZxNy8yRmNHeTNpWWpGekp1dHBPanN0RGNOVFdsT1VobFFnbWtHaFcrSXZzelVSemYxN3VKZzN2Q1k4cwpQaTQwTU1Mcm00c3FrbkJod3VnL3hYalJlbDIvUDhac2dFK3FHQ3pNWGNyQXBUeUhNSDJmSDN2bTlpZ1JRbEVwCmpYa2c5NTlZT3pQb2xxV3hHNFZ1cnA0OHdIZzBzaGptc3hjTkpqdmxDTnJjZzZ5ZlUvVmo2a3FRTkZJekR0WW8KM0lTek5QeXd3VHNsdFdXVy9PbzNza0s3WjNwMFl6OHI4a2dhcldJZ2N4N09HWG40RXc3VFIxTXFWL0pVTi9mQgozL01ZNkNUVDgwalpGOWV5SnhpaUNJVmZlalYzTzhpNkJBK3BCcTJoVVFLQ0FRQk5heGZkUm9lTDdwOS9LK1ZKCm5KdEJhUzU5YW05WWM4NkNLWVRGTFNGZ3lCRExTOXptYUQ5T2MzTWRCalRFWk9QdGpBallwc3pIOC9qOTVLV1YKeVFwNEd3aE5MUVkzUFdSNmJscVI1RStSQXg2RVUrMFBpZ3hib3dwQ2tyUlhNOW5seXVPbnp1SkxvejAxUWgydApzVnV4ckhNRmpoaDBMOEVOcGtqMlhWSGd0SFgyNFFHTTFHKzE3d1o5RFdtQWM5N2oxV1JPbFpNcFJEMG16Qnl5ClpnSkVnaCs4U3ExYXFWUGkyNkRyajcvbCtLMjVkdUFEZWsxVHlYSlRKQURDVWJ3RXExUTA2cUFRUHA3dXI0R3QKYVRPR0lQVVArNkRwRDRvQnJZbmZRT2tMOFlLcitQY2FkUnUwZkdkMEZNK2draDZRVXZESjdGUENrZnIxNmJ6TgpZb01CQW9JQkFRQ0YrLzZzL0hmemExYStoL3lCNFRacmw1V28wekdTMkp1WEd1YUpHaGxWZ1RldTFzTDBCKzcwClYwTzRYS3E4OW16MW5BaE5RcEZaWDZDU0RyWHFaWXEwV1hDdVppYkVkUEdMc3hYR0kzNk5xb1Voa2FQR0ZobEkKU1JOSzNPZk54cUNaYVpIRWd1MUgwdWRCZEdvV3IzcXI5cWp2MXQ5d1FtdE8xOVBDN1ZzaUMvV2VmV1Rtb3JKcApxcnhQOUtOVXBqVUNUbzE1eVB6c0NNcld1OWp0Y0NFK2pVOXMwY0IzQUQwcW5UZzZJTTlCVXg4UFlhdWV4QTJOCmF1d3orZnB1bDA2OEJTbW15bGFFdmlTeWpLYUlvdVpIQ3RZYU9lYzJGK1ZNVWliL0s3d1JEQ3JtY1VSZUdZTXoKUmpKODZMVmFaWlQyZkM4UnY3T1JEVWtpMS84a3p5ckYKLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo= + + + + + wan + 172.10.1.1 + WANGW + 1 + inet + + Remote Gateway + + + + 1 + + + + + 1 + ikev2 + wan + main + inet + myaddress + peeraddress + + aes + 256 + + sha512 + 14 + 28800 + At4aDMOAOub2NwT6gMHA + pre_shared_key + Site A + off + + 172.10.1.1 + + + 1 + 56bafc7ad40cd + tunnel + 14 + 3600 + Local LAN Site A + esp + + lan + + + network +
192.168.1.0
+ 24 +
+ + aes + 256 + + hmac_sha512 +
+ 1 +
+
diff --git a/source/manual/how-tos/resources/mycompany_cptemplate.zip b/source/manual/how-tos/resources/mycompany_cptemplate.zip new file mode 100644 index 0000000..29d00e8 Binary files /dev/null and b/source/manual/how-tos/resources/mycompany_cptemplate.zip differ diff --git a/source/manual/how-tos/resources/template_popup.zip b/source/manual/how-tos/resources/template_popup.zip new file mode 100644 index 0000000..3c00a37 Binary files /dev/null and b/source/manual/how-tos/resources/template_popup.zip differ diff --git a/source/manual/how-tos/shaper.rst b/source/manual/how-tos/shaper.rst new file mode 100644 index 0000000..123cf48 --- /dev/null +++ b/source/manual/how-tos/shaper.rst @@ -0,0 +1,624 @@ +===================== +Setup Traffic Shaping +===================== + +For this how-to we will look into these scenario's: + +#. Reserve dedicated bandwidth for a realtime traffic such as (hosted) Voice Over IP (VOIP) server. +#. Share internet bandwidth amongst users evenly +#. Limit maximum internet bandwidth users can consume +#. Prioritize Applications (Weighted) using Queues +#. Multi Interface shaping for a GuestNet + +--------------------------- +Reserve dedicated bandwidth +--------------------------- +In this scenario we will create a pipe dedicated for traffic going to and coming +from our realtime application. For the sample we presume a SIP trunk or hosted +Voice Over IP (VOIP) server. + +For this example we presume a requirement of 4 uncompressed voice channels of 64Kbps, +resulting in a total bandwidth of 256Kbps. The internet connection in this example +has 10Mbps Download and 1Mbps Upload. + + + +.. nwdiag:: + :scale: 100% + :caption: Shaping hosted VOIP / SIP trunk sample + + nwdiag { + + span_width = 90; + node_width = 180; + Internet [shape = "cisco.cloud"]; + ip_phone [label="IP Phone",shape="cisco.ip_phone"]; + ip_phone -- switchlan; + + network LAN { + switchlan [label="",shape = "cisco.workgroup_switch"]; + label = "LAN OPNsense"; + address ="192.168.1.x/24"; + fw1 [label="OPNsense",address="192.168.1.1/24"]; + } + + network WAN { + label = ".WAN OPNsense"; + fw1 [label="OPNsense", shape = "cisco.firewall", address="172.10.1.1/32"]; + Internet; + } + + network SIPHOST { + label = ".WAN SIP PROVIDER"; + Internet; + sip_server [label="SIP/VOIP Server",shape="cisco.sip_proxy_werver", address="172.10.2.1/32"]; + } + } + +To start go to **Firewall->Traffic Shaper->Settings**. + +Step 1 - Create Upload and Download Pipes +----------------------------------------- +On the **Pipes** tab click the **+** button in the lower right corner. +An empty **Edit Pipe** screen will popup. + +Create Pipe For Upload (To our VOIP Server) + +====================== ================ ================================================ + **enabled** Checked *Check to enable the pipe* + **bandwidth** 256 *Numeric value of the desired bandwidth* + **bandwidth Metric** Kbit/s *Metric to use with the numeric value* + **mask** (Empty) *Used for auto queueing, empty for our sample* + **description** PipeUp-256Kbps *Free field, enter something descriptive* +====================== ================ ================================================ + +Create Pipe For Upload (Other Traffic = 1024Kbps - 256Kbps = 768Kbps) + +====================== ================ ================================================ + **enabled** Checked *Check to enable the pipe* + **bandwidth** 768 *Numeric value of the desired bandwidth* + **bandwidth Metric** Kbit/s *Metric to use with the numeric value* + **mask** (Empty) *Used for auto queueing, empty for our sample* + **description** PipeUp-768Kbps *Free field, enter something descriptive* +====================== ================ ================================================ + +Create Pipe For Download (From our VOIP Server) + +====================== ================== ================================================ + **enabled** Checked *Check to enable the pipe* + **bandwidth** 256 *Numeric value of the desired bandwidth* + **bandwidth Metric** Kbit/s *Metric to use with the numeric value* + **mask** (Empty) *Used for auto queueing, empty for our sample* + **description** PipeDown-256Kbps *Free field, enter something descriptive* +====================== ================== ================================================ + +Create Pipe For Download (Other Traffic = 10240Kbps - 256Kbps = 9984Kbps ) + +====================== =================== ================================================ + **enabled** Checked *Check to enable the pipe* + **bandwidth** 9984 *Numeric value of the desired bandwidth* + **bandwidth Metric** Kbit/s *Metric to use with the numeric value* + **mask** (Empty) *Used for auto queueing, empty for our sample* + **description** PipeDown-9984Kbps *Free field, enter something descriptive* +====================== =================== ================================================ + +Step 2 - Create Rules +---------------------- +On the **Rules** tab click the **+** button in the lower right corner. +An empty **Edit rule** screen will popup. + +Create a rule for traffic directed towards the VOIP Server (Upload). + +====================== ================= ===================================================== + **sequence** 11 *Auto generated number, overwrite only when needed* + **interface** WAN *Select the interface connected to the internet* + **proto** ip *Select the protocol, ip in our example* + **source** any *The source ip to shape, leave on any* + **src-port** any *The source port to shape, leave on any* + **destination** 172.10.2.1 *The ip address of our VOIP server* + **dst-port** any *Use any of the destination port if static* + **target** PipeUP-256Kbps *Select the Upload 256Kbps Pipe* + **description** ShapeVOIPUpload *Enter a descriptive name* +====================== ================= ===================================================== + + +Create a rule for traffic coming from the VOIP Server (Download). + +====================== ================= ===================================================== + **sequence** 21 *Auto generated number, overwrite only when needed* + **interface** WAN *Select the interface connected to the internet* + **proto** ip *Select the protocol, ip in our example* + **source** 172.10.2.1 *The ip address of our VOIP server* + **src-port** any *The source port to shape, leave on any* + **destination** any *The destination ip to shape, leave on any* + **dst-port** any *The destination port to shape, leave on any* + **target** PipeDown256Kbps *Select the Download 256Kbps Pipe* + **description** ShapeVOIPDown *Enter a descriptive name* +====================== ================= ===================================================== + +Create a rule for all other internet upload traffic + +====================== ================= ===================================================== + **sequence** 31 *Auto generated number, overwrite only when needed* + **interface** WAN *Select the interface connected to the internet* + **proto** ip *Select the protocol, ip in our example* + **source** 192.168.1.0/24 *The source ip's to shape, our LAN network* + **src-port** any *The source port to shape, leave on any* + **destination** any *the destination address, leave in any* + **dst-port** any *Use any of the destination port if static* + **target** PipeUp-768Kbps *Select the Upload 256Kbps Pipe* + **description** ShapeUpload *Enter a descriptive name* +====================== ================= ===================================================== + + +Create a rule for all other internet download traffic + +====================== =================== ===================================================== + **sequence** 41 *Auto generated number, overwrite only when needed* + **interface** WAN *Select the interface connected to the internet* + **proto** ip *Select the protocol, ip in our example* + **source** any *The source ip to shape, leave on any* + **src-port** any *The source port to shape, leave on any* + **destination** 192.168.1.0/24 *The destination ip's to shape, our LAN network* + **dst-port** any *The destination port to shape, leave on any* + **target** PipeDown-9984Kbps *Select the Download 256Kbps Pipe* + **description** ShapeDown *Enter a descriptive name* +====================== =================== ===================================================== + +.. Note:: + + Be aware of the sequence! It is important to make sure the right traffic + is passed to the right pipe. + + +Now press |apply| to activate the traffic shaping rules. + +*Screenshot Rules* + +.. image:: images/shaping_rules_s1.png + :scale: 100% + +.. |apply| image:: images/applybtn.png + + +---------------------- +Share bandwidth evenly +---------------------- + +For this example we presume an internet connection of 10Mbps Download and 1Mbps +Upload that we want to share evenly over all users. + +.. nwdiag:: + :scale: 100% + :caption: Shaping hosted VOIP / SIP trunk sample + + nwdiag { + + span_width = 90; + node_width = 180; + Internet [shape = "cisco.cloud"]; + pc [label="Connected PC's",shape="cisco.pc"]; + pc -- switchlan; + + network LAN { + switchlan [label="",shape = "cisco.workgroup_switch"]; + label = "LAN OPNsense"; + address ="192.168.1.x/24"; + fw1 [label="OPNsense",address="192.168.1.1/24"]; + } + + network WAN { + label = ".WAN OPNsense"; + fw1 [label="OPNsense", shape = "cisco.firewall", address="172.10.1.1/32"]; + Internet; + } + + } + +To start go to **Firewall->Traffic Shaper->Settings**. + +Step 1 - Create Upload and Download Pipes +----------------------------------------- +On the **Pipes** tab click the **+** button in the lower right corner. +An empty **Edit Pipe** screen will popup. + +Create Pipe For Upload + +====================== ================ ================================================ + **enabled** Checked *Check to enable the pipe* + **bandwidth** 1 *Numeric value of the desired bandwidth* + **bandwidth Metric** Mbit/s *Metric to use with the numeric value* + **mask** destination *Select destination to share the bandwidth* + **description** PipeUp-1Mbps *Free field, enter something descriptive* +====================== ================ ================================================ + + +Create Pipe For Download + +====================== ================== ================================================ + **enabled** Checked *Check to enable the pipe* + **bandwidth** 10 *Numeric value of the desired bandwidth* + **bandwidth Metric** Mbit/s *Metric to use with the numeric value* + **mask** destination *Select destination to share the bandwidth* + **description** PipeDown-10Mbps *Free field, enter something descriptive* +====================== ================== ================================================ + + +Step 2 - Create Rules +---------------------- +On the **Rules** tab click the **+** button in the lower right corner. +An empty **Edit rule** screen will popup. + +Create a rule for traffic directed towards the internet (Upload). + +====================== ================= ===================================================== + **sequence** 11 *Auto generated number, overwrite only when needed* + **interface** WAN *Select the interface connected to the internet* + **proto** ip *Select the protocol, ip in our example* + **source** 192.168.1.0/24 *The source ip to shape, select the LAN network* + **src-port** any *The source port to shape, leave on any* + **destination** any *The destination to shape, leave on any* + **dst-port** any *Use any of the destination port if static* + **target** PipeUp-1Mbps *Select the Upload 256Kbps Pipe* + **description** ShapeUpload *Enter a descriptive name* +====================== ================= ===================================================== + + +Create a rule for traffic coming from the internet (Download). + +====================== ================= ===================================================== + **sequence** 21 *Auto generated number, overwrite only when needed* + **interface** WAN *Select the interface connected to the internet* + **proto** ip *Select the protocol, ip in our example* + **source** any *The source address, leave on any* + **src-port** any *The source port to shape, leave on any* + **destination** 192.168.1.0/24 *The destination ip to shape, select LAN network* + **dst-port** any *The destination port to shape, leave on any* + **target** PipeDown-10Mbps *Select the Download 256Kbps Pipe* + **description** ShapeDownload *Enter a descriptive name* +====================== ================= ===================================================== + +Now press |apply| to activate the traffic shaping rules. + +*Screenshot Rules* + +.. image:: images/shaping_rules_s2.png + :scale: 100% + +------------------------ +Limit bandwidth per user +------------------------ + +For this example we will divide the internet Download traffic between the connected +users in such manner that each user will receive up to a maximum of 1Mbps. + +.. nwdiag:: + :scale: 100% + :caption: Simple network diagram + + nwdiag { + + span_width = 90; + node_width = 180; + Internet [shape = "cisco.cloud"]; + pc [label="Connected PC's",shape="cisco.pc"]; + pc -- switchlan; + + network LAN { + switchlan [label="",shape = "cisco.workgroup_switch"]; + label = "LAN OPNsense"; + address ="192.168.1.x/24"; + fw1 [label="OPNsense",address="192.168.1.1/24"]; + } + + network WAN { + label = ".WAN OPNsense"; + fw1 [label="OPNsense", shape = "cisco.firewall", address="172.10.1.1/32"]; + Internet; + } + + } + +To start go to **Firewall->Traffic Shaper->Settings**. + +Step 1 - Create Upload and Download Pipes +----------------------------------------- +On the **Pipes** tab click the **+** button in the lower right corner. +An empty **Edit Pipe** screen will popup. + +Create Pipe For Download + +====================== ================ ================================================ + **enabled** Checked *Check to enable the pipe* + **bandwidth** 1 *Numeric value of the desired bandwidth* + **bandwidth Metric** Mbit/s *Metric to use with the numeric value* + **mask** source *Select source to limit bandwidth per client* + **description** PipeDown-1Mbps *Free field, enter something descriptive* +====================== ================ ================================================ + + +Step 2 - Create Rules +---------------------- +On the **Rules** tab click the **+** button in the lower right corner. +An empty **Edit rule** screen will popup. + + +Create a rule for traffic coming from the internet (Download). + +====================== ================= ===================================================== + **sequence** 21 *Auto generated number, overwrite only when needed* + **interface** WAN *Select the interface connected to the internet* + **proto** ip *Select the protocol, ip in our example* + **source** any *The source address, leave on any* + **src-port** any *The source port to shape, leave on any* + **destination** 192.168.1.0/24 *The destination ip to shape, select LAN network* + **dst-port** any *The destination port to shape, leave on any* + **target** PipeDown-1Mbps *Select the Download 256Kbps Pipe* + **description** ShapeDownload *Enter a descriptive name* +====================== ================= ===================================================== + +.. Note:: + + If you want to limit traffic for a single ip then just enter the ip address + in the destination field instead of the full LAN network range. + +Now press |apply| to activate the traffic shaping rules. + +*Screenshot Rules* + +.. image:: images/shaping_rules_s3.png + :scale: 100% + +----------------------- +Prioritize using Queues +----------------------- +By utilizing queues we can influence the bandwidth within a pipe and give certain +applications more bandwidth than others based on a weighted algorithm. + +The idea is simple: +Let presume we have a pipe of 10Mbps and 2 applications for instance smtp (email) +and http(s). The http(s) traffic will get a weight of 1 and the smtp traffic a +weight of 9, then when all capacity of our pipe is in use the email traffic will +get 9x more bandwidth than our http(s) traffic, resulting in 1Mbps for http(s) +and 9Mbps for smtp. + +For our example we only look at download traffic, but the exact same can be done +for the upload traffic. + ++----------------+--------+-------------------+ +| Application | Weight | Minimum Bandwidth | ++================+========+===================+ +| SMTP (port 25) | 9 | 9Mbps | ++----------------+--------+-------------------+ +| HTTP (80) | | | ++----------------+ 1 | 1Mbps | +| HTTPS (443) | | | ++----------------+--------+-------------------+ + +To start go to **Firewall->Traffic Shaper->Settings**. + +Step 1 - Create Download Pipe +------------------------------ +On the **Pipes** tab click the **+** button in the lower right corner. +An empty **Edit Pipe** screen will popup. + + +Create Pipe For Download (10Mbps) + +====================== ================= =============================================== + **enabled** Checked *Check to enable the pipe* + **bandwidth** 10 *Numeric value of the desired bandwidth* + **bandwidth Metric** Mbit/s *Metric to use with the numeric value* + **mask** (empty) *Leave empty* + **description** PipeDown-10Mbps *Free field, enter something descriptive* +====================== ================= =============================================== + + +Step 2 - Create Queues +---------------------- +On the **Queues** tab click the **+** button in the lower right corner. +An empty **Edit queue** screen will popup. + +Create Queue for SMTP + +====================== ================== ================================================ + **enabled** Checked *Check to enable the pipe* + **pipe** PipeDown-10Mbps *Select our Pipe* + **weight** 9 *Weight to use with the numeric value* + **mask** (empty) *Leave empty* + **description** Queue-SMTP *Free field, enter something descriptive* +====================== ================== ================================================ + + +Create Queue for HTTP + +====================== ================== ================================================ + **enabled** Checked *Check to enable the pipe* + **pipe** PipeDown-10Mbps *Select our Pipe* + **weight** 1 *Weight to use with the numeric value* + **mask** (empty) *Leave empty* + **description** Queue-HTTP *Free field, enter something descriptive* +====================== ================== ================================================ + +Step 3 - Create Rules +---------------------- +On the **Rules** tab click the **+** button in the lower right corner. +An empty **Edit rule** screen will popup. + + +Create a rule for smtp download traffic (email) + +====================== =================== ===================================================== + **sequence** 11 *Auto generated number, overwrite only when needed* + **interface** WAN *Select the interface connected to the internet* + **proto** ip *Select the protocol, ip in our example* + **source** any *The source address, leave on any* + **src-port** smtp *The source port to shape, smtp or 25* + **destination** any *The destination ip to shape, leave on any* + **dst-port** any *The destination port to shape, leave on any* + **target** Queue-SMTP *Select the SMTP queue* + **description** ShapeSMTPDownload *Enter a descriptive name* +====================== =================== ===================================================== + + +Create a rule for http download traffic + +====================== =================== ===================================================== + **sequence** 21 *Auto generated number, overwrite only when needed* + **interface** WAN *Select the interface connected to the internet* + **proto** ip *Select the protocol, ip in our example* + **source** any *The source address, leave on any* + **src-port** http *The source port to shape, http or 80* + **destination** any *The destination ip to shape, leave on any* + **dst-port** any *The destination port to shape, leave on any* + **target** Queue-HTTP *Select the HTTP queue* + **description** ShapeHTTPDownload *Enter a descriptive name* +====================== =================== ===================================================== + + +Adding an extra rule for https traffic is simple as we can use the same http queue if we like: + +====================== ==================== ===================================================== + **sequence** 31 *Auto generated number, overwrite only when needed* + **interface** WAN *Select the interface connected to the internet* + **proto** ip *Select the protocol, ip in our example* + **source** any *The source address, leave on any* + **src-port** https *The source port to shape, https or 443* + **destination** any *The destination ip to shape, leave on any* + **dst-port** any *The destination port to shape, leave on any* + **target** Queue-HTTP *Select the HTTP queue* + **description** ShapeHTTPSDownload *Enter a descriptive name* +====================== ==================== ===================================================== + +This way http and https traffic will be treated the same (total max of 1Mbps). + +Now press |apply| to activate the traffic shaping rules. + +*Screenshot Rules* + +.. image:: images/shaping_rules_s4.png + :scale: 100% + +-------------------------------------- +Multi Interface shaping for a GuestNet +-------------------------------------- + +One of the options with OPNsense's traffic shaper is its ability to add shaping +rules based upon two interfaces. This option allows you to shape traffic +differently based on the direction the traffic is moving between interfaces. + +For this example we will use this functionality to share a symmetric 10Mbps internet +connection between a primary LAN network and a Guest Network. + +The LAN network will not be limited, traffic from users on our Guest Network will +be limited to a total of 2Mbps Download and 1Mbps Upload. + +.. nwdiag:: + :scale: 100% + :caption: Simple network diagram + + nwdiag { + + span_width = 90; + node_width = 180; + Internet [shape = "cisco.cloud"]; + Internet -- switchwan; + + network WAN { + switchwan [label="",shape = "cisco.workgroup_switch"]; + label = "WAN Interface em1"; + fw1 [label="OPNsense", shape = "cisco.firewall", address="172.10.1.1/32"]; + } + + network LAN { + switchlan [label="",shape = "cisco.workgroup_switch"]; + label = "LAN Interface em0"; + address ="192.168.1.x/24"; + fw1 [label="OPNsense",address="192.168.1.1/24"]; + } + + pc [label="LAN PC",shape="cisco.pc"]; + pc -- switchlan; + + network GuestNet { + switchguestnet [label="",shape = "cisco.workgroup_switch"]; + label = "GuestNet Interface em2"; + address ="192.168.2.x/24"; + fw1 [label="OPNsense",address="192.168.2.1/24"]; + } + + laptop [label="Guest Laptop", shape="cisco.laptop"] + laptop -- switchguestnet; + + } + +Step 1 - Create Upload and Download Pipes +----------------------------------------- + +On the **Pipes** tab click the **+** button in the lower right corner. +An empty **Edit Pipe** screen will popup. + +Create Pipe For Upload (GuestNet - em2) + +====================== ================ ================================================ + **enabled** Checked *Check to enable the pipe* + **bandwidth** 1 *Numeric value of the desired bandwidth* + **bandwidth Metric** Mbit/s *Metric to use with the numeric value* + **mask** (Empty) *Leave empty* + **description** PipeUp-1Mbps *Free field, enter something descriptive* +====================== ================ ================================================ + + +Create Pipe For Download (GuestNet - em2) + +====================== ================== ================================================ + **enabled** Checked *Check to enable the pipe* + **bandwidth** 2 *Numeric value of the desired bandwidth* + **bandwidth Metric** Mbit/s *Metric to use with the numeric value* + **mask** (Empty) *Leave empty* + **description** PipeDown-2Mbps *Free field, enter something descriptive* +====================== ================== ================================================ + +Step 2 - Create Rules +---------------------- + +On the **Rules** tab click the **+** button in the lower right corner. +An empty **Edit rule** screen will popup. + +Important - Before you continue! + First change the mode to advanced, see the toggle in the left top corner of the + popup dialog. One click should shift it from red (disabled) to green (enabled). + +Create a rule for the download traffic + +====================== =================== ===================================================== + **sequence** 11 *Auto generated number, overwrite only when needed* + **interface** WAN *Select the interface connected to the internet* + **interface2** GuestNet *Select the interface that matches your GuestNet* + **proto** ip *Select the protocol, ip in our example* + **source** any *The source address, leave on any* + **src-port** any *The source port to shape, leave on any* + **destination** any *The destination ip to shape, leave on any* + **dst-port** any *The destination port to shape, leave on any* + **direction** in *Match incoming packages (download)* + **target** PipeDown-2Mbps *Select the Download pipe* + **description** GuestNetDownload *Enter a descriptive name* +====================== =================== ===================================================== + +Create a rule for the upload traffic + +====================== =================== ===================================================== + **sequence** 21 *Auto generated number, overwrite only when needed* + **interface** WAN *Select the interface that matches your GuestNet* + **interface2** GuestNet *Select the interface connected to the internet* + **proto** ip *Select the protocol, ip in our example* + **source** any *The source address, leave on any* + **src-port** any *The source port to shape, leave on any* + **destination** any *The destination ip to shape, leave on any* + **dst-port** any *The destination port to shape, leave on any* + **direction** out *Match incoming packages (download)* + **target** PipeUp-1Mbps *Select the Download pipe* + **description** GuestNetUpload *Enter a descriptive name* +====================== =================== ===================================================== + +Now press |apply| to activate the traffic shaping rules. diff --git a/source/manual/how-tos/sslvpn_client.rst b/source/manual/how-tos/sslvpn_client.rst new file mode 100644 index 0000000..2ca843e --- /dev/null +++ b/source/manual/how-tos/sslvpn_client.rst @@ -0,0 +1,405 @@ +========================== +Setup SSL VPN Road Warrior +========================== + +.. image:: images/sslvpn_image_new.png + :scale: 100% + +Road Warriors are remote users who need secure access to the companies infrastructure. +OPNsense uses OpenVPN for its SSL VPN Road Warrior setup and offers OTP (One Time Password) +integration with standard tokens and Googles Authenticator. + +.. Tip:: + + Did you know that OPNsense offers two-factor authentication throughout the entire + system? See for more information: :doc:`/manual/two_factor` + +The main advantages of using SSL VPN for Road Warriors instead of IPsec are: + +* Easy setup on almost all mobile clients using OPNsense's Client Configuration Export. +* Fine grained access control by using multiple servers or Client Specific Overrides. +* No issues with NAT without NAT-T + +With this how-to we'll show you how to configure OPNsense's SSL VPN for road warriors +and give you configuration examples for: + +* Two Factor Authentication (2FA) +* Multi Factor Authentication ( Client Certificate + Password + OTP ) +* Client configuration on Windows, OSX, iOS and Android + +.. Note:: + + For the sample we will use a private ip for our WAN connection. + This requires us to disable the default block rule on wan to allow private traffic. + To do so, go to the **Interfaces->[WAN]** and uncheck "Block private networks". + *(Dont forget to save and apply)* + + .. image:: images/block_private_networks.png + +----------------------------- + +------------ +Sample Setup +------------ +For the sample configuration we configure OPNsense + +**Company Network with Remote Client** + +.. nwdiag:: + :scale: 100% + + nwdiag { + + span_width = 90; + node_width = 180; + Internet [shape = "cisco.cloud"]; + fileserver [label="File Server",shape="cisco.fileserver",address="192.168.1.10"]; + fileserver -- switchlan; + + network LAN { + switchlan [label="",shape = "cisco.workgroup_switch"]; + label = " LAN"; + address ="192.168.1.1.x/24"; + fw1 [address="192.168.1.1/24"]; + } + + network WAN { + label = " WAN"; + fw1 [shape = "cisco.firewall", address="172.18.0.129"]; + Internet; + } + + network Remote { + Internet; + laptop [address="172.10.10.55 (WANIP),10.10.0.1 (SSL Tunnel)",label="Remote User",shape="cisco.laptop"]; + } + } + +Company Network +--------------- +===================== ============================= + **Hostname** fw1 + **WAN IP** 172.18.0.129 + **LAN IP** 192.168.1.0/24 + **LAN DHCP Range** 192.168.1.100-192.168.1.200 + **SSL VPN Clients** 10.10.0.0/24 +===================== ============================= + +----------------------------- + +--------------------- +Step 0 - Preparation +--------------------- +For our example we will use two factor authentication (2FA) and multi factor authentication. +So before we start with the SSL VPN configuration we will need an TOTP server and +a valid signing certificate authority. + +For completeness of this how-to we will also prepare a user. + +Configure TOTP server +--------------------- +To configure a Time based One Time Password server go to **System->Access->Servers** +and click on **Add server** in the top right corner of the form. + +.. TIP:: + + You can also use the quick-search to jump right into the the Access Server + configuration. Try it by typing *Ac...* and see for yourself: + + .. image:: images/qs-access_server.png + :scale: 100% + :align: center + +Now first change the **Type** to **Local + Timebased One time Password** +Enter a **Descriptive name** such as *TOTP VPN Access Server* + +For our example we leave everything else default as we will be using Google's Authenticator +and the defaults are correct for that. + +When using other tokens you may need to change the **Token length**. + +Click **Save** to add the new server. + + +Add Certificate Authority +------------------------- +The VPN server needs a certificate authority to sign client or server certificates. + +To setup a new certificate authority go to **System->Trust->Authorities** and click +on **add or import ca** in the top right corner of the form. + +For our example we will use the following setting: + +========================= ================================================ + **Descriptive name** *SSL VPN CA* + **Method** *Create an internal Certificate Authority* + **Key length (bits)** *4096* + **Digest Algorithm** *SHA512* + **Lifetime (days)** *365* + **Country Code :** *NL* + **State or Province :** *ZH* + **City :** *Middelharnis* + **Organization :** *OPNsense* + **Email Address :** *spam@opnsense.org* + **Common Name :** *internal-sslvpn-ca* +========================= ================================================ + +Click **Save** to add the new Certificate Authority. + +Create a Certificate +--------------------- +After creating the Authority we will also need a certificate. +To create a new certificate, go to **System->Trust->Certificates** and click +**add or import certificate** in the upper right corner of the form. + +Fill in the form with (leave the rest default): + +=========================== ================================================ + **Method** *Create an internal Certificate* + **Descriptive name** *SSLVPN Server Certificate* + **Certificate authority** *SSL VPN CA* + **Type** *Server Certificate* + **Key length (bits)** *4096* + **Digest Algorithm** *SHA512* + **Lifetime (days)** *365* + **Country Code :** *NL* + **State or Province :** *ZH* + **City :** *Middelharnis* + **Organization :** *OPNsense* + **Email Address :** *spam@opnsense.org* + **Common Name :** *SSLVPN Server Certificate* +=========================== ================================================ + +Click **Save** to create the certificate. + +Adding a User +------------- +To add a new user go to **System->Access->Users** and click on the plus sign in +the lower right corner of the form. + +Creating a user will be done in two steps, the first one is adding a basic user +with a username, password, TOTP seed and user certificate. The second step +(after saving) will be to activate the generated OTP seed with Google Authenticator. + +For the first step we enter: + +================== =================== + **Username** *Donald* + **Password** (2x) *S3cr3tP@ssw0rd* + **Full name** *Donald Duck* + **Certificate** *True* + **OTP seed** *True* +================== =================== + + Click **Save** and you will be redirected to create the User Certificate. + Fill in the Certificate form with the following for our example (leave anything + not listed on its presented defaults): + +=========================== ======================================== + **Method** *Create an internal Certificate* + **Descriptive Name** *Leave default (Donald)* + **Certificate authority** *SSL VPN CA* + **Type** *Client Certificate* + **Key length** *4096* + **Digest Algorithm** *SHA512* +=========================== ======================================== + +Click **Save** and you will be redirected to the User page. +Now we will activate your newly created seed with Google Authenticator. +To do so click in the **(i)** symbol on the left of **OTP seed** now you will +see a link to the google authenticator image. Click on it and it will open in a +new browser window and an image will be displayed. This image can be scanned with +you mobile see also: :doc:`/manual/how-tos/two_factor` + +**Save** the new user to complete this step. + +----------------------------- + +------------------------ +Step 1 - Add SSL Server +------------------------ +Adding a new SSL VPN server is relatively simple. We'll start by adding one that +uses our two factor authentication. This setup offers a good protection and it is +easy to setup on the clients as each client can use the same configuration. + +Go to **VPN->OpenVPN->Servers** and click on **add server** in to top right corner +of the form. + +For our example will use the following settings: + +.. Note:: + + The setting **Hardware Crypto** is not used for new systems equipped with **AESNI**, + when the aesni module is loaded it will be used automatically. + +===================================== =============================================== + **Server Mode** *Remote Access (User Auth)* + **Backend for authentication** *TOTP VPN Access Server* + **Protocol** *UDP* + **Device Mode** *tun* + **Interface** *WAN* + **Local port** *1194* + **Description** *My SSL VPN Server* + **TLS Authentication** *Leave both on enabled (checked)* + **Peer Certificate Revocation List** *N/A* + **Server Certificate** *SSLVPN Server Certificate (CA: SSL VPN CA)* + **DH Parameters Length** *4096* + **Encryption algorithm** *AES-256-CBC (256-bit)* + **Auth Digest Algorithm** *SHA512 (512-bit)* + **Hardware Crypto** *No Hardware Crypto Acceleration* + **Certificate Depth** *One (Client+Server)* + **IPv4 Tunnel Network** *10.10.0.0/24* + **IPv6 Tunnel Network** *Leave Empty* + **Redirect Gateway** *Leave Unchecked* + **IPv4 Local Network/s** *192.168.1.0/24* + **IPv6 Local Network/s** *Leave Empty* + **IPv4 Remote Network/s** *Leave Empty* + **IPv6 Remote Network/s** *Leave Empty* + **Concurrent connections** *Leave Empty* + **Compression** *Enabled with Adaptive Compression* + **Type-of-Service** *Leave Unchecked* + **Duplicate Connections** *Leave Unchecked* + **Disable IPv6** *Checked* + **Dynamic IP** *Leave Unchecked* + **Address Pool** *Leave Checked* + **Topology** *Leave Unchecked* + **DNS Default Domain** *Leave Unchecked* + **DNS Servers** *Leave Unchecked* + **Force DNS cache update** *Leave Unchecked* + **NTP Servers** *Leave Unchecked* + **NetBIOS Options** *Leave Unchecked* + **Client Management Port** *Leave Unchecked* + **Renegotiate time** *0* +===================================== =============================================== + +.. Note:: + **Renegotiate time** is used to renegotiate data channel key after n + seconds (default=3600).When using a one time password, be advised that + your connection will automatically drop because your password is not + valid anymore.Set to 0 to disable, remember to change your client when + changed later. + +Click **Save** to add the new server. + +.. image:: images/sslvpn_server.png + :scale: 100% + +---------------------- + +----------------------- +Step 2 - Firewall Rules +----------------------- +To allow SSL VPN client connections, we should allow access to the OpenVPN server +port on the WAN interface. When using multiple servers we need to open up each port. + +For our configuration we only use one server accessible on udp port 1194. + +.. image:: images/sslvpn_wan_rule.png + :scale: 100% + +Next we also need to allow traffic from the VPN clients to our LAN interface. +For our example we will allow client to access anything on our local area network, +however you may decide just to allow traffic to one or more servers. + +.. image:: images/sslvpn_openvpn_rule.png + :scale: 100% + +----------------------------- + +------------------------------------- +Step 3 - Export Client Configuration +------------------------------------- + +Mac OSX & Windows +----------------- +For Mac OSX & Windows users we recommend using Viscosity from Sparklabs (https://www.sparklabs.com/viscosity/). +Viscosity is very easy to setup and use and works well on both platforms. + +Go to **VPN->OpenVPN->Client Export** and select the newly created VPN server from +the list. Leave everything default and Download the **Viscosity Bundle** from the +list of export options under **Client Install Packages**. + +Now on your Mac or Windows PC unpack the bundle and import the Viscosity.visc file. +Double clicking it should be enough to get it imported. When asked for an application +to open the file with search and select Viscosity. + +Some sample screenshots (Mac OSX): + +.. image:: images/viscosity_files.png + :scale: 100% + + +**Import Configuration** + +.. image:: images/viscosity_imported.png + :scale: 100% + +**Connect & login** + +In the password field enter your TOTP token first followed by your password. + +.. image:: images/viscosity_login.png + :scale: 100% + +**Connected** + +.. image:: images/viscosity_connected.png + :scale: 100% + +----------------------------- + +Android +------- +For Android users we recommend using OpenVPN for Android (https://play.google.com/store/apps/details?id=de.blinkt.openvpn) +from Arne Schwabe. + +Go to **VPN->OpenVPN->Client Export** and select the newly created VPN server from +the list. Leave everything default and Download the inline **Android** configuration from the +list of export options under **Client Install Packages**. + +Import the hostname-udp-1194-ios-config.ovpn file into OpenVPN for Android. +Clicking on the file should be enough to get it imported. When asked for an application +to open the file with, select OpenVPN for Android. + +----------------------------- + +iOS +--- +For iOS users we recommend using OpenVPN Connect (https://itunes.apple.com/us/app/openvpn-connect/id590379981) +from OpenVPN Technologies. + +Go to **VPN->OpenVPN->Client Export** and select the newly created VPN server from +the list. Leave everything default and Download the inline **OpenVPN Connect** configuration from the +list of export options under **Client Install Packages**. + +Import the hostname-udp-1194-andoroid-config.ovpn file into OpenVPN Connect. +Clicking on the file should be enough to get it imported. When asked for an application +to open the file with, select OpenVPN Connect. + +----------------------------- + +------------------------------------ +Step 4 - Multi Factor Authentication +------------------------------------ +For two factor authentication you need the factors username/password and a token. +OPNsense supports another layer, namely a user certificate. This means that every +user will be uniquely identified by the user certificate. In this case the multi +factors are: + +* User certificate +* Username/Password +* Token (TOTP) + +Go to **VPN->OpenVPN->Servers** and click on the pencil icon next to the server +we just created to change the 2FA to multi factor authentication. + +Now change **Server Mode** to *Remote Access (SSL/TLS + User Auth)* and leave +everything else unchanged. Click **Save** on the bottom of the form. + +Now when you go to the client exporter, you will see that each user is listed separately. +In our case we see Donald listed. Exporting and importing this configuration works +exactly the same as before, the only difference is that each user requires a User certificate +and therefore their own configuration. + +.. image:: images/sslvpn_client_certificate.png + :scale: 100% diff --git a/source/manual/how-tos/sslvpn_s2s.rst b/source/manual/how-tos/sslvpn_s2s.rst new file mode 100644 index 0000000..8b36d75 --- /dev/null +++ b/source/manual/how-tos/sslvpn_s2s.rst @@ -0,0 +1,323 @@ +================================= +Setup SSL VPN site to site tunnel +================================= + +Site to site VPN's connect two locations with static public IP addresses and allow +traffic to be routed between the two networks. This is most commonly used to +connect an organization's branch offices back to its main office, so branch users +can access network resources in the main office. + +---------------- +Before you start +---------------- +Before starting with the configuration of an OpenVPN SSL tunnel you need to have a +working OPNsense installation wit a unique LAN IP subnet for each side of your +connection (you local network need to different than that of the remote network). + +.. Note:: + + For the sample we will use a private ip for our WAN connection. + This requires us to disable the default block rule on wan to allow private traffic. + To do so, go to the **Interfaces->[WAN]** and uncheck "Block private networks". + *(Don't forget to save and apply)* + + .. image:: images/block_private_networks.png + +----------------------------- + +------------ +Sample Setup +------------ +For the sample configuration we use two OPNsense boxes to simulate a site to site +tunnel, with the following configuration: + +.. sidebar:: Network Site A + + .. nwdiag:: + :scale: 100% + + nwdiag { + + span_width = 90; + node_width = 210; + Internet [shape = "cisco.cloud"]; + pclana [label="PC Site A",shape="cisco.pc"]; + pclana -- switchlana; + + network LANA { + switchlana [label="",shape = "cisco.workgroup_switch"]; + label = " LAN Site A"; + address ="192.168.1.1.x/24"; + fw1 [address="192.168.1.1/24"]; + tunnel [label=" SSLVPN Tunnel",shape = cisco.cloud]; + } + + network WANA { + label = " WAN Site A"; + fw1 [shape = "cisco.firewall", address="172.10.1.1/16"]; + Internet; + } + + } + +Site A - Server +--------------- +==================== ============================= + **Hostname** fw1 + **WAN IP** 172.10.1.1/16 + **LAN IP** 192.168.1.1/24 + **LAN DHCP Range** 192.168.1.100-192.168.1.200 + **Tunnel Network** 10.10.0.0/24 +==================== ============================= + +| +| +| +| + +----------------------------- + +.. sidebar:: Network Site B + + .. nwdiag:: + :scale: 100% + + nwdiag { + + span_width = 90; + node_width = 210; + Internet [shape = "cisco.cloud"]; + pclanb [label="PC Site B",shape="cisco.pc"]; + pclanb -- switchlanb; + + network LANB { + label = " LAN Site B"; + address ="192.168.2.1.x/24"; + fw2 [address="192.168.2.1/24"]; + tunnel [label=" SSLVPN Tunnel",shape = cisco.cloud]; + switchlanb [label="",shape = "cisco.workgroup_switch"]; + } + + network WANB { + label = " WAN Site B"; + fw2 [shape = "cisco.firewall", address="172.10.2.1/16"]; + Internet; + } + + } + +Site B - Client +--------------- + +==================== ============================= + **Hostname** fw2 + **WAN IP** 172.10.2.1/16 + **LAN Net** 192.168.2.0/24 + **LAN DHCP Range** 192.168.2.100-192.168.2.200 + **Tunnel Network** 10.10.0.0/24 +==================== ============================= + +| +| +| +| + +----------------------------- + + +Full Network Diagram Including SSL VPN Tunnel +--------------------------------------------- + +.. nwdiag:: + :scale: 100% + :caption: SSL VPN Site-to-Site tunnel network + + nwdiag { + + span_width = 90; + node_width = 210; + Internet [shape = "cisco.cloud"]; + pclana [label="PC Site A",shape="cisco.pc"]; + pclana -- switchlana; + + network LANA { + switchlana [label="",shape = "cisco.workgroup_switch"]; + label = " LAN Site A"; + address ="192.168.1.1.x/24"; + fw1 [address="192.168.1.1/24"]; + tunnel [label=" SSLVPN Tunnel",shape = cisco.cloud]; + } + + network WANA { + label = " WAN Site A"; + fw1 [shape = "cisco.firewall", address="172.10.1.1/16"]; + Internet; + } + + network WANB { + label = " WAN Site B"; + fw2 [shape = "cisco.firewall", address="172.10.2.1/16"]; + Internet; + } + + network LANB { + label = " LAN Site B"; + address ="192.168.2.1.x/24"; + fw2 [address="192.168.2.1/24"]; + tunnel; + switchlanb [label="",shape = "cisco.workgroup_switch"]; + } + pclanb [label="PC Site B",shape="cisco.pc"]; + pclanb -- switchlanb; + + } + + +------------------------ +Step 1 - Add SSL Server +------------------------ +Adding a new SSL VPN server is relatively simple. We'll start by adding a server +that uses a shared key. This setup offers a good protection and it is +easy to setup. + +Go to **VPN->OpenVPN->Servers** and click on **add server** in to top right corner +of the form. + +For our example will use the following settings (leave everything else on its default): + +.. Note:: + + The setting **Hardware Crypto** is not used for new systems equipped with **AESNI**, + when the aesni module is loaded it will be used automatically. + +===================================== =============================================== + **Server Mode** *Peer to Peer (Shared Key)* + **Protocol** *UDP* + **Device Mode** *tun* + **Interface** *WAN* + **Local port** *1194* + **Description** *SSL VPN Server* + **Shared Key** *Leave on enabled (checked) to create a new key* + **Server Certificate** *SSLVPN Server Certificate (CA: SSL VPN CA)* + **DH Parameters Length** *4096* + **Encryption algorithm** *AES-256-CBC (256-bit)* + **Auth Digest Algorithm** *SHA512 (512-bit)* + **Hardware Crypto** *No Hardware Crypto Acceleration* + **IPv4 Tunnel Network** *10.10.0.0/24* + **IPv4 Local Network/s** *192.168.1.0/24* + **IPv4 Remote Network/s** *192.168.2.0/24* + **Compression** *Enabled with Adaptive Compression* +===================================== =============================================== + + Click **Save** to add the new server. + + .. image:: images/sslvpn_server.png + :scale: 100% + +---------------------- + +------------------------ +Step 2 - Copy Shared Key +------------------------ +To copy the newly created shared key, click on the pencil icon next to the +newly created SSL VPN server. + +You will see the shared key, copy this and keep it safe! + +Sample key: + +.. code-block:: guess + + # + # 2048 bit OpenVPN static key + # + -----BEGIN OpenVPN Static key V1----- + 0960c87c3aafa8f306fe270c1564380b + 7922543563a17b5d2636b4ef9412dd09 + 9ad44974ca1b293963e0f8ac9cbdd97c + 2c31bf35f0df45c9e928ccb033e6d51d + 2caaec02d649ad081c68d7bc7d28030e + 9182c9597a83024097bea860e52d9c66 + 1b9e0048fbf951ce8659bc56edb7f9a1 + 14f7740fc9231a3750557e02eb112712 + ac4b9980d4c740ec96a4357f3940ed90 + d1bbf8eed3de135c886fe2eff8e8b943 + ab1f52b59def4c9ebeacc5eb48425189 + c43887a6237c29e0724f5f45a0f70635 + 10680bec8bfb67c21bf2b4866268594c + 9ba093668064f9a898e6a6ad103b401d + b2047132f0dc8db2230db38444d689fa + ddba46bf6f892ae90c59415f94b82750 + -----END OpenVPN Static key V1----- + + + +------------------------------ +Step 3 - Server Firewall Rules +------------------------------ +To allow SSL VPN client connections, we should allow access to the OpenVPN server +port on the WAN interface. When using multiple servers we need to open up each port. + +For our configuration we only use one server accessible on UDP port 1194. + +.. image:: images/sslvpn_wan_rule.png + :scale: 100% + +Next we also need to allow traffic from the VPN client network (192.168.2.0/24). +For our example we will allow client to access anything on our local network(s), +however you may decide just to allow traffic to one or more IP's. + +.. image:: images/sslvpn_openvpn_rule.png + :scale: 100% + +**You are done configuring Site A.** + +----------------------------- + +---------------------- +Step 4 - Site B Client +---------------------- +Now we will have to setup the client. +Login to the second firewall, go to **VPN->OpenVPN->Clients** and click on +**add client** in the upper right corner of the form. + +Now enter the following into the form (and leave everything else default): + +===================================== =============================================== + **Server Mode** *Peer to Peer (Shared Key)* + **Protocol** *UDP* + **Device Mode** *tun* + **Interface** *WAN* + **Server host or address** *172.10.1.1* + **Server port** *1194* + **Description** *SSL VPN Client* + **Shared Key** *Uncheck to paste the shared key* + ... *Paste your shared key* + **Server Certificate** *SSLVPN Server Certificate (CA: SSL VPN CA)* + **DH Parameters Length** *4096* + **Encryption algorithm** *AES-256-CBC (256-bit)* + **Auth Digest Algorithm** *SHA512 (512-bit)* + **Hardware Crypto** *No Hardware Crypto Acceleration* + **IPv4 Tunnel Network** *10.10.0.0/24* + **IPv4 Remote Network/s** *192.168.1.0/24* + **Compression** *Enabled with Adaptive Compression* +===================================== =============================================== + +Now click on **Save** to apply your settings. + +The Connection Status can be viewed under **VPN->OpenVPN->Connection Status** + +.. image:: images/sslvpn_connection_status.png + :scale: 100% + +------------------------------ +Step 5 - Client Firewall Rules +------------------------------ +To allow traffic from the remote network just add a rule under **Firewall->Rules** +OpenVPN tab. + +.. image:: images/sslvpn_firewall_rule_client.png + :scale: 100% + + +**Done** diff --git a/source/manual/how-tos/tor.rst b/source/manual/how-tos/tor.rst new file mode 100644 index 0000000..8fe13ee --- /dev/null +++ b/source/manual/how-tos/tor.rst @@ -0,0 +1,308 @@ +================= +Tor Configuration +================= + +.. Note:: + Saving changes in modal dialogs does not apply the settings. + To apply them, you have to click the "Reload Service" button. + +------------ +Installation +------------ + +First of all, install the tor plugin (os-tor) from the plugins view. + +.. image:: ../images/menu_plugins.png + + +After a page reload you will get a new menu entry under services for Tor. +Open the menu and choose "Configuration" to configure the plugin. + +---------------- +General Settings +---------------- + +This section controls how Tor behaves in general as well as forward proxying. + +Global Settings +=============== + +.. image:: images/tor_general.png + +Tor Service Settings +-------------------- + +:Enable: + Controls if the service should be running. If it is enabled, + it will also be enabled at boot time. +:Control Port: + The control port is used for control communication with the Tor daemon. + This Port requires a password, which will not be disclosed to the GUI but + can be queried via the API. This setting is available for you to handle + Port conflicts, so you can change this port. +:Create a logfile, Send log messges to syslog: + Enable this checkbox if you want some logging. Please note that a detailed + log may lead to privacy issues. +:Logfile, Syslog level: + If the corresponding checkbox is enabled, this will be the minimum severity + for sending or writing log messges. +:Fascist Mode: + If internet access is filtered, you can try this option. + Please note that this is not compatible with other features like "Hidden Services". +:Fascist Firewall Ports: + These are the unfiltered ports of the firewall. The defaults of 80 and 443 are + choosen, because they are commonly open. + +Forward Proxy +------------- + +.. Note:: + The SOCKS proxy is only useable from localhost (127.0.0.1 and ::1) + unless an ACL is added in the "SOCKS Proxy ACL" section. + +:Listen Interfaces: + Add one or multiple interfaces, on which Tor should listen additionally + to the loopback interface. This is required if you want to use Tor from + other computers than the appliance itself. Tor will bind on the + statically configured IP address from your interface configuration. + If the interface has no static IP configured, it will be ignored. +:SOCKS Port Number: + The port which should be used for the SOCKS server. + +Transparent Forward Proxy +------------------------- + +:Transparent Port: + This port is the target for your NAT rule. + Please create a rule for this port in the "Port Forward" section of the firewall. +:Transparent DNS Port: + If you are using Tor transparently, you can resolve .onion addresses + to IPs of the given pool for example. This also allows to keep DNS secret. +:Transparent IP Pool: + This is used to provide an IP pool to Tor, which can be used for host mapping. + This needs to be a /16 network at minimum. +:Map Host To IP Pool: + This option will assign IP addresses to resolved .onion domains by the + Tor DNS service. Checking this box is recommend but a transparent IP + pool is required + +SOCKS ACL +========= + +.. WARNING:: + If untrusted devices have access to the SOCKS proxy, + private information may be leaked. + Please be careful with the networks you allow here. + +.. image:: images/tor_socks_acl.png + +In this example, you can see that all Hosts of the +192.168.0.0/16 network have access to the Tor Proxy. +By default, connections are forbidden. + +Creating a new entry is quite easy. Just click the `+` and +fill out the form: + +.. image:: images/tor_socks_acl_edit.png + +:Enable: + The entry will be added to the configuration file. + If this checkbox is unckecked, the entry is ignored. +:Protocol: + Select the protocol in use for this ACL. + You can choose between IPv4 and IPv6. + By default, IPv6 is selected. +:Network: + In this field, you have to add the network, + on which this ACL should be applied in CIDR notation. +:Action: + Select if the traffic should be accepted or rejected. + +---------------- +Hidden Services +---------------- + +A hidden service is an open TCP port, which is hosted in the Tor network +and therefore the origin of the service is hard to trace. +For example, you can host a website in Tor by running a webserver in your +network and forwarding a hidden service port to this webserver. + +.. WARNING:: + This does not work with every protocol as there are protocols + which open arbitrary ports. An example for that is FTP. + You may work around this issue by limiting the usable ports + of such services (for example 10 ports) and forward those to the server. + +If you want to host a hidden service, +you need to open the hidden service tab and click the `+` button. + +.. image:: images/tor_hidden_services.png + +The following dialog will open and you can enter a name. + +.. image:: images/tor_hidden_services_edit.png + +You are allowed to add any alphanumeric name here. +For example, you can call your service sampleservice. + +Click "Save changes" and your service is saved to the +configuration file but not saved to the Tor configuration file. + +Switch to the "Hidden Service Routing" tab: + +.. image:: images/tor_hidden_services_routing.png + +For any port you want to forward, you have to click `+` and fill out the form: + +.. image:: images/tor_hidden_services_route_edit.png + +:Hidden Service: + The service on which the port forward applies. + The entries in this list are the services created in the previous step. +:Port: + The virtual Port in the Tor network. +:Target Host: + The host, on which the real service is running. +:Target Port: + The real port of the service. Please note that + this does not need to match the `Port` field but some + services may act strange on mismatch. + +The sample in the screenshot would forward traffic from the virtual host +in the Tor network it gets on port 80 to 127.0.0.1:8080 + +.. Warning:: + When using local connections like `127.0.0.1` or `::1`, your application + may think this connection is trusted (localhost is not from the internet). + Be careful when forwarding traffic to localhost. + + +In addition to regular onion services, the services can be protected even more +by requireing the client to know a secret cookie. + +This setting needs to be configured on both ends. On the server hosting the +onion service, you need to configure it on the configuration tab for the onion +service. + +For example, if you want to have a stealth service (undetectable without knowing +the key), you can configure it like the following: + +.. image:: images/tor_hidden_services_edit_very_hidden.png + +:Authorization Type: + Can be `Stealth` or `Basic`. Basic means that multiple clients can use the + entry point and it is still visible but unauthorized hosts can not connect. +:Authorized Clients: + You can choose some names for your clients. Each client gets a authorization + cookie assigned so they can connect to it. If you set this value, this onion + service will not be available to the public anymore. + +Now as this service will need to be configured to the client side as well, +you will need to add the secret to the configuration page. To configure a +authorization cookie for a service, you can open the +`Onion Service Authentication` tab and fill out the form like on the screenshot: + +.. image:: images/tor_hidden_servicesvery_hidden_credentials.png + +You need to configure the hostname and the authorization cookie you will get. + +:Host Name: + Enter the .onion address of the onion service. +:Authentication Cookie: + This is the authentication code you will get from the maintainer of the + onion service. Enter it into this field. + +When you are done, save the settings and reload the service. After that, you should +be able to reach the service. + + +------ +Relays +------ + +A Tor relay is a host which forwards traffic for other Tor nodes. +A relay, which allows to pass traffic outside of the Tor network, +is called an "Exit Node". If the relay is configured only for you +(not for public access), it is called a bridge. +Bridges are used to circumvent filtering of public entry nodes based +on IP/Port basis as the existence of bridges is usually unknown. + +Relays And Bridges +================== + +.. image:: images/tor_relay.png + +.. Note:: + To be a relay, your host must have a public + available port. With relaying, you will increase the anonymity + of Tor and it is less risky than an exit node. + +:Enable: + Enable this checkbox if you want to relay traffic (forward + foreign traffic). +:Host: + This is the host to bind the relay port to. This can be the public IP + address. This setting is optional and may be omitted. +:Port: + This is the public port used. Do not forget to add a firewall rule + to pass traffic to this port. Otherwise it will not work. +:Address: + You can enter the FQDN or the WAN IP of this Firewall. +:Nickname: + A nickname can be used to identify your network but it must only + consist of alphanumeric characters. +:Bandwith Rate: + You can limit the bandwith Tor will use. By default, Tor will use the + maximum amount of bandwith available. + The value must be at least 72 kilobits per second. +:Bandwith Burst: + See Bandwith Rate. +:Directory Port: + If you have a lot of bandwith, you can also configure a directory port. + You should not enable this port if your bandwith is small. +:Reject Private IPs: + **IMPORTANT** DO NOT DISABLE UNLESS YOU KNOW WHAT YOU ARE DOING. + This option blocks access to RFC1918 addresses regardless of the + configured policy. If you disable this option, somebody can invade + your network. +:Bridge: + Enable this setting, if you want to be a bridge. +:Publish Server Descriptor: + If this is disabled, Tor will not publish descriptors. If you don't + want to be in a directory (for example for testing reasons), + uncheck this option. + +Exit Nodes +========== + +.. Warning:: + Providing an exit node can lead to legal issues. It may be a good idea to + consult a lawyer before setting up one as you might be made responsible for + traffic, which originates from a malicious Tor user. + +If you have relaying enabled, you can also become an exit node. +To allow outgoing connections, you have to open to the "Exit Node ACL" tab. + +.. image:: images/tor_exit.png + +Click on `+` to add a new ACL. + +.. image:: images/tor_exit_acl_entry.png + +:Enable: + If it is checked, the ACL will be used by Tor, + otherwise the line is ignored. +:Protocol: + Select the protocol, on which this ACL applies. + You can select IPv4 and IPv6 here. IPv6 is the default. +:Network: + You can enter a target network in CIDR notation or an IP + address here. If no IP is given, any IP will match. +:Start Port, End Port: + This match is the target port of a connection. + You can provide only a start port if you want to match a single port. + If you provide both, a port range will be used. +:Action: + If you select "Reject", no exit node traffic will be sent to this host + and it will not be forwarded. If you choose "Accept", your host may + be choosen as an exit node in a circuit. diff --git a/source/manual/how-tos/transparent_bridge.rst b/source/manual/how-tos/transparent_bridge.rst new file mode 100644 index 0000000..198e624 --- /dev/null +++ b/source/manual/how-tos/transparent_bridge.rst @@ -0,0 +1,206 @@ + +============================ +Transparent Filtering Bridge +============================ + +------- +Warning +------- +The Transparent Filtering Bridge is not compatible with Traffic Shaping. +Do not enable the traffic shaper when using the filtering bridge. + +-------- +Abstract +-------- + +A transparent firewall can be used to filter traffic without creating +different subnets. This application is called filtering bridge as it +acts as a bridge connection two interfaces and applies filtering rules +on top of this. + +For more information on Filtering Bridged on FreeBSD, see +`filtering-bridges `__ + +------------ +Requirements +------------ + +- For this howto we need a basic installation of OPNsense with factory + defaults as a starting point. +- And an appliance with 2 physical interfaces. + +-------------- +Considerations +-------------- + +To create this howto version OPNsense 15.7.11 has been used. Some screenshots +maybe outdated, but setting should apply up to at least 17.1.6. If you use a +different version some options can be different. + +.. Note:: + + The Menu System of the User Interface has been updated with sub items. + Where tabs are shown in screenshots, these are now likely visible as submenu. + +------------------------------ +Configuration in 10 easy steps +------------------------------ + +.. contents:: + :local: + +.. Warning:: + + During the configuration you will be asked to "Apply" your changes several times, + however this may affect the current connection. So **don't** apply anything until + completely finished! You need to Save your changes for each step. + + +1. Disable Outbound NAT rule generation +--------------------------------------- + +To disable outbound NAT, go to +**Firewall** -> **NAT** -> **Outbound**: Disable Outbound NAT rule generation + +|Filtering Bridge Step 1.png| + +2. Change system tuneables +-------------------------- + +Enable filtering bridge by changing **net.link.bridge.pfil\_bridge** +from default to 1 in **System** -> **Settings** -> **System Tuneables** + +|Filtering Bridge Step 2.png| + +And disable filtering on member interfaces by changing +**net.link.bridge.pfil\_member** from default to 0 in +**System** -> **Settings** -> **System Tuneables** + +|Filtering Bridge Step2a.png| + +3. Create the bridge +-------------------- + +Create a bridge of LAN and WAN, go to +**Interfaces** -> **Other Types** -> **Bridge** :Add Select LAN and WAN. + +|Filtering Bridge Step 3a.png| + +|Filtering Bridge Step 3b.png| + +4. Assign a management IP/Interface +----------------------------------- + +To be able to configure and manage the filtering bridge (OPNsense) +afterwards, we will need to assign a new interface to the bridge and +setup an IP address. + +Go to **Interfaces** -> **Assign** -> **Available network ports** , select +the bridge from the list and hit **+**. + +|Filtering Bridge Step 4.png| + +Now Add an IP address to the interface that you would like to use to +manage the bridge. Go to **Interfaces** -> **OPT1** enable the interface +and fill-in the ip/netmask. + +5. Disable Block private networks & bogon +----------------------------------------- + +For the WAN interface we nee to disable blocking of private networks & bogus ip's. + +Goto **Interfaces** -> **WAN** and unselect **Block private networks** +and **Block bogon networks**. + +|Filtering Bridge Step 5.png| + +6. Disable the DHCP server on LAN +--------------------------------- + +To disable the DCP server on LAN goto **Services** -> **DHCP Server** -> **LAN** and +unselect enable. + +|Filtering Bridge Step 6.png| + +7. Add Allow rules +------------------- +After configuring the bridge the rules on member interfaces (WAN/LAN) will be +ignored. So you can skip this step. + +Add the allow rules for all traffic on each of the three interfaces (WAN/LAN/OPT1). + +This step is to ensure we have a full transparent bridge without any filtering +taking place. You can setup the correct rules when you have confirmed the bridge +to work properly. + +Goto **Firewall** -> **Rules** and add a rule per interface to allow all traffic +of any type. + +|Filtering Bridge Step 7.png| + +8. Disable Default Anti Lockout Rule +------------------------------------ +After configuring the bridge the rules on member interfaces (WAN/LAN) will be +ignored. So you can skip this step. + +As we now have setup allow rules for each interface we can safely remove +the Anti Lockout rule on LAN + +Goto **Firewall** -> **Settings** -> **Admin Access** :Anti-lockout and select +this option to disable + +9. Set LAN and WAN interface type to 'none' +------------------------------------------- + +Now remove the IP subnets in use for LAN and WAN by changing the +interface type to none. Goto **Interfaces** -> **LAN** & **Interfaces** -> **WAN** +to do so. + +|Filtering Bridge Step 9.png| + +10. Now apply the changes +------------------------- + +If you followed each step, then you can now apply the changes. The +Firewall is now converted to a filtering bridge. + +.. rubric:: Done.. ready to set your own filtering rules + :name: done..-ready-to-set-your-own-filtering-rules + +Now you can create the correct firewall/filter rules and apply them. To +acces the firewall you need to use the IP adress you configured for the +OPT1 Interface. + +.. WARNING:: + + Rules need to be configured on the bridge. Rules on member interfaces will + be ignored! + +.. TIP:: + + Don't forget to make sure your PC/Laptop is configured with an IP adress that + falls within the IP range of the OPT1 subnet! + +.. |Filtering Bridge Step 1.png| image:: images/Filtering_Bridge_Step_1.png + :width: 700px +.. |Filtering Bridge Step 2.png| image:: images/Filtering_Bridge_Step_2.png + :class: thumbimage + :width: 700px +.. |Filtering Bridge Step2a.png| image:: images/Filtering_Bridge_Step_2a.png + :class: thumbimage + :width: 700px +.. |Filtering Bridge Step 3a.png| image:: images/Filtering_Bridge_Step_3a.png + :width: 700px +.. |Filtering Bridge Step 3b.png| image:: images/Filtering_Bridge_Step_3b.png + :width: 700px +.. |Filtering Bridge Step 4.png| image:: images/Filtering_Bridge_Step_4.png + :width: 700px +.. |Filtering Bridge Step 5.png| image:: images/Filtering_Bridge_Step_5.png + :width: 700px +.. |Filtering Bridge Step 6.png| image:: images/Filtering_Bridge_Step_6.png + :width: 619px +.. |Filtering Bridge Step 7.png| image:: images/Filtering_Bridge_Step_7.png + :width: 700px + :height: 69px +.. |Filtering Bridge Step 9.png| image:: images/Filtering_Bridge_Step_9.png + :width: 700px diff --git a/source/manual/how-tos/two_factor.rst b/source/manual/how-tos/two_factor.rst new file mode 100644 index 0000000..42cdf27 --- /dev/null +++ b/source/manual/how-tos/two_factor.rst @@ -0,0 +1,110 @@ +========================================= +Configure 2FA TOTP & Google Authenticator +========================================= +This how-to will show you how to setup a One-time Password 2 Factor Authentication +using OPNsense and Google's Authenticator. All services of OPNsense can be used +with this 2FA solution, with the exception of console/ssh access. + +.. image:: /manual/images/two_factor_authentication.png + :scale: 100% + +.. Note:: + + To use the same feature with any time based one-time password token just enter + the seed into the field in step 3 instead of creating a new seed. The seed needs + to be in base32 format. + +-------------------------------------- +Step 1 - Add New Authentication Server +-------------------------------------- +To add a TOTP server go to **System->Access-Servers** and press **Add server** in +the top right corner. Then fill in the form as follows: + +====================== =================================== ======================================== + **Descriptive name** TOTP Server *Choose a server name* + **Type** Local+Timebased One Time Password *Select the TOTP server Type* + **Token length** 6 *6 for Google Authenticator* + **Time window** *Leave Empty for Google Authenticator* + **Grace period** *Leave Empty for Google Authenticator* +====================== =================================== ======================================== + +------------------------------------- +Step 2 - Install Google Authenticator +------------------------------------- +Go to the App Store of your platform and search for Google Authenticator. +Install using the normal procedure for your device. + +--------------------------- +Step 3 - Add or modify user +--------------------------- +For this example we will create a new user, go to **System->Access-Users** and click +on the plus sign in the lower right corner. + +Enter a **Username** and **Password** and fill in the other fields just as you would +do for any other user. Then select the **Generate new (160bit) secret** under **OTP seed**. + +When done press **Save**. + +------------------------------------------------- +Step 4 - Activate Authenticator for this OTP seed +------------------------------------------------- +To activate your new OTP seed on the Google Authenticator, first reopen the user +you just created by clicking on the pencil icon. + +.. image:: images/OTP_seed.png + :scale: 100% + +Now it will show a QR code: + +.. image:: images/otp_qr_code.png + :scale: 100% + +.. Warning:: + + Be very careful with the seed or QR code as this is the only thing you need + to calculate the token. **KEEP YOUR SEED/QR CODE SAFE !** + + +Now open your Google Authenticator application and select the option to start the +configuration and then scan the QR code or alternatively enter the seed directly. + +.. image:: images/iphone_qr_scan.png + :scale: 100% + +----------------------- +Step 5 - Test the token +----------------------- +For testing the user authentication, OPNsense offers a simple tester. +Go to **System->Access->Tester** + +Select the Authentication server you have configured, and enter the user name. +Then enter the ***token** + **password**, remember the order +is token and then password **in the same field**. + +.. Note:: + Password field should be used to enter both token and your password, like: + **Password:** 123456PASSWORD + + +Hit the test button and if all goes well you should see *successfully authenticated*. + +.. image:: images/system_access_tester.png + :scale: 100% + +------------------------ +Step 6 - Using the token +------------------------ +To use the token in any application/service that you have configured, just open +the Google Authenticator and add the created token/key **before** your regular password. + +.. Warning:: + Remember, you need to enter the token **before** you password! + And the password field should be used to enter both token and your password, + like: **Password:** 123456PASSWORD + + +The code will change every 30 seconds. +Sample code: + +.. image:: images/google_token_sample.png + :scale: 25% diff --git a/source/manual/how-tos/user-ldap.rst b/source/manual/how-tos/user-ldap.rst new file mode 100644 index 0000000..45852f9 --- /dev/null +++ b/source/manual/how-tos/user-ldap.rst @@ -0,0 +1,125 @@ +================ +Configuring LDAP +================ +LDAP is the light weight directory access protocol used by Microsoft Active Directory, +OpenLDAP and Novell eDirectory, to name a few. + +OPNsense can use a LDAP server for authentication purposes and for authorization +to access (parts) of the graphical user interface (web configurator). When using +LDAP for the GUI the privileges have to be defined with the local user manager, +to do so an import of the users from the LDAP source is required. + +In this how-to we will show you how to configure both using Microsoft Active Directory +Server. If you only need LDAP for services like vpn, then you can skip step 3-5. + +------------- +Prerequisites +------------- +A functional LDAP server (example is based on MS AD) is required. +You OPNsense firewall need to be fully configured and able to access the LDAP server. + +Step 1 - Add New LDAP server +---------------------------- +To add a new LDAP server as authentication source, go to **System->Access->Servers** +and click on **Add server** the top right corner, just above the form. + +Enter the following information: + +================================ ======================== =============================================================== + **Descriptive name** ws2012 *Enter a descriptive name* + **Type** LDAP *Select LDAP* + **Hostname or IP address** 10.10.10.1 *Enter the IP address of you LDAP Server* + **Port value** 389 *Enter the port number, 389 is default* + **Transport** TCP - Standard *Select Standard or Encrypted* + **Peer Certificate Authority** *When using SSL Encryption, select the CA* + **Protocol version** 3 *Select protocol version* + **Bind credentials** cn=testusr,CN=Users, + User DN: DC=opnsense,DC=local *Enter your credentials* + Password: secret *alway use a strong password* + **Search scope** + Level: Entire Subtree *Select Entire Subtree to retrieve all* + Base DN: DC=opnsense,DC=local *Enter the Base DN* + **Authentication containers** *Select* *Click & Select the containers from the list* + **Extended Query** &(objectClass=Person) *Extend query, p.e. limit results to Persons* + **Initial Template** MicrosoftAD *Select you LDAP Server Type* + **User naming attribute** samAccountName *Auto filled in based upon Initial Template* +================================ ======================== =============================================================== + +.. Note:: + When clicking on the **Select** button right next to Authentication containers, + something similar to will show up: + + .. image:: images/ldap_selectcontainer.png + :scale: 100% + +.. TIP:: + The **Extended Query** can be used to select users who are member of a specific + group. One can use something like this: + **&(memberOf=CN=myGroup,CN=Users,DC=opnsense,DC=local)** to select only members + of the group *"myGroup"*. To add a user to a specific group under Windows just + edit the groups properties and select **Add...** to add the user under the tab + **Members**. + + .. image:: images/ldap_mygroup_properties.png + :scale: 100% + + +Step 2 - Test +-------------- +To test if the server is configured correctly, go to **System->Access->Tester** +and select your LDAP server and enter a valid username + password. Click on +**Test** and if everything is setup correctly it will show: + +.. image:: images/ldap_testok.png + :scale: 100% + +.. Note:: + When limited to just one group, the group name will not be shown in the listing. + +If not (or your entered invalid credentials) it shows: + +.. image:: images/ldap_testfail.png + :scale: 100% + +Step 3 - Import Users +--------------------- +If you would like to give LDAP/Active Directory users access to the GUI, you need +to import the users into the local user manager. Go to **System->Access->Users** +you will see a cloud import icon at the lower right corner of the form. + +.. image:: images/user_cloudimport.png + :scale: 100% + +Click on the cloud import icon to start importing users. + +A new form will be show with the individual users, select the ones you like to import. + +Step 4 - Update ldap user privileges +------------------------------------ +Now if you go to **System->Access->Users** you will see all users including the +newly imported ldap users. You can create a specific group for these users to +easily manage the privileges or use one of your earlier created groups. + +When opening a ldap user (edit) via the pecil icon right next to the name, you will +notice the difference as the **User Distinguished name** will be shown from the +LDAP server, just like this: + +.. image:: images/user_ldap_distinguishedname.png + :scale: 100% + +.. TIP:: + See :doc:`user-local` for more information on User, Groups and privileges. + +Step 5 - Update system access settings +-------------------------------------- +Now we have configures, verified and imported the users from our LDAP server, we +need to change the default settings to allow LDAP users to login. + +Go to **System->Access->Settings** and change the Authentication Server from +**Local Database** to your newly created **LDAP** server. Leave the fallback on +**Local Database** and click on **Save and Test**. + +The test result should look like this: + +.. image:: images/user_testresult_ldap.png + :scale: 80% diff --git a/source/manual/how-tos/user-local.rst b/source/manual/how-tos/user-local.rst new file mode 100644 index 0000000..b504b1a --- /dev/null +++ b/source/manual/how-tos/user-local.rst @@ -0,0 +1,52 @@ +======================= +Creating Users & Groups +======================= + +.. image:: images/usermanager_groups.png + :scale: 100% + +With the local user manager of OPNsense one can add users and groups and define +the privileges for granting access to certain parts of the GUI (Web Configurator). + +Adding Users +------------ +To add a new user go to **System->Access->Users** and click on the **+** sign at +the bottom right corner of the form. + +========================== =========== ========================================================= + **Disabled** Unchecked *Can be used to (temporarily) disable an account* + **Username** John *A unique username* + **Password** secret *A strong password* + **Full name** John Doe *Optional, Full username* + **Expiration date** *Optional, if account should expire enter as mm/dd/yyy* + **Group Membership** *Optional, select one or more groups* + **Certificate** *Optional, check if a user certificate should be created* + **OTP seed** *Optional, enter or generate a OTP seed (base32)* + **Authorized keys** *Optional, paste ssh key for ssh console access* + **IPsec Pre-Shared Key** *Optional, IPsec PSK* +========================== =========== ========================================================= + +Creating Groups +--------------- +Go to **System->Access->Groups** and click on the **+** sign in the lower right +corner of the form. + +Enter a **Group name*** and a **Description** and add users to the group. + +Add privileges to a group +------------------------- +After creating a group the privileges can be added by editing the group. +Go to **System->Access-Groups** and click on the edit symbol (pencil) right next +to the group you like to change. + +To assign privileges, just click on the pencil icon on the right of **Assigned +Privileges** a form will be shown where each page can be either selected or deselected; +here it's also possible to allow a user shell account access (console). + +The search bottom at the top of this form can be used to quickly find the right +page. + +.. image:: images/user_privileges.png + :scale: 100% + +After making the right selection click on **Save** to store the new settings. diff --git a/source/manual/how-tos/user-radius.rst b/source/manual/how-tos/user-radius.rst new file mode 100644 index 0000000..c78021a --- /dev/null +++ b/source/manual/how-tos/user-radius.rst @@ -0,0 +1,19 @@ +================== +Configuring Radius +================== +Configuring a Radius server for user authentication in services like vpn or captive portal +is easy just go to **System->Access->Servers** and click on **Add server** in the top right corner. + +Fill in the form: + +============================== =============== ======================================================== +**Descriptive name** radius_test *Enter a descriptive name* +**Type** Radius *Select Radius* +**Hostname or IP address** 10.10.10.1 *Enter the IP of your Radius server* +**Shared Secret** secret *Shared secret for your Radius server* +**Services offered** Authentication *Select Authentication,for Captive portal + accounting* +**Authentication port value** 1812 *Port number, 1812 is default for accounting it's 1813* +**Authentication Timeout** 5 *Timeout for Radius to respond on requests* +============================== =============== ======================================================== + +Use the tester under **System->Access->Tester** to test the Radius server. diff --git a/source/manual/how-tos/zerotier.rst b/source/manual/how-tos/zerotier.rst new file mode 100644 index 0000000..bd03783 --- /dev/null +++ b/source/manual/how-tos/zerotier.rst @@ -0,0 +1,202 @@ +Zerotier Configuration +====================== + +.. Note:: + It is strongly recommended that the reader familiarise themselves with the + `Zerotier Manual `_, in order to further + understand the concepts behind this plugin. + +Prerequisites +-------------- + +Firstly, it is important that you have signed up to Zerotier at the `Zerotier +Portal `_. Second, you will need to create at least +one network on the portal in order to obtain a Network Id that this plugin +uses to **join** this node to the created Zerotier network. This network will +become your private network that by default is visible only to your nodes - in +other words, other nodes that are on that network can talk to each other, but +nothing else can talk to them - they are completely transparent to the +internet in general. In effect you are layering a private network over the +public internet and all intra-node communication is encrypted and private +between them. This is further hinted at by the fact that the assigned IP +addresses are normally RFC1918 addresses, i.e., non-routable across the +internet. + +Finally, in order to have a fully functioning private VPN between Zerotier +nodes, a combination of this plugin plus some configuration on the `portal +`_ **will** be required. + +Installation +------------ + +From the Plugins view under ``System...Firmware``, install the os-zerotier +package. Once the new plugin has been installed, perform a page reload and a +new menu item should appear under VPN called Zerotier. + +.. image:: images/zerotier-0.png + +Clicking on the Zerotier menu item will reveal two further sub-menu items - +namely Settings and Overview. Clicking on "Settings" will present a new view +with two named tabs. The first tab is called Settings and the second tab is +called Networks. These are further described below. + +.. image:: images/zerotier-1.png + +Settings +-------- + +This tab controls the overall operation of Zerotier. Anything changed here is +applied globally to all defined networks and to the Zerotier service itself. + +:Enabled: + Controls if the service should be running. If it is disabled, then access + to the Networks tab will be disabled. If it is enabled, access to the + Networks tab will be enabled and the service will also start at boot time. + +:API Access Token (optional): + This optional entry is for future use and further development of the + Zerotier plugin. The API access token can be generated by logging into + your `portal `__ and creating a new API Access Token. + When the token has been generated, copy the value into this input box. + +:local.conf settings (optional): + As described in the Zerotier Manual, a local.conf can be created to enable + or disable custom node-specific configuration overrides. Further details of + permitted options can be found on the `ZeroTier Manual + `__. Please note that the local.conf + **must** be a valid JSON document otherwise the service will fail to start. + +Networks +-------- + +This table allows for the creation, modification and deletion of Zerotier +networks. Adding a Network here will join your OPNsense installation to the +specified Zerotier network. + +.. Note:: + Remember, you **will** have to log into the Zerotier `portal + `__, select the network and authorise the node before + it can be assigned an IP address (or indeed, talk to other nodes on that + network). + +.. image:: images/zerotier-2.png + + +Adding a network is quite straight-forward. Simply click on the + symbol key +in the following: + +:Network Id: + This is the 64-bit (16 character hex) address that is generated on the + portal when creating a Zerotier network. + +:Local Description (optional): + You may key in a description here that will help you remember what the + network is for. Please note that this field is **not** the same as the + name/description of the Zerotier network - it's simply an aide-mémoire to + help you remember what the network is for. + +Adding a network does **not** automatically cause your OPNsense installation +to join that network. In order to join that network it **must** be ``Enabled`` +first. Likewise, to remove your OPNsense node from the configured network +simply deselect ``Enabled``, thus disabling the network. + +Once a network has been added and enabled the node **must** be authorised to +join the network on the portal. Simply enabling the network on your OPNsense +installation marks that node as a member of that network. It now has to +request permission to talk to the other nodes on that network. To achieve +this, you log into the portal, select the network, find the node address (this +can found on the OPNsense Zerotier Overview menu item, under the Information +tab) and authorise it by clicking on the "Auth?" check box beside the node. It +should go from "red" to "green" to indicate that it has been authorised. + +Some final "Network" operations: + +If you wish to completely remove the network, simply select the network and +click on the ``Bin`` icon. + +If you wish to edit the network, click on the ``Pencil`` icon. + +To "clone" the network entry, click on the ``Copy`` icon. Please ensure you +change the Network Id, as having two networks with the same id is an invalid +configuration. + +For a very quick overview of the Zerotier network information, click on the +``Information`` icon. A more detailed view of the network can be found under +the ``Overview...Networks`` menu item. + +Overview +======== + +The following 3 tabs reveal Global, Network and Peer information. They can +only be viewed if the Zerotier plugin is enabled, so please ensure that the +service is enabled first. For information on the terminology used, please +refer to the `Zerotier Manual `__. + +.. image:: images/zerotier-3.png + +Information Overview +-------------------- + +This tab shows "Global" information concerning the overall health of the +Zerotier service. + +Networks Overview +------------------ + +This tab shows each configured **and** enabled network that this OPNsense +installation has joined. If no networks are enabled, no information is shown. + +Peers Overview +-------------- + +This tab shows the peers (leaf, planets and moons - Zerotier terminology) known +by this node. + +Interface Assignment +==================== + +.. WARNING:: + It is **highly** recommended that the interface have auto-assignment of IP + addresses turned off **for this particular node only**. You want to give + the interface a statically assigned, stable IP address (from the Zerotier + network IP range) and not have the Zerotier service auto-assign an IP + address. Auto-assignment of IP addresses for nodes is controlled on the + `Zerotier Portal `_ + +After joining a Zerotier network (and authorising it on the portal) you may +now wish to assign the Zerotier virtual interface on OPNsense in order to +avail of OPNsense functionality such as firewalling and routing (using OSPF +for example). + +.. image:: images/zerotier-4.png + +To achieve this: + +Click on the ``Interfaces`` menu item, then click on ``Assignments``. There +you should discover a new interface currently unassigned that begins with the +letters ``zt``. Next, click on the ``+`` symbol to assign it. In this example +it creates a new interface called ``OPT1``. Clicking on ``OPT1`` shows the +``Enable`` and ``Lock`` options. Check both options. + +.. WARNING:: + It is **very** important that ``Lock`` (i.e., Prevent interface removal) + is enabled. This is because Zerotier is a software interface and not + guaranteed to be brought "up" whilst the system is booting. It could + happen shortly afterwards, hence locking the interface tells OPNsense not + to remove it, thinking it's gone bad. + +Once the new interface has been enabled, it is recommended to change the +Description away from ``OPT1`` to something more descriptive for your needs. + +For ``IPv4 Configuration Type``, choose ``Static IPv4`` then in the +appropriate input boxes, key in the IPv4 address that you have assigned to +this node via the ``Zerotier`` portal. Keep the ``IPv4 Upstream Gateway`` set +to ``None.`` + +.. image:: images/zerotier-5.png + +You may choose to do the same for ``IPv6 Configuration Type``. + +Once the interface has been assigned with an IP, it show now also show up on +``Firewall`` Rules etc...plus any other operations that be done on a +interfaces can also be applied to your assigned interface. diff --git a/source/manual/howtos.rst b/source/manual/howtos.rst new file mode 100644 index 0000000..3d46b5d --- /dev/null +++ b/source/manual/howtos.rst @@ -0,0 +1,32 @@ +==================================== +How to's +==================================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: + :glob: + + + how-tos/cloud_backup + how-tos/fwcategory + how-tos/transparent_bridge + how-tos/ips-feodo + how-tos/ips-geoip + how-tos/ips-sslfingerprint + how-tos/cachingproxy + how-tos/proxytransparent + how-tos/proxywebfilter + how-tos/proxyicapantivirus + how-tos/carp + how-tos/ipsec-road + how-tos/ipsec-s2s + how-tos/sslvpn_client + how-tos/sslvpn_s2s + how-tos/accounting + how-tos/shaper + how-tos/insight + how-tos/netflow_exporter + how-tos/two_factor + how-tos/cellular + how-tos/* diff --git a/source/manual/images/IPv6.png b/source/manual/images/IPv6.png new file mode 100644 index 0000000..e6b8a90 Binary files /dev/null and b/source/manual/images/IPv6.png differ diff --git a/source/manual/images/OPNsense_4G_new.png b/source/manual/images/OPNsense_4G_new.png new file mode 100644 index 0000000..c414be0 Binary files /dev/null and b/source/manual/images/OPNsense_4G_new.png differ diff --git a/source/manual/images/Screenshot_Use_RAMdisks.png b/source/manual/images/Screenshot_Use_RAMdisks.png new file mode 100644 index 0000000..123667f Binary files /dev/null and b/source/manual/images/Screenshot_Use_RAMdisks.png differ diff --git a/source/manual/images/Virtual_Private_Network_overview.png b/source/manual/images/Virtual_Private_Network_overview.png new file mode 100644 index 0000000..2a75051 Binary files /dev/null and b/source/manual/images/Virtual_Private_Network_overview.png differ diff --git a/source/manual/images/advanced.png b/source/manual/images/advanced.png new file mode 100644 index 0000000..e0a8d19 Binary files /dev/null and b/source/manual/images/advanced.png differ diff --git a/source/manual/images/alias_firewall_rules.png b/source/manual/images/alias_firewall_rules.png new file mode 100644 index 0000000..354cb49 Binary files /dev/null and b/source/manual/images/alias_firewall_rules.png differ diff --git a/source/manual/images/alias_remote_ipsec.png b/source/manual/images/alias_remote_ipsec.png new file mode 100644 index 0000000..d40fc5e Binary files /dev/null and b/source/manual/images/alias_remote_ipsec.png differ diff --git a/source/manual/images/aliases_host.png b/source/manual/images/aliases_host.png new file mode 100644 index 0000000..f5404bd Binary files /dev/null and b/source/manual/images/aliases_host.png differ diff --git a/source/manual/images/auth_server_fallback.png b/source/manual/images/auth_server_fallback.png new file mode 100644 index 0000000..a6fe8f4 Binary files /dev/null and b/source/manual/images/auth_server_fallback.png differ diff --git a/source/manual/images/captiveportal_template_folder.png b/source/manual/images/captiveportal_template_folder.png new file mode 100644 index 0000000..d09236e Binary files /dev/null and b/source/manual/images/captiveportal_template_folder.png differ diff --git a/source/manual/images/disableoffloading.png b/source/manual/images/disableoffloading.png new file mode 100644 index 0000000..1a53d98 Binary files /dev/null and b/source/manual/images/disableoffloading.png differ diff --git a/source/manual/images/dropdown_tab.png b/source/manual/images/dropdown_tab.png new file mode 100644 index 0000000..1168a4b Binary files /dev/null and b/source/manual/images/dropdown_tab.png differ diff --git a/source/manual/images/eye_on_virus_new.jpg b/source/manual/images/eye_on_virus_new.jpg new file mode 100644 index 0000000..d4aa181 Binary files /dev/null and b/source/manual/images/eye_on_virus_new.jpg differ diff --git a/source/manual/images/firmware-update.png b/source/manual/images/firmware-update.png new file mode 100644 index 0000000..16d4967 Binary files /dev/null and b/source/manual/images/firmware-update.png differ diff --git a/source/manual/images/firmware_flavour.png b/source/manual/images/firmware_flavour.png new file mode 100644 index 0000000..396e29d Binary files /dev/null and b/source/manual/images/firmware_flavour.png differ diff --git a/source/manual/images/forward_proxy.png b/source/manual/images/forward_proxy.png new file mode 100644 index 0000000..b79426a Binary files /dev/null and b/source/manual/images/forward_proxy.png differ diff --git a/source/manual/images/gui_layout.png b/source/manual/images/gui_layout.png new file mode 100644 index 0000000..9522acb Binary files /dev/null and b/source/manual/images/gui_layout.png differ diff --git a/source/manual/images/help_msg.png b/source/manual/images/help_msg.png new file mode 100644 index 0000000..28f589e Binary files /dev/null and b/source/manual/images/help_msg.png differ diff --git a/source/manual/images/hotspot_login.png b/source/manual/images/hotspot_login.png new file mode 100644 index 0000000..671e592 Binary files /dev/null and b/source/manual/images/hotspot_login.png differ diff --git a/source/manual/images/info.png b/source/manual/images/info.png new file mode 100644 index 0000000..1590972 Binary files /dev/null and b/source/manual/images/info.png differ diff --git a/source/manual/images/light_bulbs.png b/source/manual/images/light_bulbs.png new file mode 100644 index 0000000..3fa14c8 Binary files /dev/null and b/source/manual/images/light_bulbs.png differ diff --git a/source/manual/images/login.png b/source/manual/images/login.png new file mode 100644 index 0000000..f0edf71 Binary files /dev/null and b/source/manual/images/login.png differ diff --git a/source/manual/images/menu_plugins.png b/source/manual/images/menu_plugins.png new file mode 100644 index 0000000..5a125a7 Binary files /dev/null and b/source/manual/images/menu_plugins.png differ diff --git a/source/manual/images/netflow_analyzer_insight.png b/source/manual/images/netflow_analyzer_insight.png new file mode 100644 index 0000000..459f126 Binary files /dev/null and b/source/manual/images/netflow_analyzer_insight.png differ diff --git a/source/manual/images/netflow_exporter.png b/source/manual/images/netflow_exporter.png new file mode 100644 index 0000000..d19163d Binary files /dev/null and b/source/manual/images/netflow_exporter.png differ diff --git a/source/manual/images/netflow_insight_details.png b/source/manual/images/netflow_insight_details.png new file mode 100644 index 0000000..f5bef53 Binary files /dev/null and b/source/manual/images/netflow_insight_details.png differ diff --git a/source/manual/images/os-vmware.png b/source/manual/images/os-vmware.png new file mode 100644 index 0000000..0a3ebcb Binary files /dev/null and b/source/manual/images/os-vmware.png differ diff --git a/source/manual/images/os-xen.png b/source/manual/images/os-xen.png new file mode 100644 index 0000000..dccfb90 Binary files /dev/null and b/source/manual/images/os-xen.png differ diff --git a/source/manual/images/pftable_youtube.png b/source/manual/images/pftable_youtube.png new file mode 100644 index 0000000..667c006 Binary files /dev/null and b/source/manual/images/pftable_youtube.png differ diff --git a/source/manual/images/plugins_quagga.png b/source/manual/images/plugins_quagga.png new file mode 100644 index 0000000..5a77bc0 Binary files /dev/null and b/source/manual/images/plugins_quagga.png differ diff --git a/source/manual/images/proxy_form.png b/source/manual/images/proxy_form.png new file mode 100644 index 0000000..6429fe7 Binary files /dev/null and b/source/manual/images/proxy_form.png differ diff --git a/source/manual/images/quick-navigation.png b/source/manual/images/quick-navigation.png new file mode 100644 index 0000000..220bf21 Binary files /dev/null and b/source/manual/images/quick-navigation.png differ diff --git a/source/manual/images/submenu.png b/source/manual/images/submenu.png new file mode 100644 index 0000000..8d4ca78 Binary files /dev/null and b/source/manual/images/submenu.png differ diff --git a/source/manual/images/systemhealt_selection.png b/source/manual/images/systemhealt_selection.png new file mode 100644 index 0000000..64c7340 Binary files /dev/null and b/source/manual/images/systemhealt_selection.png differ diff --git a/source/manual/images/systemhealth_excel.png b/source/manual/images/systemhealth_excel.png new file mode 100644 index 0000000..f3d70d2 Binary files /dev/null and b/source/manual/images/systemhealth_excel.png differ diff --git a/source/manual/images/systemhealth_filtered.png b/source/manual/images/systemhealth_filtered.png new file mode 100644 index 0000000..2fb27ec Binary files /dev/null and b/source/manual/images/systemhealth_filtered.png differ diff --git a/source/manual/images/systemhealth_gui.png b/source/manual/images/systemhealth_gui.png new file mode 100644 index 0000000..39a75b2 Binary files /dev/null and b/source/manual/images/systemhealth_gui.png differ diff --git a/source/manual/images/systemhealth_inverse.png b/source/manual/images/systemhealth_inverse.png new file mode 100644 index 0000000..925ae9e Binary files /dev/null and b/source/manual/images/systemhealth_inverse.png differ diff --git a/source/manual/images/systemhealth_labelfilter.png b/source/manual/images/systemhealth_labelfilter.png new file mode 100644 index 0000000..cde2bcc Binary files /dev/null and b/source/manual/images/systemhealth_labelfilter.png differ diff --git a/source/manual/images/systemhealth_obscureddata.png b/source/manual/images/systemhealth_obscureddata.png new file mode 100644 index 0000000..2d3a5f9 Binary files /dev/null and b/source/manual/images/systemhealth_obscureddata.png differ diff --git a/source/manual/images/systemhealth_sample.png b/source/manual/images/systemhealth_sample.png new file mode 100644 index 0000000..797fb81 Binary files /dev/null and b/source/manual/images/systemhealth_sample.png differ diff --git a/source/manual/images/systemhealth_zoomed.png b/source/manual/images/systemhealth_zoomed.png new file mode 100644 index 0000000..a770f00 Binary files /dev/null and b/source/manual/images/systemhealth_zoomed.png differ diff --git a/source/manual/images/tab.png b/source/manual/images/tab.png new file mode 100644 index 0000000..1557de9 Binary files /dev/null and b/source/manual/images/tab.png differ diff --git a/source/manual/images/traffic_shaping.png b/source/manual/images/traffic_shaping.png new file mode 100644 index 0000000..07bdbc0 Binary files /dev/null and b/source/manual/images/traffic_shaping.png differ diff --git a/source/manual/images/two_factor_authentication.png b/source/manual/images/two_factor_authentication.png new file mode 100644 index 0000000..1eb4b66 Binary files /dev/null and b/source/manual/images/two_factor_authentication.png differ diff --git a/source/manual/images/user_manager.png b/source/manual/images/user_manager.png new file mode 100644 index 0000000..2ed93ad Binary files /dev/null and b/source/manual/images/user_manager.png differ diff --git a/source/manual/images/vpn.png b/source/manual/images/vpn.png new file mode 100644 index 0000000..53c167e Binary files /dev/null and b/source/manual/images/vpn.png differ diff --git a/source/manual/install.rst b/source/manual/install.rst new file mode 100644 index 0000000..e8305a6 --- /dev/null +++ b/source/manual/install.rst @@ -0,0 +1,403 @@ +===================================== +Initial Installation & Configuration +===================================== + +.. rubric:: Software setup + :name: firstHeading + :class: firstHeading page-header + +.. Note:: + Just looking on how to invoke the installer? When the live environment has been + started just login with user **installer** and password **opnsense**. + +------------ +Architecture +------------ + +The **software setup** and installation of OPNsense® is available for +`x86-32 `__ and +`x86-64 `__ bit microprocessor +architectures. + +---------------- +Embedded vs Full +---------------- + +Full installs can run on `SD memory +cards `__, `solid-state +disks (SSD) `__ or +`hard disk drives +(HDD) `__. + +Since version 15.1.10 (04 May 2015) the option to install an +`embedded `__ +OPNsense image is also supported. + +The main differences between an embedded image and a full image are: + ++-----------------------+-----------------------+ +| Embedded | Full | ++=======================+=======================+ +| Uses NanoBSD | Uses FreeBSD | ++-----------------------+-----------------------+ +| Writes to RAM disk | Writes to local disk | ++-----------------------+-----------------------+ +| No log data retention | Log data retention | +| after reboot | after reboot | ++-----------------------+-----------------------+ +| Not intended for | Suitable for disk | +| local disk writes | writes. | ++-----------------------+-----------------------+ +| Embedded only use | Can enable RAM disk | +| | for embedded mode. | ++-----------------------+-----------------------+ + + +Embedded images (nanobsd) store logging and cache data in memory only, while full versions +will keep the data stored on the local drive. A full version can mimic the +behavior of an embedded version by enabling RAM disks, this is especially +useful for SD memory card installations. + +.. Warning:: + See the chapter :doc:`Hardware Setup ` for + further information on hardware requirements prior to an install. + +-------- +Download +-------- + +The OPNsense distribution can be `downloaded `__ +from one of our `mirrors `__. + +------------------ +Installation Media +------------------ +Depending on you hardware and use case different installation media are provided: + ++--------+-----------------------------------------------------+ +|Type | | Description | ++========+=====================================================+ +| cdrom | | ISO installer image with live system capabilities | +| | | running in VGA-only mode | ++--------+-----------------------------------------------------+ +| vga | | USB installer image with live system capabilities | +| | | running in VGA-only mode | ++--------+-----------------------------------------------------+ +| serial | | USB installer image with live system capabilities | +| | | running in serial console (115200) mode with | +| | | secondary VGA support (no kernel messages though) | ++--------+-----------------------------------------------------+ +| nano | | a preinstalled serial image for 4GB USB sticks, | +| | | SD or CF cards for use with embedded devices | ++--------+-----------------------------------------------------+ + +.. Warning:: + + Flash memory cards will only tolerate a limited number of writes + and re-writes. For embedded (nano) versions memory disks for /var and /tmp are + applied by default to prolong CF (flash) card lifetimes. + + To enable for non embedded versions: Enable **System⇒Settings⇒Miscellaneous⇒RAM** Disk + Settings; afterwards reboot. Consider to enable an external syslog server as well. + +------------------------------ +Media Filename Composition +------------------------------ +.. blockdiag:: + :scale: 100% + + diagram { + default_shape = roundedbox; + default_node_color = white; + default_linecolor = darkblue; + default_textcolor = black; + default_group_color = lightgray; + + OS [label="OPNsense-##.#.##-OpenSSL-", width=200]; + + platform_1 [label = "i386-" ]; + platform_2 [label = "amd64-" ]; + + OS -> cdrom-; + + group { + orientation = portrait + label = "Type"; + fontsize = 20; + + cdrom- -> nano- -> serial- -> vga-; + + } + + group { + orientation = portrait + label = "Architecture"; + fontsize = 20; + + platform_1 -> platform_2; + + } + + group { + orientation = portrait + label = "Image Format"; + fontsize = 20; + + "iso.bz2" -> "img.bz2"; + + } + + cdrom- -> platform_1 -> "iso.bz2"; + + } + +.. Note:: + + **Please** be ware that the latest installation media does not always + correspond with the latest released version. OPNsense installation images are + provided on a regular bases together with mayor versions in January and July. + More information on our release schedule is available from our package + repository see `README `__ + +------------------ +OpenSSL & LibreSSL +------------------ + +OPNsense images are provided based upon `OpenSSL `__. +The `LibreSSL `__ flavor can be selected from within +the GUI ( System⇒Firmware⇒Settings ). In order to apply your choice an update +must be performed after save, which can include a reboot of the system. + +.. image:: ./images/firmware_flavour.png + +------------------- +Installation Method +------------------- + +Download the installation image from one of the mirrors listed on the `OPNsense +`__ website. + +The easiest method of installation is the USB-memstick installer. If +your target platform has a serial interface choose the "serial image. +64-bit and 32-bit install images are provided. The following examples +apply to both. + +Write the image to a USB flash drive (>= 1GB) or an IDE hard disk, +either with dd under FreeBSD or under Windows with physdiskwrite + +Before writing an (iso) image you need to unpack it first (use bunzip2). + +**FreeBSD** +:: + + dd if=OPNsense-##.#.##-[Type]-[Architecture].img of=/dev/daX bs=16k + +Where X = the device number of your USB flash drive (check ``dmesg``) + +**Linux** +:: + + dd if=OPNsense-##.#.##-[Type]-[Architecture].img of=/dev/sdX bs=16k + +where X = the IDE device name of your USB flash drive (check with hdparm -i /dev/sdX) +(ignore the warning about trailing garbage - it's because of the digital signature) + +**OpenBSD** + +:: + + dd if=OPNsense-##.#.##-[Type]-[Architecture].img of=/dev/rsd6c bs=16k + +The device must be the ENTIRE device (in Windows/DOS language: the 'C' +partition), and a raw I/O device (the 'r' in front of the device "sd6"), +not a block mode device. + +**Mac OS X** + +:: + + sudo dd if=OPNsense-##.#.##-[Type]-[Architecture].img of=/dev/rdiskX bs=64k + +where r = raw device, and where X = the disk device number of your CF +card (check Disk Utility) (ignore the warning about trailing garbage - +it's because of the digital signature) + +**Windows** + +:: + + physdiskwrite -u OPNsense-##.#.##-[Type]-[Architecture].img + +(use v0.3 or later!) + +.. rubric:: Install Instructions + :name: install-to-system + +The boot process gives you the opportunity to run several optional configuration +steps. It has been designed to always boot into a live environment in order to +be able to access the GUI or even SSH directly. If a timeout was missed simply +restart the boot procedure. + +OPNsense Importer +----------------- +All images feature the new "opnsense-importer" utility, which is now invoked +instead of the early installer. You can stop the automatic timeout by pressing +any key. Afterwards you will have the opportunity to select a disk to import +from. If the option times out or the importer is exited without a disk selection, +the factory defaults will be used for the boot. + +The next prompt will be for manual interface selection. +This step is well-established since OPNsense 15.7 . + +Live environment +---------------- +The system will then continue into a live environment. If the config importer +was used previously on an existing installation, the system will boot up with a +fully functional setup, but will not overwrite the previous installation. Use +this feature for safely previewing upgrades. + +If you have used a CD-ROM, VGA, Serial image without a config import you are by +default able to (a) log into the root shell using the user "root" with password +"opnsense", or (b) log into the installer using the user "installer" with +password "opnsense". The GUI will listen on https://192.168.1.1/ for user "root" +with password "opnsense". Using SSH, the "root" and "installer" users are +available as well on IP 192.168.1.1. Note that these install medias are +read-only, which means your current live configuration will be lost after reboot. + +Nano Image +---------- +If you have used a Nano image, your system is already up and running as it is +designed as such. It is set to read-write attempting to minimise write cycles by +mounting relevant partitions as memory file systems. If you should require an +installer anyway, log in as user "root", select option 8 from the menu and type +"opnsense-installer". The "opnsense-importer" can be run this way as well should +you require to run the import again. + + +Create a bootable USB flash drive with the downloaded and unpacked img +file. Configure your system to boot from USB. + +Installation Steps +------------------ +The installation process involves a few simple steps. + +.. Note:: + To invoke the installer login with user **installer** and password + **opnsense** + +.. Tip:: + The installer can also be started from the network using ssh, default ip + address is 192.168.1.1 + +#. Configure console - The default configuration should be fine for most + occasions. +#. Select task - The **Quick/Easy Install** option should be fine for most + occasions. For installations on embedded systems or systems with minimal + diskspace choose **Custom Installation** and do not create a swap slice. + Continue with default settings. +#. **Are you SURE?** - When proceeding OPNsense will be installed on the + **first hard disk** in the system. +#. Reboot - The system is now installed and needs to be rebooted to + continue with configuration. + +.. Warning:: + You will lose all files on the installation disk. If another disk is to be + used then choose a Custom installation instead of the Quick/Easy Install. + +--------------------- +Initial configuration +--------------------- +After installation the system will prompt you for the interface +assignment, if you ignore this then default settings are applied. +Installation ends with the login prompt. + +By default you have to log in to enter the console. + +**Welcome message** +:: + + * * * Welcome to OPNsense [OPNsense 15.7.25 (amd64/OpenSSL) on OPNsense * * * +   + WAN (em1) ->  + LAN (em0) -> v4: 192.168.1.1/24 +   + FreeBSD/10.1 (OPNsense.localdomain) (ttyv0) +   + login:    + + +.. TIP:: + + A user can login to the console menu with his + credentials. The default credentials after a fresh install are username "root" + and password "opnsense". + +VLANs and assigning interfaces + If choose to do manual interface assignment or when no config file can be + found then you are asked to assign Interfaces and VLANs. VLANs are optional. + If you do not need VLAN's then choose **no**. You can always configure + VLAN's at a later time. + +LAN, WAN and optional interfaces + The first interface is the LAN interface. Type the appropriate + interface name, for example "em0". The second interface is the WAN + interface. Type the appropriate interface name, eg. "em1" . Possible + additional interfaces can be assigned as OPT interfaces. If you + assigned all your interfaces you can press [ENTER] and confirm the + settings. OPNsense will configure your system and present the login + prompt when finished. + +Minimum installation actions + In case of a minimum install setup (i.e. on CF cards), OPNsense can + be run with all standard features, expect for the ones that require + disk writes, e.g. a caching proxy like Squid. Do not create a swap + slice, but a RAM Disk instead. In the GUI enable **System⇒Settings⇒Miscellaneous⇒RAM Disk Settings** + and set the size to 100-128 MB or more, depending on your available RAM. + Afterwards reboot. + +**Enable RAM disk manually** + +.. image:: ./images/Screenshot_Use_RAMdisks.png + :scale: 100% + +Then via console, check your /etc/fstab and make sure your primary +partition has **rw,noatime** instead of just **rw**. + +.. rubric:: Console + :name: console + +The console menu shows 13 options. + +:: + + 0)  Logout   7)  Ping host + 1)  Assign interfaces   8)  Shell + 2)  Set interface(s) IP address   9)  pfTop + 3)  Reset the root password   10)  Filter logs + 4)  Reset to factory defaults   11)  Restart web interface + 5)  Reboot system   12)  Upgrade from console + 6)  Halt system   13)  Restore a configuration + +Table: *The console menu* + +.. rubric:: opnsense-update + :name: opnsense-update + +OPNsense features a command line +interface (CLI) tool "opnsense-update". Via menu option **8) Shell**, the user can +get to the shell and use opnsense-update. + +For help type *opnsense-update -help* and [Enter] + +.. rubric:: Upgrade from console + :name: upgrade-from-console + +The other method to upgrade the system is via console option **12) Upgrade from console** + +.. rubric:: GUI + :name: gui + +An update can be done through the GUI via **System⇒Firmware⇒Updates**. + +.. image:: ./images/firmware-update.png + :scale: 100% diff --git a/source/manual/ips.rst b/source/manual/ips.rst new file mode 100644 index 0000000..cb02265 --- /dev/null +++ b/source/manual/ips.rst @@ -0,0 +1,88 @@ +================================== +Inline Intrusion Prevention System +================================== + +The inline IPS system of OPNsense is based on Suricata and utilizes Netmap to +enhance performance and minimize cpu utilization. This deep packet inspection +system is very powerful and can be used to mitigate security threats at wire speed. + +------------------------------- +Emerging Threats ETOpen Ruleset +------------------------------- +The ETOpen Ruleset is an excellent anti-malware IDS/IPS ruleset that enables +users with cost constraints to significantly enhance their existing network-based +malware detection. The ETOpen Ruleset is not a full coverage ruleset, and may not +be sufficient for many regulated environments and should not be used as a +standalone ruleset. + +OPNsense has integrated support for ET Open rules. +For details and Guidelines see: http://doc.emergingthreats.net/bin/view/Main/EmergingFAQ +For rules documentation: http://doc.emergingthreats.net/ + +-------- +Abuse.ch +-------- +Abuse.ch offer several blacklist for protecting against fraudulent networks. +OPNsense has integrated support for: + +SSL Blacklist +------------- +SSL Blacklist (SSLBL) is a project maintained by abuse.ch. The goal is to provide +a list of "bad" SSL certificates identified by abuse.ch to be associated with +malware or botnet activities. SSLBL relies on SHA1 fingerprints of malicious SSL +certificates and offers various blacklists. + +See fore details: https://sslbl.abuse.ch/ + +Feodo Tracker +------------- +Feodo (also known as Cridex or Bugat) is a Trojan used to commit ebanking fraud and steal sensitive information from the victims computer, such as credit card details or credentials. At the moment, Feodo Tracker is tracking four versions of Feodo, and they are labeled by Feodo Tracker as version A, version B, version C and version D: + +* **Version A** + *Hosted on compromised webservers running an nginx proxy on port 8080 TCP + forwarding all botnet traffic to a tier 2 proxy node. Botnet traffic usually + directly hits these hosts on port 8080 TCP without using a domain name.* +* **Version B** + *Hosted on servers rented and operated by cybercriminals for the exclusive + purpose of hosting a Feodo botnet controller. Usually taking advantage of a + domain name within ccTLD .ru. Botnet traffic usually hits these domain names + using port 80 TCP.* +* **Version C** + *Successor of Feodo, completely different code. Hosted on the same botnet + infrastructure as Version A (compromised webservers, nginx on port 8080 TCP + or port 7779 TCP, no domain names) but using a different URL structure. + This Version is also known as Geodo and Emotet.* +* **Version D** + *Successor of Cridex. This version is also known as Dridex* + +See for details: https://feodotracker.abuse.ch/ + +------------------------ +Maxmind GeoLite2 Country +------------------------ +GeoLite2 databases are free IP geolocation databases comparable to, but less +accurate than, MaxMind’s GeoIP2 databases. GeoLite2 databases are updated on the +first Tuesday of each month. + +For more details see: http://dev.maxmind.com/geoip/geoip2/geolite2/ + +OPNsense has integrated GeoLite2 Country database support. + +--------------- +Finger Printing +--------------- +OPNsense includes a very polished solution to block protected sites based on +their SSL fingerprint. + +-------- +How-to's +-------- + +.. toctree:: + :maxdepth: 2 + :titlesonly: + :glob: + + how-tos/ips-feodo + how-tos/ips-geoip + how-tos/ips-sslfingerprint diff --git a/source/manual/ipv6.rst b/source/manual/ipv6.rst new file mode 100644 index 0000000..cfb82a7 --- /dev/null +++ b/source/manual/ipv6.rst @@ -0,0 +1,24 @@ +========== +Using IPv6 +========== + +.. image:: images/IPv6.png + :scale: 100% + +OPNsense fully supports IPv6 for routing and firewall. However there are lots of +different options to utilize IPv6. Currently these scenario's are known to work: + +* Native IPv6 only +* Dual Stack IPv4 + IPv6 +* IPv6 <-> IP4v Tunnel broker + +.. Warning:: + + NAT64, IPv4 <-> IPv6 Network address translations, is currently not supported + by FreeBSD. + +----------- +Configuring +----------- + +:doc:`/manual/how-tos/ipv6_tunnelbroker` diff --git a/source/manual/mobile_wan.rst b/source/manual/mobile_wan.rst new file mode 100644 index 0000000..26d3f24 --- /dev/null +++ b/source/manual/mobile_wan.rst @@ -0,0 +1,44 @@ +================= +Mobile Networking +================= + +.. image:: images/OPNsense_4G_new.png + :scale: 100% + +OPNsense supports 3G and 4G (LTE) cellular modems as failsafe or primary WAN +interface. Both USB and (mini)PCIe cards are supported. + + +----------------- +Supported Devices +----------------- +While all devices supported by FreeBSD will likely function under OPNsense their +configuration depends on a AT command string that can differ from device to device. +To make thing easier some of these strings are part of a easy selectable profile. + +Tested devices by the OPNsense team include: + +* **Huawei ME909u-521** (device cuaUx.0) +* **Huawei E220** (device cuaUx.0) +* **Sierra Wireless MC7304** (device cuaUx.2) [as of OPNsense 16.7] + +.. Note:: + + If you have tested a cellular modem that is not on this list, but does work then + please report it to the project so we can list it and inform others. + + +------------------------- +Configure Cellular modems +------------------------- +Setting up and configuring a cellular modem is easy, see: :doc:`/manual/how-tos/cellular` + +------------------------- +3G - 4G Cellular Failover +------------------------- +To setup Cellular Failover, just follow these two how-tos: + +#. :doc:`/manual/how-tos/cellular` +#. :doc:`/manual/how-tos/multiwan` + +.. Note:: Treat the cellular connection the same as a normal WAN connection. diff --git a/source/manual/multiwan.rst b/source/manual/multiwan.rst new file mode 100644 index 0000000..0835b06 --- /dev/null +++ b/source/manual/multiwan.rst @@ -0,0 +1,50 @@ +========= +Multi WAN +========= +Multi WAN scenario's are commonly used for failover or load balancing, but combinations +are also possible with OPNsense. + +.. blockdiag:: + :desctable: + + blockdiag { + WAN_primary -- OPNsense; + OPNsense -- WAN_backup; + internet -- WAN_primary; + WAN_backup -- internet; + internet [shape="cloud"]; + WAN_primary [shape="cisco.modem",label=""]; + WAN_backup [shape="cisco.modem",label=""]; + + } + +------------ +WAN Failover +------------ +WAN failover automatically switches between WAN connections in case of connectivity +loss (or high latency) of your primary ISP. As long as the connection is not good +all traffic will be routed of the next available ISP/WAN connection and when +connectivity is fully restored so will the routing switch back to the primary ISP. + + +------------------ +WAN Load Balancing +------------------ +Load balancing can be used to split the load between two (or more) ISP's. This +enhances the total available bandwidth and/or lowers the load on each ISP. + +The principle is simple: Each WAN connection (gateway) gets a portion of the traffic. +The traffic can be divided equally or weighted. + +------------------------------ +Combining Balancing & Failover +------------------------------ +It is also possible to combine Load Balancing with Failover in such scenario's +you will have 2 or more WAN connections for Balancing purposes and 1 or more for +Failover. OPNsense offers 5 tiers (Failover groups) each tier can hold multiple +ISP's/WAN gateways. + +------------- +Configuration +------------- +For a how to configure read: :doc:`how-tos/multiwan` diff --git a/source/manual/netflow.rst b/source/manual/netflow.rst new file mode 100644 index 0000000..2a74b98 --- /dev/null +++ b/source/manual/netflow.rst @@ -0,0 +1,100 @@ +========================= +Netflow Export & Analyses +========================= + +.. image:: images/netflow_analyzer_insight.png + :scale: 100% + +Netflow is a monitoring feature, invented by Cisco, it is implemented in the FreeBSD +kernel with ng_netflow (Netgraph). Since Netgraph is a kernel implementation it +is very fast with little overhead compared to softflowd or pfflowd. + +While many monitoring solutions such as Nagios, Cacti and vnstat only capture traffic +statistics, Netflow captures complete packet flows including source, destination +ip and port number. + +OPNsense offers full support for exporting Netflow data to external collectors as +well as a comprehensive Analyzer for on-the-box analysis and live monitoring. + +OPNsense is the only open source solution with a build-in Netflow analyzer integrated +into it's Graphical User Interface. + +------------------ +Supported Versions +------------------ +OPNsense support both Netflow version 5 (IPv4) and version 9 (IPv4 & IPv6). + + +-------------- +Netflow Basics +-------------- +For analyzing the flow data it is important to understand the difference between +ingress and egress traffic. + +Ingress +------- +Traffic to or coming from the firewall. + +Egress +------ +Traffic passing trough the firewall. + +Ingress + Egress = Double flow count +------------------------------------ +When enabling both ingress and egress, traffic gets counted double due to Network +Address Translation as all packets going to the WAN coming from the LAN pass the +Network translation of the firewall therefor also creating an ingress flow. + +If you are not interested in ingress traffic then OPNsense offers the option to +filter this traffic. When utilizing a proxy on the same device its important to +capture the ingress flows as well, otherwise all proxy traffic won't be visible. +Downside is of course that all traffic not passing the proxy will we counted twice +due to the mentioned NAT effect. + +---------------- +Netflow Exporter +---------------- +OPNsense Netflow Exporter supports multiple interfaces, filtering of ingress flows +and multiple destinations including local capture for analysis by Insight (OPNsense +Netflow Analyzer). + +.. image:: images/netflow_exporter.png + :scale: 100% + +-------------------------- +Netflow Analyzer - Insight +-------------------------- +OPNsense offers a full Netflow Analyzer with the following features: + +* Captures 5 detail levels + + * Last 2 hours, 30 second average + * Last 8 hours, 5 minute averagae + * Last week, 1 hour average + * Last month, 24 hour average + * Last year, 24 hour average + +* Graphical representation of flows (stacked, stream and expanded) +* Top usage per interface, both ips and ports. +* Full in/out traffic in packets and bytes +* Detailed view with date selection and port/ip filter (up to 2 months) +* Data export to csv for offline analysis + + * Selectable Detail Level + * Selectable Resolution + * Selectable Dat range + +.. image:: images/netflow_insight_details.png + +------------- +Configuration +------------- + + +Setup Netflow Exporter +---------------------- +See :doc:`/manual/how-tos/netflow_exporter` + +Setup Insight +------------- +See :doc:`/manual/how-tos/insight` diff --git a/source/manual/proxy.rst b/source/manual/proxy.rst new file mode 100644 index 0000000..a08a854 --- /dev/null +++ b/source/manual/proxy.rst @@ -0,0 +1,109 @@ +============= +Caching Proxy +============= + +.. image:: images/forward_proxy.png + +OPNsense is equipped with a fully featured forward caching (transparent) proxy. +A caching proxy reduces bandwidth and improves response times by caching and +reusing frequently-requested web pages. The Access Control Lists can be utilized +for user authentication and or as (category based) web filter. + +Features include: + +* Multi Interface Support +* Transparent Mode (including SSL/HTTPS) +* ICAP Support for Anti Virus/Malware Engine +* HTTP Proxy +* FTP Proxy +* User Authentication +* Access Control Lists (valid for both http(s) and ftp) +* (Compressed) Blacklist +* Category Based Web Filtering +* Can be combined with traffic shaper + +-------------- +Authenticators +-------------- +User authentication can be done using OPNsense standard and build-in authenticators. +Currently these include: + +* LDAP (incl. Microsoft Active Directory) +* Radius +* Local user manager +* No authentication + +-------------- +Access Control +-------------- +OPNsense supports fine grained access control, base upon: + +* Subnets +* Ports +* MIME types +* Banned IP’s +* Whitelists +* Blacklists +* Browser/User Agents + +------------------ +Traffic Management +------------------ +The proxy can be combined with the traffic shaper and take full advantage of its +shaping features.Additionally it includes its own options: + +* Maximum download size +* Maximum upload size +* Overall bandwidth throttling +* Per host bandwidth throttling + + +------------------------- +Category Based Web Filter +------------------------- +No need for additional plugins, such as squidGuard - as OPNsense has build-in +category based web filter support. Main features include: + +* Fetch from a remote URL +* Supports flat file list and category based compressed lists +* Automatically convert category based blacklists to squid ACL's +* Keep up to date with the build-in scheduler +* Compatible with most popular blacklist + +---------------- +Transparent Mode +---------------- +The transparent mode means all request will be diverted to the proxy without any +configuration on your client. Transparent mode works very well with unsecured http +requests, however with secured (SSL) https connection the proxy will become a +man-in-the-middle as the client will "talk" to the proxy and the proxy will encrypt +the traffic with its master key that the client is required to trust. + +While we do not encourage the use of https in transparent mode, this feature is +scheduled for release in version 16.7. + +.. Warning:: + Using a transparent HTTPS proxy can be a dangerous practice and may not be + allowed by the services you use, for instance e-banking. + + +------------------------ +Configuration / HOW-TO's +------------------------ +More information on how to utilize OPNsense's proxy service can be found in: + +Proxy Basic Setup +----------------- +:doc:`how-tos/cachingproxy` + +Setup Web Filtering +------------------- +:doc:`how-tos/proxywebfilter` + +Setup Transparent Mode (including SSL) +-------------------------------------- +:doc:`how-tos/proxytransparent` + +Setup ICAP Anti Virus/Malware Engine +------------------------------------ +:doc:`how-tos/proxyicapantivirus` diff --git a/source/manual/shaping.rst b/source/manual/shaping.rst new file mode 100644 index 0000000..9baed7d --- /dev/null +++ b/source/manual/shaping.rst @@ -0,0 +1,80 @@ +=============== +Traffic Shaping +=============== +Traffic shaping (also known as “packet shaping”) is the control of computer network +traffic in order to optimize or guarantee performance, lower latency, and/or +increase usable bandwidth by delaying packets that meet certain criteria. More +specifically, traffic shaping is any action on a set of packets (often called a +stream or a flow), which imposes additional delay on those packets such that they +conform to some predetermined constraint (a contract or traffic profile). + + +.. image:: images/traffic_shaping.png + +------------ +Introduction +------------ +Traffic shaping within OPNsense is very flexible and is organized around pipes, +queues and corresponding rules. The pipes define the allowed bandwidth, the queues +can be used to set a weight within the pipe and finally the rules are used to apply +the shaping to a certain package flow. The shaping rules are handled independently +from the firewall rules and other settings. + +OPNsense traffic shaping is a reliable solution to limit bandwidth or prioritize +traffic and can be combined with other functions such as captive portal or high +availability (CARP). + +Bandwidth limitations can be defined based upon the interface(s), ip source & +destination, direction of traffic (in/out) and port numbers (application). + +Available bandwidth can be shared evenly over all users, this allows for +optimum performance at all times. + +Traffic can also be prioritized by adding queues and defining weights. Strictly +speaking traffic is not really prioritized but applications with a higher weight can +consume more bandwidth than others when the total available bandwidth is limited. + +The traffic shaper implementation uses IPFW and dummynet to offer a modern, +reliable solution with a low cpu footprint. + +--------------- +Dummynet & ipfw +--------------- + +Dummynet operates by first using the firewall to classify packets and +divide them into flows, using any match pattern that can be used in ipfw +rules. Depending on local policies, a flow can contain packets for a +single TCP connection, or from/to a given host, or entire subnet, or a +protocol type, etc. + +Packets belonging to the same flow are then passed to either of two different +objects, which implement the traffic regulation: + +pipe + A pipe emulates a link with given bandwidth, propagation + delay, queue size and packet loss rate. Packets are queued + in front of the pipe as they come out from the classifier, + and then transferred to the pipe according to the pipe's + parameters. + +queue + A queue is an abstraction used to implement the WF2Q+ (Worstcase Fair + Weighted Fair Queueing) policy, which is an efficient variant of the + WFQ policy. The queue associates a weight and a reference pipe to each + flow, and then all backlogged (i.e., with packets queued) flows linked + to the same pipe share the pipe's bandwidth proportionally to their + weights. Note that weights are not priorities; a flow with a lower + weight is still guaranteed to get its fraction of the bandwidth even if + a flow with a higher weight is permanently backlogged. + +In practice, pipes can be used to set hard limits to the bandwidth that a +flow can use, whereas queues can be used to determine how different flow +share the available bandwidth. + +The shaping rules can be defined in the rules section of the traffic shaper. + +------------- +Configuration +------------- + +Read the how to, here: :doc:`how-tos/shaper` diff --git a/source/manual/systemhealth.rst b/source/manual/systemhealth.rst new file mode 100644 index 0000000..b1ab743 --- /dev/null +++ b/source/manual/systemhealth.rst @@ -0,0 +1,158 @@ +================================ +System Health & Round Robin Data +================================ + +.. image:: images/systemhealth_sample.png + :scale: 100% + +System Health is a dynamic view on RRD data gathered by the system. It allows you +to dive into different statistics that show the overall health and performance of +the system over time. + +The system health module will enable you to track down issues faster and easier +than traditional static RRD graphs and it allows you to zoom in. + +--------------- +Data collectors +--------------- +System Health has the following primary data collectors: + +Packets + Packets show the number of packets per second traveling to and from a certain + interface. + +Quality + Quality show latency and packet loss of the monitored gateways (ip). + +System + The system section is used for sensor data regarding the system utilization, + such as memory usage, mbufs, states, processes and (when available) cpu temperature. + +Traffic + Shows traffic graphs for each interface including vpn (ipsec). + + +Depending on the features in use there may be more or less graphs available. + +--------------------- +GUI Features Overview +--------------------- +Please see the screenshot below for all element of the system health module. +Each element will be explained in the next chapters. + +.. image:: images/systemhealth_gui.png + :scale: 100% + +Toggle menu collapse +-------------------- +This feature will show or hide the top menu. + +Category Selection +------------------ +The category items are tabs with drop down menu's. Click on one of the categories +and select the graph you like to dive into. + +Graph Selection +--------------- +Part of the drop down menu, where you can select the graph to view. + +Select primary dataset +---------------------- +Select the RRD dataset you want to use. The more to the left the lower the maximum +resolution. By default the graphs are opened with the highest available RRD resolution. + +Inverse +------- +By selecting **Inverse** each odd dataset is reversed in direction (times minus one), +this is especially useful for traffic flows where you can plot ingoing and outgoing flows +in different directions. + +.. image:: images/systemhealth_inverse.png + :scale: 100% + +Resolution +---------- +The resolution determines the maximum number of datapoints that will be shown in +the graph and therefore indirectly influences the scale of the calculated averages. + +Hide/show table data +-------------------- +By default the table data is hidden, you can show it by toggling the **Show Tables** +to **On**. + +The table data area consists of the min/max/average and detailed table data area. + +Name of the graph +----------------- +Shows the name of the selected graph. + +Current Detail Level +-------------------- +Since the data is dynamically rendered it will automatically calculate the averages +and show you the current detail level in this area. + +Label filter +------------ +.. image:: images/systemhealth_labelfilter.png + :scale: 100% + +The label filter can be used to filer out data you do not want to see. Click once +to disable or double click to select only this set. + +A nice sample can be seen here, where the *processes* obscure all other data. + +.. image:: images/systemhealth_obscureddata.png + :scale: 100% + +Just click once on *processes* to hide this data set, notice that the scales will +adapt as well. + +.. image:: images/systemhealth_filtered.png + :scale: 100% + +Main graph area +--------------- +The main graph area show the full graph or just the part you selected in the zoom +area with more detail. + +Zoom Area +--------- +The zoom area can be used to select and zoom in on one part of the graph, the scales +are adapted automatically and any tables will be updated as well. + +This feature is very useful to zoom in on issues or for showing just part of the +graph. + +To use, click on it and hold while moving your pointer to another part of the zoom +area, on mouse up (release mouse click) the main graph area will be updated accordingly. +The zoom area will also be updated with more detailed data - when available - for the +selected area. + +A sample selection: + +.. image:: images/systemhealt_selection.png + :scale: 100% + + +And the result: + +.. image:: images/systemhealth_zoomed.png + :scale: 100% + +Min/max/average table +--------------------- +If **Show Tables** is on then this area will show: +* Minimum value of each dataset +* Maximum value of each dataset +* Average value of each dataset + +Detailed table +-------------- +If **Show Tables** is on then this area will show each value that is plotted in +the graph. You can toggle the time and date view from timestamp to human readable +values and export the data to as comma separated file (.CSV). + +The exported dataset can be used for your own reporting. + +.. image:: images/systemhealth_excel.png + :scale: 100% diff --git a/source/manual/two_factor.rst b/source/manual/two_factor.rst new file mode 100644 index 0000000..b8ad3fd --- /dev/null +++ b/source/manual/two_factor.rst @@ -0,0 +1,56 @@ +========================= +Two-factor authentication +========================= + +.. image:: images/two_factor_authentication.png + :scale: 100% + +Two-factor authentication also known as 2FA or 2-Step Verification is an authentication +method that requires two components, such as a pin/password + a token. + +OPNsense (version >=16.1.14) offers support for Two-factor authentication throughout +the entire system, with one exception being console/ssh access. + +Supported services are: + +* OPNsense Graphical User Interface +* Captive Portal +* Virtual Private Networking - OpenVPN & IPsec +* Caching Proxy + + +-------------------------- +GUI Fallback Configuration +-------------------------- +To prevent GUI lockout due to unavailable remote authentication server, the system +has a default fallback to the local database. In case of 2FA for the GUI one needs +to disable the fallback option to make sure no local user can gain access without 2FA. + +.. image:: images/auth_server_fallback.png + :scale: 100% + + +---------------------------- +Time-based One-time Password +---------------------------- +TOTP is an algorithm that computes a one-time password from a shared secret key +and the current time. OPNsense supports RFC 6238. + + +-------------------- +Google Authenticator +-------------------- +OPNsense fully supports the use of Google's Authenticator application. +This application can generate tokens on Android, iOS and BlackBerry OS. +The usage of this application is free and very simple to setup using OPNsense. + +----------------- +Other TOTP tokens +----------------- +The 2FA feature can be used with any time based one-time password token, although +it may be necessary to convert the tokens seed to the used format (base32). + +--------------------- +Configuration & Setup +--------------------- +To setup see: :doc:`how-tos/two_factor`. diff --git a/source/manual/users.rst b/source/manual/users.rst new file mode 100644 index 0000000..a9053fa --- /dev/null +++ b/source/manual/users.rst @@ -0,0 +1,62 @@ +================= + User Management +================= + +.. image:: images/user_manager.png + :scale: 100% + +The user manager of OPNsense allows for controlling access to the different +part (pages) of the configurator as well as controlling access to particular +services on a per user bases. + +Authentication +-------------- +OPNsense offers integration with external servers for services that require user +authentication. These services include: + +* IPsec +* OpenVPN +* Captive Portal +* Proxy + +Integrated into OPNsense are the **Local User Database** and **Voucher Server**. +The Voucher Server is intended to be used with the Captive portal. + +External service currently supported are: + +* LDAP (OpenLDAP, MS Active Directory, Novell eDirectory) +* Radius + +Authorization +------------- +Besides authenticating, user authorization to access parts of the configuration +can also be setup with an external server, but in order to grant the appropriate +privileges to the users they need to be imported in OPNsense's local user manager. +This way one can validate a user against its externally stored password and have +a fine grained control over the configuration pages that user may access. + +* Graphical User Interface (Web Configurator) + +Users, Groups & Privileges +-------------------------- +When using the local user manager, either stand alone or on combination with an +external authentication server one can define groups to combine a set of privileges +for a specific user group. A user should be an individual, a group needs to be +specific in such a way that anyone of that group can be granted the same access +rights, called privileges. + + +Configuration +------------- + +Local User Manager +------------------ +:doc:`how-tos/user-local` + +LDAP +---- +:doc:`how-tos/user-ldap` + +Radius +------ +:doc:`how-tos/user-radius` diff --git a/source/manual/virtuals.rst b/source/manual/virtuals.rst new file mode 100644 index 0000000..3b4375a --- /dev/null +++ b/source/manual/virtuals.rst @@ -0,0 +1,145 @@ +================================== +Virtual & Cloud based Installation +================================== + +------------ +Local/Server +------------ +Installing OPNsense on a virtual machine can be done by using the cdrom iso image. +Full instructions are available in chapter :doc:`install` . + +General tips +------------ +For optimum performance and compatibility, these guides are given: + +* Minimum required RAM is 1 GB +* Minimum recommended virtual disk size of 8GB +* Disable all off-loading settings in **Interfaces->Settings** + +.. image:: images/disableoffloading.png + +------------------ + +VMware ESXi +----------- +VMware offers full instructions for installing FreeBSD, these can be found +`here `__. + +To install the VMware tools just goto **System->Firmware->Plugins** and install +**os-vmware** by clicking on the **+** sign next to it. + +.. image:: images/os-vmware.png + +.. Note:: + + While other network setups may work fine, the e1000 driver seems to work + best, certainly when utilizing the traffic shaper. + +------------------ + +Xen +--- +To install the Xen tools just goto **System->Firmware->Plugins** and install +**os-xen** by clicking on the **+** sign next to it. + +.. image:: images/os-xen.png + +------------------ + +HyperV +------ +HyperV is supported out of the box, no additional drivers or tools are needed. + +.. attention:: + FreeBSD version 10.2 was released with a HyperV bug, therefore OPNsense + version 16.1 of the installation media will not function correctly. + The bug will be resolved in later installation media. The solution for + new installations are (till new media is released) to install the 15.7 + version ( https://pkg.opnsense.org/releases/15.7/ )and upgrade to the + latest using the GUI or opnsense-update cli tool. + +Others +------ +OPNsense can be installed on all virtual machines that support FreeBSD (such as +KVM, Bhyve, VirtualBox). + +------------------ + +------ +Hosted +------ +For hosted installations where you can't install using the cdrom iso an alternative +approach is available in the form of **opnsense-bootstrap**. + +opnsense-bootstrap +------------------ +opnsense-bootstrap(8) is a tool that can completely reinstall a running system +in place for a thorough factory reset or to restore consistency of all the OPNsense +files. It can also wipe the configuration directory, but won't do that by default. + +It will automatically pick up the latest available version and build a chain of +trust by using current package fingerprints -> CA root certificates -> HTTPS -> OPNsense +package fingerprints. + +What it will also do is turn a supported stock FreeBSD 10 release into an OPNsense +installation, given that UFS was used to install the root file system. + +opnsense bootstrap is available for our +`github source repository `__ + +------------------ + +-------------------- +Amazon AWS EC2 Cloud +-------------------- +.. image:: how-tos/images/amazon-web-services.png + :scale: 100% + +Installing OPNsense into the Amazon cloud can be a dounting task as no console is +offered. As part of Deciso's support packages (see `OPNsense commercial Support +`__), deciso offer free +access to its OPNsense Amazon Machine Image (AMI). + +See also our how-to for :doc:`how-tos/installaws`. + +------------- +Common Issues +------------- +Some common issues have been reported for different virtual environments. +You can find known solutions to these problems below. + +If you problem is not listed always try the General tips as mentioned in the +article first. + +------------------ + +File copy failed during installation +------------------------------------ +This issue is most likely caused by low memory setting. Make sure your virtual +OPNsense installation has a minimum of 1GB of RAM. + +------------------ + +Disk Errors on VMware +----------------------- +This issue can be caused by a defective drive. Changing drive mode to IDE has +been reported to help for certain ESXi versions. + +------------------ + +Installation failure on KVM +--------------------------- +If you are using virtio for the root disk then try switching to sata mode. + +------------------ + +NAT issues on XenServer +----------------------- +This issue has been reported to be solved by disabling cheksum offloading on both +OPNsense domU and Vifs. + +------------------ + +Traffic Shaper does not work on VMware +-------------------------------------- +If you are using vmxnet3 drivers try to switch to E1000. diff --git a/source/manual/vpnet.rst b/source/manual/vpnet.rst new file mode 100644 index 0000000..9b7534a --- /dev/null +++ b/source/manual/vpnet.rst @@ -0,0 +1,80 @@ +========================== +Virtual Private Networking +========================== + +A virtual private network secures public network connections and in doing so it +extends the private network into the public network such as internet. With a VPN +you can create large secure networks that can act as one private network. + +.. image:: images/Virtual_Private_Network_overview.png + :scale: 100% + +(picture from `wikipedia `__) + +Companies use this technology for connecting branch offices and remote users +(road warriors). + +OPNsense supports VPN connections for branch offices as well as remote users. + +Creating a single secured private network with multiple branch offices connecting +to a single site can easily be setup from within the graphical user interface. +For remote users, certificates can be created and revoked and a simple to use export +utility makes the client configuration a breeze. + +-------------------------- +Supported VPN technologies +-------------------------- +OPNsense offers a wide range of VPN technologies ranging from modern SSL VPN's to +well known IPsec as well as older (now considered insecure) legacy options such as +L2TP and PPTP. + +.. image:: images/vpn.png + :scale: 100% + +.. Note:: + + VPN technologies displayed with an open lock are considered to be insecure. + +Integrated VPN options +---------------------- +Integrated solutions are those that are available within the GUI without installing +any additional package or plugin. These include: + +* **IPsec** +* **OpenVPN (SSL VPN)** + + +Plugin VPN options +------------------ +Via plugins additional VPN technologies are offered, including: + +* **Legacy L2TP & PPTP** +* **Tinc** - Automatic Full Mesh Routing +* **Zerotier** - seamlessly connect everything, requires account from zerotier.com, free for up to 100 devices. + + +------------- +Configuration +------------- +Please read our how-to's for configuration examples and more detailed information. + +IPsec Road Warrior +------------------- +:doc:`how-tos/ipsec-road` + +IPsec Site-to-Site +----------------------- +:doc:`how-tos/ipsec-s2s` + +OpenVPN/SSL Road Warrior +------------------------ +:doc:`how-tos/sslvpn_client` + +OpenVPN/SSL Site-to-Site +------------------------ +:doc:`how-tos/sslvpn_s2s` + + +Zerotier +-------- +:doc:`how-tos/zerotier` diff --git a/source/relations.rst b/source/relations.rst new file mode 100644 index 0000000..85349fa --- /dev/null +++ b/source/relations.rst @@ -0,0 +1,15 @@ +==================================== +Project Relations +==================================== + +The OPNsense® development team believes that sharing knowledge makes better +products. The team is proud on it relations with other projects & organizations +and likes to mention them and their hard work. More details may be found on +these pages. + +.. toctree:: + :maxdepth: 2 + :titlesonly: + :glob: + + relations/* diff --git a/source/relations/FreeBSD.rst b/source/relations/FreeBSD.rst new file mode 100644 index 0000000..fbf6914 --- /dev/null +++ b/source/relations/FreeBSD.rst @@ -0,0 +1,35 @@ +=========== +FreeBSD® +=========== +FreeBSD is a registered trademark of The FreeBSD Foundation. The FreeBSD logo +and The Power to Serve are trademarks of The FreeBSD Foundation. + +.. image:: ./images/freebsd-logo-full.png + +--------------------------- + +------------- +About FreeBSD +------------- + +FreeBSD is an operating system for a variety of platforms which focuses on +features, speed, and stability. It is derived from BSD, the version of UNIX® +developed at the University of California, Berkeley. It is developed and +maintained by a large community. + +---------------------------- + + +----------------------- +Relations with OPNsense +----------------------- +OPNsense is build on top of FreeBSD. The aim of the OPNsense team is to stay as +close to the original FreeBSD source as possible. OPNsense can be installed on +a standard FreeBSD installation, this way a hosted system can be converted +easily to run OPNsense. A bootstrap script is available to make the installation +process a joy full experience. + +.. Seealso:: + + To convert your FreeBSD hosted installation to OPNsense, see the OPNsense + bootstrap script on `OPNsense's update tools @ github `__ diff --git a/source/relations/deciso.rst b/source/relations/deciso.rst new file mode 100644 index 0000000..f901f4c --- /dev/null +++ b/source/relations/deciso.rst @@ -0,0 +1,43 @@ +=========== +Deciso B.V. +=========== + +.. image:: ./images/logo_deciso_2015_with_movement.png + +------------------- + +----- +About +----- +`Deciso `__ is a globally operating manufacturer of +network equipment and a highly innovative company that develops network +appliances and middleware software. + +Our field of expertise ranges from open source firewall & utm technology to +telecommunications and business intelligence. The company was founded in 2000 +with a strong focus on open source technology. + +**Free, Libre Open Source Software** + +Open source software makes development easier, faster, it makes you less +depended on the supplier and results in lower cost of ownership. +As a true believer Deciso use open source software all around from our back-end +systems to the turn-key appliances that you can acquire from our resellers. +Deciso is an active sponsor of the Open Source Initiative (OSI) and founder of +the open source OPNsense firewall software. + +-------------------------- + +----------------------- +Relations with OPNsense +----------------------- +Deciso founded OPNsense and offers the project a stable environment. +The company has a long history in providing networking solutions using open +source software and has supported many OSS projects in the past. + +Our extensive knowledge of software development provides the OPNsense community +with a modern and professional approach and results in maintainable software. + +In its effort to create the most widely used open source security platform, +Deciso has been joined by multiple partners who share the same views on open +and transparent software. diff --git a/source/relations/hardenedBSD.rst b/source/relations/hardenedBSD.rst new file mode 100644 index 0000000..a47b342 --- /dev/null +++ b/source/relations/hardenedBSD.rst @@ -0,0 +1,46 @@ +=========== +HardenedBSD +=========== + +.. image:: ./images/Logo-label-hardenedbsd.png + +------------ +Introduction +------------ + +Founded in 2014 by Oliver Pinter and Shawn Webb, HardenedBSD is a +security-enhanced fork of FreeBSD. The HardenedBSD Project is implementing many +exploit mitigation and security technologies on top of FreeBSD. +The project started with Address Space Layout Randomization (ASLR) as an initial +focal point and is now implementing further exploit mitigation techniques. + +----------------- +Why Fork FreeBSD? +----------------- + +HardenedBSD forked the FreeBSD codebase for ease of development. Prior to +HardenedBSD's founding, Oliver and Shawn worked on separate repositories, +occasionally causing collaboration issues. Unifying the codebases was a natural +step in efficient, effective collaboration between the two individuals. +Two years have passed since the unification of the work and HardenedBSD is +growing faster than ever. + +------------------- +HardenedBSD's Goals +------------------- + +HardenedBSD aims to implement innovative exploit mitigation and security +solutions for FreeBSD. We will work with FreeBSD and any other FreeBSD-based +project to include our innovations. + +------------------- +Who is HardenedBSD? +------------------- + +HardenedBSD's core team consists of Oliver Pinter and Shawn Webb. + +------------------------- +Cooperation with OPNsense +------------------------- +In May 2015, HardenedBSD announced their cooperation with OPNsense. +A HardenedBSD-flavored versions of OPNsense is available as of June 2015. diff --git a/source/relations/images/Logo-label-hardenedbsd.png b/source/relations/images/Logo-label-hardenedbsd.png new file mode 100644 index 0000000..2248e5d Binary files /dev/null and b/source/relations/images/Logo-label-hardenedbsd.png differ diff --git a/source/relations/images/freebsd-logo-full.png b/source/relations/images/freebsd-logo-full.png new file mode 100644 index 0000000..b712c9f Binary files /dev/null and b/source/relations/images/freebsd-logo-full.png differ diff --git a/source/relations/images/index.png b/source/relations/images/index.png new file mode 100644 index 0000000..261c472 Binary files /dev/null and b/source/relations/images/index.png differ diff --git a/source/relations/images/logo_deciso_2015_with_movement.png b/source/relations/images/logo_deciso_2015_with_movement.png new file mode 100644 index 0000000..63834cc Binary files /dev/null and b/source/relations/images/logo_deciso_2015_with_movement.png differ diff --git a/source/relations/images/osi_standard_logo.png b/source/relations/images/osi_standard_logo.png new file mode 100644 index 0000000..a03c430 Binary files /dev/null and b/source/relations/images/osi_standard_logo.png differ diff --git a/source/relations/m0n0wall.rst b/source/relations/m0n0wall.rst new file mode 100644 index 0000000..9267ffe --- /dev/null +++ b/source/relations/m0n0wall.rst @@ -0,0 +1,92 @@ +======== +M0n0wall +======== + +.. image:: ./images/index.png + +---------- +Background +---------- + +*Manuel Kasper* + +:: + + Ever since I started playing with packet filters on embedded PCs, I wanted to + have a nice web-based GUI to control all aspects of my firewall without having + to type a single shell command. + + There are numerous efforts to create nice firewall packages with web + interfaces on the Internet (most of them Linux based), but none met all my + requirements (free, fast, simple, clean and with all the features I need). + So, I eventually started writing my own web GUI. But soon I figured out that + I didn't want to create another incarnation of webmin – I wanted to create a + complete, new embedded firewall software package. + + It all evolved to the point where one could plug in the box, set the LAN IP + address via the serial console, log into the web interface and set it up. + + Then I decided that I didn't like the usual bootup system configuration with + shell scripts (I already had to write a C program to generate the filter rules + since that's almost impossible in a shell script), and since my web interface + was based on PHP, it didn't take me long to figure out that I might use PHP + for the system configuration as well. + + That way, the configuration data would no longer have to be stored in text + files that can be parsed in a shell script – it could now be stored in an XML + file. So I completely rewrote the whole system again, not changing much in the + look-and-feel, but quite a lot "under the hood". + + +--------------------------- +End of the m0n0wall project +--------------------------- +The active development of m0n0wall ended in 2015. + +Manuel Kasper, wrote the following on 15 February 2015: + +:: + + Dear m0n0wall enthusiasts, + + on this day 12 years ago, I have released the first version of m0n0wall to + the public. In theory, one could still run that version - pb1 it was called - + on a suitably old PC and use it to control the Internet access of a small LAN + (not that it would be recommended security-wise). However, the world keeps + turning, and while m0n0wall has made an effort to keep up, there are now better + solutions available and under active development. + + Therefore, today I announce that the m0n0wall project has officially ended. + No development will be done anymore, and there will be no further releases. + + The forums and the mailing list will be frozen at the end of this month. + All the contents of the website, repository, downloads, mailing list and forum + will be archived in a permanent location on the web so that they remain + accessible indefinitely to anyone who might be interested in them. + + m0n0wall has served as the seed for several other well known open source + projects, like pfSense, FreeNAS and AskoziaPBX. + + The newest offspring, OPNsense (https://opnsense.org), aims to continue the open source spirit of + m0n0wall while updating the technology to be ready for the future. In my view, + it is the perfect way to bring the m0n0wall idea into 2015, and I encourage all + current m0n0wall users to check out OPNsense and contribute if they can. + + Finally, I would like to take this opportunity to thank everyone who has been + involved in the m0n0wall project and helped in some way or another - + by contributing code, documentation, answering questions on the mailing + list or the forum, donating or just spreading the word. It has been a great + journey for me, and I'm convinced that even now that it has come to an end, + the m0n0wall spirit will live on in the various projects it has spawned. + + +----------------------- +Relations with OPNsense +----------------------- + +Deciso B.V. the founder of OPNsense has taken over the m0n0wall websites from +Manuel Kasper and continues to offer all the sources, website & forum content +both as a historical reference as well as to preserve knowledge gained. + +The OPNsense core team want to thank Manuel for all this effort as for him +OPNsense would not have been possible. diff --git a/source/relations/osi.rst b/source/relations/osi.rst new file mode 100644 index 0000000..9f04971 --- /dev/null +++ b/source/relations/osi.rst @@ -0,0 +1,33 @@ +====================== +Open Source Initiative +====================== + +.. image:: ./images/osi_standard_logo.png + :scale: 25% + +----------------------- + +--------- +About OSI +--------- +"We are the stewards of the Open Source Definition (OSD) and the +community-recognized body for reviewing and approving licenses as OSD-conformant." + +*source:* `opensource.org `__ + +----------------------- + +------------------ +Relations OPNsense +------------------ +OPNsense is licensed under an Open Source Initiative `approved license `__. OPNsense +is and will be available with the simple 2-clause BSD license. We believe an +open source project should provide the sources and the tools to build it. + +----------- +Deciso B.V. +----------- +As founder, trademark owner and largest sponsor of OPNsense, Deciso is an active +sponsor of the Open Source Initiative. see `OSI Corporate Sponsors & Support `__ + +Deciso believes that sharing knowledge makes for better products. diff --git a/source/support.rst b/source/support.rst new file mode 100644 index 0000000..a5761b6 --- /dev/null +++ b/source/support.rst @@ -0,0 +1,26 @@ +=============== +Support Options +=============== + + +Community +--------- +If you need help with OPNsense you can always try the community options first. +When resorting to community support it is important to understand that anyone +helping you is doing so for free and at their own time. Even tough your issue or +question might not be answered fully it would be nice to thank the people who +helped you. + +To receive community support, the following options are available: + +* Start searching this documentation & wiki +* The `OPNsense forum `__ +* Ask online users on `IRC Freenode `__ #opnsense + +Commercial +---------- + +.. image:: images/support-1024x492.jpg + +Extended professional support services are available for an annual fee. +For the commercial support options see `the OPNsense website `__ diff --git a/themes/opnsense/sass/_theme_badge.sass b/themes/opnsense/sass/_theme_badge.sass new file mode 100644 index 0000000..e2ba80b --- /dev/null +++ b/themes/opnsense/sass/_theme_badge.sass @@ -0,0 +1,88 @@ +.rst-versions + position: fixed + bottom: 0 + left: 0 + width: $nav-desktop-width + color: $section-background-color + background: darken($menu-background-color, 8%) + border-top: solid 10px $menu-background-color + font-family: $base-font-family + z-index: $z-index-tray + a + color: $link_color + text-decoration: none + .rst-badge-small + display: none + .rst-current-version + padding: $base-line-height / 2 + background-color: darken($menu-background-color, 5%) + display: block + text-align: right + font-size: 90% + cursor: pointer + color: $green + +clearfix + .fa + color: $section-background-color + .fa-book + float: left + .icon-book + float: left + &.rst-out-of-date + background-color: $red + color: $white + &.rst-active-old-version + background-color: $yellow + color: $black + &.shift-up .rst-other-versions + display: block + .rst-other-versions + font-size: 90% + padding: $base-line-height / 2 + color: $text-medium + display: none + hr + display: block + height: 1px + border: 0 + margin: 20px 0 + padding: 0 + border-top: solid 1px lighten($menu-background-color, 5%) + dd + display: inline-block + margin: 0 + a + display: inline-block + padding: $base-line-height / 4 + color: $section-background-color + &.rst-badge + width: auto + bottom: 20px + right: 20px + left: auto + border: none + max-width: $nav-desktop-width + .icon-book + float: none + .fa-book + float: none + &.shift-up .rst-current-version + text-align: right + .fa-book + float: left + .icon-book + float: left + .rst-current-version + width: auto + height: 30px + line-height: 30px + padding: 0 $base-line-height / 4 + display: block + text-align: center + ++media($tablet) + .rst-versions + width: 85% + display: none + &.shift + display: block diff --git a/themes/opnsense/sass/_theme_badge_fa.sass b/themes/opnsense/sass/_theme_badge_fa.sass new file mode 100644 index 0000000..dbc3bf4 --- /dev/null +++ b/themes/opnsense/sass/_theme_badge_fa.sass @@ -0,0 +1,68 @@ +// Slimmer version of FA for use on the badge_only.sass file. + ++font-face(FontAwesome, '#{$font-awesome-dir}fontawesome-webfont') + +.fa:before + display: inline-block + font-family: FontAwesome + font-style: normal + font-weight: normal + line-height: 1 + text-decoration: inherit + +font-smooth + +a .fa + display: inline-block + text-decoration: inherit + + +li + .fa + display: inline-block + .fa-large:before, + .fa-large:before + /* 1.5 increased font size for fa-large * 1.25 width + width: 1.5 * 1.25em + +ul.fas + list-style-type: none + margin-left: 2em + text-indent: -0.8em + li + .fa + width: .8em + .fa-large:before, + .fa-large:before + /* 1.5 increased font size for fa-large * 1.25 width + vertical-align: baseline + // width: 1.5*1.25em + +.fa-book:before + content: "\f02d" + +.icon-book:before + content: "\f02d" + +.fa-caret-down:before + content: "\f0d7" + +.icon-caret-down:before + content: "\f0d7" + +.fa-caret-up:before + content: "\f0d8" + +.icon-caret-up:before + content: "\f0d8" + +.fa-caret-left:before + content: "\f0d9" + +.icon-caret-left:before + content: "\f0d9" + +.fa-caret-right:before + content: "\f0da" + +.icon-caret-right:before + content: "\f0da" diff --git a/themes/opnsense/sass/_theme_breadcrumbs.sass b/themes/opnsense/sass/_theme_breadcrumbs.sass new file mode 100644 index 0000000..779c7db --- /dev/null +++ b/themes/opnsense/sass/_theme_breadcrumbs.sass @@ -0,0 +1,31 @@ +.wy-breadcrumbs li + display: inline-block + &.wy-breadcrumbs-aside + float: right + a + display: inline-block + padding: 5px + &:first-child + padding-left: 0 + code + padding: 5px + border: none + background: none + &.literal + color: $text-color +.wy-breadcrumbs-extra + margin-bottom: 0 + color: $text-light + font-size: 80% + display: inline-block + + ++media($mobile) + .wy-breadcrumbs-extra + display: none + .wy-breadcrumbs li.wy-breadcrumbs-aside + display: none + +@media print + .wy-breadcrumbs li.wy-breadcrumbs-aside + display: none diff --git a/themes/opnsense/sass/_theme_font_awesome_compatibility.sass b/themes/opnsense/sass/_theme_font_awesome_compatibility.sass new file mode 100644 index 0000000..5857956 --- /dev/null +++ b/themes/opnsense/sass/_theme_font_awesome_compatibility.sass @@ -0,0 +1,24 @@ +.icon + @extend .fa +.icon-home + @extend .fa-home +.icon-search + @extend .fa-search +.icon-book + @extend .fa-book +.icon-caret-down + @extend .fa-caret-down +.icon-github + @extend .fa-github +.icon-bitbucket + @extend .fa-bitbucket +.icon-gitlab + @extend .fa-gitlab +.icon-fire + @extend .fa-fire +.icon-circle-arrow-right + @extend .fa-arrow-circle-right +.icon-circle-arrow-left + @extend .fa-arrow-circle-left +.icon-link + @extend .fa-link diff --git a/themes/opnsense/sass/_theme_font_local.sass b/themes/opnsense/sass/_theme_font_local.sass new file mode 100644 index 0000000..0e02343 --- /dev/null +++ b/themes/opnsense/sass/_theme_font_local.sass @@ -0,0 +1,48 @@ +@font-face + font-family: 'Inconsolata' + font-style: normal + font-weight: 400 + src: local('Inconsolata'), local('Inconsolata-Regular'), url(../fonts/Inconsolata-Regular.ttf) format('truetype') + +@font-face + font-family: 'Inconsolata' + font-style: normal + font-weight: 700 + src: local('Inconsolata Bold'), local('Inconsolata-Bold'), url(../fonts/Inconsolata-Bold.ttf) format('truetype') + +@font-face + font-family: 'Lato' + font-style: normal + font-weight: 400 + src: local('Lato Regular'), local('Lato-Regular'), url(../fonts/Lato-Regular.ttf) format('truetype') + +@font-face + font-family: 'Lato' + font-style: normal + font-weight: 700 + src: local('Lato Bold'), local('Lato-Bold'), url(../fonts/Lato-Bold.ttf) format('truetype') + +@font-face + font-family: 'Lato' + font-style: italic + font-weight: 400 + src: local('Lato Italic'), local('Lato-Italic'), url(../fonts/Lato-Italic.ttf) format('truetype') + +@font-face + font-family: 'Lato' + font-style: italic + font-weight: 700 + src: local('Lato Bold Italic'), local('Lato-BoldItalic'), url(../fonts/Lato-BoldItalic.ttf) format('truetype') + +@font-face + font-family: 'Roboto Slab' + font-style: normal + font-weight: 400 + src: local('Roboto Slab Regular'), local('RobotoSlab-Regular'), url(../fonts/RobotoSlab-Regular.ttf) format('truetype') + +@font-face + font-family: 'Roboto Slab' + font-style: normal + font-weight: 700 + src: local('Roboto Slab Bold'), local('RobotoSlab-Bold'), url(../fonts/RobotoSlab-Bold.ttf) format('truetype') + diff --git a/themes/opnsense/sass/_theme_layout.sass b/themes/opnsense/sass/_theme_layout.sass new file mode 100644 index 0000000..b5d6f4d --- /dev/null +++ b/themes/opnsense/sass/_theme_layout.sass @@ -0,0 +1,406 @@ +.wy-affix + position: fixed + top: $gutter + +.wy-menu + a:hover + text-decoration: none + +.wy-menu-horiz + +clearfix + ul, li + display: inline-block + li:hover + background: rgba(255,255,255,.1) + li + &.divide-left + border-left: solid 1px hsl(0, 0%, 25%) + &.divide-right + border-right: solid 1px hsl(0, 0%, 25%) + a + height: $base-font-size * 2 + display: inline-block + line-height: $base-font-size * 2 + padding: 0 $base-font-size + +.wy-menu-vertical + width: $nav-desktop-width + header, p.caption + height: $base-font-size * 2 + display: inline-block + line-height: $base-font-size * 2 + padding: 0 $gutter + margin-bottom: 0 + display: block + font-weight: bold + text-transform: uppercase + font-size: 80% + color: $menu-dark + white-space: nowrap + + ul + margin-bottom: 0 + li + &.divide-top + border-top: solid 1px hsl(0, 0%, 25%) + &.divide-bottom + border-bottom: solid 1px hsl(0, 0%, 25%) + &.current + background: darken($menu-vertical-background-color, 10%) + a + color: $menu-link-medium + border-right: solid 1px darken($menu-vertical-background-color, 20%) + padding: $gutter / 4 $gutter * 1.5 + &:hover + background: darken($menu-vertical-background-color, 15%) + code + border: none + background: inherit + color: inherit + padding-left: 0 + padding-right: 0 + // Expand links + span.toctree-expand + display: block + float: left + margin-left: -1.2em + @extend .fa + @extend .fa-plus-square-o + font-size: .8em + line-height: 1.6em + color: darken($menu-link-medium, 20%) + + // On state for the first level + li.on a, li.current > a + color: $menu-link-color + padding: $gutter / 4 $gutter + font-weight: bold + position: relative + background: $menu-vertical-background-color + border: none + border-bottom: solid 1px darken($menu-vertical-background-color, 20%) + border-top: solid 1px darken($menu-vertical-background-color, 20%) + padding-left: $gutter -4px + +font-smooth + &:hover + background: $menu-vertical-background-color + span.toctree-expand + color: $menu-link-medium + span.toctree-expand + @extend .fa + @extend .fa-minus-square-o + display: block + font-size: .8em + line-height: 1.6em + color: darken($menu-link-medium, 30%) + + // This is the on state for pages beyond second level + li.toctree-l1.current li.toctree-l2, li.toctree-l2.current li.toctree-l3 + > ul + display: none + &.current > ul + display: block + li.toctree-l2 + &.current + > a + background: darken($menu-vertical-background-color, 20%) + padding: $gutter / 4 $gutter * 1.5 + li.toctree-l3 > a + display: block + background: darken($menu-vertical-background-color, 20%) + padding: $gutter / 4 $gutter * 2.5 + a:hover span.toctree-expand + color: $menu-link-medium + span.toctree-expand + color: darken($menu-vertical-background-color, 35%) + li.toctree-l3 + font-size: .9em + &.current + > a + background: darken($menu-vertical-background-color, 25%) + padding: $gutter / 4 $gutter * 2.5 + li.toctree-l4 > a + display: block + background: darken($menu-vertical-background-color, 25%) + padding: $gutter / 4 $gutter * 3.5 + border-top: none + border-bottom: none + a:hover span.toctree-expand + color: $menu-link-medium + span.toctree-expand + color: darken($menu-vertical-background-color, 40%) + li.toctree-l4 + font-size: .9em + + li.current ul + display: block + li ul + margin-bottom: 0 + display: none + .local-toc + li ul + display: block + li ul li a + margin-bottom: 0 + color: $menu-link-light + font-weight: normal + a + display: inline-block + line-height: 18px + padding: $gutter / 4 $gutter + display: block + position: relative + font-size: 90% + color: $menu-link-light + &:hover + background-color: lighten($menu-background-color, 10%) + cursor: pointer + span.toctree-expand + color: $menu-link-light + &:active + background-color: $menu-logo-color + cursor: pointer + color: $menu-link-active + span.toctree-expand + color: $menu-link-active + +.wy-side-nav-search + display: block + width: $nav-desktop-width + padding: $gutter / 2 + margin-bottom: $gutter / 2 + z-index: $z-index-popover + background-color: $nav-search-background-color + text-align: center + padding: $gutter / 2 + display: block + color: $nav-search-color + margin-bottom: $gutter / 2 + input[type=text] + width: 100% + border-radius: 50px + padding: 6px 12px + border-color: darken($link-color, 5%) + img + display: block + margin: auto auto $gutter / 2 auto + height: 45px + width: 45px + background-color: $menu-logo-color + padding: 5px + border-radius: 100% + > a, .wy-dropdown > a + color: $nav-search-color + font-size: 100% + font-weight: bold + display: inline-block + padding: $base-line-height / 6 $base-line-height / 4 + margin-bottom: $gutter / 2 + +font-smooth + &:hover + background: rgba(255,255,255,.1) + img.logo + display: block // display on its own line all the time + margin: 0 auto + height: auto // undo badge styling above + width: 160px + border-radius: 0 + max-width: 100% // shrink on mobile, if appropriate + background: rgba(0,0,0,0) // make hover background of parent show up properly + &.icon + img.logo + margin-top: 0.85em // space it away from the title text + > div.version + margin-top: -1 * ($gutter / 4) + margin-bottom: $gutter / 2 + font-weight: normal + color: rgba(255,255,255,.3) + + +.wy-nav .wy-menu-vertical + header + color: $link-color + a + color: $text-light + &:hover + background-color: $link-color + color: $white + +[data-menu-wrap] + +transition(all .2s ease-in) + position: absolute + opacity: 1 + width: 100% + opacity: 0 + &.move-center + left: 0 + right: auto + opacity: 1 + &.move-left + right: auto + left: -100% + opacity: 0 + &.move-right + right: -100% + left: auto + opacity: 0 + + +.wy-body-for-nav + background: left repeat-y $section-background-color + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC) + background-size: $nav-desktop-width 1px + +.wy-grid-for-nav + position: absolute + width: 100% + height: 100% + +.wy-nav-side + position: fixed + top: 0 + bottom: 0 + left: 0 + padding-bottom: 2em + width: $nav-desktop-width + overflow-x: hidden + overflow-y: hidden + min-height: 100% + background: $nav-background-color + z-index: $z-index-popover + +.wy-side-scroll + width: $nav-desktop-width + 20px + position: relative + overflow-x: hidden + overflow-y: scroll + height: 100% + +.wy-nav-top + display: none + background: $link-color + color: $white + padding: $gutter / 4 $gutter / 2 + position: relative + line-height: 50px + text-align: center + font-size: 100% + +clearfix + a + color: $white + font-weight: bold + +font-smooth + img + margin-right: $base-line-height / 2 + height: 45px + width: 45px + background-color: $menu-logo-color + padding: 5px + border-radius: 100% + i + font-size: 30px + float: left + cursor: pointer + padding-top: inherit + +.wy-nav-content-wrap + margin-left: $nav-desktop-width + background: $section-background-color + min-height: 100% + +.wy-nav-content + padding: $gutter $gutter * 2 + height: 100% + max-width: 800px + margin: auto + +.wy-body-mask + position: fixed + width: 100% + height: 100% + background: rgba(0,0,0,.2) + display: none + z-index: $z-index-modal - 1 + &.on + display: block +footer + color: $footer-color + p + margin-bottom: $base-line-height / 2 + span.commit code + padding: 0px + font-family: $code-font-family + font-size: 1em + background: none + border: none + color: $footer-color + +.rst-footer-buttons + &:before, &:after + width: 100% + +clearfix + +.rst-breadcrumbs-buttons + margin-top: 12px + +clearfix + +#search-results + .search li + margin-bottom: $base-line-height + border-bottom: solid 1px $table_border_color + padding-bottom: $base-line-height + .search li:first-child + border-top: solid 1px $table_border_color + padding-top: $base-line-height + .search li a + font-size: 120% + margin-bottom: $base-line-height / 2 + display: inline-block + .context + color: $text-medium + font-size: 90% + + ++media($tablet) + .wy-body-for-nav + background: $section-background-color + .wy-nav-top + display: block + .wy-nav-side + @if $nav-desktop-position == left + left: -$nav-desktop-width + @else + right: -$nav-desktop-width + &.shift + width: 85% + left: 0 + .wy-side-scroll + width: auto + .wy-side-nav-search + width: auto + .wy-menu.wy-menu-vertical + width: auto + .wy-nav-content-wrap + margin-left: 0 + .wy-nav-content + padding: $gutter + &.shift + position: fixed + min-width: 100% + left: 85% + top: 0 + height: 100% + overflow: hidden + ++media($desktop-wider) + .wy-nav-content-wrap + background: rgba(0,0,0,.05) + .wy-nav-content + margin: 0 + background: $section-background-color + +@media print + .rst-versions, footer, .wy-nav-side + display: none + .wy-nav-content-wrap + margin-left: 0 diff --git a/themes/opnsense/sass/_theme_mathjax.sass b/themes/opnsense/sass/_theme_mathjax.sass new file mode 100644 index 0000000..1004993 --- /dev/null +++ b/themes/opnsense/sass/_theme_mathjax.sass @@ -0,0 +1,5 @@ +span[id*='MathJax-Span'] + color: $mathjax-color + +.math + text-align: center diff --git a/themes/opnsense/sass/_theme_rst.sass b/themes/opnsense/sass/_theme_rst.sass new file mode 100644 index 0000000..ef0ebda --- /dev/null +++ b/themes/opnsense/sass/_theme_rst.sass @@ -0,0 +1,322 @@ +// ------------------------------------------------------------------------------------------------------------------- +// CONTRIBUTORS, PLEASE READ THIS! +// ------------------------------------------------------------------------------------------------------------------- +// Couple things... +// 1. Lots of this @extends from wyrm_core/_type.sass (http://www.github.com/snide/wyrm/. +// * Try not to replace any @extends code. It's pretty generic stuff meant to work together. +// * That said, know that I'm very unlikely to accept PRs from wyrm just to change style here. +// 2. I plan to remove the !importants in here. Part of it is due to lazyness, part to sphinx's fondness for nesting. +// 3. Try to use variables from wyrm_core/wy_variables.sass. Notable are... +// * $base-line-height // All margins, padding and line-height should use this in .25 increments. +// * $text-color, $text-light, $text-dark...etc +// * $base-font-family, $custom-font-family, $code-font-family +// 4. If you have changes for mobile/tablet, put them at the bottom of the sass file. +// -------------------------------------------------------------------------------------------------------------------- + +.rst-content + // Sphinx by default applies HxW style attributes to images. This fixes that oversite. + img + max-width: 100% + height: auto !important + + .highlight > pre, .linenodiv > pre + line-height: normal + + div.figure + margin-bottom: $base-line-height + p.caption + font-style: italic + + div.figure.align-center + text-align: center + + // Usually it's a good idea to give images some space. + .section > img, .section > a > img + margin-bottom: $base-line-height + // Questionable whether this is nice or not. It styles eternal links, but comes with some baggage. + // a.reference.external:after + // font-family: FontAwesome + // content: " \f08e " + // color: $text-light + // vertical-align: super + // font-size: 60% + + // For the most part, its safe to assume that sphinx wants you to use a blockquote as an indent. It gets + // used in many different ways, so don't assume you can apply some fancy style, just leave it be. + blockquote + margin-left: $base-line-height + line-height: $base-line-height + margin-bottom: $base-line-height + .literal-block, pre.literal-block + @extend .codeblock + // These are the various note pullouts that sphinx applies + .note, .attention, .caution, .danger, .error, .hint, .important, .tip, .warning, .seealso, .admonition-todo + @extend .wy-alert + .last + margin-bottom: 0 + .admonition-title + @extend .wy-alert-title + @extend .fa + @extend .fa-exclamation-circle + &:before + margin-right: 4px + .note, .seealso + @extend .wy-alert.wy-alert-info + .hint, .tip, .important + @extend .wy-alert.wy-alert-success + .error, .danger + @extend .wy-alert.wy-alert-danger + .warning, .caution, .attention, .admonition-todo + @extend .wy-alert.wy-alert-warning + // Some people put tables in notes. Let's give them very basic support. + .admonition table + border-color: rgba(0,0,0,.1) + td, th + background: transparent !important + border-color: rgba(0,0,0,.1) !important + .section ul, .toctree-wrapper ul + @extend .wy-plain-list-disc + .section ol.loweralpha, .section ol.loweralpha li + list-style: lower-alpha + .section ol.upperalpha, .section ol.upperalpha li + list-style: upper-alpha + .section ol, ol.arabic + @extend .wy-plain-list-decimal + .section ol p, .section ul p + margin-bottom: $base-line-height / 2 + .line-block + margin-left: $base-line-height + + // Generics handling of headings and toc stuff. + .topic-title + font-weight: bold + margin-bottom: $base-line-height / 2 + .toc-backref + color: $text-color + .align-right + float: right + margin: 0px 0px $base-line-height $base-line-height + .align-left + float: left + margin: 0px $base-line-height $base-line-height 0px + .align-center + margin: auto + display: block + .toctree-wrapper p.caption + @extend h2 + + // This is the #href that shows up on hover. Sphinx's is terrible so I hack it away. + h1, h2, h3, h4, h5, h6, dl dt, p.caption + .headerlink + display: none + visibility: hidden + font-size: 14px + @extend .fa + &:after + visibility: visible + content: "\f0c1" + font-family: FontAwesome + display: inline-block + &:hover .headerlink + display: inline-block + + .centered + text-align: center + + // Sidebar content. You'll see at the bottom of this file I change it in mobile. + .sidebar + float: right + width: 40% + display: block + margin: 0 0 $base-line-height $base-line-height + padding: $base-line-height + background: $sidebar-background-color + border: solid 1px $sidebar-border-color + // Sidebar content is usually less relevant, so adjust the margins and sizes. + p, ul, dl + font-size: 90% + .last + margin-bottom: 0 + .sidebar-title + display: block + font-family: $custom-font-family + font-weight: bold + background: $table-border-color + padding: $base-line-height / 4 $base-line-height / 2 + margin: -$base-line-height + margin-bottom: $base-line-height + font-size: 100% + // Sphinx can highlight searched text with ?highlighted=searchterm + .highlighted + background: $highlight-color + display: inline-block + font-weight: bold + padding: 0 $base-line-height / 4 + + // These are the little citation links [1] that show up within paragraphs. + .footnote-reference, .citation-reference + vertical-align: super + font-size: 90% + + // Tables! Sphinx LOVES TABLES. Most of wyrm assumes you're only going to use a table as a table + // so I have to write a bunch of unique stuff for Sphinx to style them up differently like it's 2003. + table.docutils.citation, table.docutils.footnote + background: none + border: none + color: $text-medium + td, tr + border: none + background-color: transparent !important + white-space: normal + td.label + padding-left: 0 + padding-right: 0 + vertical-align: top + code + color: $gray + table.docutils + @extend .wy-table + @extend .wy-table-bordered-all + &:not(.field-list) + @extend .wy-table-striped + // This table is what gets spit out for auto-generated API stuff. I style it smaller bits of padding. + table.field-list + @extend .wy-table + border: none + td + border: none + td > strong + display: inline-block + .field-name + padding-right: 10px + text-align: left + white-space: nowrap + .field-body + text-align: left + + // These are the "literals" that get spit out when you mark stuff as ``code`` as your write. + tt, code + @extend code + color: $black + padding: 2px 5px + big, em + font-size: 100% !important + line-height: normal + + &.literal + color: $text-code-color + &.xref, a & + font-weight: bold + color: $text-codexref-color + // If the literal is inside an a tag, let's color it like a link + a tt, a code + color: $link-color + dl + margin-bottom: $base-line-height + dt + font-weight: bold + // Most of the content within these dls are one liners, so I halve the normal margins. + p, table, ul, ol + margin-bottom: $base-line-height / 2 !important + // rST seems to want dds to be treated as the browser would, indented. + dd + margin: 0 0 $base-line-height / 2 $base-line-height + // This is what Sphinx spits out for it's autodocs. Depending upon what language the person is referencing + // these things usually have a class of "method" or "class" or something similar, but really who knows. + // Sphinx doesn't give me a generic class on these, so unfortunately I have to apply it to the root dl. + // This makes me terribly unhappy and makes this code very nesty. Unfortunately I've seen hand-written docs + // that output similar, but not quite the same nesting so this is really the best we can do. + dl:not(.docutils) + margin-bottom: $base-line-height + // This would be the equivilant of a .. class:: + dt + display: table + margin: $base-line-height / 4 0 + font-size: 90% + line-height: normal + background: lighten($class-color, 50%) + color: $class-color + border-top: solid 3px lighten($class-color, 20%) + padding: $base-line-height / 4 + position: relative + &:before + color: lighten($class-color, 20%) + .headerlink + color: $text-color + font-size: 100% !important + // And this would be the .. method:: + dl dt + margin-bottom: $base-line-height / 4 + border: none + border-left: solid 3px hsl(0,0%,80%) + background: hsl(0,0%,94%) + color: $method-color + .headerlink + color: $headerlink-color + font-size: 100% !important + dt:first-child + margin-top: 0 + // Since dts get the callout style, we treat this less as callouts. + tt, code + font-weight: bold + &.descname, &.descclassname + background-color: transparent + border: none + padding: 0 + font-size: 100% !important + &.descname + font-weight: bold + // This is for more advanced parameter control + .optional + display: inline-block + padding: 0 4px + color: $black + font-weight: bold + .property + display: inline-block + padding-right: 8px + // Doc links to sourcecode + .viewcode-link, .viewcode-back + display: inline-block + color: $text-viewcode-color + font-size: 80% + padding-left: $base-line-height + .viewcode-back + display: block + float: right + p.rubric + margin-bottom: 12px + font-weight: bold + //Download link + code.download + background: inherit + padding: inherit + font-weight: normal + font-family: inherit + font-size: inherit + color: inherit + border: inherit + white-space: inherit + span:first-child + -webkit-font-smoothing: subpixel-antialiased + @extend .fa + @extend .fa-download + &:before + margin-right: 4px + .guilabel + border: 1px solid lighten($guilabel-color, 25%) + background: lighten($guilabel-color, 50%) + font-size: 80% + font-weight: 700 + border-radius: $base-line-height / 6 + padding: $base-line-height / 10 $base-line-height / 4 + margin: auto $base-line-height / 12 + .versionmodified + font-style: italic + + +// Mobile specific ++media($mobile) + .rst-content + .sidebar + width: 100% diff --git a/themes/opnsense/sass/_theme_variables.sass b/themes/opnsense/sass/_theme_variables.sass new file mode 100644 index 0000000..c87cf9c --- /dev/null +++ b/themes/opnsense/sass/_theme_variables.sass @@ -0,0 +1,66 @@ +// In here are varibles used for sphinx_rtd_theme, they either add to or overwrite the default ones +// that are set in wyrm_core/wy_variables.sass. You'll find wyrm in bower_components if you're looking +// for a reference. + +$font-awesome-dir: "../fonts/" +$static-img: "../img/" +$mathjax-color: $text-color + +$headerlink-color: $text-color + +// Code colors +$text-viewcode-color: $green +$text-codexref-color: $text-color + +// Definition list colors +$class-color: $blue +$method-color: $gray + +// GUI label color +$guilabel-color: $blue + +// Footer colors +$footer-color: $text-medium + +// Menu colors +$menu-vertical-background-color: $section-background-color + +// Menu text colors +$menu-color: $gray +$menu-dark: lighten($menu-color,10%) !default +$menu-medium: lighten($menu-color,25%) !default +$menu-light: lighten($menu-color,45%) !default +$menu-lighter: lighten($menu-color,60%) !default + +// Menu link colors +$menu-link-color: $text-color +$menu-link-dark: $text-dark +$menu-link-medium: $text-medium +$menu-link-light: $text-light +$menu-link-active: $white + +// Navigation colors +$nav-background-color: $menu-background-color +$nav-search-background-color: #d94f00 +$nav-search-color: $section-background-color +$nav-link-color: $blue +$nav-link-color-visited: $purple +$nav-link-color-hover: lighten($nav-link-color, 6%) !default +$nav-link-color-alt: hsl(33, 100%, 51%) + +// Sidebar colors +$sidebar-background-color: $table-stripe-color +$sidebar-border-color: $table-border-color +$sidebar-title-background-color: $table-border-color + +// Sphinx highlight color +$highlight-color: $yellow + +$base-font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif +$custom-font-family: "Roboto Slab", "ff-tisa-web-pro", "Georgia", Arial, sans-serif +$custom-font-family2: Georgia, serif +$code-font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace + +.wy-side-nav-search + > div.version + color: #ffffff !important diff --git a/themes/opnsense/sass/badge_only.sass b/themes/opnsense/sass/badge_only.sass new file mode 100644 index 0000000..b8cdac3 --- /dev/null +++ b/themes/opnsense/sass/badge_only.sass @@ -0,0 +1,16 @@ +// ------------------------------------------------------------ +// CONTRIBUTORS, PLEASE READ THIS! +// ------------------------------------------------------------ +// This generates the RTD sticky badge for non RTD themes. As +// always, only files labeled "theme_*.sass should be edited". +// ------------------------------------------------------------ +$border-box-sizing: false !default + +@import wyrm_core/wy_variables +@import theme_variables +@import bourbon +@import neat +@import wyrm_core/mixin +@import wyrm_core/grid_settings +@import _theme_badge_fa +@import _theme_badge diff --git a/themes/opnsense/sass/theme.sass b/themes/opnsense/sass/theme.sass new file mode 100644 index 0000000..c7322b7 --- /dev/null +++ b/themes/opnsense/sass/theme.sass @@ -0,0 +1,54 @@ +// ------------------------------------------------------------ +// CONTRIBUTORS, PLEASE READ THIS! +// ------------------------------------------------------------ +// This theme pulls from other frontend projects. The only +// things you should edit are the sass files that start with +// "theme_*.sass". All other files are loaded through bower. +// ------------------------------------------------------------ + +// Variable defaults set by Wyrm +@import wyrm_core/wy_variables + +// Variable overrides that change coloring and fonts for this theme. +@import theme_variables + +// bourbon.io framework +@import bourbon + +// Bourbon.io/neat framework, with some default media queries +@import wyrm_core/grid_settings +@import neat +// Some corrections for neat +@import wyrm_core/neat_extra + +// Custom reset +@import wyrm_core/reset + +// Wyrm mixins +@import wyrm_core/mixin + +// Font Awesome 4.0 with wyrm extras +@import font-awesome +@import wyrm_core/font_icon_defaults + +// Wyrm core styles used in this theme +@import wyrm_core/alert +@import wyrm_core/button +@import wyrm_core/dropdown +@import wyrm_core/form +@import wyrm_core/generic +@import wyrm_core/table +@import wyrm_core/type + +// Pygments styling +@import wyrm_addons/pygments/pygments +@import wyrm_addons/pygments/pygments_light + +// Theme specific styles. These are likely the files you want to edit. +@import theme_breadcrumbs +@import theme_layout +@import theme_badge +@import theme_rst +@import theme_mathjax +@import theme_font_awesome_compatibility +@import theme_font_local