pax_global_header00006660000000000000000000000064141725565410014524gustar00rootroot0000000000000052 comment=7e87ad1e4057fa1ef9f3a21f6e24d2d96a5bf615 ocsigenserver-5.0.1/000077500000000000000000000000001417255654100144055ustar00rootroot00000000000000ocsigenserver-5.0.1/.github/000077500000000000000000000000001417255654100157455ustar00rootroot00000000000000ocsigenserver-5.0.1/.github/workflows/000077500000000000000000000000001417255654100200025ustar00rootroot00000000000000ocsigenserver-5.0.1/.github/workflows/workflow.yml000066400000000000000000000017321417255654100224020ustar00rootroot00000000000000name: Main workflow on: pull_request: push: schedule: # Prime the caches every Monday - cron: 0 1 * * MON jobs: build: strategy: fail-fast: false matrix: os: - macos-latest - ubuntu-latest ocaml-compiler: - 4.08.x - 4.09.x - 4.10.x - 4.11.x - 4.12.x runs-on: ${{ matrix.os }} steps: - name: Checkout code uses: actions/checkout@v2 - name: Use OCaml ${{ matrix.ocaml-compiler }} uses: ocaml/setup-ocaml@v2 with: ocaml-compiler: ${{ matrix.ocaml-compiler }} dune-cache: ${{ matrix.os != 'macos-latest' }} opam-depext: false opam-pin: false - run: opam pin add ocsigenserver.dev . --no-action - run: opam depext ocsigenserver --yes - run: opam install . --deps-only - run: opam exec -- ./configure shell: bash - run: opam exec -- make all ocsigenserver-5.0.1/.gitignore000066400000000000000000000002741417255654100164000ustar00rootroot00000000000000*~ Makefile.config src/baselib/dynlink_wrapper.ml src/baselib/ocsigen_config_static.ml ocsigenserver.conf.sample ocsigenserver.conf.opt.sample local doc/api-html doc/api-wiki _opam _build ocsigenserver-5.0.1/.jenkins.sh000066400000000000000000000005301417255654100164560ustar00rootroot00000000000000opam pin add --no-action ocsigenserver . opam install --deps-only ocsigenserver opam install --verbose ocsigenserver do_build_doc () { make -C doc clean make -C doc doc make -C doc wikidoc cp -rf doc/api-wiki/*.wiki ${API_DIR} cp -rf doc/manual-wiki/*.wiki ${MANUAL_SRC_DIR} } do_remove () { opam remove --verbose ocsigenserver } ocsigenserver-5.0.1/.ocp-indent000066400000000000000000000000521417255654100164430ustar00rootroot00000000000000normal with=0 syntax=lwt mll max_indent=2 ocsigenserver-5.0.1/CHANGES000066400000000000000000000753341417255654100154140ustar00rootroot00000000000000==== 5.0.0 (2021-10-16) === * Completely outsource Ocsipersist into its own project: https://github.com/ocsigen/ocsipersist ==== 4.0.1 (2021-07-07) === * Fix compilation failure when missing optional extensions for ocsipersist ==== 4.0.0 (2020-10-27) === * Switch to Dune ==== 2.16.0 (2019-12-20) ==== * compatibility with lwt.5.0: fix nested Lwt_main.run ==== 2.15.0 (2019-08-16) ==== * Ocsipersist-pgsql: fix iter_table function ==== 2.12.0 (2019-07-10) ==== * more fine-grained verbosity control * disable profiling by default * compatibility with ssl.0.5.8 * documentation ==== 2.11.0 (2018-12-19) ==== * Ocsipersist-pgsql: no longer hold a database connection for a long time ==== 2.10 (2018-12-18) ==== * Compatibility with OCaml 4.07 * Compatibility with Lwt 4.x * Replace tyxml.parser with xml-light * Gracefully respond to invalid command line options. ==== 2.9.0 (2018-02-01) ==== * Compatibility with OCaml 4.06 * Compatibility with Lwt 3.0.0 * No longer use Camlp4 * More robust Ocsipersist DB connection handling * Various small fixes and improvements ==== 2.8.0 (2016-11-24) ==== * PostgreSQL Ocsipersist backend * Compatibility with TyXML 4.0.x * Export OpenSSL options through configuration file * Various small fixes and improvements ==== 2.7.0 (2016-05-12) ==== * Fix content type selection for XML content * Send gzip trailer in Deflatemod * Log more details about SSL accept errors * Support the Content-Disposition header * Optimize buffering ==== 2.6.0 (2015-07-21) ==== * Fix cryptographic-safe string generation * Fix performance bug in Deflatmod * Fix max-age cache control directive in Staticmod * Resend cache information with 304 (not modified) responses * Expose Ocsigen_request_info interface. * Wait for error message to be logged on shutdown (#81) * Lots of fixes, UTF-8-ization, cosmetics, etc. ==== 2.5.0 (2014-09-30) ==== * New "sethttpcode" option in outputfilter * Adding "continue" option in rewritemod * use Lwt_unix.fork instead of Unix.fork * Xhtml -> Html5 ==== 2.4.0 (2014-04-14) ==== * Features/Changes ** Use ipaddr ** Support "Expect: 100-continue" * BugFixes ** fix PID file (#24) ==== 2.3.1 (2014-04-14) ==== * fix VERSION ==== 2.3.0 (2014-01-25) ==== * Features/Changes ** Support for DELETE and PUT http method ** Support syslog logs ** option for ipv4/v6 in ocsigen_http_client * BugFixes ** Prevent exit when an Lwt.async task raise an exception ** fix HTTP bytes range (#8) ==== 2.2.0 (2012-12-07) ==== * Relative filenames when not running as daemon * Small change in ocsigen_lib: encoding of parameters with '~' * fix Ocsigen_http_client.get_url (and other) first "/" was missing (close #311) * Installation: Do not try to chown files to a different user * Fix error on make logrotate * redirectmod: fixing default to permanent (as written in manual) * Minor additions in the API ===== 2.1 ===== ===== 2.0.4 (2012-06-02) ===== * Rename and split Ocsigen_pervasives into Ocsigen_lib and Ocsigen_lib_base * Adapt to lower-case module names in TyXML ===== 2.0.4 (2012-03-08) ===== * Fix licencing problems of staticmod icons * Server: ** Add a notification for connections closed by the client ===== 2.0.3 (2012-01-31) ===== * Staticmod: add a "cache" option * Cgimod: fix use of old $1 notation instead of \1 * Fix problem with etags, post and safari * Add charset to content served as something/xml * Licence of polytable and ocsigen_cache changed from GPL to LGPL ===== 2.0.2 (2011-11-18) ===== * Server: ** The command line options where not parsed when the server was not compiled with -linkall. ** Improve error messages when the log firectory is not present. ** Add a Cross-Origin Resource Sharing extension. * Libraries: ** Allow Ocsigen_sender.{Html5,Xhtml}_content to choose the returned content type (close #53). ** Ocsigen_extensions.get_port: do not return the actual request port if an Host HTTP header is present. ===== 2.0.1 (2011-09-28) ===== * Directory listing: do not use URL encoding for displaying the current path in HTML. ===== 2.0 (2011-09-20) ===== * Small fixes in documentation. ===== 2.0-rc1 (2011-07-15) ===== * Fix installation without dbm * Option to compile without preemptive threads * Get rid of C stubs: they are now included in Ocaml standard library * Log files are opened with the right UID ===== 1.91 (2011-04-08) ===== * Split the ocsigen package in three : tyxml, ocsigenserver and eliom * Rename into ocsigenserver * Revproxy, Accesscontrol: Handling {{{X-Forwarded-For}}} and {{{X-Forwarded-Proto}}} headers * HTTP parser rewritten ===== 1.90 ===== * New module {{{Eliom_client}}} for client/server Eliom programs using js_of_ocaml. * Eliom client: calling a service from client side code. * Eliom: Services taking Caml values as parameters. * Eliom: services sending Caml values. * Eliom: new implementation of forms and links to be compatible with client side programs. * Eliom: sp parameter has been removed (now using Lwt's thread storage) * Eliom: {{{Eliom_predefmod}}} renamed {{{Eliom_output}}} * Eliom: New module {{{Eliom_output.Customize}}} to create your own register functions from another registration module * Eliom: Module {{{Eliom_sessions}}} replaced by {{{Eliom_state}}}, {{{Eliom_request_info}}} and {{{Eliom_config}}}. * Eliom: new implementation of user cookies. * Eliom: Client process cookies. Like usual browser cookies but for one client side process. * Eliom: Client process server side state data. Like session data but for one client side process. * Eliom: Client process session services. * Eliom: Session group data. Like session data but for all sessions in a session group. * Eliom: Session group services. * Eliom: session replaced by a more general concept of "server side state". States have a scope: client process, session or group of sessions. * Eliom: session tables and request cache now deprecated, replaced by //Eliom references// * Eliom client: Possible to call another service without stopping the client side program, with bookmark support and back button support. * New extension Comet to allow server -> client communication. * Eliom: client/server communication channels. * Eliom: client/server reactive programming using React. * Eliom client: syntax extension for separating client and server code. * Eliom: New module Eliom_output.Eliom_appl for registering pages that belong to the same Eliom application. * Eliom client: syntax extension and wrapping/unwrapping mechanism to access server side values in client side code. * Eliom client: Relinking the DOM on client side after loading a (portion of) page. This allows to use directly nodes created on server side in client side code. * Eliom client: XHR redirections for Eliom applications. * Eliom: safe unmarshaling of caml values sent by client side programs * Xhtml: Xhtml5 support * Atom module and Pubsubhubbub * OpenID support * SVG module * Documentation: New tutorial * Documentation: New Eliom manual * //and many other things ...// ===== 1.3.4 ===== * Eliom: Now supporting list of lists in service parameters ===== 1.3.3 (2010-06-13) ===== * Eliom: Fix some typos in Eliom's tutorial stylesheet * Server: Fix usage of {{{accept_n}}} to avoid file descriptor leakage * XHTML: Adding missing elements and attributes in XHTML.M * Cleaning Ocsigen_cache * Eliom: Fixing actions with uploads ===== 1.3.2 (2010-04-30) ===== * Add dummy findlib packages ocsigen.xhtml*, that depend on ocsigen_xhtml*, for compatibility with previous versions. These packages might be removed in a future (major) release. * Port to Lwt 2.1.0 ===== 1.3.1 (2010-04-23) ===== * Split out ocsigen_xhtml findlib package * Configuration file: when no protocol is specified in {{{}}}, listen on IPv6 (if possible) and IPv4 (always) ===== 1.3.0 (2010-01-22) ===== * Server: Each request now has a polymorphic data table (called //request cache//), where you can store the data you want to keep during the whole page generation. * Eliom: actions now return {{{()}}}. Use the request cache to send information to fallbacks. * Eliom: CSRF-safe coservices * Eliom: the number of sessions without group by IP address is now limited * Eliom: efficient implementation of limitation of sessions by groups (or now IP) for large limits * Eliom: the number of anonymous coservices by session is now limited * Eliom: the number of anonymous coservices without session by IP address is now limited * Eliom: now possible to unregister services * Eliom: New (very) experimental module {{{Eliom_obrowser}}} to use Eliom with Obrowser * Eliom: Now possible to have constant parts in suffixes to allow URLS like {{{/param1/something/param2}}} * Eliom: services with optional suffixes * Eliom: form towards a service with suffix: it is now possible to choose whether you want the redirection towards the suffix form or not * Eliom: lists and sets in suffixes * Eliom: Now possible to create services sending custom HTTP header values or customizing the content-type * Eliom: New notion: "Non localized parameters". Can be sent to any service. * Eliom: changing the order of parameters for user type form widgets * Eliom: changing the order of parameters for user type form widgets * Eliom: Eliom_tools.menu and hierarchical_menu now compare the URL strings (was: compare the service) * Eliom: textarea now take a string (was pcdata) * Eliom: The type of the iterator for lists in parameters has changed * Eliom: New options in configuration file to set session timeouts * Server: now possible to give the config file name to reload server command * Server: now possible to do a "graceful shutdown" of the server using the "shutdown" server command * Server: now possible to add custom commands for the command pipe * Server: EXPERIMENTAL now possible to observe HTTP headers before sending the result * Xhtmlpp: the parsing now fails if a quotation for an Xhtml element contains superfluous elements. (This can cause the parsing of previously incorrect code to fail) * Staticmod/Eliom: attempting to access a file whose name contains a NULL character will result in a 403. * Server: HTTP headers containing newlines are now properly escaped. * Server: correct missing xmlns in Xhtml DTD * Server: now send last-modified and etag headers when returning a 403 * Server: Now accepting several requests at a time (as explained in "Accept()able strategies" by Tim Brecht & all) * Rewritemod: more rewriting possibilities (still very basic) * Eliom menus are now more robust when finding which item is active * Fixed handling of incorrectly-sized multipart requests. Thanks to Mauricio Fernandez for noticing the bug * Upload directory and maximum file size can now be configured on a per-site basis * Renamed the field of Ocsigen_http_frame.t * Javascript events support in Xhtml.M ; Thanks to john @ 5070.info for the patch ===== 1.2.2 (2009-10-17) ===== * Add react and lwt.unix to the list of built-in findlib packages ===== 1.2.1 (2009-09-26) ===== * Lwt 2.0 compatibility: ** Adapt to Lwt.t/Lwt.u splitting ** fix Makefile to deal with lwt.unix findlib package * Fix ocsipersist-dbm Makefile * Fix for pcre-ocaml 6.0.0 * Fix typo regarding --stubdir in configure script ===== 1.2.0 (2009-03-25) ===== * Native code version now compiled by default * Now possible to link extensions and Eliom modules statically, for example to use a native code server on platforms where native dynlink is not supported * Server: Partial requests implemented (Range HTTP header) * Build C stubs into a shared library so that bytecode executables may be not linked in custom mode; new {{{--stubdir}}} option in {{{configure}}} script * Eliom: non-attached services now called "named non-attached coservices" and created using {{{Eliom_services.new_coservice'}}} with the optional {{{name}}} parameter * Eliom: now possible to create named attached coservices using the optional {{{name}}} parameter * Eliom: now possible to write libraries for Eliom sites, loaded inside {{{}}}, but not generating any page * Eliom and server: EXPERIMENTAL now possible to make extensions that can use Eliom's data * XHTML.M's pretty printer: now possible to set the DOCTYPE manually * Eliom: now possible to set manually the DOCTYPE when registering an XHTML.M service * Redirectmod and Revproxy: now possible to do more complex rewriting * Accesscontrol: add support for {{{}}} and {{{}}} conditions * Config file: {{{aliases}}} attribute now called {{{hostfilter}}} * Revproxy and Redirectmod: now possible to filter on server, port and protocol * New extension extendconfiguration to allow dynamic changes in the configuration (mimetypes, charsets, followsymnlink, directory listing, ...) * Server: new module {{{LocalFiles}}} factoring the common parts for sending static files (with Eliom and staticmod for example), while checking that the files can safely be sent. * Now possible to use XHTML pretty printers without Ocsigen, using the {{{xhtmlpretty.cma}}} library * Add {{{Ocsigen_lib.register_exn_printer}}}, better error messages * Now possible to use the same configuration file in native code and in bytecode (.cmo/.cma filenames are internally translated to .cmxs) * Signature of Ocsigen_extensions.register_extension is now more complete and more lightweight * Userconf: the options set in the local .userconf file are kept in the enclosing {{{}}} tag * Server: possibility to ignore or to supply an alternative command-line * Ocsigen_http_client: timeout when the distant server does not exists * OCaml versions < 3.10 are not supported anymore * Extensions are now much more strict w.r.t. the syntax of configuration files * Staticmod: accessing a directory for which indexing is disallowed returns an error 404 (instead of a 403 previously) ===== 1.1.0 (2008-07-15) ===== * Lwt removed (now distributed separately) * {{{XHTML.M}}} pretty printer: fixing pretty printing of empty tags (for browser compatibility) * Eliom_duce: New pretty printer for XHTML fixing pretty printing of empty tags * Eliom: secure sessions, secure services, (absolute) https links/forms, and using secure cookies * Eliom: Adding special "void action", without any parameters * Eliom: {{{Eliom_predefmod.Redirections}}} now called {{{Eliom_predefmod.String_redirection}}}, and adding new module {{{Eliom_predefmod.Redirection}}} that use GET services without parameters as data type. * Eliom and XHTML.M: Small changes of types in interfaces * Eliom: New session ID generator * Eliom: Adding types {{{int32}}} and {{{int64}}} for parameters and forms * Eliom: Adding functions {{{lwt_get_form}}} and {{{lwt_post_form}}} for creating forms using cooperative functions * Eliom and Staticmod: now possible to give GET parameters to static pages * Eliom: Bugfix in Makefiles for native code version * Eliom forms: Adding missing types in interfaces * Eliom_tools: current page is now optional in menus * Userconf and Eliom: there was a bug when loading both Eliom and Userconf together * Reverse Proxy: Now sending content length when available * Web server: The default content-type is now {{{application/octet-stream}}} * Creating and installing a cma file for all Ocsigen libraries not installed elsewhere * Ocsipersist-dbm: fixing bug when removing data * Deflatemod: fixing memory leak * And small bugfixes in XHTML.M, Eliom, ... ===== 1.0.0 (2008-04-01) ===== * Config file: findlib integration * Eliom and Ocsigen: changing namespace convention for modules * Access control: simplification of config file syntax * Eliom: Allowing (module dependent) parameters for registration functions * New xhtml output without pretty printing * Web server: Bugfix in HTTP/1.0 with keep-alive * Reverse proxy: Bugfix GET parameters were wrong * Reverse proxy: Bugfix memory consumption when the connection was closed by client ===== 0.99.5 (2008-01-11) ===== * Revproxy: pipelining of requests * Access control: simplification, generalization of filters and syntax changes in config file * Eliom: EXPERIMENTAL session groups * Eliom: non-attached services * Eliomduce: new functor {{{SubXhtml}}} for creating registration modules * Eliomduce: new module Eliomducetools with same features as Eliomtools, but for Eliomduce * Web server: now possible to split the configuration file into several files using the {{{}}} option. * Web server: now possible to have {{{}}} option inside another {{{}}} in configuration files, and the the first one is optional * Web server: EXPERIMENTAL user configuration files, with restricted possibilities (for security reasons) * Web server: IPv6 support * Deflatemod: now possible to filter on file extensions * Eliom: new option to keep GET non-attached parameters or not when doing a POST form towards a non-attached coservice. * Eliom: bugfix path of session cookies * Eliom: bugfix POST non-attached coservices called from a page with non-attached GET parameters were not found. * Lwt: now catching exceptions raised after timeouts * Cgimod: bufixes in path handling * Web server: bugfix - some files were not closed ===== 0.99.4 (2007-11-21) ===== * Ocsigen: Changes in the extension mechanism. The extensions are not tried in the order in which they are loaded any more, but in the order in which the options are specified for each site in the configuration file. * New experimental extension: access control * A few small enhancements ** Eliom: internal cookie management rewritten (+ bugfix) ** Eliom: Small changes in function names ** Eliom: now retry all extensions after actions (not only Eliom) ** Eliom: cleaning {{{Eliommod}}} interface ** Ocsigen server: Internal changes in server (removing "send" functions, debug messages lazier) ** Lwt: Adding a few functions in {{{Lwt_chan}}} interface ** Staticmod: Allowing to personalize default error pages for HTTP errors ** Ocsipersist (dbm and sqlite): better handling of database errors ** XHTML: New pretty printer for xhtml using streams (up to 15% speedup on requests) ** XHTML: Allowing any value for {{{}}} rel attribute (for example {{{shortcut icon}}}). ===== 0.99.3 (2007-11-07) ===== * Ocsigen: New module Deflatemod to compress data before sending to the browser. * Ocsigen: EXPERIMENTAL - New module Revproxy (reverse proxy). * Eliom: New session mechanism, with the ability to name the sessions and thus have several sessions for the same site. * Eliom: Now possible to have one site with session inside a subdirectory of another one. * Lwt: New module {{{Lwt_timeout}}} to implement timeouts, new module {{{Lwt_chan}}}, new module {{{Lwt_mutex}}}, new function {{{Lwt_unix.abort}}} to make all threads waiting on a file descriptor abort with an exception. * Ocsigen: New implementation of lots of Web server internals. Better management of Ocsigen's streams, file descriptors, exceptions, timeouts ... * A lot of enhancements and bug fixes: ** Eliom: Single {{{}}} in forms, by Stéphane Dalmas * EXPERIMENTAL: The Web server is now extensible. It means that you can add modules (like Apache modules) for generating pages, filters of requests, extensions of config files. For now there are two modules, one for static pages, and one for dynamic pages. The only changes for users is that they need to dynlink staticmod.cmo and ocsigenmod.cma from the configuration file. The syntax of config file for modules and staticdir also changed. * It is now possible to specify the encoding of characters for each sub-site. * Now usable with Ocamlnet 2.2 or 1.1.2. * EXPERIMENTAL: If OCamlDuce is installed on your system, you can now use it to do the type-checking of your pages (see the documentation). Warning: This is broken with OCamlDuce 3.09.2 patch level 2. You need at least OCamlDuce 3.09.3 patch level 1. * Removing Ocsimore from the default distribution. That version of Ocsimore is not supported anymore. Ocsimore has been rewritten from scratch by Piero Furiesi. ===== 0.5.1 (2006-12-14) ===== * Bugfix Konqueror: Multipart forms with now work correctly with Konqueror * Bugfix Internet Explorer: getting around a bug of Internet Explorer while displaying page * Bugfix NetBSD: Makefile * Bugfix Debian for HPPA, Mips, Alpha: Makefile * Bugfix: preemptive.cmi was missing in the installation directory * Adding manpage (S. Mimram) * Adding logrotate configuration * Daemon mode: adding setsid and redirect stdout/stderr to /dev/null. Closing stdin. ===== 0.5.0 (2006-11-23) ===== * HTTP 1.1 improved (HEAD, ETag, keep-alive implemented, If-Modified-Since, ...) * HTTPS support * Pipelining of requests * Server can listen on several ports * Multiple servers: you can now define several servers in the config file. * Virtual hosts: filtering on hostnames/ports (with wildcards) * Asynchronous file upload with multipart support * Large file transfer improved. * MIME types are now parsed from a file * Changes in the syntax of config file * Accessors for server parameters. Use ({{{get_user_agent sp}}}) instead of {{{sp.user_agent}}}. * Page generation is now using {{{Lwt}}} cooperative threads, to make it possible the generation of several pages at the same time. Practically, add {{{Lwt.return}}} before the page you want to send, and use cooperative input/output functions. * Typing errors of parameters are now catchable. * {{{static_dir}}} is now a function * Most of global references have been removed. You now need to give sp as parameter to {{{register_for_session}}}, {{{static_dir}}}, {{{close_session}}}, etc. * Links and forms now take {{{server_params}}} instead of {{{current_url}}} ({{{sp}}} is shorter than {{{sp.current_url}}}) * EXPERIMENTAL: Use of preemptive threads for non cooperative libraries ({{{detach}}} function). * EXPERIMENTAL: The {{{Ocsigen}}} module now contains a functor {{{Make}}} to allows the use of several ways of generating XHTML. The default way (using {{{XHTML.M}}} or the syntax extension) can be used by doing {{{open Ocsigen.Xhtml}}}. There is also an untyped xhtml generation module called {{{Ocsigen.Text}}}. * EXPERIMENTAL: extension of forms. * Reorganisation of the code * Bugfixes in makefiles * Bugfix: escaping of strings in xhtml with syntax extension (thanks to David Mentre) ===== 0.4.0 (2006-06-06) ===== * Full reimplementation of the core using Generalized Algebraic Data Types, * {{{_int}}}, {{{_string}}}, etc. are now called {{{int}}}, {{{string}}}, etc. * The type {{{_http_params}}} is now called {{{server_params}}}, * Services functions now all take 3 parameters, one for server parameters, one for GET parameters, and one for POST parameters. Note that {{{**}}} is used to create **pairs** and not tuples. * The {{{a}}} and {{{post_form}}} functions now take a fix number of parameters, corresponding to GET parameters. * //URLs// are now called //services//, * //state URLs// are now called //auxiliary services//, * {{{register_post_url}}} does not exist anymore. use {{{register_service}}} instead (idem for all other {{{register_post_*}}} functions). * Changes for prefix URLs * Small changes for actions * EXPERIMENTAL: sums, bool and list types for services and forms * small bugfixes ===== 0.3.27 (2006-04-27) ===== * Change the way to get server parameters ===== 0.3.26 ===== * Load unsafe modules * Other small changes ===== 0.3.25-2 (2006-02-24) ===== * Small bugfix for 64 bits processors * bugfix for static files * {{{action_link}}} is now called {{{action_a}}} ===== 0.3.24 (2006-02-07) ===== * More documentation * Change types {{{internal_url}}} and {{{external_service}}} to use polymorphic variants ===== 0.3.23 (2006-02-07) ===== * Better handling of static files and "403 Forbidden" message ocsigenserver-5.0.1/COPYING000066400000000000000000000654371417255654100154570ustar00rootroot00000000000000This program is released under the LGPL version 2.1 (see the text below) with the additional exemption that compiling, linking, and/or using OpenSSL is allowed. As a special exception to the GNU Library General Public License, you may also link, statically or dynamically, a "work that uses the Library" with a publicly distributed version of the Library to produce an executable file containing portions of the Library, and distribute that executable file under terms of your choice, without any of the additional requirements listed in clause 6 of the GNU Library General Public License. By "a publicly distributed version of the Library", we mean either the unmodified Library, or a modified version of the Library that is distributed under the conditions defined in clause 3 of the GNU Library General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Library General Public License. GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ocsigenserver-5.0.1/LICENSE000066400000000000000000000004131417255654100154100ustar00rootroot00000000000000The Ocsigen application core, and other portions of the official Ocsigen distribution not explicitly licensed otherwise, are licensed under the GNU LESSER GENERAL PUBLIC LICENSE with openssl linking exception -- see the 'COPYING' file in this directory for details. ocsigenserver-5.0.1/Makefile000066400000000000000000000115041417255654100160460ustar00rootroot00000000000000include Makefile.options include Makefile.config ### Building .PHONY: default all default all: build .PHONY: build build: ${MAKE} -C src doc: $(MAKE) -C doc ### Testing : local execution and toplevel ### .PHONY: run.local run.opt.local top run.local: build install.files CAML_LD_LIBRARY_PATH=${BLD}/server:$(CAML_LD_LIBRARY_PATH) ${BLD}/ocsigenserver.bc -c local/etc/ocsigenserver.conf run.opt.local: build install.files CAML_LD_LIBRARY_PATH=${BLD}/server:$(CAML_LD_LIBRARY_PATH) ${BLD}/ocsigenserver.exe -c local/etc/ocsigenserver.conf top: cd src/server && ${MAKE} top ### Cleaning ### clean: clean.local ${MAKE} -C src clean clean.local: -rm -f ocsigenserver-*.tar.gz distclean: clean.local ${MAKE} -C src distclean -make -C doc clean -rm Makefile.config -rm -f *~ \#* .\#* ### Installation #### .PHONY: purge.files install.files # BB If install is not run by root but OCSIGENUSER, OCSIGENGROUP is somebody # BB different, make files universally accessible, we cannot chown. INSTALL_CAN_PUT_PERMISSIONS=yes INSTALL_USER_GROUP=-o $(OCSIGENUSER) -g "$(OCSIGENGROUP)" INSTALL_MOD_660=660 INSTALL_MOD_644=644 INSTALL_MOD_755=755 INSTALL_MOD_770=770 INSTALL_MOD_750=750 USERNAME=$(shell whoami) ifneq ($(shell id -u), 0) ifneq ($(OCSIGENUSER), $(USERNAME)) INSTALL_CAN_PUT_PERMISSIONS=no endif ifneq ($(shell groups ${USERNAME}|grep -q ${OCSIGENGROUP}; echo $$?), 0) INSTALL_CAN_PUT_PERMISSIONS=no endif endif ifeq ($(INSTALL_CAN_PUT_PERMISSIONS), no) INSTALL_USER_GROUP= INSTALL_MOD_660=666 INSTALL_MOD_644=666 INSTALL_MOD_755=777 INSTALL_MOD_770=777 INSTALL_MOD_750=777 endif install.files: @echo @echo "## Run \"make doc\" and \"make install.doc\" to build and install the ocamldoc." @echo INSTALL_CAN_PUT_PERMISSIONS: ${INSTALL_CAN_PUT_PERMISSIONS} ## Command pipe $(INSTALL) -m ${INSTALL_MOD_755} -d $(dir $(TEMPROOT)$(COMMANDPIPE)) [ -p $(TEMPROOT)$(COMMANDPIPE) ] || \ { mkfifo -m ${INSTALL_MOD_660} $(TEMPROOT)$(COMMANDPIPE); \ if [ "${INSTALL_CAN_PUT_PERMISSIONS}" = yes ]; \ then $(CHOWN) -R $(OCSIGENUSER):"$(OCSIGENGROUP)" $(TEMPROOT)$(COMMANDPIPE); \ fi; } ## Configuration files $(INSTALL) -m ${INSTALL_MOD_755} -d $(TEMPROOT)$(CONFIGDIR)/conf.d ${INSTALL} -m ${INSTALL_MOD_644} ocsigenserver.conf.sample $(TEMPROOT)$(CONFIGDIR)/ [ -f $(TEMPROOT)$(CONFIGDIR)/ocsigenserver.conf ] || \ { $(INSTALL) -m ${INSTALL_MOD_644} ocsigenserver.conf.sample \ $(TEMPROOT)$(CONFIGDIR)/ocsigenserver.conf; } -mv $(TEMPROOT)$(CONFIGDIR)/mime.types $(TEMPROOT)$(CONFIGDIR)/mime.types.old ## Log directory $(INSTALL) -m ${INSTALL_MOD_644} src/files/mime.types $(TEMPROOT)$(CONFIGDIR) $(INSTALL) -d -m ${INSTALL_MOD_755} ${INSTALL_USER_GROUP} $(TEMPROOT)$(LOGDIR) ## Static files $(INSTALL) -d -m ${INSTALL_MOD_755} ${INSTALL_USER_GROUP} $(TEMPROOT)$(STATICPAGESDIR) $(INSTALL) -d -m ${INSTALL_MOD_750} ${INSTALL_USER_GROUP} $(TEMPROOT)$(DATADIR) $(INSTALL) -m ${INSTALL_MOD_644} ${INSTALL_USER_GROUP} \ local/var/www/*.html $(TEMPROOT)$(STATICPAGESDIR) $(INSTALL) -d -m ${INSTALL_MOD_755} ${INSTALL_USER_GROUP} \ $(TEMPROOT)$(STATICPAGESDIR)/ocsigenstuff $(INSTALL) -m ${INSTALL_MOD_644} ${INSTALL_USER_GROUP} \ local/var/www/ocsigenstuff/*.png local/var/www/ocsigenstuff/*.css \ $(TEMPROOT)$(STATICPAGESDIR)/ocsigenstuff $(INSTALL) -d -m ${INSTALL_MOD_755} $(TEMPROOT)$(MANDIR) $(INSTALL) -m ${INSTALL_MOD_644} src/files/ocsigenserver.1 $(TEMPROOT)$(MANDIR) uninstall: -make -C doc uninstall -rm -f $(TEMPROOT)$(CONFIGDIR)/ocsigenserver.conf.sample -rm -f $(TEMPROOT)$(MANDIR)/ocsigenserver.1 -rm -f $(TEMPROOT)$(COMMANDPIPE) -rmdir --ignore-fail-on-non-empty $(TEMPROOT)$(CONFIGDIR)/conf.d -rmdir --ignore-fail-on-non-empty $(TEMPROOT)$(CONFIGDIR) -rmdir --ignore-fail-on-non-empty $(TEMPROOT)$(LOGDIR) -rmdir --ignore-fail-on-non-empty $(TEMPROOT)$(DATADIR) -rmdir --ignore-fail-on-non-empty $(TEMPROOT)$(MANDIR) purge: purge.files purge.files: -rm -f $(TEMPROOT)$(CONFIGDIR)/mime.types $(TEMPROOT)$(CONFIGDIR)/mime.types.old -rm -f $(TEMPROOT)$(CONFIGDIR)/ocsigenserver.conf -rm -f $(patsubst local/var/www/ocsigenstuff/%, \ $(TEMPROOT)$(STATICPAGESDIR)/ocsigenstuff/%, \ $(wildcard local/var/www/ocsigenstuff/*)) -rmdir --ignore-fail-on-non-empty $(TEMPROOT)$(STATICPAGESDIR)/ocsigenstuff -rm -f $(patsubst local/var/www/%, \ $(TEMPROOT)$(STATICPAGESDIR)/%, \ $(wildcard local/var/www/*.html)) -rmdir --ignore-fail-on-non-empty $(TEMPROOT)$(STATICPAGESDIR) install.doc: ${MAKE} -C doc install ### Install logrotate configuration files ### .PHONY: logrotate logrotate: $(INSTALL) -m 755 -d $(TEMPROOT)/etc/logrotate.d cat src/files/logrotate.in \ | sed s%LOGDIR%$(LOGDIR)%g \ | sed s%USER%$(OCSIGENUSER)%g \ | sed s%GROUP%"$(OCSIGENGROUP)"%g \ | sed s%_COMMANDPIPE_%$(COMMANDPIPE)%g \ > $(TEMPROOT)/etc/logrotate.d/ocsigenserver ocsigenserver-5.0.1/Makefile.dist000066400000000000000000000021011417255654100170010ustar00rootroot00000000000000 ## ## Usage: ## ## If the released version is tagged in the main repository, use: ## ## make -f Makefile.dist ## ## If the tag has not been pushed, use: ## ## make -f Makefile.dist REPO=${PWD} ## ## otherwise, use: ## ## make -f Makefile.dist REPO=${PWD} VERSION=master ## #VERSION?=$(shell grep Version: _oasis | cut -d ' ' -f 2) VERSION=$(shell cat VERSION) REPO?=https://github.com/ocsigen/ocsigenserver all: dist sign dist: @rm -rf ocsigenserver-${VERSION} \ ocsigenserver-${VERSION}.tar.gz \ ocsigenserver-${VERSION}.tar.gz.asc git clone --local -b ${VERSION} ${REPO} ocsigenserver-${VERSION} # oasis -C ocsigenserver-${VERSION} setup # sed -i "s/SETUP := setup-dev.exe/SETUP := setup.exe/" \ # ocsigenserver-${VERSION}/Makefile cd ocsigenserver-${VERSION} && rm -rf .git .gitignore Makefile.dist tar cvzf ocsigenserver-${VERSION}.tar.gz ocsigenserver-${VERSION} @rm -rf ocsigenserver-${VERSION} sign: ocsigenserver-${VERSION}.tar.gz.asc ocsigenserver-${VERSION}.tar.gz.asc: ocsigenserver-${VERSION}.tar.gz gpg --armor -b $^ .PHONY: dist sign ocsigenserver-5.0.1/Makefile.options000066400000000000000000000030421417255654100175360ustar00rootroot00000000000000THREAD := -thread BLD=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))_build/default/src INCS= -I ${BLD}/server/.ocsigenserver.objs/byte \ -I ${BLD}/http/.http.objs/byte \ -I ${BLD}/http/.ocsigen_cookie_map.objs/byte \ -I ${BLD}/baselib/.baselib.objs/byte \ -I ${BLD}/baselib/.ocsigen_lib_base.objs/byte \ -I ${BLD}/baselib/polytables/.polytables.objs/byte \ -I ${BLD}/extensions/.accesscontrol.objs/byte \ -I ${BLD}/extensions/.authbasic.objs/byte \ -I ${BLD}/extensions/.cors.objs/byte \ -I ${BLD}/extensions/.extendconfiguration.objs/byte \ -I ${BLD}/extensions/.outputfilter.objs/byte \ -I ${BLD}/extensions/.redirectmod.objs/byte \ -I ${BLD}/extensions/.revproxy.objs/byte \ -I ${BLD}/extensions/.rewritemod.objs/byte \ -I ${BLD}/extensions/.staticmod.objs/byte \ -I ${BLD}/extensions/.userconf.objs/byte \ -I ${BLD}/extensions/deflatemod/.deflatemod.objs/byte ## ${SERVER_PACKAGE} is not only used to build the 'ocsigenserver' executable ## but also to generate src/baselib/ocsigen_config_static.ml SERVER_PACKAGE := lwt_ssl,bytes,lwt.unix,lwt_log,ipaddr,findlib,cryptokit,pcre,str,xml-light,dynlink,cohttp-lwt-unix,hmap LIBS := -package ${SERVER_PACKAGE} ${INCS} INITPACKAGE := \"$(shell ${OCAMLFIND} query -p-format -recursive \ -separator '\";\"' ${SERVER_PACKAGE})\"; \ \"ocsigenserver.polytables\"; \ \"ocsigenserver.cookies\"; \ \"ocsigenserver.baselib.base\"; \ \"ocsigenserver.baselib\"; \ \"ocsigenserver.http\"; \ \"ocsigenserver\"; \ ocsigenserver-5.0.1/README.md000066400000000000000000000047701417255654100156740ustar00rootroot00000000000000Ocsigen server ------------------------------------------------------------------ Build instructions: =================== * run "sh configure [options]" to generate 'Makefile.config' - For the full list of options, run "sh configure --help". * verify that 'Makefile.config' suits to your needs. * run "make" to compile * [optional] run "make logrotate" as root to install logrotate configuration files in /etc/logrotate.d * [optional] run "make doc" to build the ocamldoc * run "make purge" to uninstall everything (even configuration files) ------------------------------------------------------------------ Local testings: =============== * run "make run.local" or "make run.opt.local" in the ocsigen source directory. * open http://localhost:8080/index.html in your browser * if it does not work, look at the logs (see 'local/var/log/' in the ocsgigen source directory) or run ocsigen with options -v. ------------------------------------------------------------------ Authors: ======== * Vincent Balat (project leader, Web server, Ocsigenmod, Eliom, Eliom client, Staticmod, XHTML syntax extension, documentation, Ocsimore, extension mechanism, Ocsidbm, Ocsipersist with DBM, ...) * Jérôme Vouillon (Lwt, Web server, js_of_ocaml, O'Closure, ...) * Boris Yakobowski (Ocsimore, module Extendconfiguration, Ocsigen server...) * Benjamin Canou (O'Browser) * Jérémie Dimino (Lwt) * Raphaël Proust (Ocsforge, Eliom client, Comet) * Stéphane Glondu (Configuration file, Findlib integration, access control, HTTP authentication, Debian package, ...) * Gabriel Kerneis (XHTML syntax extension for OCaml 3.10, Ocsipersist with SQLite, CGI module, forms in Eliom, deflatemod, ...) * Denis Berthod (HTTP protocol, Web server) * Grégoire Henry (safe unmarshalling of client data) * Pierre Chambart (Comet) * Jaap Boender (Ocsimore, NetBSD and Godi packages) * Gabriel Scherer (Macaque) * Gabriel Cardoso (O'Closure) * Jean-Henri Granarolo (Ocsforge) * Simon Castellan (HTML5, OpenID, SVG) * Piero Furiesi (Ocsimore) * Thorsten Ohl (most of the functions generating XHTML (xML and xHTML modules)) * Mauricio Fernandez (Xhtmlcompact, static linking of extensions and Eliom modules) * Nataliya Guts (Web server, HTTPS) * Archibald Pontier (Atom, Pubsubhubbub) * Jérôme Velleine (CGI module) * Charles Oran (O'Closure) * Pierre Clairambault (Lwt_lib, Gentoo package, configure script, ...) * Cécile Herbelin (HTML5, Benchmarks) * Jan Rochel (Ocsipersist) ocsigenserver-5.0.1/VERSION000066400000000000000000000000061417255654100154510ustar00rootroot000000000000004.0.1 ocsigenserver-5.0.1/configure000077500000000000000000000266741417255654100163330ustar00rootroot00000000000000#! /bin/sh # Adapted from the ocamlnet configure script. ####################################################################### # Helpers: test_binary () { # $1: the name of the binary echo -n "Checking for $1 ... " if command -v "$1" >/dev/null 2>/dev/null; then echo "found" return 0 else echo "not found" return 1 fi } fail_binary () { echo echo "Required command '$1' not found!" [ -z "$2" ] || echo "===> $2" exit 1 } check_binary () { # $1: the name of the binary # $2: an URL if test_binary $1; then return else fail_binary $1 $2 fi } test_library () { # $1: the name of the library (findlib) echo -n "Checking for $1 ... " if ocamlfind query $1 >/dev/null 2>/dev/null; then echo "found" return 0 else echo "not found" return 1 fi } fail_library () { echo echo "Required library $1 not found!" [ -z "$2" ] || echo "===> $2" exit 1 } check_library () { # $1: the name of the library (findlib) # $2: an URL if test_library $1; then return else fail_library $1 "$2" fi } ####################################################################### # Defaults #--- Options --- # value 0: off # value 1: on # defaults: set_defaults () { with_sqlite=1 with_pgsql=1 with_dbm=1 prefix="/usr/local" bindir="" logdir="" libdir="" mandir="" docdir="" sysconfdir="/etc/ocsigenserver" staticpagesdir="/var/www/ocsigenserver" uploaddir="/tmp" datadir="/var/lib/ocsigenserver" temproot="local" root="" ocsigen_user="www-data" ocsigen_group="www-data" } set_defaults my_pwd=`dirname $0` version=`head -n 1 $my_pwd/VERSION` full_pwd=`pwd` ######################################################################## ## Option parsing ## Which options exist? eoptions for enable/disable, woptions for with/without: eoptions="" woptions="pgsql sqlite dbm" print_options () { for opt in $eoptions; do e="o=\$enable_$opt" eval "$e" uopt=`echo $opt | sed -e 's/_/-/g'` if [ $o -gt 0 ]; then echo " --enable-$uopt" else echo " --disable-$uopt" fi done for opt in $woptions; do e="o=\$with_$opt" eval "$e" uopt=`echo $opt | sed -e 's/_/-/g'` if [ $o -gt 0 ]; then echo " --with-$uopt" else echo " --without-$uopt" fi done case "$bindir" in "") bindir2="/bin";; *) bindir2=$bindir;; esac case "$logdir" in "") logdir2="/var/log/";; *) logdir2=$logdir;; esac case "$libdir" in "") libdir2="\$(shell \${OCAMLFIND} printconf destdir)";; *) libdir2=$libdir;; esac case "$mandir" in "") mandir2="/share/man/man1";; *) mandir2=$mandir;; esac case "$docdir" in "") docdir2="/share/doc/ocsigenserver";; *) docdir2=$docdir;; esac echo " --name $name" echo " --root $root" echo " --temproot $temproot" echo " --prefix $prefix" echo " --ocsigen-user $ocsigen_user" echo " --ocsigen-group $ocsigen_group" echo " --bindir $bindir2" echo " --libdir $libdir2" echo " --sysconfdir $sysconfdir" echo " --mandir $mandir2" echo " --docdir $docdir2" echo " --logdir $logdir2" echo " --staticpagesdir $staticpagesdir" echo " --uploaddir $uploaddir" echo " --datadir $datadir" echo " --commandpipe $commandpipe" } usage () { set_defaults cat <<_EOF_ >&2 usage: ./configure [ options ] --name NAME The name of the server binary and ocamlfind package. --ocsigen-user NAME The name of the ocsigen user --ocsigen-group NAME The name of the ocsigen group --root DIR Root directory to install the package, every other options are relatives to this path. (usually /) --temproot DIR Temporary root directory to install the package (usually always "" but for package makers) --prefix DIR Subdirectory where to install binaries and libs (usually /usr or /usr/local) --bindir DIR Install binaries into this directory --libdir DIR Common directory for Ocsigen server's libraries --sysconfdir DIR Create configuration files in this directory --mandir DIR Install man pages in this directory --docdir DIR Install documentation in this directory --logdir DIR Use this directory for Ocsigen's logs --datadir DIR The directory for data written by the server --staticpagesdir DIR Install default static pages in this directory --uploaddir DIR By default, files will be uploaded in this directory --commandpipe FILE The name of the named pipe used to command the server Defaults are: _EOF_ print_options >&2 exit 1 } check_eopt () { for x in $eoptions; do if [ "$x" = "$1" ]; then return 0 fi done echo "Unknown option: $1" >&2 exit 1 } check_wopt () { for x in $woptions; do if [ "$x" = "$1" ]; then return 0 fi done echo "Unknown option: $1" >&2 exit 1 } echo "\n\tWelcome to Ocsigen server, version $version.\n" >&2 while [ "$#" -gt 0 ]; do case "$1" in --enable-*) opt=`echo "$1" | sed -e 's/--enable-//' -e 's/-/_/g'` check_eopt "$opt" eval "enable_$opt=2" shift ;; --disable-*) opt=`echo "$1" | sed -e 's/--disable-//' -e 's/-/_/g'` check_eopt "$opt" eval "enable_$opt=-1" shift ;; --with-*) opt=`echo "$1" | sed -e 's/--with-//' -e 's/-/_/g'` check_wopt "$opt" eval "with_$opt=2" shift ;; --without-*) opt=`echo "$1" | sed -e 's/--without-//' -e 's/-/_/g'` check_wopt "$opt" eval "with_$opt=-1" shift ;; --root) root="$2" shift shift ;; --temproot) temproot="$2" shift shift ;; --prefix) prefix="$2" shift shift ;; --bindir) bindir="$2" shift shift ;; --logdir) logdir="$2" shift shift ;; --libdir) libdir="$2" shift shift ;; --mandir) mandir="$2" shift shift ;; --docdir) docdir="$2" shift shift ;; --staticpagesdir) staticpagesdir="$2" shift shift ;; --sysconfdir) sysconfdir="$2" shift shift ;; --uploaddir) uploaddir="$2" shift shift ;; --datadir) datadir="$2" shift shift ;; --name) name="$2" shift shift ;; --ocsigen-user) ocsigen_user="$2" shift shift ;; --ocsigen-group) ocsigen_group="$2" shift shift ;; --commandpipe) commandpipe="$2" shift shift ;; *) echo "Unknown option: $1" >&2 usage esac done case "$bindir" in "") bindir="$prefix/bin";; esac case "$logdir" in "") logdir="/var/log/ocsigenserver";; esac case "$libdir" in "") libdir="\$(shell \${OCAMLFIND} printconf destdir)";; *) libdir=$root$libdir esac case "$mandir" in "") mandir="$prefix/share/man/man1";; esac case "$docdir" in "") docdir="$prefix/share/doc/ocsigenserver";; esac case "$commandpipe" in "") commandpipe="/var/run/ocsigenserver_command";; esac check_binary ocamlc "See: http://www.ocaml.org/" check_ocamlversion () { echo -n "Checking for OCaml version... " version=`ocamlc -version` echo $version n1=`echo $version | sed 's/^\([0-9][0-9]*\)\..*$/\1/'` n2=`echo $version | sed 's/^[0-9][0-9]*\.\([0-9][0-9]*\)\..*$/\1/'` # n3=`echo $version | sed 's/^[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\)\..*$/\1/'` if [ $n1 -eq 3 ] && [ $n2 -lt 12 ]; then echo; echo "OCaml >= 3.12 is required. Aborting."; exit 1; fi } check_ocamlversion check_binary ocamlfind "See: http://projects.camlcity.org/projects/findlib.html" check_library cohttp "See: https://github.com/mirage/ocaml-cohttp" check_library cohttp-lwt-unix "Missing support for 'lwt' in cohttp." check_library react "See: http://erratique.ch/software/react" check_library ssl "See: http://sourceforge.net/projects/savonet/files/ocaml-ssl" check_library lwt "See: http://ocsigen.org/lwt" check_library lwt.unix "Missing support for 'unix' in lwt." check_library lwt_react "See: http://ocsigen.org/lwt" check_library lwt_ssl "See: http://ocsigen.org/lwt" check_library lwt_log "See: http://ocsigen.org/lwt" check_library pcre "See: http://ocaml.info/home/ocaml_sources.html" check_library cryptokit "See: http://pauillac.inria.fr/~xleroy/software.html#cryptokit" check_library xml-light "See: https://github.com/ncannasse/xml-light" # Check PostgreSQL case "$with_pgsql" in 1) if test_library pgocaml; then with_pgsql=1; else with_pgsql=0; fi;; 2) check_library pgocaml "https://github.com/darioteixeira/pgocaml";; esac # Check Sqlite3 case "$with_sqlite" in 1) if test_library sqlite3; then with_sqlite=1; else with_sqlite=0; fi;; 2) check_library sqlite3 "See: http://ocaml.info/home/ocaml_sources.html";; esac # Check dbm if [ "$with_dbm" -gt 0 ]; then if test_library dbm; then echo -n elif [ "$with_dbm" -gt 1 ]; then fail_library dbm else with_dbm=0 fi fi # Check rlwrap or ledit if test_binary rlwrap; then rlwrap=rlwrap elif test_binary ledit; then rlwrap=ledit else rlwrap= fi ###################################################################### # Summary echo echo "Effective options:" print_options echo #Convert 0/1 values to YES/NO if [ $with_dbm -gt 0 ] ; then with_dbm="YES" else with_dbm="NO" fi if [ $with_sqlite -gt 0 ] ; then with_sqlite="YES" else with_sqlite="NO" fi if [ $with_pgsql -gt 0 ] ; then with_pgsql="YES" else with_pgsql="NO" fi ocamlinclude=`ocamlfind printconf stdlib` ###################################################################### # Write Makefile.conf echo "Writing Makefile.config" cat <<_EOF_ > $my_pwd/Makefile.config #### External binaries #### OCAMLFIND := ocamlfind OCAMLLEX := ocamllex OCAMLMKLIB:= ocamlmklib CHOWN := chown CHMOD := chmod INSTALL := install CC := gcc # optional RLWRAP := $rlwrap ### Options ### # User who will run Ocsigen server (not root) (eg, for debian, www-data) # (This user must exist on your system) OCSIGENUSER := $ocsigen_user # group who will run Ocsigen server (not root) (eg, for debian, www-data) # (This group must exist) OCSIGENGROUP := $ocsigen_group ### Paths ### # Temporary root directory to install the package (usually always "" but for package makers) TEMPROOT := $temproot # The directory for ocsigen server (binary): BINDIR := $root$bindir # The directory for ocsigen manpage: MANDIR := $root$mandir # Where to install the libraries LIBDIR := $libdir # ocsigen's logs: LOGDIR := $root$logdir # Config files: CONFIGDIR := $root$sysconfdir # Where to put static pages: STATICPAGESDIR := $root$staticpagesdir # Where to put dynamic data: DATADIR := $root$datadir # Default directory for file upload: UPLOADDIR := $root$uploaddir # Where to put Ocsigen documentation: DOCDIR := $root$docdir # The name of the named pipe used to command the server COMMANDPIPE := $root$commandpipe # The source directory SRC := $full_pwd include \$(SRC)/Makefile.options _EOF_ ###################################################################### # Finish echo echo echo "Please check Makefile.config." echo echo "You can now compile Ocsigen Server by invoking:" echo echo " make" echo " make doc" echo echo "You may test the server by invoking:" echo echo " make run.local" echo " make run.opt.local" echo ocsigenserver-5.0.1/doc/000077500000000000000000000000001417255654100151525ustar00rootroot00000000000000ocsigenserver-5.0.1/doc/Makefile000066400000000000000000000035701417255654100166170ustar00rootroot00000000000000include ../Makefile.config include ../Makefile.options OCAMLDOC := ${OCAMLFIND} ocamldoc ODOC_WIKI := odoc_wiki.cma DOC := baselib/ocsigen_cache.mli \ baselib/ocsigen_lib_base.mli \ baselib/ocsigen_lib.mli \ baselib/ocsigen_config_static.mli \ baselib/ocsigen_stream.mli \ baselib/ocsigen_loader.mli \ baselib/polytables/polytables.mli \ \ http/ocsigen_charset_mime.mli \ http/ocsigen_cookie_map.mli \ http/ocsigen_header.mli \ \ server/ocsigen_config.mli \ server/ocsigen_request.mli \ server/ocsigen_response.mli \ server/ocsigen_messages.mli \ server/ocsigen_multipart.mli \ server/ocsigen_extensions.mli \ server/ocsigen_parseconfig.mli \ server/ocsigen_local_files.mli \ server/ocsigen_server.mli PLUGINS_DOC := extensions/accesscontrol.mli extensions/authbasic.mli \ extensions/outputfilter.mli \ extensions/redirectmod.mli extensions/staticmod.mli \ extensions/deflatemod/deflatemod.mli all: doc wikidoc doc: api-html/index.html api-html/index.html: indexdoc $(addprefix ../src/,$(DOC) $(PLUGINS_DOC)) mkdir -p api-html $(OCAMLDOC) ${LIBS} -d api-html -intro indexdoc -html $(addprefix ../src/,$(DOC) $(PLUGINS_DOC)) wikidoc: api-wiki/index.wiki api-wiki/index.wiki: indexdoc $(addprefix ../src/,$(DOC) $(PLUGINS_DOC)) mkdir -p api-wiki $(OCAMLDOC) ${LIBS} -d api-wiki -intro indexdoc -colorize-code \ -i $(shell ocamlfind query wikidoc) -g ${ODOC_WIKI} \ $(addprefix ../src/,$(DOC) $(PLUGINS_DOC)) install: ${INSTALL} -d -m 755 $(TEMPROOT)$(DOCDIR) $(INSTALL) -m 644 api-html/* $(TEMPROOT)$(DOCDIR) uninstall: -rm -Rf $(TEMPROOT)$(DOCDIR) clean: -rm -f api-html/* api-wiki/* -rm -f *~ \#* .\#* ocsigenserver-5.0.1/doc/indexdoc000066400000000000000000000006111417255654100166700ustar00rootroot00000000000000{1 Ocsigen server - API reference} {2 Persistent data, writing in the logs, configuration file extension, polymorphic tables} {!modules: Ocsigen_lib Ocsigen_messages Ocsigen_parseconfig Polytables Ocsigen_cache Ocsigen_config } {2 Extending Ocsigen Server} {!modules: Ocsigen_extensions Ocsigen_local_files Ocsigen_headers Ocsigen_stream Ocsigen_comet Authbasic } {2 Indexes} {!indexlist} ocsigenserver-5.0.1/dune-project000066400000000000000000000000451417255654100167260ustar00rootroot00000000000000(lang dune 2.7) (name ocsigenserver) ocsigenserver-5.0.1/format.sh000077500000000000000000000003241417255654100162330ustar00rootroot00000000000000#!/bin/bash echo "# Removing tabs" find ./ -regex "^\.\(/[a-zA-Z0-9_-.]*\)*.ml[il]?" -exec sed -i 's/ //g' {} \; echo "# Indent files" find ./ -regex "^\.\(/[a-zA-Z0-9_-.]*\)*.ml[il]?" -exec ocp-indent -i {} \; ocsigenserver-5.0.1/local/000077500000000000000000000000001417255654100154775ustar00rootroot00000000000000ocsigenserver-5.0.1/local/var/000077500000000000000000000000001417255654100162675ustar00rootroot00000000000000ocsigenserver-5.0.1/local/var/www/000077500000000000000000000000001417255654100171135ustar00rootroot00000000000000ocsigenserver-5.0.1/local/var/www/index.html000066400000000000000000000000601417255654100211040ustar00rootroot00000000000000

It works !

ocsigenserver-5.0.1/local/var/www/ocsigenstuff/000077500000000000000000000000001417255654100216125ustar00rootroot00000000000000ocsigenserver-5.0.1/local/var/www/ocsigenstuff/AUTHORS000066400000000000000000000014741417255654100226700ustar00rootroot00000000000000Oxygen Icon Theme has been developed by The Oxygen Team. Art Directors: Nuno F. Pinheiro David Vignoni Naming Coordinator Jakob Petsovits Designers: David J. Miller David Vignoni Johann Ollivier Lapeyre Kenneth Wimer Nuno F. Pinheiro Riccardo Iaconelli David J. Miller Thanks to: Lee Olson: Contributed drawing used in application-x-bittorent icon. Marco Aurélio "Coré": Improved audio-input-microphone icon. Matthias Kretz: Contributed "audio-input-line" device icon. Mauricio Piacentini : game icons mashup Erlend Hamberg: "text-x-haskell" mimetype icon. ocsigenserver-5.0.1/local/var/www/ocsigenstuff/COPYING000066400000000000000000000227241417255654100226540ustar00rootroot00000000000000The Oxygen Icon Theme Copyright (C) 2007 Nuno Pinheiro Copyright (C) 2007 David Vignoni Copyright (C) 2007 David Miller Copyright (C) 2007 Johann Ollivier Lapeyre Copyright (C) 2007 Kenneth Wimer Copyright (C) 2007 Riccardo Iaconelli and others This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . Clarification: The GNU Lesser General Public License or LGPL is written for software libraries in the first place. We expressly want the LGPL to be valid for this artwork library too. KDE Oxygen theme icons is a special kind of software library, it is an artwork library, it's elements can be used in a Graphical User Interface, or GUI. Source code, for this library means: - where they exist, SVG; - otherwise, if applicable, the multi-layered formats xcf or psd, or otherwise png. The LGPL in some sections obliges you to make the files carry notices. With images this is in some cases impossible or hardly useful. With this library a notice is placed at a prominent place in the directory containing the elements. You may follow this practice. The exception in section 5 of the GNU Lesser General Public License covers the use of elements of this art library in a GUI. kde-artists [at] kde.org ----- GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ocsigenserver-5.0.1/local/var/www/ocsigenstuff/back.png000066400000000000000000000013371417255654100232240ustar00rootroot00000000000000PNG  IHDRj sRGB pHYsϐtIME  \*5PLTE}}зɾ«Ϭβ𚚞 >,tRNS-::::::;;AABCCCDEpbKGDf,%IDATW[`з6,ljC$*?O. jlyQ'DLֵZ7*F-6uͺFS'm_kl6(J.i4Up>Mr `.Ǡ^smzV$IT ru@z ^I PBkVRy`u4 dV.Ki % OQ#ѷ46]9IENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/cdimage.png000066400000000000000000000020431417255654100237100ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME =6IDAT8˭k\U}=sfLgr/ZZ}A7AQ9'DYljE%ЇC ih;L&s?g0SmE\/Z\.A߂ hxx\zUtR"@Hc4[.vO9GeEZo΋Fk@JVK51H K Z::Gk#%R*6:pw29cZ+Xk89uXϧY[optM 'ڠBk1c.9Ze|Fyxah}qcmB!ƚQhR=`c K 9KlDm)x:xEdIv6 E^)3T5>gy1R<Ȳ,cFG !A ux]*%<ϑRl6T dyA##cH!͠BEchl6Z|0HSwy8PJ 44=["#2Μ>M"աgCgZRrKQlxֲoJt_gJ)RBզ{Akkz=66VmdSgݓed9snJUڵ/}| @c_O-"~M'ARVk (vyO>syE1$I8J0 H0\ŗ_]nڄw;7s)I Io0tssW>~گTn,ܢIp;˗/3Msc!Rrw~v{zNdՕƍ_e^:\Yvn޼>zӉ kȀE`U]lD!zIENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/deb.png000066400000000000000000000022001417255654100230440ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME 0-YIDAT8˭klU3QDTjՄ тEmTÈaL (D0"IE v)[+1䛜|yrwOE èTu=}aP7 T J!!`J!8 H)v${PTEQ*2c)4@ムU-T00qeBm=tYY85լ^^7>B4 b>"<8E>]]]=#(*.eY0qu&Y`(b)^ E(bqM|^l@X, mzK m\cp)>VzE 0-T:egʞIR52Bu3PTx(|zPPȉsY;igYnp|^^@*m5mN|WWӼv9t YLlU-3pu̘_!gD\<{|`P%.)$n# ssxiӦ8Cb*ѲbכWa{/-_Iutä$3`=t9;6Kw k8voa< Fmɥ˖=Oc7^hd q]rH|2s1iaY&ñc'܅?:,p Bm[d ::cMMC f.H&ͻI"4f2ttt$]IĿD+ⶱull6j,ۦĺX!$GC\J}jvݿ.[9Fy0 ekkYk]׿&;IENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/dvi.png000066400000000000000000000016351417255654100231070ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME +$["IDAT8˭k\E?3ĻUiw)>5iI/DJJQ ">ڒ E̺j^XCBeInsma{3~QAE@._(8+C=`j$DqR 5J'kA=ǎq;j5:kkkxD'yȑ>gscCVVVDDwsX|zܺySsO{f~BAt:{ĉ\zc"E<}JARK.AX l7?VqZR0H_P:;n0#"+WAy)r"RH{ iI3Oy2nZួ .xxD,CE\)>P#RRS߷_Jo/A{abkkk<63^ Aq|GgK11Οq£VzC>K33s=t&jHdIq1&ny9.wN^+(N?a ay9~ҥY2lDDΞ9#RY\| CY]]ɍCa@ 1ޥVa%s4yj199˗gW^Mv[wT(o澰a},L2Ϻ+MIENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/folder_open.png000066400000000000000000000010771417255654100246210ustar00rootroot00000000000000PNG  IHDRĴl;sBIT|d pHYsvv}ՂtEXtSoftwarewww.inkscape.org<IDATxՓ=kA<%'I; 6~!e>mA K"hr$)~ O 6hK Xڦt{n޾63>Ж[MqbIƇ]#e|q:k>6ZȱӃ4Zc;Ib>$_L} 5x~fx3}$[8<Ռ6 Z%ذgOة8Ҷ(2SEr3.X,8u Y"HUq.O)/HCMu[VsuH>_m ͅI .E7@KКe Sl d$2`.ИIS_Gof%f [S1YʼnN"#"JFt1ض |}]mM M6QF! QC>*qK)-cC\KJ#^ ~Q)5j Y( +vmD)<laU[O<&/?' gr\÷Ɖ ^l۾H)/?BήgKě`mKaȈedJ4|&)%2 8qT0رַ`R'u9L؊H-l }J3>|$I@5[gv.mc;ITlBvH*f4RI|ϣR.s>S*N, &v7ٹaBcj% 4T+{u"4@)Fml>;^mU|ٳA| sȶw};PJSBJUE2 Nu썢Rŭ--HJj7o0ΗKF/,T#S FIENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/image.png000066400000000000000000000016401417255654100234030ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME 97k IDAT8OhU1m&fZNl3T0QD+`,Vh;\BDu[] PQvT`8IRb4fu1X;Z+<{;5RT*d-(U1;uOevufX$X~} Ldo?N`T0j \W|rhO[!撚u9:2I(eū7)/2qT1.svN$ctdZsvfjyz-~/[E&/m$*#{5sOrjg_ܹK?z$5Ĩ**T]qϰ;X 7Ǥ ^}C@EUDATAl+-$J>y.fsWf =AQT,EŢ6" u(<֞;ї;&n}9೚ϱqMu/ \ch3G.--BP̳|Ôުm \¦"UqǩtzbږmC@E(]釶kE#QBDAH^CCDx:wh; XHi*FA!Zo&];<8}0_=H. c/~'EUQcP4u_~dǀWRy̶,APPT-tǏTGF\"^ PQiUhaÀ=|ѧGF<|WX?x4Z?W(f1upX\~9Z ~%IENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/ocsigen5.png000066400000000000000000001220041417255654100240330ustar00rootroot00000000000000PNG  IHDRX[ pHYs\F\FCAtIME 2):,tEXtCommentCreated with The GIMPd%n IDATx}yչYYWQ$w jܢ&5FQH47&13\ KLATT@afﭶ}Ꞟaf7LOSSϻkV8*V!  J9c2!w|BٶݲL"/y ]E֏x \8ΧJL[iJb#AU#ðRz>.2e%\R87|3缲kTb|~ pq]tqB2n L e;@ƺB./A1.)5-!QPST*RUiXS1POmnw5y,F(qʔ)k~z޼yb@9r00âIS:I$i;I IBYʽ,\xqŚ?wy(G]]N0Cܷd:eӁӾy䥡+~ر_|q;@*V݌PX 6rJuI!B U ޗW BJ|`3̊A80J}eA.\1.ho;SM*VAYi2qA?B/)uK)Br̞!!)ZCg=5;C?Q"qvuOP% V {˘>*+H*6tZ12&ܦܦN`M e28z9۔Ȧ@0y#F#Pf(C,u~WdW\qEG{'vUS*V!BpC9&!qLxz`aNX 0NQ ;5͜tɅd<]9F+@_Zx˲yVR 1:H\wM-0G{PƁ@ HcL 3b)͵#UlAQzg&}R>2YG(\Lg熺p(AG_JL&}h/h5k*J*6nLe,Z>.b[)!ŵ9bG KbNa%ݡW`_)VJ2gC%ڤ~p@F?ͥbD(iT{Rd ƹ䂄de38HWV//۞/*ʹYD́zR@?yЋ\*I:2,FG sʉ#=x@!׿^zR 2D( :2.h̲ ))uq,i2nmG`a`6e5 -A9Yk;*A43tA iUH@JjbU5h,Dxgk_ZG[reSSSegXtrd Y>8E%/ӅCI:B-f =6cˉ}$9De{CPTJ9#LCݴOj PPuMu5PPp@S1BSq}Mtx@8}aÆk4K/Te*VA Ӝڄ[۔ٔKn'e k3 h*VQ")*vȏ@ngD| N/ NCJ֨FHXK,JbcMUP*/PܦK5i+ F~brFYjUeǩX. vI3 Loz=:EAiiݒϜL.fuYrg|NI~<1ޏrΣa Bȹ@` aF}$RHY[w&:c(:0xe>l:@FDk=O# $4mj4|Г\EPĴܯ[P5yDAaB۔AAGy¯wivänٴa&9I#A%$!qӦE5+ a3C=}'bt0;4Ș-&ܴiSˢL+S5!+]<#aw7xT}EУ‰<6~u\Bt:QHkJyG=MҞٜє'͢ LZ6U AG܃!>;E w\ĉ Rf MɑA;]݀7}H7-(Ym)pW~t0w g")lݛ[OE 1@x[r\24>'SN-hׯl=DLq_c̲iSÅ@ӦY*}Mu8.h4nׄ1,94|"D =(ws_!U!@t{l I3*H@3,-:Dp}QT Nad2MԲpAfZtGMe1U fm3)H@UR6lJ9_ԃP H||&]1+!3x0\w(D+LQKCjjjZZZ2cl۶m \nݺW_}/`M8N:uj[U( YmJdM 65,jԉNLverdtPSq8QU nkNh02 eXx{Æ ڍ((̋ ھ dNЋzNQ$:#!\UQ2mmڱj]sK+<4X]u4cT3AO8Z3i=j  5jTGkooG{]{d/\2WwzʢxODʹ%&փܥ"GG**Nv"mq.4 J+1]R yW" mq}OC!Ç/hD% aÆݞ<ƍ+3{qq=6\` "^,Aud V0 D(X2m%V@Sʛ% !r $-r`$+]QVdo&%B(I*((DBpANQe"9A>'ST:DT04,mڛ|Ѯ̴缺*9\rզv^3 /F&-91Ckjjʹ@M1 }/+3;`\ a$M* Bs讚eHMD kЫAUUe=tAm> sPfrh Sf|^ N+c mەiO@ PVfPN($\&xO7n:]&lt%z,ݧjҜ (U!B{ Wf'e֔I!H1*Ӟ`_O22cNv weEutR˃@ʩ  u慜~ӢPP j{M'`>laoE*+pHa(Ίu׎9X,VJnT4=*3w(z((`$ 6,jXRPX傜 TU jBaI5L[iݎpPBPAw2W 55<0LsmdvU0ƕű'XUUR+{J 2 {(hXT7IڤiMD0mjfnOM3-E570FFGjBV ap L[Mma#5MA! ٌ?i 0B Fܚ2*(8TPQn5M,=n:1ӦM*sU^":`y'Gԉ f#ceEe32P\(n`wAcW͜6zĺP@VWH =Ҟl P0[?r!R6Qʓi--V 0| +)o-N0,=Ģ3F+sw((մ= ԰DALQђegNQBUq84*Fv.`MU4cTa@7@.mSٍ&/>*@8pj76z7|{cƌꪫ,XPy0*/ x=%d(06`I|Lڅ@ #EdxN^&Ȁ̑؄moJZ6 b&%cNeS˦~'oe@X<cTl[(Zh 7'HI&M6-;"(en]ƸJ I|((KF\:A_Lȑ)I.Tp9r*Uh>LE NQ&(w(n>#uÍ 梠&*:jAӢ@X+DX#!@jQ,ڤ'haemX=wѼl. % m a:`d@I#! Ah$LVJW*80F ƹEFCZ4 ei֣t:]FQY|X9R0'52IipI<)Q7X4`$bƹەER0 FqN9C$d ( .dcT[ Kvm̘1%X  z1^P7<)Qvc`N6zMŚ_z!Pf41)HRNCaB 3΁1n0*L[  ,cAq+VrAv*30bMM7ϋ1,fԔP7; 4T0CMUB%TCA5PTqӢBI>A!C"*ڑ.mq;5@h2@)mmmmkk3 Bx' JiKK˶mZZZi1iUUUcƌ5jTyᢶnݺ^{ @mq˲@ CHb1v R#ʜP|AAf*9U~d1 V3 JP VA(顖= CZ(Z!e%Ri9+p",0Li8:3j%B(~$3m1 h8P#a-AUS&\7 '̅  ؄BqHjΝ;_y7|sʕyNhtԩG}9s9+ڒN_{_vy^uUv'ɷ~7Xrg}}ΕºI&p3gΜ={ɓ{(@y1;١uڄ(% lj : jT떖Mvl4ݾZE8׌>ź݈M/EA5U hX2p.eaqm v}}'9ga2㚪`G0[o⍶/Knd$~ a56f5cFJ E B8ZᚊCA*Ţ0 .N0 "B4S}ǿe;Sm_W_|Eo4#7~w,'o;+[}Z[[}_/b<^_ @/Ozdދ:u^o{@?y11';)pܡR> Pb^*Scjڼm/W#c+Pl}1$EP`84J(JP# M-6|5o3y|{ T0|#1:s`'4%X5qUfTaJ8ZuU&P `ش=iͶOYi "U媓 G!Ci*nHC'N_+I^}kvժU={wܱhѢj%Kna͛7駟ލ'HZ7x-[&݉96ЀstҟWPH-ZTDg_(p>:AF}(hڎX?tݡaDw IDATI0|(wmXpe=*5u.DJQuUд)BHA0) iѰVQT_lm;;}ܴyzrF7ۦ֩#SyZ@)jc`mU TڒVK7;f*mMB(s!8s9@6l$C5NwUkaÆioݺuѢEK,bsw~g)ꯩϥu͛7oܸqݺuk֬ٸqc^f͚/*ל}_~_y晊 cR۶ۛb1RC݈CzyW>|Rëpbd^e;e 2!lز->hRWu󻓏],  2JDf$%7ܲ6޶sVC}[o۷w釘޾e! (9zy2 6 !EYT'ɓC-ryIq C7nhfY:ꨣ]Ow^Jov衇<[nܹR+oA;6Bvرv>@U[[opg⋃z?W^yea#Guuua|ׯ/:lSSӷH$E˲L.c96/ۭ u 2/YDL\"ne3B31iH&򟛧}z4KԵ/;yq8dƏ׼KqX v2=n,cR.ci2&ґ Յ$@E!j}5k5ٳl_+-irHLrccI'e˖؂ ;s/>3tҟ@X^q~6!mvr)/>#9!ڵkӟ.Y3-N؆PY׃@BIXniQ7SN(5Edвyy^_h06fX 2jVR|?z-I}w"!ʹ(3g((wqؖ߸Q{[JÿFmg-ʄ"Ӧi(1!*X$aT| C{`wJ-ZQ‘#Gq[ZZZZZ \qe]p]iӞx≽޻N;N{w[nwFg?O~R`17ߜҀN:o۬Y^6, P7S:PAG8^Pӏ47(ȹh'/G`^3/pDY5!MlZ :uP}q0BJ=; L~=-Wq-u[\qzyqLeӴ0UABaҔALڔ1ƙȨxZu݄iCW(:u$?gy{G\ys',{ݕF3Cy5bĈ~ԨQsQGrΝ;w #7o^CCC{{{{{{[[ۮ] l-][o-pe]x\q;v{ 裲 uiI.Y{^*i ׿;W:Ι3gΜ9?_WdEz'MiZ_ϰeYwqGW\" J9rYgn_ky"oll+ $U544yEǹ曗,YRJȰ+k܁@/T03i٭$d]7M&9s ypIG^3n&~o}^|գ,]T 0v9b *ѐTʗGҶӬ1CQ3+zӎ͉%v~)m^h0 E!5zD'\,cрaQʸ`"2 ' ^P&]m$GA6p͚5eWqFĐ瞅 E??s=w}a͛7_@rgvwzPS"A+Auݖv=Vp i0`I_Hٰi(: P\pB_@ 0&5~Q=(́3+]wmҤIӧOOG?*yw_W9 _WXٜf2¼ u̘1]!@O?tҥ9G;sڢYÆ{s2bv#rhnk$11(i^ -IŕJAݺ3ӝ)"ɪAι, [0RF)SB!D@gNB @STY!B袋.*mڴK.)wUWn3a„a4 &m۶uwڱcz3v*Fv۶c>f}V/zLSS!u@9z.:AEA cyRA@Jzޏ>z=ᄏ0~̜9E"I\Nh:˲N;.+=y'v"8(lÆ E)/_5%rl½/#Ʀ4yC usjC檒z%#єn+Wikm@hS=} Dy"MQAuB)M"rҡLdќGa [[]ME-1MAaT@Bʧ+gCH7|/zuוЃ!SLU\h5559O>}q7s;,ZźkMMMřGANhjU&cW ( >J\P_Ʉc^qNu`DP`iǶUE PJ (Y4B, !,%R0Ur,_twEj Lw},x@J"Ӧ.^LNދmR@ D!һt}b B<gܸq{n=\Ѻ'|ǡP]]] +VHWxܸq3f̘9sGqAE" h3-X?32@TؔQʥWD޲ %JeYCDP$+hao[ZIxv>Y,}>21m= j(z˳m m7CĮ|ΐb<JP#]`1;˖-87|sۖfOQΘ1ֻc7o޼y BiӦ}_=9~+eq$|s:E-||eb9Mv~ 4bDeqn.n;{yz֢KȮ iݮLB8s%BPU1d@e]_js/-qtZ@GJϳt`0tcS١>wh& h* G߼NR@N;HYj#/O/eτb  L FM,29L]UEA)" kJ]u6R_jS hiV(BP+GJ'w* u{{s/Zw:Uk\Jxuu=\$N2a 99显^:ꨣ֮][6~3f=~X* 0 ܱi gͿ"4I$;i& 2M%A$РsJ(ȗψ3Plc<I#*qp:_%!\v\P7 5X8T!UUA$`Tk=mYTU??ʺ_B@j*t$ "ɴuG|-:BH]f*x.\pP Dꫯ= W.Oc?9suֹs{#F _gyǼ<9s2חɘdY܋L;;hselK}Px`a ka-\mI&"ybBdJ֠XQ$j55n4 @kíwq!DJ҆8PUp.vH¦^ӨHXT0G"av [ouܹ@E+lgqF_8)BB3^z/_ti{u~ ,XdI:Yg=}+W> z{Fm]eilܶw gi' JQ{yY^fɟFԠE@J`+,lmOWW4SƄ( A@kG Qb2:XDݸ=IJBQp(vZ6l ثrAu.|l14yD  /*{!AyA&L]|b)Z5teՏ>矿xO?9 (fjƍ_w9KXU4Ƅdqommttt銘ra߾>" dL*țZf`\Gب=e\D!,T0JvbhW&8 "fMciz7a& Ȁ|p5 ^v^昄%K444yᢲdr'Y/~s=f%*'gLqC瞢OooYG?쳦I,,Jt|g:?V4~xZ"m'n:AMİa1@%Áﯫ tcL [lٴ#OhQʚRiD(@  k656% 염V!EeB9Y_>ԩS,X03,ܤMw]D>KX,imf(ʼy͛g믿^/^|E!ĞYM d .{xG?ZTYpu㌉{M~#FJokp۷v}79g_vo-Di#en]`Vu#_w` DJH!1SwMX)As )"!D(K S誔\pQ=5zq/^|bGJ 'ttt s(5k֬YeZ7x7-[gק_Au͵׍5(9Ŷs./]]~zks):_~y(}3z?{N:ҥ(۷oCѡtU (>w}^gҔC}o}Rny8PnQb:BD׫V\Q/4g/eҭ+3@ BEE@*X l*4e ;[65B\y 7Ξ=_|o~k;Wbm)CM;蠃,X /lܸ?ApL&x] e9ck8nnYhǝz7ȴAS:I^,Щ lf9 G1Tk0  '`MQ04FS0 hJ8u$MB 'A$\M7Cm^xacc… wc_ .jw?R.+1駟njj>|_( IDATdE}zرcy}Ee^ӫN :rqc/~-j' RɄN1U "꺺a0z”EkFP)]r2^PJ z lZ6]Q{_t1hjMmFqinj6i6me!QnA>WWA?+]m"̴aQY6O0eФ(&R:h$]uP Yv*LL7y#T^i/Áyf.D~[m[X; ׄ#!*(3>*Vq!֔ظ-TEv7 &E k*UCkKP!>c=~){i+V8O:5krzjՆ1>SK9nB ܔiDO8\A_?dWSuW]#f=.%vR'I$u; $mҴI &5-*sa\cL"c Z "֌9[75{#MѰvaQWƪ#PʹiU4!-0BD$تH@Qp(N]]] Zꪐ뻤M)}Lr-0eYO>' qʋ&uļDJ d ~I iꆃI 65΂nGIx"+-.U}ʿm=\R TGs(0hZֱum=oDK6BPSa涒0FH`ȪL?2 kRsg:뢋.:c{4w}˕4(_msvava+V(aW]vل >ax<^gyǿΛxEWEܿ~y]_퉔-~N<ˎQ ^|@uC1FXYrr9=82.:'Z0ž`Z[fL!do#ƸnBp*R,dM ´YʤMN; Tò-24]yGyN8cg̘VUU]>iرcڵ+VXl;K!;?uQQ xsNINtk_ҥKO>!V'Mt ' ,E;&/~sR`\!sR$>e26j$qܵkgW(Xo=?لrƼRLх|BhΙ ?|v2zS7-{-8ռ[C~RwOæ,ԶoބkOTX@+_F諓vNr!#! L[5F̓%Dڴ-ܮuJۜ$*d oK.p`pԨQƍ1bDmmm$QsNu0!E"n `gqG%io%SFaÆw^]@6n(VJ#e4s:Dž/3:h9I~+pn31ņ)JmBlF %661S˜ͨqAha5TmS7lwyL( ҭuܡʜnT_.{j _c5u!ݴM҅Yk*`0B0F2$ZS-sΘ >*h*qaYT)>iӦM6(ӟ7n)Gu>϶}-<裋/>3 :cfRzE1ϟ߭AoO~%;UJ೭>]??maos|^QnŇ_|X)գ> GEճDtVyg/LƇ8\pWxvV M\k݋[VȼS3 Hd5fg4l qòBmqO&B\X6-U+2.dt/Ţp`X4Tq0O[>{zmvM7kΟ?ԨQ͛={0vت*!D2lll\zo /lڴIQ__]w>gnm]tg}x9!K.Yn]WOSA0-[}˺u뤳(9/?oZRy׶~^ӎm: ׌k%սh{-zQӧJ޾uqFEQ[-z?G3*ٜm!,{X"-q#utL0g&U@ɟ=Ɠfmu؍;xm i*m hJ$7!ojk%o|7pôi?\z_nkǎ=C\ve}B⌱og뮻; 6\~导Jߪj@<JدZի'|/ӓ UX.֎Uh\p_+lo!гq~Hh߲["F{Ӻ֕. Gpz0ŷ"%2;R&vmtLeԈRΘ{!9ƅ!Xw`ٴ#TD%97,ڑ g<Pׅ"Au$tQ&Lws%;veY7x≲׭[7f̘;t:]]]ݕ>gϞ~B!)eG)moo_lҥK{챮p=Cַ l۶l+H$];w[w}w_຃>*#!e%']/Cr=ʉ[GH -ߝ½|ľf3>Ӿue]Yi6uFtb$͟\4ӥW Ռkц}@X a%X8ɦ"P#F?o(BNhB#!@Jzr9)aBXl!k(eM9Ma7Fƍ%LpKZbG#1S7w /<_oLύY 2GW|~Q)^ӌܽk+θ;X5 !_εE"=ڔo羥umr6rNδ9?D5Ct-: h PDʲ 5JY4P0BB#T*UF)-Q!!o|{1q\{ʴ@"R,,rȎ[%N'$7iNn'qȲHV (`It`Sgwvvwv $H8?339v\lSǹ`BmlV*/H*j!J*XMCEHҫ ӗҍ3Ԯnoũӥ<ٹK_qrlvh_u6pBR%%BMDY&5u bYjJZxDoNZRʉi{:k3&qs:cij )2)dx<~=s=O<֭[mۖakmmlr_]>!t=-o>|(x__ߧ>___ᆳ[zw;?oB^c< *<&sVsw) !c 2F )%nzg䧇/=|xbbb&̇a-Zz7nܸyt7o۷o9$ɻ{0>>c=O?ge1xwΰYC˽Y4R=쾪Mś.HAȬ='cLQ&0E KgR^bonqvdG1501 c81)Ar)<])`\99W;>H#Tp<! Ԓ`Bht2?>w=N)vQPhi !1s5}B'<Q<1B.D# ^zѣG?~ӧOMNNNOOgB.cLnf4TmѢE]]]K,YtiOOO2Yq4 gΜym۶o߾cǎ iUwhf*\lo뮻rCCCvڳg?~̙l6G]x{{{ooʕ+7mt77.v>a0:bgZ/P'hUUZ+mP Yc0T{K)d*Qk5)$P-B4SCͭR R&={9W BZ;;:dw9Rr0&:5b2"ͽe?SM2n9.S_ RJ"|!$BRl;2k+8<ԩe=M6c O99ͻFD*$f\D--BΌN#Lg2o}0ސMJ|ER(<e! U ~v0BhՖ,ԉ^ʊ ?հT)wy?wY D\\J6J)0R 0ӧ^33U\[޸^@qyZj1FcB."|1uZbGs*"LD%ͫ6!<Rع{Qϴ)ʸ[15`:XJd<[ c^؃J'cK௲B絨t"eSAG_y V2+ (@徘8 _O,O=K6W56үi#Mۤӧw{s xNfᖾG(bj*uiD`e --DT煶t4%t![=D^U owos, 5< B$BcQl4bjK jT6͈ԯRJO `e L U18=&B#E_H1&3v*a!\HP!=0. ̈́5`{焽b<(j[=Yv{g4 dx^ ?)J`/?Bahֲ~0!~=Ҽd葧lCpx(84`Q=-Ri#(gYlX^v!8bjy˻˛":l&E<\W#K+ɯ:g?_Q qձNjUkwn Fm1F BqN.7 Qb$bj񨞊1Ks.bB2p#ĥ@YшQpBʉ|K*)ern;ʗJ$q{ \@ybZ,kWv| U} Ka{AL о)Jɨ*WfkOm[|U}(\@?܈" OЕ8 *ʅc-5=.TvX`B0cT\xstߒq1:Xe#Υlu\v):9 \ެ0/H *tRICRRWꢐQ'Qy> Q!d5UydX()̵z.W }f$e%i=khmk_d]t(u"B1(Ɣb]#)F1`1B0@"V j !e6fJC g0Lt`O|RL-J<"e ZQ RR ~>s *a/䫙:Zo׈u̪9jÞFLt. ȕr瀺]V<62yTO!S:̯d@ &X|S@.seFBVKhj Rg07{ `n73c͎¤} 70B`x"Yą\(]%swX65p*DA39 D @x99ѮUyFYaHQ dFHJ&o$f!$>Cx##!DŽq+Ŗ&:FP킯h.,;]p%M|}ڧOm<_p$!Ul/7l0w`'Nt E#F B1!&_" RUS x.+q1R`b\R .~zY ctvӋZz2n&b2mkfrN6BN,\;!;z8s e⿊?]}5W+ )Y<(xʗB>,)+6`@Q:O[Wqg~0W됹[8|zs/~k[yy ?N }Ռw,9Wk\CH"j0!!L )RNK! .&l.)ũŞ0FUJ)B~<)0Ĉ, `Qy}pQBhklZՑͻ;Led5Nsgm$a9z%<ͯNfrpOS.H&"%'+ԸpQmo,~ YMdij.ԫ *]*i|UXIJѾ*䯾 x 0'?7SNn3>7U#ںY+-CFtecJX}!4s΅q %#ө:ΕYt`E?r.$VD *1B:.]!!DR¹@!.3q!⬈`4#Zz˄ll&59J : ;hv {Z*)DRZ.OJr%@`XqH5zig*j3":ph'T65lL. )ޟ{?/}{f Wub +ճ3bW0 ihq%ЉQS'FT=.$cq$Xq1Y=MNm++b$bVHl*wP GXD7 ĸ۞QR'm{7}+MF,u9&blT,LjT8 6+8^a=+qkI?bjy0/8lڮ/SDz@0B&cFSjNQll*LPoaGƳsK"G#Q1.rTh14kDPJ@1<% Tp+5+yΘl r39 V"ڕ̂SY礨f)p 񰣪.] 8r 0!3rOP3k]m5$0󜌓-Ľ3 >%~}+:5`ta#ЉehDKDA\Om` $cJ(lt^^i3E$RE/!e4#͑֔k$W(ƞ'rAPvM FHXH鸜ٜ+/=5A鬃 B@ q=Tle7˺ob[cx7U-uR7WU^-xҩ: xª2ëL)`fS;|U}7r+_fC;3ujԩs8*Lof% ш8LM!JӠ1KODdLt9.5E #%FyїdNYS K- ɜ-ezWSQP xhWB%ϫ[j$JhJ_v=ufze?|ֳCIbњ75^O(QF4;S?BGb]æN}iRLp1TmŊ l#ݒڮ`ޤ!.æF29vT#lމXhVy!BETQ Ŕ`f`*]sx<U3`M#R[W&>fFԩ%%2J`+SI` [mfႳr Djz2$TUPhh'+ CUbR-J1b\NelTb]bTPr!;.S٧BJ;] :R@ظ63Jb .xbuJ0+ыXK / ؂ 6(&TL텬kRBF| }K2[ 0ȺTRuKV^ɫLyN27[؛5]ovkjX+ 0(cBb])ENqy(RB *r+xys\1p|=CsKȋPiX87%"SA#b Rfrrb11qP11+,A5n k 2%Ј3n>FCA{ܟ !k$bi\Ms;1(B' |XJq0@a!zlpr;YW۔u&> +jk\T*]Ƴ v΃J-?KYWFBQ˚cݺ u*)UW˹Q {.7[)Wu1,_@J:5y\݂\UcK!Ez-vYC:%FdZ>E4`LMQC-D@Kq@̓\ح"ٜݢh\2Y%-&| (ټV,bT^͒/-_5%br:S=0+acw3);WJYd5b{ -22PDQRƢ*>k(58'CY]Zz!D,}D(!\ͥhxP}ky^x0;/؛G[+q@\q]ËBxp<8cǕ#,7[(VKE,^I)/hDlvzYp, h9Q%@vsyWI"fz!AUaIBS2-*e\#ts%Ƙ`tiTb,B.  *8%$9GAG s5 T%* r UI *T~IUMVÙѱUX>P 5PWe-bhW|^Պ$4 fY[7Ps-,$)YQM e}$Q~_5B!q1E (hz6_%s1BAMCp(cq/ä2zghVgh#{VO,TPK +LeBie:~dI}kŪ\ AsmdSKVaA` .mUH-k xu y { WGˏPҌ @Ƴt[ݢ\|票|˔(F#S X{<]AE[06,_Tv8(hbaJiPCNuP !DŽj<)BJTSdܰ #5rƅZ& RPPM.Sm#5J 艨4C#|b @V5wCaBHBePˠ`slOpW!:YS)S] XC` JZѽTʡ! `u\5qPǶ9pB4̊}h3l=To-y|:#$R"5˲@Z.P(.~ JQSעi#˂ 8GPiBI ]# 4hD\Ʌ`󸬨AņA=Og9д6-A.Bhİ]OE(XYZ2f$e`{\ȉ=ᒀO,B$dsqC#b!;+eBЭ,ܴ:ECmu|5} cX?C+ qXV%@M5ӕfQ.-h0B(0|TΟ"*+0F*[ N"+R3xD3uL %H9 r.\(R&}rਔ2w1F)@ 0_)#)L&B%c$KRi4hQ-bP]..FhORMSBT%P 2% UjF5ZS}糊eY\jkuQLn d;d%)薍9@!\ XݬۅBKm.`˜X(EPY)*A)ʣz !9F ^cVRrE#o{*%#=ӠQSKDT\!zĥt=zܣ*:RJBtֱ]NU Ah8`S@1kD/ٙz*ec151p\VXBSV:-THF1&}bK@*w<ԔZx:VR)\g ePCHl& ҀY '@rFnm3)8rYs Wϝԝ?]ZK5[lz {Rf.j)Փ1pRraͦA^}% c\ܢ O>cA#*V.ORs?,:qbHT$H%OF-!G&9R-&#ƸtEu`39'fR);o{N1A ?oz |VإUJ@ǥA) `{N9 k4+rΦ.G~Nc^Q0^qu xɘ{;M #AW/9[ћ%?Ù8<}ڎ-m?{-S?x䢞ˢoْܳBN?uЉ)7NL;/)U*n;Ww')[\wwoXm{ټ!w]sՊֶRQlupg#JPC'F "I0"~Ch @˔ Hi1pe.hh.㱈ќQ25JD%M_(  Qq ySU.g{eot$ƅ/HI؄*F9w7拵]OmεM8t }s!D.0] Y玁{cjr(ecySwݰ#Nѡc# W\s9;/ÿ}H^n L0Vn;TP~sE{nz7PC aѱ_9u]gs􅗙%bp=/?^SӅMUR ʬ.BKx@yL0.XU%U8./HȼdL֔Ք04J Mgv)A&uRJPY751{Zc`;66 wpn_h{SɳG'tɘޜ4o |iY.R_=5?z|dP4lN*6Q5}=q}\;~&SotN%,ƅ"elg %5}Mo?>gשȁDӔ&Y!mmQ̹s2+9K" ~sM#˒q2h"7YmMlӣ?y!X2@ .Sabl޳zqxNL@ tVRG8i}&hTF=9V~12ar3Үę|p51m?go1s:#wzj-WwuDΌW6ey-$j<}Mg ɸE)V!u:AWk|LR\A V[(KgyNM! \EVșB1Y.`ɊI/*U4nk2iLHˠ:%ccϓ+5qd;̱FO,ǝ: YU?>A,932䬠q59q@<B,8r/òɃ':g֛;[͟-a\׶SM\ݽayS?zhq7Yw9|rNzxټ{r8ۮ޴{n9,oܳne:˽T IDATzc/6,jscfY6t޾yg`b=w56ruדj|k\͸O@$Ԏ!hMYyigk?3vnt!Լ_&TSb_WN͖DT; (hn_}ck7jO¯X,ye2v/iM'fxTQ,|amэ+y|çҧG!Wܰ~ȩx~I_'n[vz4ϖzh Rq}N?s4W~/~6}b+Zr!E3c^>5]zS1@x%﹑C mJ[Lo_yfw;jZ[UKǯm7R:}S݉OW^ S͑_yw6%/=w@dQyϚgwy}pݷMS?uKvBG߾Cwx[Ɵ o^d"q!v:s-W-m>|r?=81mǣWw}{ A׭_95dܴ'>CO ϔI>8'|;n?56UbĤ[o{>w|ph] N 6I ;}nיG'nodavd|گ9aNg/`wp⽷<=4;rjzh1u:ݰ~4׬jW_ڕp\~j$\HŌmOrjޑ׫xnYlٶQQRvƇUf*n|CQ03Z_}c==ý<]׬n_vtz>zhM-ᄆ-{;=ޱOo>z:wp$ՂJY4+CW&5܉۳]VbE> OL?gvyecJӚ2?mػVwD;玁ٯ"y $kҦG?'OZovMX(-_|`CC#ٱB7sF'''f\}igw*Xy`Nر?rT0a\{3&݉UOJC=w c)A%˜<(1O^ĭ!A^Xs[o\P1is_>8Tw =O־CLk{0BɆ/9Qni`htӆΩsοa ѧ?鿶ʖJNd9aԪ y^:c\sl6 "3*I…,vr.N._nҸ;?p讃ׯ[-}869q6wZǝ{x(&)13jiɿ)AȚٞ&B-}~=dog|gSu-K)n΍zR sdnsPKk5J^=rtXDNN}ra ~d֫翼vJ7ᾮĻ,D>Oe.uM 3jiVp踬E0(՛O_BE`{Kw^vu7~ښ/쩷ɸnmTA꾦4Um\66U{2jI}{cSׯxBH?}ZkJTG=ۇjݲt %. 8t4[ŇNL{N ]4upbkdg.d&nX)aO-X* $)a4'o?z(u}(6[ݴ~ѷ=lqzCOs|xalҹ^tlْ{ XD_׶/bUoFRe-~Boz}pp#,B )F`,Ƀǧ^z\?в`ӿJYwUo4Q| KY6쟸" uamaaQ;/ÃkNp6+{S'fY1GQЇ޺7Yiqx@}#5#SM+2yhnez07Ք0j:-kq\u\|E:y+{~N6l{8?&*Io]SvUz |yKuuUMG | ;q_@2}׿8 GO42o~c Ѷ, [}VkB~{~7n<5mdlK l)ޔ뉧wBVK uFڛ#CiBpgKdEoc+Bw,wۇԗnd'_SXD[|M}_[KZ˚i밡TM#F0f^v@MCs=/]mO DO !"!CW6ٯ_T*C*Om(Tc%UY$k*Aɼ%\q#[LRFl;p|6)+(bjB/_yv?p|) (7 .\}1!] )7SL<012tզ2дe/F7h=tbqЫZںe-;b̰cN"3kS'6zp !WI/VyOG ]H".]:[KſC'f}gk9R\5-Is㊶?.p|ҏnX޺W,ل-ڱsi4hK*kIE,SOŭKZS֎Nn4(buZr6}x\i=b #=J'>3D-ܿ$k9j/xg#]!89<ӌkW>9]ۂcd2߿8wmԪ8v&Ӌ1ySgVmMY=KeЁ$wjE ?7'޹|Œ3;O^ڔ{꘥Jgy:\m\=IˠmM֯tʫW/NF--b_}ߺ>4W`3K'66`{*u˦.Yڇ^f3=qHōO!kg+*s˦.5I7Xw'~m+Q4;RwW;:2hB ?a^wl^7?UK?θ8w|]T׈wa5[|9U7l;V"ի| J꾦sLFe=I)^qe)a^jѦU 6]8ߵ@Sʄi|34qyӜKBhMtX窈ᅧQ) L|m+1樓QQEXY:K崁79o_qeDm7-]ޓSDF뗷\? _;|_~ho&˗;瑃+Z~Mװ[ýXJ8?}eaz@=POǧBZZ"m)p:AVDhy~ 긼5e}ronjLJNX'}ě]*C=G_=4O\;vxᄉ+='|EnnkȦg33>ݼ}灱+\^}US]CK,|zɢ_{:/tQ̸PJlKY͑oi2bj4Q R#6gw9'̢<!=&>F(l_V#fiy3W#"@S[~mOeS_cB9qcJJfڠGiI 4d\ e4KD0 CoZ%ֻªeUMKҘU|Mr.[Q!t88o@D2_5E 'zﻭmCONuޣmLꮖ,x0.,A5i<I 'l.ђJl ECk9Ծ v}I&sp<~>y=sSm`ۮW_m?) c'\Ȩs!Q\HT9 @Ũ"BﺩQ<1U=VݴJ}mW?QB`h4oyCh:H b(%ÂQ)j]UDt׮8v&qؙ;oY1ȄFI! rY ca,1w.zǐBd~QKerSK{iIgqbB . 0XfxL $Itfl؉\JP;uBr) %hLg ǻH'Tz%%٬cYzTlܙ Y[h"fD{\.Ya%#YM#~c+ 1…0¸4cC'_9YpXOGٺUN1CAemG mbuRuFryb4r -B*"n5'nG}.0%x[ٱ3zx0 ʸhPȏ|@/sE jI̮x*nύO@}1(Ŗ@)`ښ&˶ڔobB02T^FX .Pրj!6ɣX5P$Fr{=1"#& \z!ũE]GY S8D9Pr)ˆf1#jRJթ*o{q{f8| 6 @|>F g_(3]U94EreEkS " H鮪;Xc&5כXvmhGUѾ\E\6Sʅ:GY߯GGx`f6w_ۿ zOWxGR+߾:kfuMLH{弭e\C"Įڪ1Ƙ_u6Pצ.N~s o_Aa7jygb1Ƙ_h7NvHC|o;:@ft5xjrqDawN-1j=`=Ѽow,,{3f91M1= v{jѲ\8W^ M 4(b5+,6o͚RdBc” nhכxa>kYd^]ݤn$+ݻnjrƂc̣X-B6|Yy.k2TY)E0|)Nϩyɢ~7nTXc9D,λ&YX89 "LYTwޓsH5Ytz7(uD2e#XC*|wa7 1Ҩm7sv.;}u)xj6<ֻ>IDAT3D0xQ,]+6@pnw,E'_X4_۾;~1Ƙsɧ'TUކQPUaeQpآ9~fam;)z'"r(*a vm?=/Ŭżu{4j1朼#/EP+ kR=kFY4N<< 3+~._p{뗫|_7q|K"ҵ̇c 9K u#218RD֐GUޤWoWT":渤ނc9wTTUTD(uh;ì")s.Ѩލ8rT8w˥u 0NcΉYCfUU Z wHXP 5z4A9K @E6CJ&loAh1 K :ATEIYDt SNjAmbX^?Zt]d.f Bc1$j (+֡aznc^:=\qk>^*7qiHSy`u1Ƙ3x]* oOB"IIENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/pdf.png000066400000000000000000000021641417255654100230740ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME xIDAT8˅MhTWyLjTbDB"XˊK]DEB1 \ ܈ЄV,(tU1R*&$ڗ1.&3h\.ssn_6̲,%uoOkeDV߁mG1DZq,n$?7RuT$IXժ$q8#mi0S [9γglڵ|g'ol^°F&|G@DNej҅ y,"mۤi, 1ƠVɰTRd zo&ûa*׮b Y@a~=ֹs <1;0@#$A{^PKX#Rr:; ð_| C`&ڻ?n(D)RIbupp&'Yy'&纘b1l A& CwzoBكھto̟:IkKm z >\ܕ+޸ӨL$Ik5ݻWqttxZ fT._B lc `q~SwW ٳTA';Kvngǿ?"v)}*Jn7,%RR Wך;ggюof퇻Da~="RZTQ:Xc9֚W~`P #E.-AXi gϠ;oEaN;7M +@e©M\ QD^UK.\:7leqqFIη"251昊!B Ü3|<77j Jfs3g(yAJeXPw& ^=k-< ]^|w6DD]677iZc4%f~~V۷OOnWdeeex4@5Lg8~h3s_ :rX*IENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/readme.png000066400000000000000000000015611417255654100235600ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME  IDAT8˝Mo[Es]R'@Y$HlDE"U3 ,Z`яHn8ݱ"bUM&"~ܙsX؄Q#ts@ټ^ŧ@׏l6+dzmhWF99G6Pl95/T ^)fZy{™խ[c@ "|LJkeVUd, Ki)jvNdYD@$;S L1${U>xB/Qm ǰIm /-] j,/a"#lb1I2y; de2-}8i>-|=H<maWHj\ALL5^:F0L8@cTH U%F4Ո1p՚' =|B;B'K6UBxJHRtGZj@Lk ~T>n0>HwVV|UZ;=GffcLgU_ρ/JqA?tDMn1*Gtȟ| xʒ``퍍os\{-7xQ4he5f*}#D4f@翛P(NY`d&j)!@D%ъ R  PJyvSvtMӮ:}{m -nFׯ` <ۭ 4rc?-L4]0zǶQB@. |M2^<#sc+w/k"Y[K 455].!0 #gVd,ujX̪M]LA @\ֱsֶ-N2c$DUtnx`˯, F8hPܓx~خ"6C0(.Tk n_R}F2D)xX \dž0s\ޙ(d'dSYY;ot>V,k` <` gq}ݒ5GQI#+ټn o͙8Njkhj6sϿpmɕRUXKuU ]0-%Iҙa ŢD`||X7B Eűm4RvEJ&cQ 4)eQ*(SWg}~ ]㶺8UνB Iv!z{3۟&<ɛ;ڑA@Hvnm`B޽J׮:ߝ:޲e0΍L98iFF~BXd`` BGc*#F;[, |dy6"0 R>9zt{BЛZM4MJTOOϯ7W-{ @f}>"p-KIENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/scalable/000077500000000000000000000000001417255654100233605ustar00rootroot00000000000000ocsigenserver-5.0.1/local/var/www/ocsigenstuff/scalable/application-pdf.svgz000066400000000000000000000165221417255654100273530ustar00rootroot00000000000000\kƕ_|`Ev18 DžFbhzۿ>ܢDJbc4K"Xu9ު?,OfX]F]Tj/V]EMWrj]Qvkcտm[nw{uyf6͇7U]7o>|SU]mw wT.e{ӮvKˋ>cOl}s^mwʛ6{J%sTҘ5j7oEn5JK\kChgu -wa_lwY{;f.j1?jhJVӛv{;}y1}5$_?wW;R5j%UmrN{bz{\0U};nǏ_nvUyorYkv׋e[ڼi/o+fC3%[N/˛M{ no% ޘ>߮>x?DݤG+< +|o5L"5\1͏|*J+A[݃n7(A{- A ʶe[j׳rJ=\ƞw4ޘmLrOhnOzKy٬1ʹmm[EƑfӭ&a=m{ƣ mOC >nZF,q)+jJm߉t=t޼6ɧ_ (NE9ECxw_H6:l` e.J2u6.hڬmTȃ {tn1(y@Wj77zף6(L4/B.vV$4>Y$o^hB[2@:wOcޛњu=5֞o/9ǟ->̤+}MRC? j=/ċ;Άgo7ni۴y+f=0BM$xer լRV6MIhٛAhTxhXޥRUkdf5<bIRKZQIO|>W0=q>窶 ɘ n&2Z&@d;Yy>ǦbU4CF'e'rMtbXONItpeߣtlК=Z_/5޷6l<+22 lhrL1|eBSWmja _ͫ{v`zBzYt[?^ ʭ6#Cnm˻ͨ?0)@3`J~5d h_M9mG NkRɆgXFhLڝi94 $?#i(p^ڣ$r~$zpW~h9QunyUÏ鱆SV>g{9vL_S׏AT(  @Lo 66ڞaG.g6R_vgDIJCchbplcr:FAZsVA 8o z^8KWof}4נ:ԡx42+D__!6NEgOL.iyMU{w:jxJ3lR* IeAC' @̞A)fÛnD^+ e Wx*N|F9"24G! 5~8ꗿ ӁiAlr8kUڝQYgP*?X R{zTz4RC4~ n cp7B᷃X#^ʯZI̩cX7(-Qrdf({5/P,P/X3u^h3t~Qxj$'DX@j͜GU5StZƘ F&*׻c>U%PSNoECGO=~henQ݅ͼ/wt~{;>p]_~ן1^odwzDm h/bvɇӫ{12Ygm6>xq~ eۏ6=mW5…Qn1ok+ g}qw9HsN/atmma~?]6c/n?!4:W>7ڬoi owCO.ɼmfafk_p\ȝ$xz>0ri.O+'1r7,>-*PwRqWBٮWˇU!V7(^5Lz^]oib2W"9]$h'F!=o&_Ֆ葶lj|ҞB5!Hcusv7Ow%&o?@7Iwpრ> {f F8\8LZi˞ml͂7]}X.F=t[I-.س-^A}8} Ti].ו>zv`}o]Lo'4Bے,B\ѼeݮT\Z%I\ \nwMjVsuQ1֯\Mʒkb!W39bΙ s,A8; .FP or*8.&ktx WQ Υ`*Ӳ NRulQPl˨ MiFC]M9Yu9ǠٴA'c̷X<$ї0GQ#@|䓜kǎ&[Iφ5a>5GvoW#PP"mEIU B۔чYD\6T6.[[|CJ%)|idIy)5*fX'e.lRyAU ~CiA<2JYt),5r J[ѫX蓳4p*{"1輊S9Vp]6Y7)tqߋUCTM.z3(Pu_KaRYʜ&K$ss;E JΤaɑe\]`뀑7g.i GKm|5hLjL>UJr"pIԉ IHrW Ȉ5~S%-2e. uY b -M~jD#.ۺUaqE1ѾA@ `$;<݀25&)Q) JToP k05Br [ BNA~Xָ A^1*/\; (sy)nSnBi,?P w'"&\0 mv+@x5*I9 H+F0dn E̡|%Ex7!s3^:)2==Z)SA%q1E[Ǔtt`K|cQ.=Yo0/uW"^(kC5 _b_>F(8'HʏA0$P"\'g1ܿCW6:ҐP?/zC* z:#14"NO@r.iK䜆A,/ /2b\Εu術mωgad'\Y; w25aD g!q4-a P!qߢ)|P1˦HŔ"g+0H9ad*uk µ/R$ta= s4&]tʒ-b-jN=`n)q"BSB: @rȝck$xQyatp/nD2$yWvru,lc38v?aP4be_SDFVW1mMv&h!y;j`QMD$!v9Я"M<-64uAc64nx>dMWbQ1J]vZ9Bºθs@~uEۛNflO\Kzڞ I ['es:t s@!%ILe-#sWqFi M܎ITA(LLftbhs~}74hH 1 Iy`u)W鐩P 'MщD@ ԉG;'7 gP!ň627LQNiA66{[1Ί0EdbDϙGTɃvrA{% qh(G4لnLJB\D^g! 8D#dlԙ0`S=T=iTK0< ӣ| P*0Ǯh!2DivȌQ(q;d7?u/]=H}:үMWݦ[>S0g8s 77&pRhdbE[ICo8Z6;|ix)1vC,'ZLX ­ё`N`_fu]p#bOD8$䘋UÈcɴZ>.4aIi:QDtc!R `a-?;H$32Tҏa\rTV<vaMB%!`RG0 ,# _`$aIAz4@w⻝u{; LEu2h1Ud l-Dn' UA $⏖zaȝ2rLK3;j!ezF+i+"H#\{g -C 6aPvU $"0lBܞJHAB[r>v7 B'$- QȐ5&f9`jЀoTX"Lfx' ˛h3-xZaѣNRa$]ݨb5Q4\_Y9E2SɊ2 kDސŨ#Bw{Ý>>0 IbQYza&EkR^S\SPf06e]Jk~\- |b(cӝH+`^`MP1H2 })qH%8#'$Q`C˱`.Yr;183z q lFg=@Br@0-|,\bb4 UDKoC4<`(A0YwHևaT5U(M"`5Y֗F"lYBx|nq>1dkzrpvdͪ8]Χty4Uւ\8Oidi.#BZȎku aGM[nR \" 琙<\1 )3nXD5-a+bSb{Yşp9kLvfDS'*IiĒ+V`:KLSZ&$EX$D ~b^E3>O I KƐCs\ ČB+IzZd~pF[f mgG KJg&k3,qA{JCA["vΚ=%#0(ynidž5\Ogp!tmbb KɂKSd)9F"Xe=Z`9-c P^ cnA 6u?IBEgE 6y781e$Ș4g=r ˄iDa:Tkl#1e1" c$񬹚N{C#Á91f8H`j  M͢,D-vn}Hf`dd 2Ҝ Az<}^Yz1I? EdBLW ҽetXoMr%gl(DkeE)n rT?O BE@ `?2$q J;J ]O1ח)fk#,~ E%Z:Jԟ<; &K KN4bz )0#& 1i1W*Q-9lYH3rB&n(y|\Z%;j̐-OlJ,yp aza.7d֥8ƒRtBJ+eHd"tF9tm[:4p;ړ"72h|"9[4B1]L0̒=H!h/+ 5 fu<%5.Xng[ eWP;41_+/3aΫFijSW@+>f|n7,buu}Kr\}٩{t>hf8؈qqA _ߗƍDKVV*3ݿ<Ϫϓr:xkuUMÇWZFaa~/? ϋh5LW{r<KyaVݦ6GJ%sVژ!j _VaUUƳmj}#O۽oº^?-Ɠ;9&wCU߮n[ͬ鷳$q4,#$q2q=}^TmM4~REIu9Wt? r>jn/OO<&QL5gy,՝ o<=t6)]_Ob/p:]f6OV_h6~=s}`z;~}IJ]{+|mW 5NYօ0I)Pk2Za1bCzfIV7j۬7JP^mww BʖI=g܍Q@[}U]謯n =1ۘz[h;MvF9mVn'v'YƞnƓЂ"q<\c7M{42 @Hۏ Hoz00B۔)ti9Yt>e9٫a "{~ZL~ ҤuN> >_){TS>7W)`0:S J}2UZ:^6k;xv;Aܪ0~p-Z%_1TjM"^z &T4g-U!ZYX'4Y['oD t=8Xz|w3zCweOxjg>nФ}|+uMR-[mxsrvzpiyQͺUJk3Hq{[c.BTTC_ZegVɻ[*UC HjYm@;/F$Tj1isj| 1sv2fI-t@2plǦb5L5՘6 4:);PЈ U}r CqIWhh+kNm/5;4q0@P84(wD0)eC30|5&Yvs2i1IGLڡNǤm>F@0]@{%3Dwե~G쳅S0+kcCf"vh.8qʸ٣#*ْX~3n^=&{1pˍc <1&L@<ظIdi4dxTx\& HC9@XCWʹNA xW|sVn2l^ij/5H|̪_׃l-uaZ١NP! H- lW*@|^d8J XFlO5EG.-YH?؃;c"4!| 2ZGՎkto40NJzs~/8'waK~Dq.At/ҶW5XPjS6Z4חk;v~sayZ>^;o\BSNyj)@iMJ_h,؆H4@ IA!z  i6\nk r\1?On!wVVqrEr[wyR i:*;`mC{CtYl5*vQY{T2_XTv`*T 0hs[c :kEk:DӦE5Co[OEK3W袅TcA#ŧΕmNv4?a_f߱Y<K!҂v{uǽuɎ-={C$htQi.jNl24ζwx95;zF:uP^.5 xZTf AQ') P#!@Oӫ=RCYRi0Cbƥl:RU:ttbFM‹E;0Ӿ]IB^Bк:g𦝽WLRs  ZCǻFklǂTfsmd-k-6ǥع,ϣ:g-HɖyBB[!aeu>hKA+D!\v]a&E`E!u] ^){;%2qwZr ji{rcۧtlnR-m丈b0ϝ߆x _vGe+>zp<1(03xYNT[Z*9/a"R|f<1S b\\- ,bVl`36;gX@ *[KsiB<7 Y(z ʈ0 ` dLe(*sa=9mL _ b* Iʠ?]\S6-m{u_\"{“FYbocoTl"x\ E缭sodWKݝ<43m8";<w>DQ8d1龺li鯨`;4B4K~"У)2kWS_h| اxϙpJNzJSqceڤZV]Uk_{5pBϕġn~wS5*g'lEx ?crnXTm4`됔 \7]SWCfnmh5D,sIu2ZY/ YL1W{Յ^Rn%W'RMUXf%.FDں2!h4)cM,4nC)3U ]6>RT `ciGi>HuV[1G52O  ; lMtM1v(qwq6yqL[9;P ƥF*?!1.Z9,s-ck.#D];wa?|& 3Y33pL/}٨}$z^xBWĞIc:` 6ۛP0Nv#ɌAxG<s[ 96V6["y.n6.JcqTTtN׃E`Z ny$C;lHu<ϥIt'ϋu8= %&cH2h{iA;u-b u"QdyW\sNC4=#;rT;guތnҴmBONͨ}+ =# d|P'mx 乽fݪV?=?$x,|?Sv{9a=u8:;j&k5YO@_3>ʻZy3Q%=cC+WTqX?zү$9R%[YklA2U1;+==Q\cSMe3THjZ'k"ҫ{wm t oFE}>{u>q2w}JءVXdc6Nۧ0M3/~*iO+F_'F Z6lʖ_>,d>>ΧUA4,gÛS/sكLSc= xG ްqa6̀GO鯓۞E3]*N/&ʅ?MVÇmBMa!fօ_*Cz]mQUMŒ۝R¸Om.M Iِ5-/t{^teӗMr;:}OgΆFzJd5F[*.1A/y{o|-k`;-=EFD?6:?frM}A)_ IKkfu=fk՚5ׇ0L@U~67P,?=Ch nl 0z>(A8wN!:W= 2ۻ _\wrJ⦧^lEWٔ%*Dr)EϼI*F("c ;2MڥסgwT1=X&逅fln6R(F4(8;2:-5SߺR]d#Ǿ 8ű+ Q5:jF/JKzI}r .A{ 2J6~ [<>jԈf _;{k'~iu)j)tuy*̰N}lIi)\nd$n hM:m²f栲qE5nQ$E/p5EKIдmJ,Dw,wpRq6$[?W4{SMF).ZCwjb5*2T zXj3nfjL0 dc Sާ )4nvς*@Ư"FhZZAEbZEe[ϥHD@&kaJtY_m-2H`R`3]_Zyad7{[ʝۣ%=F8)]lR)9'$s(E&$līSb:[dqbH[zZJ'J@RM&V9jqS.M>I<SV$yVl9I.QnQR^+hVEHuwQp ͦ+fh1NG'hKd 3+5LJBۍd.Z<B3Ϊ6sn1I1[Zè]?&΢7՛>ĂrΥ,z͆ML;*Ɍs6$D  .k(_le do;qS7Aө/mS2^VcLdp)[H9< AKn&17 /!xtfX%ܧ@Yu\Mm,dPt>;Q ߈Şt)6'o" &Y၍А@.%F у5:hq?+!ĂiQefH'ל^r Ĵ6~t:.ظj=$eeT$kE႑,I `!3gR`i6Z&kSrzC:B*}F$PP"Lm2MAhBv|MFF/Ʉ1Fn((w1A0JopDVX \DtM t3IR 镰/|b+2 뼖,I iD5l.0+I7?\\hAjpPD#1dzՊ^^m&[Sl/'(1@SbP! >53nJT)ʒjciLef*MArqz cHFm@R\ ԉԫ6-L\]KFRtJ597\!6-naSe Uh%3σ"пnU@!p7ɣTC@6cyjo_BژoBΠcXGǘ7AfE>6B]iYymHUsⳏNx*m4xF账46v9m9Fc$2SYc5(fŁ=/anceAg֓e7^Vm9rRI{dIP95px©N]亐w@P&!Y ILG uJIŨ OŲ`7bTQbЃg&w&R|כ}R>V1grTɆ$[LC9>Yد匿b6?oݺl oGˏbK_KٹZ ;R/y yHaEdu$dMЭ$9" s,/<*" BdLO)6/Jt'Qc>E i}g0C+Nl;`Y Bd#p.iiB?6'y/E<3|gb~cWyM {YN(t}qr=czrQ$ {PI $2Q{ 8Ij;dI: F_ ksyA(!^e]A8ac rhzm1q<=iæE0( ?醴?RʯB;)eF6] .K \'(ϼ䈼;ϒz%K{R倕1%`ϔLVZbA`rF:YS "w%SLC @/ލA࠱ނ'2+/c:j !ɼbUMW´6>״'}vw;)}[zEG1s&:n`}&24; H߁ I{0/H\z&?U: NTH-]8޹$_zVo!jtMUr/V9rsegodp.N޲}ŜӏU0hVJ>êSEQӟ7e](yw_7V$~ 8Oc[gw,w~7,VqU4B<:08f#,V҄wO#{%´f:f^Q)hI[F +Cg,NQ+衩\fTHZ)2 .C)V'hZl52w>VoX7$aEuJFQdJ9]2r3Sܦ5=-寐1eEdR%PAW;.*2xiWn[2.bYcgP|B*Z ϥ.w5kmldH`ʑR{N16q"*]06EPC6cp35v٦KS?}=~ i,Yb,#h8:eYz3+ o`:Fn[$C`QG09/JٷT$c^b;sT:p3 ##o<̱C /w{2w8D Bׁ7%&{]he[PjAyU-ԯu$@]sB!~UwԱ VXShR3D#K x)o;P[ռt""ܨv൪% mJv!hO*BTm|\xCژX@lIG "h֦70b/mJZvGebᡰ+H@l3mrDUǨo`lZ7". [&}e ZhV^0L9h$hE1Q#x'%ِ>%&Eb6!ZΖTTC\.李dHЛ I H`m$NʙEXĠbN#=ՁD8M&Ḃa/s iBO $'E6.#{)a0/1dfI04X̤PCjyXQC\2KLIk*>5`p+u%֒ Gt| <6'p(0!d(sS-٨-jFZHph@bNn$CpJJdzƗ)x$I^c;ՒBZ -S'C1PiltG"{4=ZyC@*S`#Ӿ@;y {IWGfg6!eQ"TcVacIѳ.3d]St%Dr4Wŭ!MuPIrLL#K.[f"eI$wcs%Me:l@elg kʋS#y:uWD]Ai 3IrN()|9>ɟx/潅N3pNh扥 &r?u}<H^5戙qi;Ol7[5($M7̓"sV$xE}}՞DH9s,z;QGvocsigenserver-5.0.1/local/var/www/ocsigenstuff/scalable/application-rtf.svgz000066400000000000000000002723431417255654100274020ustar00rootroot00000000000000}YJ{ KQF^5s@H $І;"@~\X2#sSuO);fgnM>~{,o )+;$aە!;I}Om~}^?9A`YOoo8EPsQ?S?J߾wwg4ʇ;_.s5 P8 ,qWvYewOomu+0 })Rl(6ڡ7|p_uӿ {IO}%vtfU>0|?@cߟZz^DRp4E>y|OnVmuWir<}p^WǺ7,gρov??w??oyQ G w/nmޅI|4ݧ~NR-f]wK,C,]?{~P%> ۅTr%BxWYOe?*}AǮU<ɋ?p)*!w*| `(ax~)E~2ÐC>C27ş]uס>UvG' 붓 x0 }Cc}MeKXmmJRJhJUo Xϗee9"1s,S4/K3s՘^{$ES[R$,c wP;yOiNQOX*ධpX\]`SqP7傛 xŠd>vȧs4=$jY?7tQotOFݑo7nՇ߮c^n?jv}V??:>$XHx+Lޣ˅wt ^^ܹuqZRxSSXq ,E`8r!=q;K{#h@WpD"w8yAI%P  P X Xuϰ8NqvK)8䎸 2~Oñ|X@>4è9K rCHʰ/@CC{[BE#=ŒpG¦,pWrpo@pֆ{8.qwc"8t/J|}Q=ǰ /#ɒBZ_1h_W㧬s18F#wϑ4qsF~`9hģ3#8^ЧV/w'8}}e? V|eV w_g^) E& 6" i@|D;S<\^ei'!_i8hq np  ;mع$NG >w"6^GCoPQH.@|P¡*'Ea?'1$ WIVVI WGU̗/{ r6`67B*4Ф?ގ>J 1=?{'`{/6n*~ O(+_1b{kuaꏿ d!_8 W䳁#G`8lG}cz*_X=}"HԞ~ #БI7{a}e?ʿD1dBflC4Gp27@8/p4kQ 0w4,1': !5c~!$&\?4YVp?E!bA#D\!_>+fW; F>iɌXfﳀu|nR8 9u*AE yK = H"p= `,A*P @6p:r_1Շ|0>|O6C C ݠ 7TzRZ5opGU"ȏ@']y8,M>A6$\,zxS=UY,G߈n`*2 -WN8LbB5E =7R4R:Lyp?toVKPP|Djo<ϫpA܌+@3,u3h٩FSb?6^r$9ȾamG?Z=v^U˼Jq|A8wG䏦8028xFMF8AqSu1{-bu`o?g| ɧoA{؞o{~)O@3esP )fx5m0C ~7fH!-~bfHBj̐_CZ(6i1C m睘!V3n̐ߍRm#ccb ijd2l73s3C9n螤? ߗ&ZݹZn`S73^?[x3$אMZ~13$kgj̐^CZH6i1C{F~3$15Bo_8n̐`ߍ,#ò_B;2~ ۲[{bI/'B~ ȧ*D@u~ soZ?#L`2iq ñ+X9]@\y8C\Į:?jx2w'~O LI脕=?4gв_;n'>k{šgUn%.OsR˭׌Ed?Q|3(j[ac q+zKŭ^"84_ŸduV8>Wn/ŭpmzS gI1jmKĭp1n&nE2\wfyw[{#`܊®XanYd/dڿo ;n+VO/.=b$ ]J'y;.u_kܓgne{$a) *^pvB4{$4Ks,? @3 {9god Bp'svZ}XIfv >IX{4FkQ43 a]x9\%N,TmC}s"^"aPap s4,Cr,(G7h52o&=s/7FaK2-M+Cٕٹq4`3FK ݌Ьkܭ/sXoeNlЋ2?J v+KHvT,v67cfKQӏ}ћeݛeی(@KCk K2c $x|ך_ăƼ~pk&?f <^boڦF_X荍Þn7OwŽ_ڑ~b?^Ϯ|yί_Oq7ֻsoOyO6B{A<||Ї-nk:6y樿y;n!ͷ<z8ggy_￶Gee9|pk?oMN0{ENr{GL_1In-_| pob#|8G/:> '菙{ Ot3Qr_^xRqܕ7"qs/o<%Z^Pv8vvvHIKE NSzv#%y=/lI}&$|yC_^'F$ٟ~J}H@I80_99 ĠG!8F 'n4SCFM>w ЄB!,5A;dOYƾsp9xK7'<9D X_Ї0zL w;jZM$D^#ġG{x83tytx:=I}'Ky*$pWi.S98ALHDewCxI?O^~Wӻ w99ϋVoJY]e]0}\}2LWuzݨr^L|G1R'F{>_mA:!w?VO2Sy.4rw3AVgc!ߙ$CyǙǸ6S&?cwo%*N\v IT>Eȟ=S:o#gnN&Jo?sN_~8?́ݽyI묧,S5U#D 'ӋOq _pG=n)AwM%aLyHt{^;wctNu:#!)~:|=5N˟ G>1I3~3GyOxJ& 0?$< s]]ꇽFM{Zʰ 9BK%)|{+B读vݏ݄CƏQ_FrKʷ3p!~h|ïW& N/P{q_?py<" ˽`y6^_~ʷO9]V()gɯ`ʐz]m)&,\2*(Hh8#BC们 x24ǎ^3 fI?Ӻo w뾙}HϭfT{}fN|)-NM)o9}tO-º?HK~ uE5}⟧-6/K,L!'=ӶZCkMa=GQzn%W ~^gTp:w$ΰ _j[&uCh)wX% ^wTK1|M]ro3'.6 #Y!r 0atۅ+r;{;p{;)+ 7S7|׵,ߙ߁zHDq1T7T{?GΓYϲ4A[CW}y?x>/I[_AG|*!+N,o{|q:d\{7O'Q?jX(ͳ-+N'4]ߴO̳+c>M~@J򼾊2^?𼈂Fy~?y]~|<ۇ7<"ڑ:/<χگ ;XM` FC1ߌ&l$w Mr<4zcNEk`YZZZe6Ce d9—̐x<`s)ȼrSG=ψOm5jW̄ˌUh}3$ @ "ȸjxvX4ԡHY#^nٙkD2,M.89_9~D5KEbMJ\Z )GC2#5%9,u+hL;nC7IY O◡bNG0*#krk>ϫJ\djO9XQjrʷd/hNQcu4qaTKY3̜,&H\xbV cL ci:ahN9p_0l)ܠf'=^NU._Frv|H UYbm2KsM+5ge7NRmYGNl;熙Dײ4D`9!I>cc8";*T3y,jc0X.o!ŢWz~>\j#tPI'j6?2Ȭյ 4h T(\ R10.arAN< iOa#lw9V;j{eQ#*béu+&̷T`iݒnGZ0S!91{:s\ 'd^Vc1z.ͱ[;5뉟jeZPQN]CpkKjcw`cj^%#|Љ໳3e/5ҸlTM/!R&y+DxFEyEfN9M7K>sb cjq-Uh\He8Px4~nC9f^D`k)]4&kȩvٌ3) qjʏ4TeeņQN>v`" "UV(nh[gRcacj;FzAtɒ<ͺ%-R :i6œ9]\<"`yqKj s`)67Ô*"x y8 ЕDj9]=dl47m=JG^flWtfNm]d ƅ(k9 uaD.l@,mv f9Luk-hLr(5h{ulk}NNԓ1XmUILT 龓oEɪ}fC"1BECD6NQFq(k&2 !6#.y9Nj ˁ1)'FjJ~TPʻdi(9fǩi5`(ͺ9:HŸ2se!KHhYe! 67|^ZElW ?utThTy8C-I7s5! Pf77Emؗ~!49q+vAC n- $P^Wֹn6Ȋqh9i4 yR''ف|ؓQWd!tvF{ITU*^z9yT8΁ Cz7G20S-CnmɋdG5C9{ʁL!AU]+? a&=̊%i?Ket`SF X!+IlΣޭ :X &G1.CXU181OĊ8WA"QD@o j~teVF%[gX崜&?^jG8"Wij'+IM:):r6Q-!bmɷm٧UY^nGem թVxebr/DmY{i/.hqTˏ2L59_Ns44U٦ڨIă3ph AHJ O̺]ZpTZ :W u½np'XhNO'Use6DIp.Zt"i:;ڙC eUT58r[WXsۘjԜgoly߬s. 4yu12ݥRYa&&ju& zgubCmdnM"aԎ܊뺚pҫ]Zk''9+OkSbFIhSm\LQp+9m(ue3ImrOFEPܺҙv 1Xt86]ظ>S +CG'hOM'zz^'<3|j D6HC4CGwVeQb3[\RZkeQyd+а5yAlx#{Yr;ld4BN4(CZKSM x-O%Ѳ٢Hke'֒xt9Nu}4hҖpxx1hz%9&( $n0ڝFIn&"F9թγ1:SS/7!sab`Ih̭_=~8]ujsۨ;0uQ-E+6DTJ9U-O2%GxpI x݈+k[UjD9۴Ck*8hGdf*sl'Kfya[be -E8Fbcc2qѲOPhzρk$Rf@:xݙQZ-'5&Ǵ݀={!R z4X cY,zBS\uj,tM}C=8 $TL(V d{1^i7yfcsƹ 7s0-HI P P@7]' t0zHҢ3j췔<nȬ{.m!|/ȋ]pfCG.:>)!Ux0n/b2F&T_/SsS˩#dLdi 3b9]o܊7&h^ąrPx#a.%Kq/Gi֮Xg۬1sأmf55Q8j=?_ F w[:]LgtMMӲfeSO0xE'#ip@k4@kT0 Z ڊ: $8ꑚ[FRŲ*u:lm8}R;S6p&ٮFė8az5/l( 0ݞ="]Wa ]<= S5yF4)^dZc4!U~6AU@`1&B .Pfg^Hظuxg*)U ڪJ{|ÇaGYκlD W fY.6ĞCnjtDɍ̬\1y}K-ԐimN~'t c,ב 2Y#mҚeMʄL92l3kU*rB2K)nu&ϚC:x@a犃 Bu;xO'wAm(ʫH=lǩDuY- DW\l[xeXT Ur=>M-n3ƺe-:qOC-B$}r\#!/=syN8ӢECEk.l`Ǖ%N'.ɴclǂN;8UvŶ( 3= !R("4(y]gj"kI){md,xeF젢;h.J`e# hb.|a7=EMY['` ɮS*(խlybēk˝U,u14!KIK+] 0-qYu]͋cl*om 'Ƽȳ{Ɇ@uyojPN[-ta̡gI%4xȥaI-xRWI0>^8.:WV'h%Z=k+WXFKL$Wd\ T4=a7i#YpmheE49W=ƌ(3׋t D %M^&Y9Z*Tk%/!JMpAC&Ge/ӓR܆/G"m-a aC9fy卨:ީg20@j Yͳq(jǓnN l.hi .M9 ^1.qFJ;^v遊i,U,wlCIgʅ{f>5EvQU${EJ9u;PGNDi'9t)R D$W?vudd9w=? JnhRSҸT,c7_O }-sd"fdҾc&;(UIn _XKVIA;q59NBdIB4A!FCc")W6fts&4Kko|ܜ^̚ȍn9~CS>qHU5 rɆvQ 2yĴBB]ytV9aA2̴&)MLJ V>խdlZu0ט{ȲJ؏l=<{*v358X@'Bv曻 _Q:B#fSӬݕ x =H3{sNXQllydj?1y4zjFʡe.Y-m2/E5iZ 1x^δNC*$exv Ьt$ 9T\kz=hfvE4YOxX,j[._8M4uM=<,/>P(%9mxt|6Z,ٔbPq!ɂњhHQ.&*l qbʗ*i56%iF!c ɟ9 g.ѭj:&AVsI'kد!r59uB J_&,%I>r?imZz4Ì0B\n n0#֜%r"Yj^@7xzvfܯjx!.R;.Rbgj(S1R-ojorm2P&,q,\T:By?Yq][h3f0.k!/z3rlnA0rAOKUqF~AVNvwYc$q,UX$_gHUu3hpʥV* B((„[6vP6=fLzOyG3H)VLlnyU2/5@p&]D-BXIuFZo"f^%I*dѲhALyG qD#sb5b09e:F\Yy4!˘sK(Bpk 8=#,B^#@pƼ@dpbdn}l[\ԑK5㚁]UwtDn1Q]%Qhp-dmdM]9X[r$CI䥷4do-4% q8HHbIj+}mX.F>"&8);l~kj-9v 7^#XFLjdhh@]uѾ^,Tg3!%QoCg17vpTneٯf@"|2sUSK7lĒ'٤GgJ&&y۞ EsISY`@Q$+oi}`ܣkl̊45Xe+34!f^{Hi 5s_P3ɜ=;Uj5r(,ބ^0wژ5OG4mf` }3Ҳ9.m2xl Yc>6tj?j!2Y>]Y5)YXi5.Bŕ[aSXΙNT,#n7ۣ rdGSu|1k!_%a<.{(@eXKhkt; F 4Npb!Gܽ:v@LGe~F@ 5Q6EMr.U<"kQvn"M%x\xa3#h̙$fZF:W(Sj s@j+g^M-Df6^;dS"t;m 6n(CRr(\DgC[@;_X=X[#BfHcl<%#3..͡; piaP*FevܺzqqqhTA,8lh{#:adη,XLXT;@5K!*"g'|U+ٺ>24GԸmq戮%S2(dWqzY(lĒ0(t}8, g#t#7ڣQWe$}l Z*:m::+>P(0@Cu mI}^cȡm)4Lb hޅE!7hARyv2OM|@Mb+J ,Ϻ2y!+bi+#/H(2?~JjFv,wH8* ? @wMv-B&t+QnBvJӄ K PyJxϏ#|z;(p 2ѩ"C^YG4 vz1[Š>M(EE[ggRcBn4!x )~u ekpVdzca!ҟlߙ3Nr|(ɯ-o9Mɔ؁r:Al%23ٌIh5/Aw&7@@?+WAIS&ȪHn^zx^&d"2E*YʒT_01DO/;6PP߈2}3̳!SNB8"knu_̺}..k9<捂g]דO(cs[ dRo(l YyuZPG$ry~:8I4+G*cy;}BsZŻcגDb"9b=nI_TDCnN磖J?^HLs:}N;b҃I4ͽq:aC+eVpi2q'"R(5uhsLL|=~wZR'R`tF3h,@Mlk4Vv-ղS#I $0ܹ[K׭dWia <ѳ ^v®=7,;ĺbd:/K=siʯќ轓"`n^dnV;:G'ok.q 6]C*NEWogB~gPERV M4b߼]|% 28{=欝z̳ _;Y4f}@K<YI7nc%~Jšf q;BrFd^8c ;.LIbjX-6/pVf{% }y}ߊ´_oBbMή!U`ի>]K輱 2Y{Plhgʊ#~]r6ْS D~Rw7]챺4*8Ćo0ȸ̒?"&t  ȡiM6ݸo^ë7:)L K8^V͆dA.xm?Mv"):cեMy"E4}d~t1" PV@ 36\t<3dkMBЉ&e'X ^.vR?@t/XLmU-3.ϕMr=sԦ.F&gv#m! "a(ZR;++wՀ.iUq4Dl` '`at=Z ouyxf9U ʣ144/?vHSru$HL^kYrTy+APR28 +BEPW%'x18zƵÌx`6MRSss۫BmoHcPȨ7+LP3d G֝:>,@l $S4]wh~kʃe2I{{47i$Ȥ@b6Wk.#Dlo[PЁ>DKZ,oZx},PN)~vp /@،Fa)_U(*cU2Ѿ?w7ؕL!lEU /7 iagZ!ޠD %XUӞ?*Q] NGNNgB2z=7U^>4*d0o%b v)ĐI}HUw;S|xJ  Š] -Hg} rmwȆPՏ2pQRZ35 7f !pYHۣ#ohqrۜ`: Xq8 GOYtס: 8"= pZCU1B-&mN1EH2cu=Uw ,荋 T'wn;=ND5*~U@"4i"w}rx,ec~ jI2 缵;aJs(gfa?@,"NS@&3BĿth4I $Zx}.[U9JRaa[PiNbr0bs46 }d\!\];r4@Qt}4Oyxߺ ㈥ٹfodi#AprJdÊ|dz `3pA] { Y_+f (TbEDҖ̂tmKo}$-tcBgL3|uʛI%ӅŒ\ A'ۓgL{{_2qr±iʻs Q4NM:>ցas6sZ}s; }FȡOuRCc`Kի:Xa5Tan )  }gG>=.5W v^f<'޽/J E;5ߏ_l\J_|ke7\!*(`eigtë 4v:4HaWfylpuPG܁-zLaݭݨ\BJ??HG `͜tbms|rM.BVLԭZo㣇Ԡ8,!q,3e0TGu+:t#=0|D/9F=IσY&W$-L$ٜR:xB\vWZoic,Q0-Fg3qkڠAǮ/) 8=.;HLMdͭa}7:֥_b@6gz=8|%@zmsaIF8GE]ͻ_V̟N^QC~_H-nV}P`h !>k88]j+\m6ɳ9D2&Y [C!7v.I/Mw,uwl? K6܅TŃ*?ߧ/t:EmCf,Aw:m/RMBFx}aXFa-dʥN˽a [kM讚 O5>inD}dGy+moabj":g"[wӂK I4^y7JJ( OzEd%Cf΃Ish)ILOy$D:s4=\y0E飗sj%ԔM9 5H:b~e ȰX3I]ml5"YyĻkJ* Oyx]FK\{&Y,WAh!{X:~Hz)UXܔ|R2^yqߚo(\ʪ61)3d94~3mB__kX%8{aN&-]a](Xid)%eo[J3#_p*:#3/3 |+{_^$:/.#{V1=aj^c_菿&o~ OĻD˒ح0C"ڐ_I~[0E %{#*mʉC*̎dx(A]I!UUwtBcݼ%DM!A9T'Tt;f%hK dQN^a tf .kUz ofJ->^cR!xAy_ 9Zz'?IRwy?ĀbtOk!cXfkO2)G_:2@VH+05!7{|5{w̐k}aW[EϿ`NLà)ԫXӲ+/_%-OU?MdnXPM=]90qR'TR, PYfi`w[a٧SE@ՙt+zE1:S'1|H=熸\;IxV8nB c'{v09 aL"y699oZxR*;mɍ)C} c9J7|:%e͇eaPҘy'wsu3n/'/ơe貋ok;pm(0\Nݑ2gj k.8D]g ጃ$#~ ןt&^dL|:r-Յ>! YgA#H*)F]Pshݒ~yh,= n} (*pYٕ%JOvU>2^]À:i3@U!1~S'Ž}Rl=\XͰY0S9Ds xW'n;kp# X>œX)/1 ,|#UP:ɢlC:mcLԄ-Rά|GhiвZV>f&f_7fjFQшkrtJww$خwږ z#L?c6:zl=pᱨOv{'5S+#I^lfc0<{ T(C}~_e|682-yP\_;2<,>ꟗaE@,qSMm#BGgE!L.)>\4]P\?J5´eo$Ih^2Ou>Y²K2`<\ԕE@ "zyr ws.0l+7E>4A}x31_!] j12z#ͩ?/F(MVZkƋvq}yـÁ qlZ>pWnI$ bp8Q(m&܈_EN6Go4qۧLq9H6#*54TH-kiMOP O47՗8x9'oB1x{ q%2խ$hTd%p=g~Zox5/3CSfh4ɜ=r֦>AVVa+҈q,"#540mn[`R My轢l g_^Zp x.LIWD q2m4]&4ێU0h (em㠧dy Ƴfwb0)u>ΰQedwTL[pR,5Y3G 7!6Ggƕk UZeF D<ߨjJ"RnDLd\ OKF?r'DV'q52h(>ֈ2\3'@Ҹ,B Ip>cȨLa 08Az8,;VN+䬿}۹zA`? ̈́$ɬ|%aN̈ UOf͙uA̦/ERC;Z7wwfϜfjC^8mL!KS}mh}ZLv~!@(IVNz#E&[W)ei|LԈ"&g4^oB&ڊX9󂠩7(N':=iqFj{ վUN~u.r|3".QW_St 묇GԆdm]Šh Շ zo3-Fm ϐ\xg?X:"ƽ\sp޺KB%ܛSE_#^ICGaD9xS ^+v\~aȁ@r#abmT$~Pň1t+F1}*C<4,ɏo(N:F jB⹚j` \.9%o[=!<5_G~:ygo7}s>s;ɘ+ӗ'`x7LpzI'(8P:r:{f$/ ޣÐg6$͸Zp\aCg$אlȓK ~:VdfcQ GEgVwڮ|Z1V t<-稞̽QRz_?([b  k ",)Mb Quʝ`Bؾ#H?;-Y ȍaEYo먹j2KZNT뼖 K[nj>,QZbϗ^KYc!ͷI N>PN)hf EP^CVnJm`~ }hEZ^ߚ̻hGR2=: H%V/hu|_^\\?GRdgp[BNV(liXN@m/mߐCAT}Ty-kpBp IY&YѼq{X{5˄lI{}|{E$B{>kvڠ'ՊYI]/2GL|*uz:N͂AJoxTVL\XUO\zuLs4ވ漀QT €Y"㡼^ _dE.wc7{zJnU.v}E1!{?֭6&Պ"n 3mt?I2' 4 8ˍcsWg{fT,@6_giͦ0__Y.#>+ҜszQdjԀsGՐ@=s&ͤIǶt8Bǃj-ݹ{#Q0b8OfToY?:)2Bю WpW}I iF{ZQ+uEQWzL=Kڙ Uc]WǾL:勬(HxEIiMFM&ToV+dio\KQM$cPpF9$[W̭9|&)`s醎vV qD:d!f;0 k_Nh5nc@7a>\vI6p6-<xxXZΝeu V83c3&X"b/;7CC:W)c6i'扷RP,NwpE9fI`miX6'F1#Ne%VN5\;o|p:as~zI#E$`-ZY;Trݡ!<-PaSF3:EcpBߑң5)cQfBSd\zGS$=LufJ  ?,M tCebn#l5&r嫴˫}M C!Lԗap8+_}Z&~%9_Vy07!!~3HnWQR}mRbi/;BSsF0C> G# 7gh& CMR :g8AGP8g)MҝpBwYQq)af/i\6:1!>e0{2wPL]yDd$xnJ^ N[3{"MDZ Ο<l_E,V:rGaL\|ZDjxdH`m9q\P!/™`:iceX0_g/hKԾWYP_?*Vm#2M{ɳnUz:l40޴U-kܗhFRj85sVMC8՚z7~4k\KdEuܪlK,:9AK3O_UL25`hsoJˆ4!XJz*m%H:<_H((tIZ`bߏ%7ь1ptK`kAD[A%OW!IYtX|MM7l]*2O63~e Kv F0 .V]@'ҿo: t1--Bw u>LPq qKY=P%H&:쥭tk- e!j/ݑZ/XGjaM=Sj1y.B+M!4%F2<$_|b>[@ `wۼ$8-)1EmʅLgZ q<>"9 A1G A ҅gaOw#{DB!ˠ ,B-e%R=Lt~ }ԫL}3ƢUSt48sdӢd0Fϸ#ӮK!<'re,RaC_9@irV\ "Nɜ}#W̍OB~"}MD7RW?rd6W7T,}~m=i9fD'4%kۮ{o"vQ 8+pYw:൉<+32*S$0?eCDVhsvT?E]<Wujv>g\ZTK\YΛ%bݪԟM!åcYD˟X59,ʌKAX@t}/o9Rl?<)`h9^@EJW쯤ۼM\`>j p9UAKXolvR&_L ]a]hvBaJC/ Z3wA|fpXB iNi $Ja{$)運PB l0TWqT%}*zDp:؎3rT 诰gpNx?z朡QUe%/{qBؗGDɬC_ 0hlt2 `Hx'LBg?F/=y̸kj .D3Z  hiJ?Xu,AD PVfwLT%}1=޿ۧR__/ZVImUZ I5#y_:w6_(wk!3\ =70)̇2+s>9%{ EE)y3! ~on2~%O[ׅ &DtX .8CK֥Oj,Il}T{BPpƧY;K-%_KEa/Umtu[jY(B.sv 1 @QeMOb5_X j M=L -PbvAzfE%Q~ϵ4oվ( {П'i Sso: ZS/< ?Y{9^HXF!H$=Ƚ\"KoD5ЇJkaAuw k,鑗|Δ}CFz 5:fgH< g=[ z읷=|ήqW$kZˎAH W2!HМ1"ےp1!Mx+iDQOo,䟿ݹU*8=s6mGKۆ=$~]*muW9ڽqzo='fHZи|Z|rݟkUOΥ qnF_鼠8d)gJϭGA1Yۘ"_{1ڎdU\1rn{ELVc9Ko1) `l>7onlFi]bҚ~pUIzʁ+%y͹sb@r2"'Fdߑ kzy=YKtp⇉ĕݟT^j =;̾?YX^ޯ/W O8]f1w/*|eR0M_~bpO'hsѪg9h~&8nH$BBzl+]`6tK1z> B45[w" tҳ-lbl^Pp?ιbTNi5W4WDz`)gZgsiN~U?&ƥJheԽB{MdܼH;POxo 4 $By\罿>5 C7Ki<Ke-EjmI[m<"sG-,e 7 i"˴E``64&<2 Zk4I }ʓ?&=kt䉿n[!8$o{K ޸3ߦ,+ -FO;MACe~t Q/e8qNp`5ѣd@0OKG@ t03 s)Oigӆ\(vWeok03i~ڎD ? Wv F}8ʼ~ 2)7ET5íܼb\ 4(8^08O0ik tSRn[έATqCyΒV^&LB2K"h)U]㳌壮Ji;v<x`@yHVtkN:"-~h)qWRX:6n^};9XuW{ "s'<ݱK+ 6WƌQH Z%SfIUu1>'d9MZ%/=дVrz?!+@a'f|tG68D@8l7Gx=hR&qz'>3R~/? X&VPf?f{% w..!y\ʌT0ZٽR`>3 "'Df넙E &NO釴P^V[9tqKoTHGH`w,KR $CM ep: gI}U' eK w@uA4f§K+ӲۍͧQ<\Uħi_Eb\tU=S7%6/\j ~.O%ʝTHruWSCWa F!-SEy?ԧ9龭 :|iTa:QWzࡱ2Et jHFv*] fU#~B1C&\8,W /4{[&A=5oÂ}PcIzkpFl`w<2 "߶!Pt'{,Q! %`xMH9ܑIdmFk;ȞЯ\>Zds=mv 3H}URW&_%<ͫ\D֎ b pb2:ڴK.S=yXsNJՎ›g"]@y^4]۽.T|wUCaoĢTtvOa b5@4fė: ,Z?h_x]DXay9{֖S=.읂1[''ZT& !Ky1=*$? _װ+t_@ԟǓO{*<ǽwJ@`*,@F^6.xe\/bET* z.R8(17Q\epq~(Gzަ= /+3QůsPS`aE^)4o_ZM {#Y$c 4->G򧆙M@SvD7O!gMnÅ+b> hRr yp tw h^wU@N迡k΍`U@6pP%@_u)z>y&{dX_'RX)MZ[vVpC&>c7$J!xjLJZs[Nkڞ5|#(B}b -vCj) @X>CZOi kygʈ˵Xu+B7XSO?;|X\ ɚ*T Vxd%Ǻ6~TC( 6әwA%]ߴW=C m߂IUޠJ{9rbd^m-сqН#U]A3Q߶ ˆ8D" E`}[IS5D P>p]\݈i8+^]`1 VD6Dp"xDVh62Dy#4‡v_2 tЁ5;鿉o1U[738%n}̣ #Y(}~Pe_G~ynQo-F9;^E./BEyͻ~ė+Q:]v AAHHUL+xb1 *|>+$Ѫߦ&Ef ׯm+_1Jd #?Ϧcd[U)%;m<#zp+^Qv27gA=SȕOA jXwאOiay86NON_SZO 3 8ˬļ@s7RȳSo N8ߨVRCۨʎ 7:()-~]t qqkh+#9?VjL@`ߟy#gwL3jK|RR'ѠD%hJKS1yo'-:WVKܪ~"VG~4Z=a#n;tq4g',{dWz3\FVղ w1 ?uWӕ2( !~&4h^ôշǧIxA,s_r1;IUF|X=3rϬbGP 1% q:Ti̫wK\_r͋XˋR8G7y292Q:`_[uzT2NvrM]`]}uW?Xr%:QÁY}RHR[0%s&p6,hM%++O9m&|i)o3":vǭPcd`5#8*KTpS*\R.- e|lb10;) YX(EPpn ^ >zI e7}k$xkI8#.z>BvFio}aVή'Q2u%NuT߂5`-ڪ+Ť;Isځr|wn9^r1 oTF95G74E N[_Z5h:87جLaH! k[6iN/SL{rS 몈n~I Es L^x~>pPnςMÂ.2xS^R{D#Р>_5/d5ZPS.LVp.jjr&V{ }Wz%C>=#>olPySZ :Ιjb1]x9"?e ̭|yÿA;{Fa!ѿc W=V!y#'אc9%+0L6Q2t~ ZD< gf] "HFl}^˔s3U@:qt^4=>)T߰&uY}Etg h۹ eS'"ʄ$Q-߮Dijy5]-mpʆ*2HGuks bI`V` ZIP|0UlA0]1e~>ܖɳN5ɷoքvϿ-rP*?NDE[]c:ι VСdHLH$bC ͔tBl5c0&V3K T9}\T2 rjX!䘳\~k'L e{5tI}Tu67'`hU\[wi~TiZ Sq^rħ*%Qj;/wN)%:EPiPӼ*$鹭1=w}'0k=SUy>k'ĉeStkk<,4wY\tUfm:!PԤ OȅDP6R*`dq^@.D/0\D?ևGv|cA_6F'^G uKkѿ$|iJ Z6g$^⎥4YP%MHan#|Gt$sb % dU0x #S 'Ǡ̡->̉HVnv|y/H_M+:(.,4yHξo qwׂEZ2¸4HG `K3}KcM>dX T4GF :p&f9fС/ڡ2A23/yEquҢDKd#oD9KW.kcچuy}FE,p>Jf~*ۄL~<[w97}_H_=l_kIυ-(bаQ[wC#i.%;?NwpwMh~UssۨL0/$$dߏ5[ayߵIK}%Ufi >IqK)6)EI440C*#:g$WseH ցw!N{C^-Ô߾0,3pAb$J=fN {y+ju-$z22D3{VUI"iH?YK R >E)n~.Aȫu}KK3oM)7}DT)8 9<Ao)Ew-S0lw/xy͠\a&4TO\ˁ>O&: aQ%T'kz WvI|RU{ w#BB5B_9.uDpr_(8,\DM.u#"A} ? &>,ovChV\S_Rj挊xl@TDa^c$^=H"Lr' EHuBdJVB1~(_.Z։c+ W,ٜ 0z\$R6Z%ud  $_p9bƕʜ|Ü2rH!|(FhjaHxDm gشiѭ7v('䉩$'ܵyaeA H^ȃ?D"//*eY4F@PUn6^6gWH9G! =WGTϳO PgG9^iXM}js\HI@XҚَz,B}U0HQ¡-:W$:r 3}~K Ș6S ˜?DB{-<("L{n2>rg}lŨG<] K,ocly9Y QF4qy-zH_ۣ25qطc Kw5[/fCO]CqgSxiFV=?/C W:u'o>AF_߲HÁ^ƌl^KSٱ8I^.8+ {(FL}9"$*GLa.vF6r1$'`M}i1tcn=u71|z>[i+B3%)kҜx8_1P( 2hl@o Na$[ZDZ/A3L10QS'7#ӯxD&27D̩1b-MA&գRf9^0{ LB~q6'dj\M&z62 GNV=o&P.6І{{K!3fX .yJJǭVF8GF3ƞ<)#`7W3zn.@szpgSʯB,OplrII%B[lҮ Y۞^e,0G9'W#Gѣo4h0[ߍ2 ~ZKe?dF`>zJ .Zf{=ώK{!>\Hr&_F0t(q@ N,qd%0K_`3|)ջU$m[Pk>9IR5ǃ}2{* `Y֖Q)YT'(OWiZ{W|_6Ԏc& Q.U(D֘z48/i VS%uu@Q(y$GSDiai[[/A=QLC8} /*HI&3=&8clwhvP˺N>"R6ʶ@z!|m*W}"I/6V/kSםk~Gi^ӘV}-%9^ FaבZ{)<-UN\oSw `[ [NpMlA*X$U5_7/U{bTz 6L!o>b_*%ooTtlo^cEZU/L J޷m-)$j2v"kFTh՗^-|2 -UZDN~t5h(:a~!u )m_YK ?@0Ev 7[$V2hH 0Zo{}Bۂ#1mg%i!/ ?|c$,,ecm+=x(&bZ=kpd6(DJp9#}r@IetT\ow[X&/tHcYo"a` nkK@XYmWjլ 9[Jc6kY $S^yDrl%TG?B̼n/#nd8H[tY=gZ2Lhfq>߉x<[5&__zC7q[2c(#08뗾0zGaO}HX#Xx]Rm6+HLDirW}PYsYۈz5>f7ȧG>0RbDVJs'\U !>Plqvv{TqUGx+24E磖"u8Q凲Mck"27=%?$Xx~^} Zb[UI}FYבz}|dgK6Ukucrb +\* ȁbA3 ї#=Wq7oq:ةwILC摕CƸ߱rO"%2MPI#=z~wKމf;?+Hvl5[%c@qҺ?܏: sN!55O늫W?Fcm)s.2TBjچ}]$!\Jj\8TȊIhR2:GZ_R6=I=mXoғ^%A?C84{\i׳bN 1>:$R}ȏQ&[ Ɠg" v a_Wf'Jrž`pzΙYuPD R QYNj%a oZc8^o>.EЂ u%gDc %r ޓ-SEQbuˇ2͎dv|8c!“︆ۮGF*X]%c V|dV%6΍ĭ"9i1C!6J!\zxDOE>\Y}=$E@JsfôzIWCGx ֒7%̈ePAu-.3v,fe?_[oQ8DܸSZr]@D)}I炑J,Y9\n+jP !)p2H08?Hn0=F^G~A5rt[̌ۈhV,vk: \nH؈l1tUqe\鿰Ö v A?+.A2NNקxƘYi[:԰'ɦ}/F$oQ\Vz\ק:ѣ_ag/_פJaï`9 [@T9OdD67,1qma\;R"ѻo RdZ4Q&>4oȘ_C x.|I= p Oԝa7¶K37kM^|;`14Y-:ŒL#@4$Q\5^OrVcYތ(|u}SCF@ImXJznK6ݾ)'AD~){Og+pI]*݅ꭊآr/x>B㘲>Gx4IN:pkY=sn~,j[fFr 鯪 Dxe Ħ΋vkzT W/լlB届fUb"w/~n_# #QNc H3K{+<0#G һ=FiNQ7;t!^ ~9eηAK^=]8> eA83.³صrL )M#sq_~ʸWOS%ucI8**]H?i;.rWCS{T]_qsr]7z9 >:1[LZ,-#zѴMѺNAYmֹ\Lw] z]/}()T-?u]HV8, D|Ec0'zϣ5 FPL{6$؇uy6ngrR5`tuskaօ_wV&G_W|u7(̓{Dq(+3 I/3ezJ&V_q cU1sָxʢpɟu !C=RW藆ף!4_~l;7 /ujS]qbKMJ]r'>ISHuVW _1V@ J=䠠)`"Rgcr](i/;^VѬMyo w`$¤|])ezD?#Q61SnĬ#30(=iT'aV44)P~tGaC՝NL}쐺b<;W$5NcF1aCojCT\Ii:/o#L|vv9 4A+vrRӇatqK$P ZQM74bTi=;@m{ß#tcY  aۖd7{_5ю-^3F 9&[xIk:hu%R.4lx1lbkZ%uxf}~ ,jg~^PNR7rz ZÊ >Uf*ROi牽kChy wmAIfڤMި|Rkz$GmRv<,8W[Wc_||3"p|0ByB 70ktDaVp0q;xn~-4n?U@C)K:tѼtF; Sd1DLƸ-ldyHF0`J̭4!j < @=ws>4&/-ǫ1B%#EoQ;],XV$p̛i$TܵR۷!͈ :4ʢ Ry#Htgק6[E9d[=a\N9UoSZK8bЅ4X漯͐%/+POc[R q~l]:>=\IC _45OZ"^踆,4Tp;Mx#Ga «b)%Lt?hͩa;*bxIM1"ﷵhuQw5ήGִ$ӊLhn>`_jzo=n*oKo:;;Qم!G}Sy+ѭ7'ׯ%3Јj-o/[0m]999B!Q ){\مT!coA/&F8aGn}8^₋@1br;tگ5L${,*iOs '=TyJvż } Ӡt:u|g?aZʿUrB#Z95+9ӍO%WQ^/3 ԾVQ;Rti ș5nWg@8tn?@ׁTR `|۝@y&1՘7OۦMmnMlPVrEuY# r2c hiӟr#~7.>y&as"CHS<-R՗Ԧroc:Mw[{<=b_e)E|z}D;v*^2W}CV}:16F5!UqIHŲݽ}vDo,}B5:{yޟ5ÂO9y홆}[nI{N+_TNH$=B{|̿J}Klw0yhV},w+՛|̩c]+*[JnRdEv>G jU {Giy`жR^Akn_(u^-AGs*a0Ft1{t3LJ"1XQtֽ4x](A_V~'-=|u%7<>`sW`ğ"? ./|݇HW=9iG]IhE&G).iDrJĀ⒫$\$h?@Cn?>Wz>|qA5,hA{;_AcikIӠ`1:'ygA_Hʩ͠ 1KҕXIkjƪ荙5_sСLѯ(j#TB݌Ntze3nX7"l{5iX7f_~* ˞#*;*/\9/Fg~٩J5AP{E(:`|wNȁ2dކѨاWI"k2$.6+ߐ3|%A$KO:]MXe4b:BOya}Np"7S"K^5LSKe)BʿDD7YdG6/W^8 H%<bAc% FIQ.`O/8=YھGNXU;&\w9!*)UZ$?Ȅ0a='P 9!X u.kdZ$UZv`JI}58R '+XSeQ~W*54 a^I(o.zUWaBZ]_$#2܃>88?)65j# m,Z8X#$ۊUv3ɆE6Hn(αPyWjPY5EpRջq}PMoAEaP_K [$^;02c)I&~żrs9kӫõ>c޸cykh8k&t=ExP:WG^BS+vbHZ#`%n Q="ʑ5Y~`mKf"I ډd4Quneoh̴dA])ۄNJAF# 5z\3Vv^MaH,.y,_ OTx 蠔&[^pTlmy qhlw0kD_q*`i҂=X\_x(ԽGҼ;Jκ  Ė3T/ VRMaMUKDs0q PVqV9t:iVIBCuO ~D33T^E ciNH|H|ſr qE!w`%9￁R%(MF7T΍F3)Ῥ6y*/GC^-ImdыfWVKQ nWV*Z6q!A2F@WS=::ܫZ%`#W^IJ?;7wW G ˫0,pOLxB}V*lm4n:oF{W/~dۆE#_p7a&Pst}a۰XoE107lv_}c[Xpe !(u5plF64 h$lPb\_2"c>nEbnTR\ѧw_M^s,TM>23""'6^>:}baIR"?ʓN tc{M:T nzPNe%s*TV> AIW^i}g3ѵi0n.
X}6\J'AȎ:fO7-*7{Xi*HUꎱph TƢ RRD?1;a"36\im Jo--\.i=69-g/ܑzE)4p*R=׋eo|boH>i<^|c,y]Xid3y<@uR#Г nHJCFаҶ qd^ӊf]f{EA>yFMb  {ͼPWDI{Kۥя"\5D~-BN[h3'!3hyYHVY8 x~~첿=u֫>h4,똃/`c79|xO%6uu]A ouP Xo01|hJHPt/CßJBdmeOY]{١H௠FY]ŒTݯyձw}:Te;Kle4<3̊SLE1C{MQD.+lװÇ '(^zcRJW춱 P 2]tAl@<^zƋ ل(6dNB씟՝_7& *v=djDe{j]o߱hNeZy8(}'bG{4QAgXk#FΣ-GaԘ,rM;>hR*̲;Kc~xJrtck?x!>`֝+]a dPAcZ |H!ee ^! o$=ǯ4`qSiSV)*~w|6ʀ1"F6<(ȵcβ(hsWv CmC;2ށd*"n{>a/=+iQB~> .&RYX1]l[ U+,R} *&0P&'X:|E7CSit7JaʕЧ8VP% Yop)mB{Z}}[\" z ;rvʛmyen ~Ga+l8ӽ CB+Wt͟R 2)1CɃkې`,d{Z=0=|kPB@3/ W7"$G^g5t<%9p&e _R߉ 0qS;h$ '!P IG׍ 5UK%yUu8?F5qa>Hf801?]űr6rҘmܜ$o7H{i3.3>: O0 ``Q $e>M -h?k7ńEg7O8}~pіZ@* 0TEJDE(IF&ؗ+Gp"j=!Y~SkG^J(*ǵAټou,usDbppnP9QC}>'@rK/Q ]q߫u[*,]KeK^)<άu*R٣oHB#P"=E -MVԺf <|Vw&j]#^F S~cmDsgc46]4S#psoGd]~yTb ka8WJ>c>:2UObxZCpT쭦{KUIvc4#%%x^g6젵,BꇸO~Db MʨW(|67\Q$@r @G+&G V2bW,fAhOlfUr #Z,E>&'./On`A/^AOH!#G_|_B噄'`M y8 2 }r, 7>YF'2jϭ "pg՘% ?}nBhz2yL{6w@T*puoD.3_QosaVEÝH2(=!/V @:ռkk5K JySw$gzlf/y;n[ mI c[at|&C D6yC8yaJ-ʗHMvNbwムJ7i9}ݷe6yKy"T7{6I-d"sy#yΩ/d´ `/D!G8xzG#ۜ:W'4.}~Z= RŸ#:~4gX M` p!#Ɨj8 dNƧVX'%}s5pCۅ:SG 2 o1\=5sKHS/. PCc{ev{RBW;6I2G~mlh>s OxXE%T=zp}"L$ ,{_` X _kϒo ;׹go؈g&"?1<[!Zt@[#f%&z|~w(?ʡ BYk7d]P `E`Y1,$eu/&%#yI}'&Q`JZnRRƯBtP 4slcmxNm/i#|wT`L8>iLfe@ëY }aaW6 =N.Ւa-Zl}ـ~dG902[7dIH`MnYQ*(=/r.Ք,G`l:6fYRb[nl0 ҇{9x[QF,}K>`6o4L5҉"#[#:@e͚u,Woua+ AF]íR¬4Bv(*x2s;>wϼ"_ lu^3.Wvc;#9- _?,b ƣUލ[=oΆ--oD~0p\~͓{^ 0a.K/dyD m,Ӻ:1͖ W滸P#cLq z]>\ro.-tRz9S6pQ/q'Ji硪Y̤GcC#֩ḹݾ {V^9̿ܐe)FHzas Ԕ,:ozXT}|ЁTZ1kC-$ۮɿ?}/V3}%8u7J.}]DKэ >]Ik_Q_x3ɩ ѷ>|O\l rN-(1/iOZrh80J~4][5otAI3īϱR6Oףj(;),ai` ]\Pbva4&$!UV1"9E9`55zhYvajw3JK>g'UWzpMn&v4+c8!D\jU0yO,:Վsé$gt:k޿߰_b%_[vxc#TU,pNq`K-FUOp.U/pZ W3/zS'8dze^{SH.vF=X?#M Waς3;2DfXiuW` Q\4퀡P{¡5URV_2`"r፳ mj#/hy5aE2)!m:T&zT85YÿS:˹̜ j*pb|ը,[P%tt O0|<88MCLiM O79$Yr.Y7GGM[߬h6,Ho0K99X8_]m?.U;:>x;X4xG+Ud QԏQb#uvw$Km$.z{;!kYIrT[ۻpI}^vqك>Ѹ9+&0|F<8Vn+WB)M/|hc@f$_$ pXގ`AN¿K^s}7LqM +}lD> ߧaKȫW5;E$A=+- hSh¥>&Nk6ٔA@k= 铹ߗ G CL Dӏp81qZEu٢|I=1QDkaT'o q/d W$6F6=1h~(D3"!KEX8˝4p;AAv:eT syQb0۰*k}?Gu]TpaƼ])1ʶ.8zbRȍ^Vf7o.ˤ恳h'-i^vҎ4k2{ wXy5ݞ_-F]a52@TŞ(=z/K6<о?ù u~V1e܋&J[p~En^)^8%8ϊ26a ܭ3\"kcLn Rn##S57(gtZq˪ dM y(SMD((4>$CXa"y6+V/fW8z~Qx Εvm8l:)Z )c:lX}ͨ XfX8p%PM5 g#-: m2tMAjR_;5J xhѕ!kcO~!#y=tN79oa ԯȮ |xa&mn m3Rg6丢v,>Z6cz~Tm@ yZ0 Qd/XN-h@s~]:A8>Fz)*GTXq/_ X,At0ROvc ?~[vSjV Bq{oVT8G3[$ly*o5a飁"f ^ErP_p1dVY:B/WE54BOv,4ʾUnO'|s 1{azŮ =ؔb):oreM)`ߋ 5ҽ_sn&CTL-^Ji4__v'Xa=Aƍ8jWx*e _|]C6P%k[fѹO,:W:U̅TR"EwSM4,5#S].yh*m! ߔ/W =nE+6|7&/VFd.0\GzL<($,Roa9䶶lĪ_d"uꞚRQ8ZLrr ǚl»#R x$q8ޛj4#bBeYSK,*r°l,9HX7C㭏>`;#C{B93w St˙ *3*ь^X:ð;d\D1}ȏ݈#(J?3x 2];WkKyu!ߘryjc˂{UuyI5-չT`E-`>SfWW(&jCsi6V7r'$w0!|F]#ҮT'KZzn>&#$q.7ݵMwRbv Wxtw(S4Cty>qƭわ{0KD__U+mox9ɷƶv`&|!_4!~8gB?%smPS晟_Aȃt}:>oE^zC1يౠ_T? Ry"J>  ~-{rpO<>>W򬞤Tv&DGሆnli\XTf`_y*<ev-%zkI^|vWZ)r4t4} Uc8푗jH};m{| Wk^' +$zkBB-E: V~*"gd:5L0дyF)O;l9sҦl* ~K@ث 7b< YQX-qYVrVR>ܞ[毋6GEN|5ĕ e\։>4O@>0O6 c3] (zW.+]֚}lp㰲}go>T@x}{I@*ggp50tM}R!o Ӭg"GloCT4̀W&X,ҋǠ2vBs,oWUVg\!};-0)t(RDLnlà]"oǖ`dO\ 3^m"lѲȝ); yջ2y>b{' ]nM- GcyӔs (T?E0 K)n*<3YD`p/1hSM)Cb~J8udc-kQz"wΞJ1-h4RƐv(K@ Mz枋H#h{˪Lcwx\dw'(8zGdg+J;AԎv>yhvW38V6a/ "IdaUz5g$󃇯!l]w+=?):38(7u):Wiٳ(vPvϔ.orr-{{a "Q<B{5W*ǁ>?˒wG^h+_yp88H]]\ kE:}1FKpl %tգ'6J%d]/_H;SgBS]M9aXoQߦgCCsIѧעRA}%ppYCJZP Z"BٽLz2P,pR1ӵ̛hD2ͣ!M*DᗉdЋ'w 94ďuGm1[SVM9Pގm˚^b@ւylOG4vD}|{ ;MN (yWuYx&'3Xj953 l*ؤ QmAQbJF@].txjE $Z+H(=w=]o>񼚉E)7 A^= Ά/)p./W(ub8'Y-?aY6G0^0cyk D0CN"nxmaOAʈZ}•?um(.\/,yRVڮ:g^i> A}qk':9 9z}7o{dO=\Q⠎[hNhzqO*ݘ?*vp+4W #2B[5v$!/X~13V6cv58ÍkկǕ)GyO fp>OǢ魌vN[z\)i37$1A(cyj1hB"lP7Y߶rԖђEC5)&bQ?14f"Z \IJ@g|\~oc8(k( Z'y'VgZSom|E+ʙ>3O"u#+n%5yX[[M 3Bl}¨T045`VpL?m+1 rxY^A`=q84C0k߽MD"0DwBMk.iJ*ж+)7p@E1&r] ݠ-ALRtԃ<)i! \)2X_l i*gOIO=<\a,#Hr~R\DLߣӄWxۄwlx_i w|>>Şw2oK\T,ܧ܇h̶^9{hĪY' iNnmCfѣ(X: +GBzOvŴ'פgntb]oÀYnv7Sz[(Bf3!`N2cyuˌc֓8L6^ 4.nS*mVYۯB~=Ck߇>GPGp!fd#pkTvSzo,+ŧ}\yno-ӓ 8{u˙it˄[r*6$#;wDfW -"`]+TC5'Wc@\1Aw Z,g)u G/M%t $ )䱂L5n"-Vz3 ss`*RΤi#B@h^WsMŲ:0}Y^&? Ėj ء><#lKg{k'gˆLr .AQ*G&&hTu6Sܥo Sjz!/$Ob2Z_^Χ++]햫u)7Й9 !k º-(-=g.ڦSҝXQ#]63s rF+ȡH8(-DqL,hj72HY,w?kF8qܙo, &bw)մNw_賥:/vzX̩lb!¨^9Jk#A?+kKһc+(w=2Cf)x|7a08E?7OZ>:>֋d[%i,֕{1MLqL~NA:\Y@i Yp͝1u˧P 3Ѯ;(mZ.֊~ICx"NV*쁃ɍ.6'<@oA1 .޴KWb(ѹƞwtQvhʫ> wӳfl6ckF.4JWc5qGcC1jJh9J9%񈖈  Z{8v!F F7MuJЌq}+m KTx?S~WpbpTg6:NU;G=.wtƍJByX_GDV@ƣ0$"y0Og<8R4d|e1p4s!.ˎ3ά~M5n Mm& &`ڝGkAAO7UFsUҭ\+HEOgNMoړo 7an@P ۨi>%O`~ޣGy n֬1'LsZ!:hcvZhaEߍak*h:tgu55)gM)ɠ|qxI{{Wl +mʵ'wЬsn󲬵ϟZ.) J$N稢s}_X?A2ra^~V{T~X^ ~<2v@yi0/LPmZfU*^"3J􋸚%kJ2c|#Iɕi;'Gi*Qr!0p-`*H RslB{i%zpf,պR5̲U1< (``罚7U/iԓ핎}{~oԾfh_`azi:Fr^)rT"`T:_T[җ,T=3Ui**DA_`̑Q! <ΝgX=M^M`BMDN9EvHpqЋ)9!śrBP7ݑFϋL3{Nnx#PS ȍp%}o9LyJ߃ͅi7&%8 B^\Pl/tN+uqre45*7}{Cf8r=݉rWl /X Zp>J< N8/g*7/A е'Z3;4m׶uU]O~n:;֬2"t?ϻo~)74[Û[ ʔ imOc[Cjj-ڔE'fOi_`KUAA'p7ޓBF΍pKhTvÂ(Q6jmxUKްTBHdD ]!IǚNqZ3at{[i8Džba aR\o=b/|Pmj9^)ߗTb8*p1Ow_c9쓘fu$>r@r *Cͪ.vM %uL牰oϢ7'.imqRpR9ɜű}FG󀖟C+p%Frt*r!2fwq4MU (<6U3fo ]SslZΜ6/R][_O8"v~*\ X<콽ٻ0K4b]Fi 8F=SjNBFQn8YG :><U^Ne3!z TqhŧǩDϧ,C,xMV ̚p^rcVD||Ocھ{2CE}vtcC@|P߰*@XE)wGW0{~3NK=ΛCvY龐ݬhyQP[TM#IBۙ`0Cϻ=Rb}|>|rgz#+ '`g }a4o-Zrz.> H8omLKlΕ2W34t6̉s_C~KX¢0jj&:pn:ATQK~'!fRfOdAT9-k6lFBܤRlPو9QK^L8^b9WKne"~ULxȗ|ONX{ ;uYzaJ Z+^6X O>D ru,8i% #:?t̊MTW4"8c- w8j +pge,SO-}=r 7Z~V#ȌK$(@}eo+מQ^EgEs@2aUz 4i9l*_^wQ&"$½ T ե @}v_.eҽd7>JG/f%c_Jl)Zzvd hgD]1GqG zdec/Q"S[:b&$3~8"Md2v u7cx]7H'XgPgɢ<>Ke[J \ֲ["6H 7> }L`,F?;r%_!7ss+5]RCw YLSڃN+Tr Ry<;#al5wn~"Ʀ$"Ǵ!9f+3jNW0GKh1;Z?JNu9( !}rdB][rMqLZ`AeEY'6o\4oEl,~ؗڻّ.JO3/Ep<\OqZ(Jw<$9Sq=4MˈĚ".ʵ|xĨ %  ca8N,ru$s<)2fڙ6~uKAR~}ngg=vYl6,ez;Bz@@!Vƻ* Swc6`'eYd+fe݀?L2IB}k^`":|J"K uV i]K-V C4]I(~[$ٖ„$}AL=vg>9F0Kʳl*ÓوKao7@Qn-k8GBF9Y)_a/vUo8c4*n^h"Ur}o<|h:M+\h.8gB|ItcwFV&NYNCyjg!3tH2K\94C]gY)f|l4hˬ>w:׆oyT_Yj)^;R~8@p#z^ ;Q;J yQ ׉jnLlV: 9#Vُ_~^ᱤF (nŠ=?B{Q5xTâ9!*iSjPb1i]9[%`J(oVN'QS\i_gFAnӪeoU -՚rkEg9%2n|iR6tDlUVj7D ߿fu;1d/tO8AzF{p&UAjY 5rM0?vU瑌pyk,3x-ߦ|NofFe5fPt_  ˔5gI$Bj~ǷnX氵Kj&"r ]yARߙ23ں+jC9t8Re>/"gNG.QeN62`nȌ F#Sd #A1hQ/5%=-(45#M.7g7ιɆe!-=lr,;a/_L9DN)jY:4LjN-hVZ]= |JÇ=yu-},o%k _ V&IAp9>"<5u>УEb\ 4v028ϝW@ Ym:,dI-G]XD[ 2EZMJ*bN;ZY3둓.!$5iR@=eF?h:ނ4 O>OZ2Ԡ&nd+ \|Kaa?2WYԆiZ k„M Wf\X8pRPѠS%O w[OVx? k0QZ?56@9:rP@,[r@-g24M,cTC_/;x8i%e>CT/hƟs^#]Z,UϠm9P9gC4ޒFb60+ڿźk1nNPܶz"BG 0_t3HNpP \Пy*:U~IMk4 V^N nhhpԟ0TTϻb*~ReRk~s'u-yr|[Iy<"^ ׿OW#A+hYefZgba8zy<ȡCw(}Rp^v >g!*߉!LUSo^ar>[G֪i 2w|ƒ-f+WR,^ykB<he!t>R{̭;E P!`V>sOIbLUiꐡe*j%\`X%W*Y ,dLڑ3`̹jk薾Ш%I_P{w>B9K=X:--e)aR;Aqw~iAB> OUݢYM@SD-̘Pj&I᫂$4KN]/j钕:XBIVmK!_y+~Qwc /1dN8n&]nA;DI4FH:, c4{w16bGl m dz%p-F<0hXk}bEyRSHؠgֳYO)O}kH7ύё|bXfUjc)G+څV/6j~ɏXR G;&tO&6PJs tcN4ԬA,76sIN@_.n3qK=NXNb<z~2xЭJ@_Pf#N\XǼ0f"2-;T 2Tu-].Y*]i~'Ձ F3 1ORۿ|ĺ acqX0$xs;C+{yh7}_ jnAvi ف|\lcj]`6]iY_kZr@R| fGg}9Q Q׮D((΋v (uXhO3jA_ꈀ&})FE_vX08wAVu/F ¬8V wI`w}b@oa!7ewM 6>T[/|3S{ ߫ؤqT}263ڤ#ÌbF,=R2T5Y藉~?X1uFAͼ@s`Y[M;cJ(蛈qkY;If$Sl?J oN kR_ʮUyE҈uмh# ([𱄇 /\&ӤdPUs+rw)P;A=O 9_l2QZ'l?F=K|g%'ѲzL%>Xbyv&: ~}/O1VGjάa(%.áEr+[!Om6JȋW8mWUE鳨|3pA *j#qr\'C,b-~@up#K[Ik]'r/_Q'g#cÏ#~_֓T%˔X`֣LhL5]_1dT ^RT0nF6v7e[w:. }&pWӰ*+Tgz"܊U~V?ST,$!v?k)zNK"o~E!q}!7iªVF88rL$U2}gY1k?ik 'snR|eӇ{h V]cdg)6WNserlWlL> XAk}Li{ ?Afu%azUY^  c<`|fx*XA;x{[ОS :0)-f}W E&DZJ `@oɿ$>}?6'Fa>ЅE"Fd7_Ǻ'rqJm ~=o3u=aΠyb= 5OQ6.ۀ<1Tte܍R+'\.W!ozoҪ|针TGBwr\AM@nyD)]]#A#Δ#Sebc~.PL x% tS-&eW^V)'O':u$'o&`n, =쌇>c[͝]FOb̧? oՋ y{w|A1C? $cc5A܈Ym3{|1PH`@uj{z EO&UR(1,-vFw"2WƩ3cGuk+ܳԖ/P+6jHn"+)θCbKh:ixRqik( /Yj96>kFkޘF"'Hc[v,~}_AG)c1+,=23N-xd6.ophC~CC:3(&|tFcAQ6'];J伺BQx|lӯw=W_wI=&ڌ )4_F `KTxKxЦn%gv$_Tʠ)#?&@hZX ad^2$)_W:a+M}4a]`dqUFg z<$x=Ң 9(UM*2<ތ~VkL٠bv˖S+9G3t@?Oܿۥ&b6јIkHN>:êHW;l #!v= D)X]XZTyocHV d!׸hk鐓3U#,Gbɡ5bv[9?~OuKvQWw[J}TrO VY,Oepշj>SCJ%g|٨ٖ٧WZhL=z@prXa|נS5 QGAݕ~TueE')ge?!?M<"r ͗$vtxw ň_ Ĩ:>KǓ- ,;0diZn$ ;b{:eTTU\s JiK^@Up۶~,O]!D^Uo2lzu慫MRxy̽$BoK3 {PK+[޵Q߬E z)Wo؈M7ϻi=#C\s;׷2]}4#dwa„J#jh$}ܠ]m F(=H .{%'O05?10Q;0@TZV?6(7*$zp P`u/;صA xgƂ^] 23NFM~a}ҥTJ%Yſ)!ȗ.؆ 5Zxϥ8T*ǁs{e ž^Iq>"@i;cNg{xĒYt9bzO8"KV 蒓j#ǃƢp4*A߅4j505ű?/=ܵ8J]'3P79X8Eev3dP.7DW٭հcgBMxuWP_,7VOh,&V=y Doz'hyH#pwgZWCZu%W9DZod| z"!@K!!ϼ GT$S>Fbw ʇ ZR|=:@A͘bI jir,ۻ0ÃȆte|!rQ"qS- ryT\ۧkُ3 M푈hf7?WͿm`\[Qԫp?JofVz}D:ɜ9{}7n:.\z4gv)y` Rwo$ X`C쀁&:\fT_=qeV?&<&Cn4 @J cֻbe:B}:ru$^f ItTBY>2pwָBETՍߴ)9aڼ13"ҙob}rCQ(W oG5z9J$oHvCA%ڍhL?'29b%apI e0r18F<ϓaldNUP /y_ d=)w=xgE p?!lSj5jfW_<4$}(,5OKC7rҝmH1 c.}]L8آc|Prۮ,)Vhl0 ݐkǗ+@GNVr 7! a ./2DcߖI >/bG%ͫ62[p.&I-?"xz;Wo塺REO#2!YSCzlPr/!¹f2|wXakEF;~ǡU~q󠥠@j"òI|[xWF!|5d'cE:s:ՃiA4c _Gcr LU^a(r}r?Ǯ@ߪ UEm4!?ΎܻXB?2s9O.z8 7ol:{|"<np~ѽp*ϙiҷ؃:v4ޯͯ= _E3.C#xZ},#yiõ~XsKFcLK#~w#q9[7(2AA5A1 SWh%oԵMTJ5@cvFֶg^k;dtaqlc_pN+@yO;>n#WǏ*r#ϗ4;Hzoub }A5F`z0F>!VpWx%6G,~i@E<;+ [G0e=[; 7c2~( U #*+vQ%nW dw~{e8 !%-w}w)S@EaNυ%'{0X2gC?=}K9OX8 4#XNYYU[.)|tAJf/'t/obq3田#=e!LJ-+_09o9UDa-b:f Ior `NWY>uT kCyU)1J^ ϸGk$Vk 4|$SUa|}8n,VkP#kw ΢$'UJc# F^X8/C16A||+ gЀ 9=}걠4&郯 '!U}wU&Nov0cB`JO}T8[B׈S{ƆՔQ{4&WIcxuomheaY0?/ Yoڴ^yc m=. 9'gEzv>׾;J%oljX5Xhtmօ ڑ‚DD=MgkVEYpR u՗EpIdHś,<9ةVzfEsgI+(Ҁh&58zSaDdn_(pȩE[ %Ŵ)H>$LR)@ jo-; B^3yo@*#Z>)Xᱱ{A#f6vuuC/*f.2^mhFQ[HޭRkٱgԇ>cWKI YʩT9nx=lݘQ*]ƪpA3 _yֿ$) 8p#^O{W+}e㳽>%"gwj:οuÐh! rU$iVpi"8Q)-WD^go աgXBrs7'n]V@9Ʉ򻽢^(g "{Xb&\$Z#+D #?/2vych}s.I07w]^9}_Ɒ}_'EٯG VDg<(; i%+^_zV͉G~q7>]*^>V\ݱÃUb(y%9~(Kv `IN硎\|ŧn!v~CѥEHwPgmS9LeDBv*֫H!YK1FW(spROA1T7}`k73򈻜OrqGnoH^|{%KD}fz T=>|cmt?Usȶ_]~N2~,Y(7"i$1gr -kֈԳh nz/<%.4 Ѩ`Ek $eI\nʷ IX8I=z<#0גcǹ;l-yȜn_90׫{y0aO Z ?2/~ 2>Ĝ-&љyX`xx FМ#A3n1MO:NE!630[ؒ1Ե@\/9,}!Nc|v[z!:MP[^Hw 75/0A')*ua}^+^2AͣaPN%o DžW8Q᝵,(nz3)V(ߙEv2gB5f ^ھȚ!3QE)~ :woCq=dx`>SFW:*!E|-=T1߷I Z8QԝJRYRԻ %GQwdÂ@ DHup2 R^\c:3_M#x]m()ϔ?d^\8]&I#;I+WbZ~``iME SL8{|̓Z<)In|2UːiVMpļ3W8d.,b߂~g? YT1>f׉{3}*o:k(PNWoV&ˢ|㞕nCrҪz83 V_旮of'S! v{cS9Dp4ʚjt:_.wj "Cz댏1A@0)\ӈs,qiY1LK6S` o.28#lFwuTʌut;L%)̐J[4l6q">np REQ$A; ^l^Л_ϿMOOwnM*6NK8$gt@m[)[OXقuU6V߹h1}Uw "m. e|̝$c˾Z[beђLwJeQ⍜RMtBT r0%0ѳzWHx{C%`JR mk3rl, ݱǛxIt pun14r\:ץ: CNw!08$u|L"J(t]S̑2 TVéZiJ0l[ nQ'z6Ƃz*k?XK/[ziPa$4r/#Ӿ 4^,=n^XJVMmfIf8>3ֆۨR#A`"g>2l7 %;.w*-EC4E$p.̄`ϛ`V"c; ZZ+cWs1j[_nl`N~/ɇz u:qPRxJk%t]1+}_g)eL$UZ}%.d+{MMp }påS#-ܡ6).}o19Ei|-ӧ'@ћk"a)Uⷤer_JELܚ[YU-x daM);BP*QȗOKRۺ'_[&YeTkN/o]|h@hp=(,%g|4J"A^]"?f̀/8JDJaQƺBEjYf? Mcqo'~wFaF |tM'Wa'KH9!k2/QH'f0r 4l!pΠN:pQdE[TGo{tuH+k?4('夽Wazm ;k>ROL:F KxQjBhi& [s|͒ag%l {ΝnkɄ$oP9:C'r1>jP@ nʿG_{՝:~~:/g TAUkw19g^BH"_g ccս.JfCavb۩[ƫIf὜#NZY'`?J7,5!b-$&7kfyeN֙9[RNGR9yLbr\~7(+Ya7;-N iݾPU<;Q?8mX洬,c{9F[N۔U~3mfƽ>sLa1jmYtzi[zNj\̡Xʍr]X蝖BaՃ\W5옴ӈe&i6oK<=A;I3=l;yL'hZitvxQΎ*o^<3A̩lǛF6}\}j61OzMy!''ٮq2U! {?Y{׵)V r d7cz^MeֱHS{ S26Xn{MjsV*׃9a:+JMåcׂt.6tӣRZjZb 7,z}\ }mD6Tޕ cKol=JLljG|:^2V␡_NZvu)i?R#w}hf˧j/W73ZЍm.SmEڲ&־xj8i̻ʡRM,;5o&s*Z k`.A3ꩂS5*bf:a!+b$ l5y{=6x9*2jT3,˽Yu3WF.)vu?*BR-ռڶʲ$ .7d X]6wČSx֥ܹ%OyOj19VPW0 N}}i]'cض*1fVx1(M>܉Yg&ҳԌޚ(`XI1g21ʨG75b7鏬b^,9Ḵp~ד;h $YS`6ffفVlZa֬XOF`#J̠^py cRh]+a_/ʼ>lx :ge\LmZ)fdr7ڬEϫNtj7R 4;iW>N!l:ӘcW)]jnV?WY6c Y=t+Mh,^DZ˕ns'V-VX솜)c^eG/nN-QiPtZlWzVƋV[L82sհbg3m)QcXC>/WF];՝`Ãᄚ`:lUN\ʜ*nڛRI]jpx{Ǜ歰<:Wb)dfx*)׬/V7v2(]g9pw;<CW!ԞqwX(Jl~d^]n紽h^~ү6ps6]>`iyT56֒ Q˟%2m&oZXjv:2m#g0pJN@4J*0s-GswV 3}dpɅ"S+Sg9O'6t0-ɩBadps=֫=YzMEt^Xǚ`5NJU+.T@=Kµ]am_,]\t+a>hQ5HsWԇñCwUݾrk8LSONj(M?Gh)weRXqp&+˩*N< s+礌^(bp5ӱ%u1k3 UlW&n?4slm`Z6FT) l8X{Q'LXlX7MUk+B:54|[>-{2(7Z;zWk5ךtKCZI|2P--ׂy7lhdz mm-w=CҢw^ǩxqlڪ*YmmSgza2:z4ViS1;MXx$t`ܖC4;LE 4wÚ!bade3zwִ ;zWRz\#ю3.FZWL[j V^eNMou<6[0du_6JY3&@/7qӻL}sfFrwj/PFjzhVP2]{j xUc 3fKni]uɛݍCiP>])b 9(9Dg}l lQ]2N#Uf=-~7F8 3km8pqy䒠ճƦ\l}yM&٨fg.zaP=OPi< VRVA- Cq"~4hQܶSmN2\~gQvں6bOx9m&RTζs,ǹiWdevαe'GjV`9 >NVOK6vM=Ŝ^>&iViy\joL4 d@JۥٸW)00^rhf#/S7ͺ-i,n>q0b/~TK bfLn|ft*F59ӣ Z NĬ٣"%gؚγbF-/iuZa8!l%&\N&ّlEkN]gZR9Xv;[[_hjH9"զ#=W.]^%+^F?hvQů6קE%ȚSe<<7y0 +ˍ| I׭We{}7zK?]}wTpN|nNy,i10_LR)9Y if{a6uKW]NirpT+VT+{vVZ궘jIQ~4B~F4+[DnrJ+Q>'ǁzS0 ;=O{5 {lا-ePiWvQy꾍kTSe䭴r>0vg]V\B++ҁS.;$`MviudsYqGKpڬ>/Wv=mg !4nh|5 LY֪=8u|?gQ j찲 X]V}eBt^i~1W[-Ά6n,2vljRnsLh;]6;Il+Ψxe `vF+3uv;>Yk~|qBE #\ϝf_ˣ0pz/&Ue2wU\򶽕E)KF!w];xtmr0-%UmU\Hq{[MmEtqլm]Yh m ڥ\Ƿg 6^g>sSVZk uS4rq^b̈cA8 TH՝j1IUˆa<*=[)iah>ZVSvsi[nυ^i{r]wuY k?wqz*xNzUn8:tj[KFo4'3,DlU`,u;Wr)>olNFV:kq@R/웇 bfX\ZtveXJnQ2)V+KSo^~77 ˞/߿iўKWT[rk9_]߱o[ז -OP³fop>U{l]pm~1>@M{p(NP&*GxW׶cu[ [/%kAۚ<3 \[?).mwO?ܕq{d<X<$Q5d.XGB/EθFMqq.!^R3p2gLmyFA,!T@,O!TS>!YDO^n #MyrhkRߌ;ǟy?C"B_ӇRT}4ڇ?4ʏK~! s"?ω~;Qٟ/HC~D$-?C_D~~4/"_o_?8V~HS-N|~n/e "۬cO>\[b6Qsw6@h?'ǐ>I޽_Ɵ?<ֽȒ!d>"E6Oa헞}69nVp=HV|0zvf{lClCx?gg?0 \=Cp23s4s_#`2 O5K׀m\|mhŸ4,>A%ô?2?U0g_9ϳ!X+!X ϳ!X;!X >φ`WfC0 ϳ!LeC>g<?˿9="rjjg!2M8e_j T q?A\f:3(ATg M%Hzx%0z\;E#:zAKm'̬}pL/ACY`:# M [~ .nf4ͬZng%k?:x? jj+[92-{_O0#u wR>΀ &@񾠡0W-.^lIxVftFߛiJ՛]Hө[T'W:Ktwt!VOEӌuב/mۅ(+x ,Qu}kB q}E?oPb =? wzTܚk{4-1e D.~{맙mo{y:ȗ o%O2*HO\ WԄ- AUL%N5 N $@eJRxC%p\~@2Ey%(HPE>(.S e"`\E ' ٱ/ߴU^(H\D¿wjJ8 ;޳n!o+W~PI0z$\H0\~g) rI8=Id2~Tkf͇) R\9XBC]bF0Ĝ)_`"~?ʰ@rxc@ IQ_Ŝ$ğ6щ7'/viS5pR`Xb %%tq*Ք8MhPo$0rJ|K !-F1vjj C-5r@ D"#0BP8 i2Ca(1`ңဂv0g\W'UOZ.l<#FdF)v8Q8P`$hKo'7$a )FIaks|RXa8L.e (=Cϼ'Ǘ@X :MBuR^Х{ol);9[@hUa:̑LD+nAL"@Mdޭgb@rΩ?,[_8TPxoF'3XmR52%pi J%2ĺOT@G\ťg"*? #O8HU};džE+Us35꽇/]'BP\~'_ٛ8cy%o ` h!8U h 7 i 0X*ߞMYU~ZB n =ߦd~&/!~aB# l1L` %4>Xz1vC5w,]"1/'NMO- S>#qsǟ' U{nXc@a|Sb@5{uC BXoJ)E2PUJKN}zƚl_OO3s+H@ `{|0q]ţG%1>G\_S7óndC鯟JC8'KP "@<N]sVnOo^{6B f*dƟ{Z)qI"z݁|ߺ/*Do|LGZƟƨc>ָ|#yǯX8q7ٚ jC c FnնizJX ۙ?[מ ]ϞێB_J3TΣ$)پFA7gQۓP1pT|jOpDBwC(ЌóUں})3 7dW1~B/4?yMT'oœ ,0OPp 2Ng?][ٍ7V`Lx6߼{;}zO ݃?Poj~ioEeύ^@ dr כC#Ɩ/%;^d'7`Q;X[|"8+Xo+oWfamL,0*U`׮ޚSwݸSV{&~6ş2 L1AyY^Ҕ q"<Ì( SG(D$mE,tSt($b@!5]GL(̬iT.@OQE)!Rq D`WPMuɗʈLr!G54JC j]&+h BoLP"\GU^)[&ʢDv4'e ɮC߅Cl̑VN/5'5tJ ]0 x ʏ֠un"CULvZLlV2 N~s+ v^Oog#ޏqn/פlFAQ&]@ruB#Llerʣz In\@.LŜB~Y$ `f$*#L~lR£أfV#v?4GeA0(P0*MN' A5Ur5E:c@]}T6*KaDĴ|O !+BBE48zԸL$*CEQ+Ѡt=tSH})8s)R A¯hX#r..~RWҢ8YrUL,P (WYQw',s lDDU. "*C.TWXTK@ (_fGs-jTn~ QBUHzDDU&B@iEnaAN"otEIe4+4r=`?pTC&w+ 1w]08NmE\#ojD/2)it[_kDύ?U\G/K<60y5" h8@4]:cߖ9)PS^`#xHR#F$ҽ頉O%b$qq2GuU? #THpbE.jytq48R`/}GEsJ u%~zY$=D-0*`7/r_u brJ,!L:quUfzA#Q*PRzu9sL~_u(ܠN1PG#i@de!0AL P6jKJ8>000 FV.,ko&W{r#=>Y8y54? HgF)o EPzQD vq *x>@*mxpw +xiƉt9jThrXqz'EVI<7Xdckz1w:Qb} r"GR &r.W!4BZ! H@=HXK/ 1i u"kU4\BG$'=H2/q(ݑ2?GX}(C "EHd2 Ɖa]TgA.@hܯ*)aTJ,Kȸ],|>b,`Az_ꑣɮF$(P#QQ$LHuQ́7=qҼ\]&|<.XoD [Hoј^n-a* +?LTlU/_-ML2 r;X%^QZ ?ϻ@tpENJ\K/ ˓G܃c\E(A;`  TF>-DTbNx , <иh/[HIIr#\:Ƞ3.1j&ĉP Mm" , QCn)Cy(qJ9cG`K=d,LT`EӺ7pIrqu "ʠ}qOO2E 2*{7fI5GLavH$q)kuN{N/\kPP/Ձ5\.b.ׁP){3>uG1o"pR h@!C.7i2V9*(jMR %Q%a%"zD:2ژmq B3%X!B<%؝}9I$`AtA$ @. AEdG`P"Gz#b(z+QR}Ic8&X/cvKG//oC{]sg_гmҵ׵4ɵzǧ0<sJ/Oؐy}Mog:q9Bd~X|b[c׶=ze PN&\Go UC~xw;qs1ce qkKrZ..U{ArOfjo7xr)cKlvVK j;[ޮWXfqŠ.0%\<,/9&[}LJLJ__Hxr/Aaۛj,sjy~dn׏lud<}ju|z _-k !>䌾\I ϝ_ߣwԳXEet-.WW_1\ups[--#϶7>/D,j^?}Ϸz[K=ѧDr-Һu^*dkL2a=B0]%_򽆵ayhˋ:buaxzyϋ BO mGhv>^=?/AT_~ Wήw/!; /PhVjژ7wgVh2_enWf_Zu Y#:b:Kc)ae85Nr`"Τ8n3i'0p& nx/IA4j'%Ly$ĝթ_=XhŜtR:RZLEN <4{d:P9KC1p[x8M  naIirc3shp!\4 <LK9v!c2<7>F99dpff^1]35wTWe̤7ĽӔ`_lA10Ef6*qξYZhP 2`B*|^$8J*[ٞe!)t.4A] 9pCW}` @n\sX4siO)(aDJFSd}*8=d -ÇM{`c5LG=_Wu^'$h:!IQ{mAf8fmRMw; wZ3&>o]Zc;vr 9N(ؓo!Ƒ)D@s۪0.[R>fӺIqr?Ѫ@ ] cJF*I]$HNg݃>jĢQ(~-6\7[ۆ)ZtMȤ͡[,9׀P@'J OI$T|!@Ϲb 806jsnbL͋/כLS>rE3FNP(DzdM]æIN%$| Fը遪GUpj e,Pj |*cY* A%~~zuɢxyuvJElX#}+nFNWELWPL[㾇 >D,'p4Eb5TExvn_DFTJT 賑*MQ i:zPKŇisJ6ӤM:5b9 MI :A<]AD0"Y3c P.w\B7HK)GB?c]WbNX5$lgY 8[*"!>kM0x,9GA `~{\\|tCK@SI";$( WpvG"#DF;!24T8]8Hu:R3N͜i`#h'A2D0rLC8GȊ(GBn;c|,B_ v)99/%ȩT^i2~.Mssɂ/ $dɾia{,XF"@pdPM IMKYj;FR/?Ť_ZBea5j,"iJ0ɬ-(&==edyP=m8 ڛ!f yRz0@DŽFU*wY>Sӱ@Ǟ'iq?8Bp{q@eAZcIZcYIZ4Nb3ӱ@Ǟ}N iьiLšTNyTEyw"-ڱ,$-)%'i,3`R9IE7wQE7rRY<2NEw"-&)#14Ø#bms{?A&Ue;p @0riՌ0s`!w@|A 8K3ZViLRKIx3)HZʃs<!1SQEy+IAB6xc&II=(!B0wS4 *u]Q .WSA{ºeVAΞ9CY! ~ y:kb!a($8:8JY /+(}Ѐ]-m ߥL@?/WW+Cw}U7.CK UsPIp3 >mp:t=uGn# Ɩ77Mӕq\oN!V'O/o_Eu6 mx\oy^^_n~;j,֍(;czg,?n.xO^==V#kmPV_@XC'f%ك&f S:DGC`*{F, F)@WF:衴X'lp bnϺ-*Ulz ]- *Wqa@vD:<p) wB藮k]:O fmSFz<:D!#NЧoL`}o1 <䝀^1ZkFgg99Ggp22_c*Vt sI|݊Q]R5Ⱦx&9=¾x1~xJp: WC٩5Y-QPC|-)y#*"RF$e9gQzX@X(}G S_iTda" BM‹4qtm )[ # ܩ̫F˥62x6 'XYP L.xe"j  Qd5KC|&?9_R 9kWKxSծاX֋__ ?ƬS ;9i:*vEZ;N$(/LO튎#Bǭ]1] ǒQ$F*F 1 9,'BmvsĀzdRN|8zHJxTHF1`5 x PcƠjR MZؤERyҺ0 T][ܴF\Ӟ kaܑ”Sr+˽g\8`G%mMnF|LH );C$_ǖ׀Tum485/0녌Cs $sA)o&}.Εe9  笝\++A[k :W^;h/@CW҅zj9Ŝ !), }EmK~6u!8(abUڦmR I#HhU|Ne=2XF+;R 7L=n81'kuk>zk1x[C^:wN8 OmcP<6%!3\K;\A) 2 JL3ob;[| 6f)@^$^$ÖRYpa`KFNϤPA;!>mXt$Wie ,z$r 2y5)]ֈI`%@N|[\-n-KnM% ǻ9, C? ` ?5s!q>7E\Cg5a)a!uөXȟk5G59ф^E8/0s.uqj^6{qt[EM}hI2>XӕbS(ϟVAA{Dr?hpؽݡ$).1"PXh4l'Y-(>@sF_t>:48\}Dkҙȼ2~.¥#q*JLu9m'9Ж;!=n7v;HH]o%}/?$qjC>5k*WL^ ȧ8`#b ue.VZQq~"]+ܥO?X }FAPIZj.SaR߾\M w4pidy KIczlƖ$( "j_SSr~eG? ׼p,et0׺ǀv869a?ovpsuz2$-vJCFQN 52Igiy:ЈNP:@j"pQ?O iMK>@'i ;џ@jkGc6')-$[4<I~n8@:V< :EJ{rVܾdig{ొq GŲKzAg"{b',Ӌm5[h|)w--[ku- dA>[[K%nA*z|Q3:32V\gm}gkM0-Xv82{#!4fZMQpiTO{ ʾ,4{$>/X-H]_)thia쀐{Lk'kȘ3i"2`!"2ft5D꧴H}/귆>aL4X{ S,biuph_ !,)!ACE< =fB73| ũ Di4kmVr{ AL譸Px+.'~+Wd ,Sf AUed +ʥ r\jMg/e6dYi{R5@{[$U,%Hjf.*\),&HgnHǪQ1 *Q/ڹ erbV+G)+r_V૪?b^"V\*]$@{4ZJI#.J,|ZNicJE=۫t_]~YE}}TϥKH|} _w>i%WWeԖ+`UJȸz湢v_KfW⋒xFe;Uku Rgd5V"Pp*m ~᫭_hGp>y1Ʒ6: j/?᫯*4qThJ`N|ߢ~mRk,a8.}ۄ5 ;aoڸ<dQ vRdA  +.ƺXD 9،nӠ@"+UZޭ}s@? VL[Am MIख़~Մ5ҵuJGDf "6^eҵZrkx}g>Y c4J5 5ʳ۞{Rߝ_.?܇o[yqufAoAayd_R) G"S7Ywgy񷛛节~d :!۫_/&V!{,wwa{*Y9pܷ9pl@Wۛ5uw=.-ѵ/W׀f&FG5ew`WqK.@6yXwNjeumy <Т|Bqkpow7Wudcݹd/zw+ݶi[}\]mjZo'ܽ |ĥjmfm˕h{Ԯr힙~]ݯޯ5VqٟBz춡.vFoŠۛUњ7,:!Պn:jO$RˇØ-רT-;~}lDկfw岤g[𖴻3811^[T n,: σ̥dF̀S+S3s(wx2 Pn-7~fɎ/41Rh!x# g^ςn-B!+:DD(pA7)f#2g- EšŨxkĈ0T4YK!TE`eEe XQ[( Vĩq9;^Ro5ӷ=<58 WxaEj{sMz:SAÈ x5,33ﴶo̺0; ɔA8?Zp7?n+JʯA w2DqmȇnЅVj^֤xPD3*M% m.)EKQΔ5032{j*gq/`'*jNI1; R(6t.p4wLY񐲍μX;p'( 夨XUV vM(rDЦ6s`?m-29iRD`Az%\RÌfg Z90JЗ7;[V2vsbFxd*XБpb[e;&yI^rz^u]dzFpI d񡋷8:CalOS&\q[yh fp2:c1>Փ'\(Tw@f$a j06r*JOD70ڂkpzk[Q5 ItƒN[X =h4:of _m7LGiƔM?|q \/^J1zz + S f>|ӽ y"<,wc,mxy.vČDFpH,,a"g$f7-(bi,[bvrB3ehc@,HVtePMŘArS9β ʬ8Sٶ#?Q摟X"9(Y5)/gDM!Z<` f>ppQ2G!2嘊1W\)@!2Ӆ(L<)P%}H$7<ǂ*&KK&L֐lu9:TzBtfI S%4c®@*l^  ]ٶ(@Ґ(I!q^'{YB &jJ`En:-ՏVň > J%qZ&qHV{$el/#㭆6ׄ&'DH:pfr\tJ fgRC|_n`60zBPFʵg=0+i 9l!ªƳC!ص;:-IEP "}{HP?G!}F:$=񣍕p"K'i|6g)%976 2񁒇^ںP~ۉ/[)|wߜn r~Z#>38lK'2 LYmf# B= Pgg߲oB -'JMci,b<6鏎ƉB("KmGѠ~sN\ҧvA"?Hsu+`RHcQ)JILvQF (r(%2.=ϣ&hLo4# YycMTӐQ-jt"@YVkf}:gyQ&|Gqfݔocsigenserver-5.0.1/local/var/www/ocsigenstuff/scalable/application-x-cd-image.svgz000066400000000000000000000266101417255654100305140ustar00rootroot00000000000000}Yoɵ{T&c_ۆ 6̛Q"KlIAR-|_D.K-\$zi<8[st}U|w"qRmnζ7ߝ/Iu9__mo6ߝlOou]pY?lΫ?VvSLJ۷?~l.[`8}S|OTUvoߞ}wVpw n6כSӓP_9^_ooS͛_ٛ:1SNQ|TKUǕz S3m::@spwyfpۿYL7vGKr߮6b.WWOJbßoN6ߣķ,ׅOX-Pk*%oԲZۮlހ>7@ Q>_mrl{{gMmlʓtGcK_~a#U[bVRfhK=fu\l6 0ffBrkgwgv-跧cڏvW3|w Ʒ?m@Z8,E hݟI_7R[܃^wr~k&)ca%7Ǎ@, }Bw- gtUFYd~?+~;Q vAZ&h'K&`|s$D\]U?wN,PI5FP 2R pêPpԀTlud{C>2 t.Q(J BBO} @nJJ,t\J/X\#sfhZJsq lAu^wD1.A ,Ma(9(Ճ;SjV@Syi4=q. sPjs6VBSv<5'%(II6Bm$i~$I>(VO rݛm}1sбҡm@U$AƷJp~|p"T$, j``P_юk)m#(?}_j,Or'BƖz}a>9]1-xcMm\2d~͓[xi ZI Xʀq ]b K mtP6 _u%qjHkXٹ&V]v\K=³օg+ M mmQ.F+e~)ښj\VZ<:Gum]{Ī'M U]tfT~]teȺfFcО^RU@'>bОK8Fd9/,u+Cd RA.R?o@W51Kp +ZT鈳/W)ꃑ(j{LNvC8]w[g;N1yi6#e X=ӋA&ŽB?7^8O1 W#Bp``V"9r/ ҈ƻ(W w^0(%hŜ6˅eE āR~>`U5PFc?byna F>2#-d.f04uD}8K8",aΝxDG' eJcQ<0NO!nLjXP[;5hZ6P@:=7:0c4e/d=#է)OS/oxIPAKaӔ`4Y%\GY򢊣I3>k(i^;c:8M*B锥HLFSfC 8}I{a?imt~ > T}?{4*&zB0Gaic J1-#Χb"Kxx>b `äJnRDJwuV1m>n J:K# G>"iTT\KPJ|fi3)eG]CS JU4yhc˂r01!uVW&ҫZ;2{Kүaכ.7'ݺ_&):Ż{ҿѫ/QF{#v:G|ś&S#Mmif5ϷgxY!Yww,p:eW~,?}Lv{yևz|W{ &̎];JW[ھ[_gWzwty}|E;GWwwyxXw'>Z]^\p|juc ofPҊ'>/6 T}TUo-ܔaTO6#@ދv>r2XORzґ(lD|5e.БJ+XRI_Je^H+PqomG%Vr-(WiyM~/4f=< wd!Uw=_F󳷔DߧKxt}~п>?{w.^ y~v}J~#),TG/6ߧ6n0z?aߞvӐ.&djn˟6WWJ5X Rt;$Z'vCb>Wg|CJAˇw4OKVI&h4 @ѕ€ S{3$=fTKCDbhF_T+z1HJ ýORs!d,j+VLSr`5EȖ)<d4mALcæ[-I]]M$Dd ϑ`xt^mL^g;?$}hDZ겜zԳRV}x|se<K#kZ3Yo磡> `srdF'f} *Ia}y+kC!ROs5_LΩI0 J=orZI`g6B1*!kU}ɾxߍL4`QA6RU2**l\:_àoqq?$N޺ WRcUS!;Πn a 0U0417Я- :t4*f\Lh#}mI ׎Z[VxRnD,臠\pt`&Ɠ% Qai&#ƾDnI2DM.&:p_ͽVzU>vΆXU@#W^ 'd$1o@ 9g.љJ$R]V_g!TIܨk%cG_Щ[on2sC Y^8ʫ]cLD(iRe9*ˇ^ܘW~x_ _ ;s.5Kl#/bk]H>&;K%ԃDw!QH Y(- ljEaDQM+@ XݢS$GbP1cv/EICtEqreЄQ( oS/4=d>[a+Ku/d$Jg5xTf5~j+m!_O 'FpW1~A ]@$l ˄"i dۇ`Lt]yz3J#?m_m?m iccxcfhԮa#7((dM &(IBy:q32ynAXsH }S|9m 葬ɿa IT)p1 f ҆!q)챀-Fsm8p%pYuљz^$͜A0@.DX h)%h)r8FY2=.dA%z<,:֓i1wi]:Vޘm5wpX$)YU ý&|m`= 6l`F>&L7DLXD8$c;c-5U~5: 8 *drK3(c,]㽊i9B@)>DXj'/ ^kןo XQ]~bȫv}v$4c`TKh5BTERQ`Dwkuwē(,`E0La0KO-5ϧc ZE߃F `B 6Fb§bhQLPV*' rקc+NG;S$>1|1/{G˃gْU$-( ,x~K }cY1H"{$m f]8yHp'|l_lo臱|}Gmlb!q%L>\=3 ^b A!! B)ueBwq%QUs^\Qz տ& >j_T_> Y&)Sgh #pvmKJ*%2Cn(=j9NZAڡ@rTRUOBTwc*jvZ LFVь6RVºPwzCFiG#pɔ1Lz.`(RON>ʖiſCZk<[k"=*bZ9h{0@y 3zbm׭9Fu}BE~jn62LOjXU"%++Y2#6MNU!"$7DhVqچs))| :o`xJL!h ,ڋv}0nd#0dtc쌀`ԑm KU'2Wzdnqn3CbPto>xk/ѭM|oItVM`&إS.yHGpJxAHIBެT,̢bpnO{1*Zm0KVJ j I Z #*!ު9-2L99L[C*U+vb];V1wʻWz;'ׯNSDK5- *]`/9^<݀hvn}G)Cp#S?DRF+@ i&l: ~A|Jg߅ 57웘kQA>U08"62P@5F]TlLQK^:tr"jVDd}[ */%οBlAU2G\IfJHGJ@1q? _Д{,ç_QJVD-B} X%/2 h#cg/|8L=2ʨ[xOqqgҴt),7-*F7HF[=c4w?3oaBQ΄6J59n>av졮c.D#B:X{H׉&_1gΕohKK.QOph|`ȃNnvu8gZ׭/+es*ҭtE:4AJA[YTRY*ߥ%svKd5g G@yfQ :f?}9&ڄ4L`C:kʃ@Y;zCi+7n!,mkMFVWIQ#Ls 8Pdʀkx`RJoZ;65F(7$1X1Zq"'8J|y,f@0 2MGAdĦa/xdhx<$=Dz5jwII~H8A 9`1tfu "U2R<% qECIk=gQ.#0ؙ%J a~"3`y1UĮ /h? to;x 0 1-ȼ+H6d/Ê{s> =k(:9ɠDž+4ou xmb0?A4%SM xt73p:G D0*gP-^Q}8Oɔ|.a )v9fc$SDŽL,wDn71IʣaKt YiJI"S?1+0 [<;ĀM $q[[ʤ4 ДL5w+yY܈"$#G@BT>@5!PDeS"95P̐aә6 fLT4t9+gPK2Zi;x>+]v-L>o}xx(ao{y6<#"`II7+D?U(.Iyq 2@7\Y ھ`cf[Z}ݻ׷>\>ɽs7o/]>~zi|xwqsh^};ǫX7) ~\mŻ uN>o){TS>o_6: n.tѠo\PFT+Ǝ|aG/n96k[|AܫpŶ|BWorGow„jfтXu^[e&٠M9B2hgDZ2Gp:ynњqu=5֞o/Vqn_\׋ǟZ2OoEԴ)*tF*O>nnozw/?o4uW+[iml29JJ*9rfUAبl,*y|JU&c&56=/F$T6*Ĥ+=q>Ue7NƬ09E셸6Z8NV)5F'ej6ѱx )^ deFK|vi>6֯`_j2lY{SPlA1)}uN)}LPpZ2H6l|e$ݎ6HBKQvxҐ6JϊY4GB!rsWC7 8EȿQ c y\<*_MRiboaMH>r1;*/)//G1%ٕqOdbL&\y+Hd NHvSOq-@"Abk\UΛ@e~uʭS3dK$(\7՟ǃcCuXd_ 4;{*[Fj[t4J X`#ks|̽EldC0p^x,QsNRPgR Кs)h/̰ꪧ^.: o웛#XCW$7PQ{Mhv*:30>[gsjtq=MTN<'qTG(MID6Blq$]񸭞#pv nCU5@NvXũ"+gpߓp[xP i*qSp<ǎ%7ص9_zh08hV&-&[3 =~QJE: S頦zAs718?9"4 Fbme&bb3{M3a !2BLzmДZ,l֘ MѬE(奞Z]Z~[ w#G-d3߀Q1L #K S=xD=ߘm夡ib-bhby ei~ {,R΅7ںBD mc:bfE*ZC>e} ol<6j ͡vSR >[qh-ugo;;{><јA]]^8,."ȗs %JYhnFn~= ueP>(wsSM`iJ޾ʑ_~[sW؊D3aj' -|S(ѻ~4 :˰x9O(Mzf_S yxaf .-9C2d,ѻMQ,@R*Pګf)󸢦8Kf~ Y33mfw5^@vf}O@|[kt3H^kc!?ºU뎤hn7>`8<[0ƩysP ufW}1pxYzM퀼fH~ k&D:fžwߩQHnbwL3?7̄T\H8>Wn֯v]:vʺRCQ*:w&VZ9 ofVznF3й 3K>A~Gڣ[@ didK e.8&M4 DT whŨ,{;=ssH{{vG1A=>A;So7VեjW=z|Ko 4$'m8gg6nF̏;3B\?҆ZхؤbWٷAJ7yD]0~uGoyM^qy=,QU3;? xK0?q }̮=7mPf$ɾys 'ژWqΙ8Ɋ֖+sL:.뀒<=ǽf#6c؟4h-7D{i>p{dt\6WY%@jכc}{⩑}~Riq9+s }/+TsRR/F^5U-I5SI;Uĥ'eE[`]jPK-\헶Z䗔6Ҟze(q|+hKr*-/V/.-fv ١n=/v-d @͜J$^ʩAʞ΢Z@[C{`Ӧ |*}OzĻU`F ߳|z*~G)ncWR>ƞF߳,iAT-`I O,T֜Wٳ#09Z'0ssԇUߟ='a\wyF}%kX\#{Œܜ}q0XPf(wXN3f>-qIx9;uNƖ)fߜmf,Sd 5<԰!"yٍ9EƍxICt<QDe60bȼO20fd>/j?Uq.(j$vb4#ԅIU3o6 -%GcM5[>p:)FT]EhNƼjˆiƳZ%~.>`/eVKFON1v.RS61%Z Άav󉣑8Y;FjH.w H9v]ٰAXF{zO=;6Ov?bW7Xʹ37 *&XsLCOzgEl/_*$gH.V\^y9&3X7dӒrLyNP+gJQ2S1oӜZ9dJL旖' [!HAO4\ ͅ>"Gg ig|9x4F j@y9F a{xf$~FRǭLN求f1g44ԣ06y $P)ē<5M0kdz $a6C4:A5:f79"Ǎu̺5wԍb膧FɵyپW3PC}ӷQU?^c& K+Ks)_ *h'qQiWcDD<6 $IMN+7قo2>+&dZAq^9Ph~먼d$()%l2*^c:ꦎbG0S2->{'n9_'|zk_[c|GZ{CSUCK웱1,A2藲:bʖ8q\ں:`LuT0}'.Ǫ^V7bvNgT<ͪt͚1ꔴ*@c}A9 ;k,jeI~7I꣔h0/Ǫ^V!P"J!>v8Z,@g!)؍Gv'k&7.M$KsGNxzL$ƺr!R"t") b;)V#O:BQcYc-vv8|%$n&ؔ=͓;p=7掀Iד_Jap4qgxIe!uO:S%}8\'~*wȹS??53ϒgqicKNOrpT5y '|F\㋥ڣi1X~CGdj.yȗEi|Gf}3<а8qnz"s9 .Ko\l]97#s D^e9}=a'>80>t|eSe@?6=@P|@[޺fkv:z0hzsA[%:&YVWOjzpAk>r5bzҁ$Yû8Ţkm4 ÀZSkla~Knq󛝟љ_.?yW;ʿJ/>fӜ},UWgf8o9zWsÔXrÚ`T+,ѯYoab9{KN%)bJd}6oɹV~7)huexy(Y%ћl|ae{degEAG# xF VF< KE5 MFA&' z{n9^TZ`n8!/E ](PP}P}jWQ&,.QO\s|I6vQiwM?\r|rYrn/O}~Q1s H|PMx1mN`$C9/_Lۙ`mH"0,0ypXxe3cf\տk*!S5qx ۺi^*{ؾ0XQϴYݧ:0T'x@(`I !vZ׀)#/h7s(ݘ½u8+ KYCGPS<9"86ipK)K$XV{Vloo{N!gMmhQz/~wJR'6ˁF"D ޭ-RiUi?6Њ(&hRK[.Jz!Y+L3Z{WT٘- Q qm6.AFJwB*m Zfc!)!4{@f86l6 Bxuk)^#pXc[@~e<՞56A!ERCDcb2aYX9w{<vZ$#Jy dXE2q 2{Gr}W P(JӋqz{LyD,ar8̦=al7h׻RXd- ƣyGgq9ƞ"Tz3@,.S,0cyG@Q= Y.}/#x|1?JCۣ>:;Ny=0 Xg:y8f<%ccC޸CdS \8YTƸf2b⻞0}QQaA3>4Gˌ'}Fqڸ1=g=cWe7181)$O=qV <eyy} :D{n{ߵ~}ۭ0%LXAlOA ~$lhׇomW?tqu˷/ݽ#A0֞ rgIޛ.?jUʢ{VŸ?MIsW/o9͏ Aysz\b6푂McYvk|n'Lmh?>^ܽb}qpw.>^u{5҂tQfo?w~\m }'>_j ? Ho?zO#?5vv#Vw#_WuݦY~~~}PEsGN)縮y!{TWko;zczp]J&js*or>s06byo˦Ki˦Oӆ >4n- RnxquxѱݤBͫJ^^w` +\-jwuﰉ^>||w0ѽW/_p˿>^ A׏7Kc30n߼lAa 7*y{ssړmͬ_t[3;p/ BȾ^5;6b,F.h7POh>1LNK[AbrNr)K]9ଔ8"V^E֌ -IŨ+Al*:fP3Cb3%H &dNQTl TԯL"^s0+['xP缲Tb^4J>86tJKuuMI0[1t?%YvƉ`*D+}yx5i&Z7& 3oq )o2',f2+vYLUǙt4_Wà 0s?XH7 濐6eAhLOkGנqEX@l|i|1q5"%s5o6%Bg,P2H ~K)IPop\J- ~*J$x%F2jU,Y4qp3L4HqWt b.Hq U¯ч-ҩ]WdVBݥKOq!0Ie)sJ{Nu. +nv{LG;E~ɀ2~]1F(;ށbH̆tƯ.vkYLR' DYy:IN^ar`BʖNڲe7~MãTiɖXe\*9ސnLϮL~culDU(Ffc |L8K1L7`䥕| bhU^SPhC @a*ABщjZ " ^%="R`k(^DB&F" su?We%1F0L$!\^Q~*P&v/o]Qu,:\3e!5In ĦD ? ytN IMQ/6Sh)"6g[N78|PޞvJƫ G 1)fG/S02*n?LrJ*EYBUNk0C'Gg~A̲*Kp$VfLs8w%tzئ Y)5x:T Cq^.H%dr QNyFs+_֭^XuYYzD4TD]*@yˉKC9 jsJ,cW"@+A!֏IEOÈgD.M$Ӱ[H0о&< CMLn-toB swQ}!lQ䄆T\k!:LAP s4蔥PWt '{mMSZ6g&i@ )XRo AvQa2i,p#T1+q $S@Bw&lcQ=8+F\Ng贎^NB&I''4 ,ϺG tiůC3+xir$2.$l4MP*5vVBe#S^ĕy%OYh' ܤX=1&ƖT,ideӤ4K%CcF6Qu8Ϊ R\ &,}BEXZU8!}À &Y#I Q6 "$%!4UF$!jm='rN1d<vHiJLJKD)C0ec`OP^& !gYa71Jcr< 8*FɌaM2"~,1[;}h;fS-iw7 u` Mk@s5L>2 E qP3 򨅕W;QkH,F݌&-4FB qf`W1\jWrnICM agp 0zZy)0 ܥ[j340m B&&;Lˡ['p-1 ,%&8,P:0mG.ہO6}T&#)4`L2yĎsSپ^jKN4_ ӱs_/w׷>6]cnW)]᧋OѶsbGHq''Z#=B h t#/4H͛ qTS+g L&R45S/HHO~$+/=wۂ_W(*zC,,4`FZy Oi)ӸaVѦ%xZVʳM\C4%]T 5%9\/Apls1<U}?Ga$3(aڮdI1̸׉68pBh0uRV՚ U`xpK{"|FZO!CGN JI˗־<|9ʡ{q >.Mq`t4?YnCO0і׵d U1Қmbm+q0R.:8e@Ml%,)ӔsཀྵђTKd,4DD'rƕl *@ kéj`%CB:mNۥB4}1Juhd.҉٧ȋJ\b Y/b3='DY<,6^oZEZ4*ڶA_.)Y 6 gЈhkadGxx|V^&Ebp=4d3 ^8:AYG]nZt]fkp|9{!khI8_ռ`СpY浴X\jD6n:ұaJ ]09 3A;ڣj&F6cwc6ʊ-c QŌ)vhD0SȖ,  .͆i r:Ai3r1Jɕfhk=e*K:Xa Éf}4 [[-aψaoh0!}@SxnߴpF3C35}4Szq&J֊YKSvCo4Jk 5 ~5ՎE2. tr٠ӡ谝Uv6-K{vvPTsi lw'sXx`ZJ#f'YҦjoU|5BOZ}X(}Dy>=H.ː:Xd3L#pJ7|c{m, VO^ċ"VVvohzɉm=;]_]UѦjUmJ#⪺#u?J4ʻ+_G&N|űTd hJ6U1lXyCF]{ ~U2rŠ *Lyqĥb ^lb DP$Py'#I  Y xW?0h>X7dk`/(ړ\(^Bh"33T m;z|z{w:T$ٽD$f L|7?`/1Upd?rDŃQuO6 ޛJej#>>F'Fe61Oz_ F,O =)o cjZxfMɞ̶3don.K>Dt,v+j g,3ǽx:l XUU3r^ Ůu'GC~=*uq-+ F+s0C9)5 =r 8(8jm_3IeU}#'&K KYvߤi2U~Ќ&0S_7i}ቮ=596k2 G`1CEǸ&L|1=5]פ.\<8/h3~p='i=Wt`EY=Wivpo:I^&>/_}KSs=vAָmn\ٙ~ɖ4n}8͇_a3}b1V2׎H~9j.8zwݎz=Ǹn}jwݖf캵c#nON6vwEd~)>溍`u{Lx;oz}qr_K9rí룈3EJL˷y6–A1TEg,llvs=\ Ӯ}`nzQhKJ$PFF]vBJ וj+߫ m9I'V8P}ԮK ABε/5/m5KU{Ds[[;{ew\cS(ϗ3 u̅Lp˷R-&Z1@EEԶx^ : r&>6W; AyH!;⚤yrm7* GիsTww vtG$, CP]{AًNw 5Jמ5CYu;NZ;2P{hoeA*׸ٴߪ8V1@={y>V׿n_VȌѿu)gLR})יd_i7GڪOJ_EſɓlŻO|z{/ :W<}]5Tn^^G1ʮr ӭ_Ku$QD )0x(#CPM2Dt .o8NQU5$& K$7 Up%ZJoh$ MeEe(0[O.CsyAI_:&Sr=`H:ÄUgދ1'!I,Vb^JI̤It*y2sJlgAe\K7kIGg*,Nf#H̭:p$Xnx󥎤)k=)XH(K4sT}+g(Ie&dN%-XDQoSFX}g x` 5 ΦT|#s뢋xTޕ%@S$y@q;%:n).Y}"CXĠoJЦK$ ȨSL:︬e夯$)Yt Y;VU,+Z6!ê0ǒrl=7,]$)ĩI+J 9R͒Ȉ/0#vtsX{!CFi0#fP&tX_(#sIE"Y{$*\UL=-$(uٺ!25LQf$k 7`1LYl$jdB@x%3X^!謓XR@ZP̃%l-W ZJN0"hfm`L$D]h;$f@u'Oopyls54FJLΆҸ%x){Oد¹AS$B]f:,fA+7^0d*D.0JE) ]LM 96ቢ N9yhF@BҡkfY%)yA& }5̙ l)/1M0Fa hcjtfc  W0r".\!풊DJ"5/s$oܪ}^ I$NYuW̬DTy;\p2'G FC{H?`N%VUz,K̿1!UU6ibrF0L&M ekG/L$X A6Il9aJ:mJB VtF!6۷Q~lLi%({ͪE14 ׂ6<}R5KƒY /8jC }0:-sot޸^y%SJ (O($[S?0ʌPH8( ig14 ^3uhި\A ^ne@`f5EF)/ِ4 `W* f)$Զ-xVL,ɂ c+)N (LCX# j/wIm֒ۋ#(SB?0civ+LZFĐN| 34c!Sb&ˢ+OƮmPJܚ'ɓ"cb];{^4P,3Si!m}-V(L[:KP9lbOI$dkKOȀD L@,͓/T2K1L0 R;7Kkà0Is+-譪M :r$=UHET3+^/M&(7R4eiFסk`s5TͨL%{&9e6뎂NK8^Ƣ*^<,ܷ,;so$5 [[i98}$wVIN{о-"t Fu!<%qvd2I~SpU4XR򵄯r3n߉ *S~Q` xB,mT`ZUˊ]SXbj$c3Z^ e/)z'my _΀$!H!GP>} N4Rw/L+ocsigenserver-5.0.1/local/var/www/ocsigenstuff/scalable/application-x-mswinurl.svgz000066400000000000000000006032741417255654100307350ustar00rootroot00000000000000ks$Ǒ-}~E-E TGǓڎd#3]۱y1 h"_~GVet6B\"*Ǐozu{w}_bwo?/vw^_yw/|?~x{uqzwywvW^}~ps/w~N}w?|ѿ՛W^闘W7o޼7fvogj[k\x¹q~OWs~v?~{R~o^~{u{}wo/޼Q!WO\w>:k~_Kz'WL{/鋩L?UѺk]PvyIw[w7s#z|q<|7wW*nv7Wv͛ۯ~%;Qa+= { \>PţxV|K?vꛫo\L+i!JIӖGvyuO߿:pn7W:ś/~;\UW^*#@KmǗm?Ugw]}t^S%_ᷪo53;T֖Rt%VO9y|/j)Q6c>JA}.ٹzԻ((Dž^%4/yN' ?겘Q/ջ}Hn`vE/D\.K!<}/}5FB18<ݟ(Ƞ=tB~^NYgK4#W˧zqAL93vOf»fwo;}{7nzq6?Nyj'Zͻ˝;f8;Jlgy]k)>!5!w53\ݝo$=IHwt*rY,w՟}ާs{Sg>\B8/C3kuB~Gjew^ꬖz8W'gn% GDVޕ}хߵʦ u\d^gNޫ iL^tGY=ؼo)c{ڛԑC5Z+wEj>_z7;CO_|ZJs'՟/>]_7nz O-.:9>bvf.W2 Һb(ҍBTd>5 3*>>0aS#0򩑎 N-GFZ4#=<ڏz Dm9#qTT=d/v?8=L?R>~#r>k'&ͅѥg bz5veb5kՒͥ/7KXGN 5.{M,5PԹ%5Wj.wjT4٫R]j[VvUWyWꃻkmߢSP\#0&' NT P Izj?0WD?)ޫXrLޑN*Dd BSTқ/>"'^}LG[ϽSL:lNVJT뮩Em ݹעF0!hnv؝{9!;p}n1 ݉Ҟ8 |.*) ~%=#XjRaP+! ZRϱ^^dN\{{B&:/?$<Gy 3"6nWWSNKS[\31()(GU ~SA5[XWWlf|_N~5 O:F,KYmO.slNT77.=sj;3R!>dњk?^.bL΂5WtĪz:i!<ؗbO?sf\MZV[TNQfRw <ǖU'a]J]~R<.pBT:I{WMuo~?.]i ۟H?iY7ʽc}qϢgH7Eyԧ)4?M9eb!Ev9gl%: }߼?#%%ZCkH>mDhC[ ܹ=ںJtz?ɔٷ`ƙȕk&6wi]M+Su}VY:NFT|vF'S%c~"H˟+g'tj cyhAj+3 ODAi0< 8OQ x8ኾ)L[sv.>!X>'?# 8gh_˳0:}^4?4W%E#anhZX4A_O5].'Đx34 ԶLi=ɧ%
    3m1S^gy 6U-rJM>-ҥiɧQئy×-d46myQ&RFzl/K&_FH(lS"A&_a¶6ElSmjðMa[c[670)f n=)%lSM6M1SM/aBm a)lBXm aɮ0{ /[Fe]MU6LA㙂,ᙂ 38 $bB\380/ګ5uqM=kfioa[W:yɣ`< b")NaluX.:uS:-֩+bQN&Szy-,nM1Sq}$A>&S6LůY,aϸ)f*Gu%yeh.?5><죸z*ɥ[mI~\=¾JC碇?{o^3w->{\ r1F3b"+bQNmN\EX'u0X'nuҊX'-:y:i[W:yɣ`2L.Hڔ*e=n,V {Jf[3d[czap}3r^"m҆ɩKb˩SqY SWO̩[{u/;@[ 7N$s}${!tD`cy5ҹȖ5l 7:uuQ:J:LBFWO\'''ERFWO\'''ny[b⺨?q?q?q+CuuQ:J:LVL+'Qa-fZ?q]ԟҟӟm1ӊu' {:Od">T՜i^JVϼ(ce5]Z]`1l06nuڊX-:mӆ:u[:-:L/ZFGnu[44?i~S7:(彞.:/[F0P ja&j2)fBYdT8y2?6L-S⒜ɩki-fJԵ$nYO̩[{/4^I5H#">seF={}I gNſ%?{oaI٪΍uF:m[W:y)`29QYEXu XaK+bQNV-du"F:mC*[CŹ\ Ycd薘8~vgw~Cz#o \ r1rFɩoAdIn1r_תԒU`޻lD9G}CH?}*)vBb)Bq%ѪsLݏ2. 2B"ԉNaNZu(P' u¶P'u"G:y:yESA2 )lRݒCzۇF>2-fԹ 6FJ )uՅm1S[-NZRW#Nod:3yZ|TZճƈVKh$YBc} Gŕ}H-H{ +ħwY-ͨygb2F&Fmu@E XLJalu|XxxȦXzX"G:q:qEa8 IM!V>s->g}<-fʫzk׳z#-f*$ΗAr|&.nz9u.ɩu:_V]rE<r.ɏ[1>{{§3<ւ>^f]YGI׬kmN[EP uMNpA@: uҦP'NKN@:iSzP'%P'1QaѼ)=dCAl 2 lʛb m q>0ۇ)RҒI i-fJԅ$.ARB;Xtma_N%sh()-*|!3 .[G[[E:eES!2 ) -Y_uXԯ:ү:үaK+"QNmΊ’CE=72桲);$nCl?!lb&Yεd RH8d릘IzudI$Nd)f\K2d z#zjJNܩ$?r. Qӡwob<{WK<{_(\]TRTnuX'.:i:m[V:iI`< ib"ɋNaNNYu(X {mI]o%{H0ڶ{HڒC=tIsa}~^GGrl4 3ϾgAo/o{Wk:s輩J<>4KED5D~~BJGդ/ќŠݧD7W|>k_<{$wz͛wvݿ?_|xOo>nSS_yc)-tιz,k_ݼ~ջWz}?.ÕB}}u;}.;\~{.^|6yo?sJCA:cxƇV{Ynoq›I~}Eﮮw7{|.ѻׯ>;w8>~tU:C:z>?zw.ޟ7/=u}o/~~{G}#~]9Ѵ`nw̖I>;u7W'r羻Ѓ3@ݼ{c?r7{P8gGڎz^Bjxx]%/1z33/i,06%sd.T}}էG&Sʗ^_8jH~}W>˯>Vp]s罾 "zuooߨM8|pr2GgoU>^,}wW}VDk|տ_y/dCsUѷ›TWo7xso!]-N7(e4+}&}/7;)_OwkNE̹.wA]p>|;;ʙrv!ܾL<ct%f%XA>]D=FzJH՟|C=vEg՟*.}jګUI$g":a2 DL6NԯNTz9ƈqTO(1uЋ,U wqv:V뭔d?轞Qv&Zc9{jzqj KW% Ү#C{TPc |Y_3ZM|yL'r9MopՆ=>8脅վ_ua_M>}4P&Dzk!fJPŹC>ʥ:y$2qJKZPy,fȂ_#qeuf?YxĚz唪!= SvZT..]qboVE4Uo"B.Or] |Z#e_u.\=UbXRG'C#rB1Vx, f_Owe. &ȉdm]yQT|ђ&mgw&A !9O^ w\"G*|}&$&g*-|ۧ顾2~$_c)xb,(MwfyWϜ^H5S3 tݨ_d*e{@F* Tt^~_IVKˑ#̾յeVH~#iY2S,?녦G VwtDK˹_6>{5qG~4ϯy6Y pn\N0Mf[nzPW]Uv;@9U;j!!LP`ފ"<տSo. ]N5$T< **.'E쮰g~FWxA !6'<}C=WΧ̵t~<0!UUC73俒;Ug4.NWS%R/:$ékŪM+*[C_huRj( z&q:@}_05%I=y}4*EN%4ub^0uB*㑬 &땿+p%Ǟ,?tIhs@qϿ!̫FRwV]\Nh] M 'T$4 N-z?RԂG*X!أ`բ@Gm<KN?|3PG; "_=SX"A ⃶`^F`a>CU;##4Ϗqo(OܧfUs%!,]aart}G-@*Eי(F肺.6 ]a݇*] C: RpHa ۯ^GY@QA@զZ2xQk:aԘ:ux*竟)zRQU+@j}ֹth!wupӋ äWˉA81nhJ=ؠ>~Q8NEN!*ةToTSgTkQEA+**ʖ)W*~:\Z?2ru?N :>=ۄB\(YݫP<NdbM?.Utb>W7޽*jG?^Aܞf ت^޳Zf꫅O,1և0u A/uRcMIN:V:)K }>eE6S **:nXh:V$yU!wJz8UW3+Id9rw"<(oz&:|~.TXr.M][=8]ŪKUվClmyL=1= R6z۪wױ>Hu@W1R^RJ,a@ugp_,;, xP"$c=7T+HXWݠMJ&i+ѝ8oZ;дfF9vUuZ2U[-j٦>QE~=uJu]4&Tq*>TC&,-WqE?=YVy};BTX"A*0L1$ 8a8b0'diRUq1䌮RH"Z^@TRc4#`-Fճ6痾H6q4W쎵J0[eT'W(^vjA=L>=׋TߎĮu=8X85|uxH/Y>{@'QԦU+=ϫ6{paq껀5-\8]*6 K`l{ubI58}PZ9UW+Z st43sW,'t1iDYİ)փdt!g44MJ7a}>XC6BW_l`A% Pc=AY3&6PTV8;8YRJ0v Dj{8U:]m\R. w؛&Hh&|y=;U} rnp˜6Fe3v:Um RL IIY N?tlDZ<- K9%5F)ȫR!cK0pku8v ᧰:ՑuhdiYU&M6 9$钋JUrI;9s(Vb}DN.yu+Fۨ*Nˉ-劲FC#[NI %ǪvRt.ptj8AO#$LjtC 8=GW 9_*M)T"kP!XUGq ~ €p.:vY9{c (RLE4NFR_Uohcp.Sm,yq*-(\<]I$44T^~1D #R!L~afJ!$Ve !lz~|qa\}318A%7*h Fċ,б|qz..6@KHlH"# źG| ָ"$]"! cUs( #ʌU) !ћP^Xl.7 C a*{N^ d_b+2DȨCRB@~F 1_D #~3By. @0"&J3%z=Bå0އVaˌKwKaS}4Ue Ƃ  ʪ98DyARwq$Rtm4,.⍠3bQ6$0BQ*2u1V,Vc p]$*T2",h3 ~GSL4hI%a4d|`MogaAM[@(Yu7P=g p t2G<1k3SC.u loFw` f8@4+ӈ(hai EFȤ,#": qA3K&s+6P7a-DҼ ? 7!,T>C >%s;tjn'r g &g,_<|+:RH -?!muHC am&a#~ ٜ9DÓBW 2^\TDR`p.Bb&v.ltcNҍ5Q`/Xuee;W:eYP>Öu&eXflp10^ u+pY" uVdHʈʬTGZ5`.4s(gc˽JZR2]~0H`UGbazhPizwA&z2*V`Bui K` dȓzICVK0J@[tub]ѢKHZ0ɖa^r`YxC"/X4ӐER%sbUhn6& hY` B'+BxR) [sJCɸb!9!49bW,؈ sPѫ@,J23!F)QGdd`oTjС0ã$.JXNaEhPQgN8@Ƅ roDrRn ЖH>2b}7ddĒsTz_eeBzC ecΐLEݝ1v>wQ,kREkRgvM"8w`~꩞kHU}mC{OOu =8B  BG:{M7Е |6bi$6g ߫a0 /R ӹ(t`B Cզ+JHteB176""!“5M TH\@hqFpa"[qȔE]Cg ЁUT.D*bh-]Nhæk HL9Ba(S2:, )f|dZI!SO(E=L\/jǮL[ԔT#̗dQc\3X!i7c]6#Ss ^2!9ĀvyS vd030Ř32]!Ǹ!]yG@37)2b@.  f6,HFY˓S pH̫ fIWёӲ(,i+XEGȟ}tgܽqۇqD*0sc3k'*1Ƈl1f V: u1CH!'8Wd "i yղ<-Ǚai$L,J4ǂu$l@= 3EDQ fҳŘkZy#ㇹBo\ sUs| Kg ByLwAٰc]=[60)f& 3_ #I1#l}^`e8)|7Yx`Mq%0h&Wr]Bl8ZU q4I8Waldv3BhνVE]x&BM/X_]>|#kG }Ám84~7 z$};%}}vy"}+@Ȁoq 48;k3 (>F6:ߋCH⊡'w^~ީ^{AמwaTf> [U:ыǟY% |`v^T?l` ,V813c'¬P<#[>$.`'P|6X}>{p !3 id4I ٜ<Y'V#\qO[}\^gHQ,fk,[cA\C"Tj0 c,Lv5c7?H7&ch *LxE!0n`pVE:-7ۺDV/'JH R W`-503O3 ezu w\eWbYs6z0 *eD !Tqh<w[9AỄ̙6OFOEJi@mDذ@Z"}h|#2 =7ICyyKIb '0V\dk,Ւe@9*R*a<ˆ[^gCwDlI1Is dlJ{^-2y!#lWӿC{k F-ؼm z}Ή;7wRæ]fl@O̾ Pןf^"ͺXâ_!=&7oǰޣT3Ez1fcBƵYiD:fGltITq if틷P{]-<]J͛p!uS2M2eGNă׃,MACYbxP8xIxHe?2a&B٭d)ҳAˮk'󨠛 6RKte (L)vȕl7+!UE5;UQ֜b*A\f6 9[']!n"R96QU$ɨc HF[5xlLt I`*,`(@\,s .]KF,&)"ĉϯQSL %`Lh J B^9>6DÍob;PcBR1h,@JyxۘɁq{kS0zXpM پR献zb ǀ }HiOx$G`Ot6n ~\d-$ kmvמxr[ôXW1¥նaW1ƅ\v 38a)Y4n΃Vb;C0V7h[_,qԕ#6H{ nԗAh&tgm`Mp"nHԐULT F5j&# t%~gl2r= zɟL:wXڼWJL|L- de֜'l Yl12PZif mbCbH2ўU2(xmpd2J6Y.nOfoEauId-.)2 3Ⱥc"Mz)2[z{PdJZnPFN]{&4 "࡞ρGVvz=I&"EoS`3B.D ~^P -[9n9ECϒ8Np^R_F;3BΊ !{ qdD9DSSyDp#To~lyGX {FI sD%\Ǎ6Qc>٨#0ɍN/z|Zd6.q6%g'XOu2ebɘٸHI|0an105! `>5 MaԳaNm>,dT{0uiu>/:??atUl`URcφIwTgrB"d |W:-nI'襹gX(1"9bE8lluU dW 9@q;6*XzqONu.''cSj/X&cnG l|JG ջ|98o|Z6 cl7q{rO&.;p7q½qʩ;oEdr09t 'Gqǽ{Ø{oԽ77hq_t cfwl;yp={o}jaʓƊp1 COD.ƹaNqqx}`.̋VϠ 8bqԵ,k27aqT`,wU8یc\?]34+MrG4 5:9Uc#;gRYhVs;ś7ٛxX4I@ǸobiJo3hw0?)8C\fm };EOu߫t?Nrt\B$?|җS/h ozeGGXz)#(jV;4/u{Ǟ s ^Ѓz P1 >ίVQwO)9%bk)fIc a|a&a0b<⣿jMYTVhx|-4xod:0֯yF%BSm92_E#> ܕ@>(ݍ)M/;_,jl9YEhVcGN23;'[{hs6eEe3MJN6ד;'X`rf;r3l NS?SUg?9Do&N50J*ýF/-Sb~h J~fp,J4-(Y1Ywcd%r>! DzMD Nw}^h?S81AЭ @R |֩MDT\ThB~FRPJT/nty/vHvkYA7s5Qc&'9Մ˘1Wf{0s5Q]:cf+\f jŋz=C*vĪ&Ws5I%\M]9jr:t7|qj˔4S:iAw$ʜG4UJJ#2b:^)Zg=T&6sSjBMĈj4J<{u$RdpPga,8 L{y{,75Q(B75|y0mcĸ mcX6Aog,~Zb4Hb ;J-TPD.F+=. m1)#Mz}(MfmXk}XBcb[D=$w1 Cጨ+OY\QJ^ 3٬+I8^bVl6BlS^Etsd֮g!@T@hm̤Rb4wB CC3T#loLlWW@`YfC&~ӎ];vAvܱ0}/7Ni}nIM;v9ٱ &Dlw6+-vزRbc &iHNYEhUM]iラ46"8nNӦ]b" $ lڴ+YϦM @H-*=smndE2BW6v^ݑPV0`9LDq{Vi}> &g+.V?թ> hǮ,+'gu@X#Y UgIV #{@rlcw& `@PNET#U3+7~*/9*ԞIu tr,Ѕ1 tj@W륬]Z܂C}Jz fI\ c*+l{fJղ]d˽JFtX:qºMM[`(υA\-C/%Sz04OG=`92XIQ%[cЅ P Q5Kd]\P xC/XƠ]4S{C,^Бa R+&M0#a4Ea~|b:c煬d< _W{ yo}MR36*p+ /H굴KҶgXw V[%jEFLpuN @FKՀepP߱ ҍB #:V6xd6's[+uy]o(:wPߗ&!d*C/` K/H1ĩ ؔpZ_%G:SI*,[<ҼMxT71|<# 5 "Y7s2n5Ⲣ;-xk xM OZvr!#hpbN+3N4{aC%b=螗ES"ƶЩSdHh{ZlPZAت7:P޽Tqݩ ZWea0$*-]MySO,S;YP2jA:x˺(c[.gkW-l%ۛzĜפfcW0lJǖaDv Ụ̋@`={/2 nި,#b,NZ562&gܳ3ʹN;tICŻgH%ć=ϭ7ˋҡ^0^%~|*:ΏSAC;FnS9v d {WAq!XQšbara`[]#] AsƉd}(kHO]'Ԗޓd3Wˬ#/6.mqW?N,xQʹB;VMj6$-u.`%ջܢ :ΘnYSs-N* <-4-tP{[x'\-n|)6dz6й F2vZ"^ .s{[dSm$܂6e{|^`/PeJ{15J겱WeCc/ֳCc/a㬱z}~h<ԛkhК36qM^6zs3̛όYYkUmUgSk/$ݝƗ3pً̅hI{-F {!&ƍvle11nKsYg/ŬJuUђ@g/Ŭ{!,&ً6Y3@Ͻ`~>tFDC޽*uDȅvMk Ȳ&S9ZACSB&}#m az'"2YP\)CE^JZ22#L]1F:z:Zv`9t|D2$7{]䎹hcf;䥳h:1la3J57܂ӪTP-5vͲpTkv-"Ęz̸ݼw,}N6c^zܝ^|Qu {d!cAPM/cí5尲.}DV{"dC_7:b-+ؾ0!:&Md8)6֊8q ck}JEwn]# KvRbhD[3!dBV?v@ˡC</¹4Z;;$hN tb;䤳1gJMEUKD-l¸ 䲡/0:d+.Cӂ{< N(V>Xd:2>uT2z\ilc t1q0kJd]X 4R 1UZ lKˈbg !AW* w6r'7`Oi4Iȹ:F9ˉ[F?CdSi]xbԓbO :Yo9COFG5`dUD3UhݠuNsCP3'XnWcO8Vpώ_ ]6mCQ@xĜ -RXrWOl>?RhGPӏҍB;n$x#y]Lc,zD \>o#Le)-X%_%er,4e鰄BE pԥ5taX=CkƲXo'5;E?JBj(zDY,:sU \,޺.Q*!d E4OX62{0|\QdԪjnJ3]b]d,$Md=1K! ܓ]5dlS!kh26.t5U.tW)%ăbdlS "ڃԆt<k:;D+Oƚ>58kuX?yn.ҁY¦q=kNfZ"6uMwhF76uPM]Âc/,+qwɽKaa$b1(vbbԫIcaPڞFe *ŸPٌ?3%5;Ryx_C$5U,_oȽƥҊG >PQ+N1t/)xxR$W>z.85DCS<=,_zIcAn{K:r}-Vj#CG^$ãCaWi M5WޔT?y{adAz 4Ǫ%C}UAC^I|h^]cϩ4zռ"o_V^:k}Jd{5XCz>3R< =rꡜI +[;-HVP5 (wRѶSnp:XsC}P !3 (R9Ђ̀2h (zqdBOf@)Tt2;3KSN ft5%OԀVحT6 s)g(4 뗨ӉfȊ~P5 364WW p,>WN޲_]c_9qr#toosˏhG )!2)$m=RHP#D_-G >)n(`mG QB<5< $yGjS;ƒtI-!$izdh30e qћ\% Q UD$C)d,AGmʴtt<*=ܠR(l$uZ~dgpU h8t)PF&I:]HEN|bx %O.*$N,'8m`<ª+b >ZcnA5]#_7HUͧeG LL[d|}+դ+%XHW0DÆW`-wO)ɷ$U)HW =t%C1W>iuBBpJ=:h a˺~`[)MU^wNÔL@ /bg'kN|$+ޓh֚؎izOڽSq$7z5;aSj{C;{'xrOf0BXv,$|~F,Ԃ q|A$&D8 >! ydDz,=U3˷Q >2YςOuH{ Mo׿Aז{K= 0aj*P Q6L!8ո:j@H{DK1 5}ab\2Ƶ6nʥ SBތj"jdt:4PgUo1n&cpi`Q'l[OY,@f/jӲng W=H5Ӓ 9Ȝ{e$* "4*r}X2W朽y~(Sr@y7'`I>J:V-Ѭ` G沀M?L ^UaDfZj_Y V(KR0K8X3% ]9W14S۠I)y#kXݔMKy71y8'x(HB1+!;0:D%4HJ5^K}'1w!lUӇ06:ܛGU0HN9?A~!!e[wdvJXVa`b#٨e87=.HҠBb6tni߻&6[ļ~Msb< $!p`ސ7=QOufYЄn S0ēFOMНJ,1jުfz5%ns%ZHM>$dEcsUaa&DW 6իdp|4RBb;&I Mb&SS"aT0&U'bX-|ɾ,\J4]#@` >XW%B.zT׏ކ~a>ȁB"$\i,LzeXs uY4N"+5ۖGהN^/E} @s6dl#<8WxkW%M'kAӒD7W8\Cze bM_aJ"ZwVz RV9Q8*fqoeN27HĚu8Y2Mp"yWɆ7Ex,uuZU}SZ.>xzhWP, EE2' >{yD<(i^_.*J+‰F P(FU/gvh.G͘%;穑QK_EMͬ(4:TVTI<%%]'P;- %ZJ |T JC輞Z |.4H |G)GU12%S&Cd)Eɔ1(2uʦmIiLԲSdf6:5?S\3r%rMJm& }r'b2QSD|a9n 6Eu!0Ejd7mSDYo"j};"Zyq&Sj^h-l 1d'[f~kD-dhksm(EzE,me"rOh$|u_!Rl$.=^nemX+lDh Œ+2O@[|mjlْYY49ibgo#x=,!+FAza\7B%5B%B |*B 8 yH{1sVn9&scL̰s̜d9f.ƺ6sl1srs3ƒ~9SY;2"g3D%&1=rsfΖ1]2}3gu mr5(:+KfDYYjُ̇8 Y ]4ebU `W Gg2nΚe&&ܜ\bLB̾vt4EzFdz 0K0=%4bLD XNY MQXˋx%sPF(4:i_4namc2}*6{BveI|8C&@.ڞ @BX%wRZrHJbĊŬZY"#S%bكjiJbF!&˷HFyuWlarؕξK YyTE秀\[8g/FX:5",|e(1q+% _$.>xк10+Zf]'{o)9ߒO!SPҽPBVӋogIm!_}LH( Sa.uu"%61ҵ^w붉(p2nclTKr%}zs`%:!6zmԻCna HA'>CI.Qn`ˌ!N[kT{9F#,e1@5%|>aQuu8z3tPÚ3%rTm2}o}Y$f yihIHhԚ\g3*h$UBjsGȦ{AwdSB%M:8,|Harcf[9/- 3Us2PɣTɃ6ZQBIe}a?vނg 6pM b*AմJl,ka!"t_VxZ-Q˖7-6*Hl tWusizVFweu/:dY%Щ!S^y"7"JVr8EhAҩ[*݇yg^8wv撳)S9Ʌ~,WEbegZ4eםVރOsTEL\R*! IIŻ[Ȁc )$FdD 7;D HճI,*913EpEޢX8sǠR1|-[5cI0$mC[uޜ{+=K g^t^RB_c%иD0b#D9^ܗ%o3X^&%?_ 6#amr?&Ic$=E|.\/m$-KAo`AB{U BFzݦɸ~d4$ZjQnNvRXxb4.CKCݢ?gr IdIL:Jy9ֿ'OIuUA?CjQ'9iuJR'_pDs,٘`׭8]v7f&8ZHW}rJpg^,U&BȮ.]DgMe]4চ ;/,&YTkyxxW/+[-uTB,ttX뜹Xm/1rd׵{7惞5N%$Kt8$kϫWxunHfx@g׶ԷM),jՋiכ˚3C'Wk>O,g&Dj`,Y19~&/cR׶(JS`/_jgst~-ygp,vG'-T=]uџ0+=`BFs=EZڗT "0=) GO #\>)Z%A)w$'^IiѵMM*3'OjRJMUCÓQbDA['XO 9~d[!]ڽ3 ݺ (p(^qf$b eQU eE #K ѦGyx])5D)JK8T-YڂZ'X&7 ΞcHͶ P6g42RNlH۲BPb~׀(%쬄kH9BYD^تlI%LY(1cfm&0تhBHE,$R9b.n> U ڎBɃ͸ECBWMA-/ك7x44%dҒͧR,6&^`LNy>n{3ci Kcw ٣=b0XNBP+)9!<= =Ցa KKeCd6%sK雙\)KzAh9J0,GK|\R(G?gnMw6LUڂp x)ROF ҤdɇuH@G|5ݝz4{G1]FaoDImٽďF65ya9&O1=%vv1%ܢ~a PJdtG+h]r Xvg'H? 3 H'&(#@kGI H%J|&+M ,^! B~P?a+\Yt'!O$ P2)Bխ' ʠz}Nt>KDJܡ6of~z=bz=Q] ߝp?y5pOBk[/~xH剭W_nZMɞ3'NƯŹ⾯_K>1ksBZ^<ĉo4nOcg;;L kzfC'&Mxz !K-R~wxv8$tv'-/8T}[=9 !ͣZ_Ko7Szݾ5˷k {^pz,(#J;{m7WU%o 7q?K)tKv,oפi^xŨ=פiΔ79u?q3up{8<eW\dIq¾^V0|kɯkt{o{ԡ^q)H㽟W+~ν/ V^-8pzǠ;Du{M3 {AuLb{CVXc|$#lcW>q~]09|^q1ʈXo8/]H=/O5}3BHPqtƉDq8U~i'b>q:c9ǐa}\L琜׫aArxìXU^mE}_Qk~bKy#'׿WKTNB;IKt~x F}^ihZjhę?_ѓR+_';|5Ppn}z̔\/a3b)NkS' _mz4Nyp0S%iG-)7A"Sr&jSى[EAB9\qPF 8?x֡ X-|4KPGwk,z$K0",JuGvGފ%Q`lx[GDHQ,~4R,'K>F<%Gmi41PY < '-0c9&WQ$0xCGLRG4O3zqz/ų:3)Nj@?W68!r#tI3HĀR{) z4WXԾԝm]-[#ۻc|T_ k=;FWr0[)q(hhv_#3v_)Ͷd];=^׺b]!g$ٞo?|foUl{r|Jmw<njv?޳Vg7䇯v1c^fO;{]q{1+4 EȮoO gx{?oS~XMWhj}(EdL:|}]HT(~Etj叄3ʩw<0˺"ǩ$Oq&Aqj7}VޕTD)|a:8ԥݦc.]oV'QfK]3v%ss뺪8EYʩ˥RO.U|zISK&&,dP^'_j-m.4-KۄCv6+^{PgQRJ+gTZ}@IgTkE*mgLZ>{bIjIg/TZzzI<8TBRi9NI0>r:V#KZi9ҤzJ{E|MisEzKus03FK%jϏdtO?-%{;a,;N3a]0tQqoMPnFcqEl9{YML-<&*ri+BH;i{%sbqaq"ϽGK,B[d4zאm1BrZ]Po}|2ֳ^Gɱ#r= yVK\ײ=/e.9QbCh^!64L9??h'+gKSAz܄t@]om͠Nn'Iڔ]($m4|Ilk$Yr$ 'IZ2i|YIj%cc.P9 cnו?zu%zSo'j5-XPѩBdчo};f=z4;z4.20գf;zԪ$~M?/Bz( taǘn[)PM8VWW 嫗aSzwWAX^X+N01^zԈX:J8둵ǐYqg@Ʊ# ȴ]S'%[^G Zy W1q% %jw0]Q}`I+ 7%M5EL^|޽rywASA/+u' 늪߇]P}A| K7L{^3OTqkkZjmZ]~%}Iuk&#NZV&V,]x ~h`>œ}w)f|ܮ{35)tNrk$rRzY^/=pYZBޗ ^9+^>X/쵛 Nڍ"f6}ojHHrF^;M3ҍ^;% Knw6C$ZVj]nW%M=v{$UݒV"Hb+#777K{puKi"9lᶻ'yKB w5.pj;QzyDީ?SW"y'e"LPMm@aujj/سIvY+1UY'^N8A31vCHbM]!aXο<6qeݷkxΗVx4AS%F/7rz/c? b﹗{; #BSQsCSU:s&:5_8 =W`*{1mcW_j?0,hJ`VU|IoŘBB.vY _s+NxYR1+ 0Erl1gK0\ȘUx:LRH]n6ZF?!nyk(C;pV-_|,-[]?f>UNaȂ~09 dGϜ)*򠖃x:5&% Ȫh`o ɦUo`܅օ-Vt HjK)smZHb[Jq/1dڽSbncxh1qB[8Pk dl M)y :1]'N7Ԓ,ہIUnCV!_>Q2ЭKBןU*oMOżnCD/4!pL;SQy\f5Q%Zܑ2;*Z8D`շKq$շT OF-+WoT~uZMyu/%^Jov+X4Ⱦi@kW^h´:ՐZDZVdn-6HWdAQRՈP3rAp6%=sISͤV5&5ŌOcv:W# HA?UF8IKs@re]JͨᰶԝB!K~ ҈Vz% _452dj2=rMOr[$/%R$vuHqқ%tB3sc9YX.{!&&ܼU0^f4h%Fe(!Ԫm FncPsREMf`F8DOycLxR9=fS{^"$=FdE*%tkx~V }K[h)F%NUz'԰@N\[&22f)'dK cqUzG&33*Vַ(M\3yf\U3SNEUYLy:)0g/D$lRU/ 56{uUƣý!4cw*ôj%0 A%Tmͭnh@PT턴6M=¨UP/j, ?jK֊ >F :`6Lyv&.r7`rgFI$wx!b"^-XwZ1eP"T(Fe>wq 8%f_,U~nz.ڣA"V8/ᵄm$fzbYOvo+9pIR1@P1ifK zF^.gݑ. Jbs^nb*ܦ뮷ʗv9`sGvo —U-5Cro@b0,NW]Jȝ)6`ZkPx(JU2z"fnK޵0$Q*SNbNؠ4<FZP78xs&"u EkX횂Oy{uX?w<~w⇽R|)g'I&{Q&XxmJ|δܻu CRRAIՇ*OH0xcy!ko_^Ei<ƹxݧp|o>q{vǙ}Ʃu|3EN~?Dqr UiDl܍ܸm:E|zuu E(5(pܒA zTsdb)Ϛ^7=o~Ȇj43i%!.EM؃W_DwNdd~ݭ6]smLb!Ypv֮c9r$l™P:@&\.&tG@'>1FĽkD{$(GN0:Fgcٟp=0 &D8./{Iǵ.T԰3CVF4nJיQDc1Bʱ{B`M-:FկAI՗}eO &iP Q5e1UvKdK$ٱF4X5}+}Jo%k E$>zT҄$[_n-3N#jsH( a51nHBC~YLOFD4-@VK6pڥPK9BYCP&EVR,!ޣR#P!aBWK.[G/E=<-p0XSbz'Ia)RBJ% v֣79mr WH#W"-¬eGp),LR骊U:76KK$懥 0rqҪ ,5VNRdIq޶rfe"3.D+pC0͏KDj GA+!K.+XAAєTUZ(y_ҜmsR(+nŘ\f_1 ÷!FX)|BFL Oo{6B5D"8< _rԖθaѧ#1paEs2ڪڰ>Oā#h&fқcibAXdPGPhHۈ"ok(FJoFc0VSU݆(SSdc(ɫ,}&({E'=ϟ[XΝAP$bH8)̱cIh+:=+)宿=#妸4WF~??x33$ޠQ# 1!H/ON鄓a'V4Rwñ!rrSmgVZq߼ԣ]Rܤh'V<?b%ŒK>K"5<uoKVY+:-[PϺwIn ev&`v[,$+bOCTBՒ&ȨRml>q[𸖣G:_u.XRJ -X6?v^^2zLYСL"FSqX hӤ5ub@|$ieR+T CZR_~ t;^wXiR/8}Lc8i3Cf9KӜ3GhI2.' %G= n%-Ix͝0 mNR S1GL] T}N7 㷝d$rI$g)_UīBy-<WqG^W&/mKa3Cp|*Gd!rc>qF>^r[j})ddt)** cp GD]} l@, gI=)И1-uN̅RM H<*uU\l0vQ~2 b|X`$&*S΀󱙻^!"r! hx8Yn'YHn-LR+g 2&/%cўw]t w*eqj؅X39>*K''&e0)tbZb1hA'$8,fž[h K S((s)F8?dV2gRj^OccF#[7#ro$',ֺbo O)VZ_T?faaJL_io,ApMq] tpȌIG8A$5 B?&h)!f$F0dV\u$NlԳY+34(9ԖX"j% 5R/ m4)%.% N0Z 9+}:KCʅZ $c]yP%S;w}}5_b>G 27J3Lqn3}QԢL9iტTm$a.RX9N9?]G/D)Ѧzfaս=[%'폤GHq.'<=:,(? ]]7hbR`*ó< Gv.:vѻwIelg&TV,5<\XQ OOyhuUN͊=Ej{tB2 h6n%ǵK^q7yZ!ȒE} Sfb~M`"18HRLCx@n&quM)!E,FU1=&-XYԭ8og.ѻ| ݈^޶q[0jAP=1l?UTM,;q:#q͉vaÈǾd m=a .t,ޝEH4d:_ϩ39>d hj>_ЕKU/1%/+Y;?Y%KSY BʳTXJ%@rAg9dzdYY)s;Tz'Mwp3=w`r5]eZg:fޙ'*پm|{ A`AAPi8倐fBA0f![0iA? }cAf#4} Y:0$d @:,ga?p H M4u M(4{ ~0H s6)jhX:KD=p0He1BZޠǽq2ea+;,Жƽ4* NTp-;uحbly=P;[HF ϓB$dWUpFc*E3|Jz2~͍Z[,|M{>m=h؍KZ6acv uAf86^aN?I஭Zހ?l:.KazX;3WxXGCTXP. щ4ONvK,mDRu`};iY8ĂY^e!_lmbN̰Spew˝wbD`7=JX+LԄ,]O6ᲆWz)A߱M KdTѴIY$>n^ tsLYPkA%˴l+6j l2B_M:߁u#cYEv wh|I~~ʍڈ+Ax|0b+z.)0k\qĂ;X-pC زEfJ2 uV1}}^q__KgSl +g0;϶߽hgc l\(>x훾e<~}L3=?c M{LZ 1/{@:CNP*! BTcY8g ohmOj89uDhsgĹҙq*̒8ӚgDX_{o\irLdYxlK dq(%{JrgKzBj>&g*ptsJѢKB";ߘ _H4ayz~1w &`f2ob] WQ@O|O2$&$yl; 4=t~t֫848!TDN%VϑNb&r/W<Ρ>m6bF%y:^^Q|񹖷zbs$ !U{ׯe4x=|+4 @?>ȒkQֈLjQET`{w lP*!.Dڥ^#nٚ&R-@"RauyY+}8.zل߬XMN4k# SVe[]e BY~ެxM7l]ԨIaXܝЗ@o5Z˱I:~ĜJi^MrC5&Ij5Sb# vLbP.Ujx\[WcDcGW)ONgO4kkXvPÕJ2K$F3<*BY_:V+Txq5"?dZChhZ.˗\0570ɢ q%9F^AY^L3 K}\-H#æRYYYmS5'qEf荥[G*N.7'޵ܔW=?c3swܵq#VO)syx}YOL;cFbrJڞ3hO0%ڝǤѤciMtV _'~. Ĩ%ܽ$}Ilb8G29I^#.nHQ<6DWtLg5a;2";ra8mM/ȑx41=!K,"DiyxaBCK*A7:5TH5 r<-ȊT n 6~QNb?4IY"$S!.r0]&alI+gkH1dbY;.}Ŵ(HL$*\B9kc9)/\\<r0,pܶX/@Erj5Sei*Yq=mV2CO5)] U)U]c/s9UdKdzoUoqU }'uTHss(|!Ο5/)'=3zS)V-%Ŭ&X$j7j;xpv^k޿ 0)Xœ!an24JCQ6E`dvL2L~T8KAgÿ)u#YL%=v/&t[wq5пhYh,_ <4|+Qs¢sB퍣#<*HU!1UAib(Hj?x{o *Mu2"P» ~aeq H"Yدr( bخbH1h7̮r6U.o)/Xڸy">/yƆ;}CctF9k:G,W9G 1AB.g>5^\ɖynEY{'xJ Z}W\RK=g4qGxi3Gx}?2ALx-s1\FgBL9"d>^N'BJy@@UFh6FGY,: reRF HqC,u2:bEV+bQ=h&mW`2mXqJF(&T6sK? m ]HA I(8/mh,TiƑ8KE(vuA5SA㵩"MWQIK+WT&'FAE} 7[q]Nozzn~:iO{}q挻OG |0hOW\Z.Id@{H$;gDA(OeB{XrI> ElS"V鴉hQN7dYF[OOo@ltIOPl]l?Ct\;Q"7'-UxnXh*ҐgI!tъ;8 rsK9fBI&S6E.mp$sV! qLE'DG}g*8 = #(5ecӞTqalUnhKa#/=n.dL%țw[l42܅>HMrP;*~ǠɅ<w\H+T;F!?m,PkTp7+ 6iν#`Ej3KKyb1 Cj Saۚ$0mLfqI0Ix@FcDXҥ6gzҘ4/Jv'MJYL \l7j44]ZV,`!ol/_ڨ?{G1Jg[TĪUYfU*R;g^dMR~qTyjԛeU]J%ثJMcE1I{UP=?:P f'܊Q'`Qdɸ z3f[>hĩ}# 5#3#عB?SJ '3:d؇3|FC ʹ'G,3X)]1Ovz2FWͣ--/|{:f焞i'e5]u8N95w:fZ{TnLeLOYk0dbNPd9܎J|s tR5NYl)9锽[qH{zHW}ĸ&x59eqFoV71 wϾX_fd.Oq0XU-4n$MTiӪyRNty4a?( QAyh %}Ɔ4)LʼnT*6xo%8tR.}rnMjGj/sZQ̆c/*onOQyv\ⶮ ֻt+ܻ~:k\ZU2XϟEo \vnHx.K"G%|c%4%}}ZƩ 0nש_M6p"Ԩ׻cFF94|@vVhXgd<鬲Nɔ^*taHݔΡOV srz6hu{ k]qؙrII۰GrLCB'g'DdUeUTS"UĽpvdՓ^ߡ7^_藓:tZьr53_n>T!ą!{%4\F"7TQB{!b+"r*ŔBYQ1 Ѕȫ߀*HGFv/И̮eTabT/zjU~ZzpzuDDjPt$-r@8P_qO;R@ V@!HAU@ߤ@" 0Α1)zd@Z@ +Hd@XT9Hjlt) ;s$48 %c@XF9y4r I941X뢵p(eAwPO|ƦM>eAx~]xy- R"dߥ(%!,iş$hW$AF[ ݞ6)/#U?3兑V u= VGo ði0GR7;9(oDZ̑4{{夺=hu3VwBPD;n K$獖#+@9p;%/<R/@)2%3F-X,@E R_pI-%8 у0~fxJOYMuA6zQ{` # Rǁ@P*1&cftEФYSj$JED%`*UpLQ}%T=ЁSa_Wq* }AaDG!6Xlģ>VH7WjIG.qy"|f凰A*LR]*kWu^A TKRű_Kr.zZ!yEpZ$EՒs#O^jK -Q`%X,bsrOPڽݓmYwѿ¾K#w,- *U^z,r:|ç 4t Ќü9}Zd]&%-Ex OoV|zRJM\>5{C6P!˜/}偙R]PF. %@ OPqmdlDPc95tl;zMC(zl_ʜ'Ic4?ih4{BkOE5Ojq*ڛEPuP5jSX)AWH_[F[5/@ r甄 >4Q FQQ%ge7R`jz2$wIDwcǂzq>ro o8xBܗb,w .jC(~V{UYnSbZ|O,GT U/ukm5.]c/ eԗjco 7ʝ FxQnў E_[TlKbd!"UCio;ҘM?KorҳB3VR`K]m[!ee%u]"TjLa4b<3)Hf//)taٝBWQ6blۿyb'x#S6II, ?#L-•/*.P|Edn ҈/Tc*#)}6|uI %UQ{qwRG~0+3ENwHCEw*PfrCQт2YM8lǷk i16ФW%rluÝSIm\s\qt!)xk~q_p6c,8s|Ly mC<mϼ7^E?%ce bec䀕RF kIWu֞U=⍔zj q폝)gwӉ$*ǑͿ3bj2꾣7/Eh CX)w(R\5^g+޾`=5<#AYhPJbl2 !.M㈹n?$14T[B6=U2P(pM)^6 ?y|E<@ EfO/q#Xm8A5M_MwcHܴ(QHbSEm 6F |ĄyTxXjAfueF(C}x15R,b zD-J)LY-1K89ƗjtΠE}MMUZ#% ( !=,h:4˘XPƴΣ?@UrkDaa(TNx7x^Kc''@0O5i/Q>֐gg/eYrŗH@3&J#4d8D&~zSLy2lw]|;;g \ۍG Wյ x ӠZH&WP@ZʿRH@38AuB â;7"L1 3By7)vl=D e}.Y` (?DWE")k~[_Hzvk6nj! =8C+I0Ȉ&iJ޺MS)a@k얬wy8Sz7Gz/[;|2Ȩaꭻ*7KjC֣ϰY3z+1SXoʩ@5%jÄSRTfsoHr{:ʼn^֛rW/VǂgO I|2Sc)\ ^ `XhťYb GUį1b?M 0+x XY N+P|gs+.1bn-ЂZ!PfZk^fȧ[T!q.u 2܄%%TtYς%]xGrBHP) 6oæh!Tͦ]qx/E7$|Nd%ť "E:e&RD;/%T NO9BO05 ػ _P5w%\b蒔y`QP,TgGEgFYŔ % '1?@ih?OؾHaIDؾK4OOI܋0}M2r#tR'tߤs:Iڔ_=}>IӴ*RT<[%SV2Fx樘EHŔ~'?Cco 9F3?s$)ƕ(|y#ùQf8J"GRߎܩ`WwWۣK2 PqgݟN>"P];q(4&) B3ƑT 9*NڙRֽhEOX|mf:Q|x4k9\yxͭNώwX%X 8W}eZ,->X5"ppη7^?Ƒ&. ǎ zÌR CS vDT'Kx~V+ {~g%wXkN91\ɻbev@oɼ5)Q8{R?W&'65$9  #Ft:j|٥B:Yha'pDPejaAx^wJR "XbU}VN*Yp;iTH{yHʗ')IjT!<6a[8tE WO \zVl{ _g)lua}ShUbJI [K!J6˓VާC3]Z#?'I9]w-EfQKUz *8薤ڍ~vHtd ;EI N*`Q;j`C!r"lRXN 'E-ӱA,2!;0=bq,CG= V6)Ėx/HKUEM1Yvڒ]\`&pD B[e1=hCDhL C&C K L^C]́[SC&,3&SA,"uM}>[@Kc$rK u1P(YMqpm G"0HR%T@1IEi# s7 *:R.⺡ (M6z0`ԥJvt(M\׉b6\ [RRq4$ddc#ֆe{/ i' Oyn?LNh(ucl@xtsUQ3aY.?5@ &!nyxp%=XgkjeiiEΝZƊg!ԋf8zj7eƹg YPpv?]_@#cM50yX4Ev%!/X1\NǙT|ީa 7 ԛV4N#hARxySNԘ |ĀÉ+]7Y;U)ŵmZ|[sηgG=©ne횒{8Aic~̑Ϯ_4]S`3xtXbgkxTC=hæ֥^n6KDQL "eu#wmQl`e} rtvcH MT\ p%ZׅL%ݲ47Y5ԇ CփIV7KR% ¨ 0iC߷CARVAU NZqӺ^!TaX-,)zC"yuceVJGF!͡#tVxy+}J2U}s80Xfvv13C4sBkLvǧ8a*݀Bm3=Qׇ70&>GT~_ڻBTLK+ڧp_-1blC{IJ_D1jQ`եQ6lhhc}슦FF5F%ObS n( xYU^i UUlX_M*(Z %&ϫ ODaCabžtD[IDXl…xtyN&N 39x _#$з۶!Sp0* PkjصBpŪ] %3"`69lh3btՈ "_~/ oh UYD'gU8e*+#%P?\=PYП̖Ce|Vh+3 ʊWrHI"%ʈ`d[Ab 銒0&X_۱2sbʪZLØQ aܿBe(NJHnE.2u3%5 PƩC8,F!t9$T--e`~Eo8؇ZQGk":ZfsS=ڞ*A*֮K8s:%D4d/jR?JP7+סD3%܋zA4IR-rr_:]{.[@#0,)Xw!QI 后5\}q>^c=N\n?uI5aj/_qX̾dR-9!{oH}DDIo[sZ@ܻ*7?ޒҢ&[aY 4[ #9$ lV@f"' vjKJI;5gJ6 ZsH%[\ŸCjO=?$?#e]z& eӜ?%W)jy?G?6F5ځƟ!S;I ~g{Xy\juP2w)7^_2,e$ܽ')wPNL+݃ePXE,w4%&P|Z9{<%"Pz&Q9+DsIWJj RH00|%R&TI`SSEuIQ-4-d˞Wz6Lh¹rKj+9PGZB|Q2Ȋ'tQ6hʘeƭ /w$uK)_ɂ_`PWSru_wԑGR:*Xp+Ma9I"2D[@Zn4@RiP}n'uH]5_ҫKNJC[yС{K|ҮAU Gz]XsB +n_|=E^ q[P ~.DR'Xrε+U-\i\8:+a[ x=b3,Yl;pD)jEi%0m9?(;hYN.\Mv4ÐKvKX%ODG`HK5)tƄ& x08~;+R ZcB^ܗ0N%/9WkDTTg1Z-CW.O46s8C2+9Y")cb}P!<"މsHVW!,о)"$'sWG_(('ܗI\n7fOqiKZalq[ w*l^0DYw IJeWJ$Z"_*|H>k.|G˽J*pK8Ӆ7 1]tUC?EI}Lul; lIc Wd,lݐG7Z>H{@)/㷫ap>|z#;^; :`s 7T3{D&Ock ?CKQG=v$}eu&HklGl[up)~w@w(G=X-TJ ȂUN3hq^TO6M@h,UKhLO,b9Z(NkP"92Ur10łH]e(ݯNpf5,[JfF`Nf_)JNΎt+ǚE G9ؓPG鑧0LpR"[E 8w1'O4 X"Inj@ֱ4&f(Rd̶oEwmRڪ)/ddCli'XjRMDa?DB;&!*(8HcO=L@lᚚϣԉ]ocD?Nh7(+s&U|;sD?ƴwGj\brCq I DZ[r+'Dܺ܏)"Y܌BuGwYcli O[\Pz-d)8("hL0g$b޿( !ٔb8LÐnE0R\ !/z!n׋]8t8ĿJf⾧&x/Z!Dz (B!z׋O8IA)لt/2hmY:_$BpgPt%*o!f$BF!$1+2 ˋ=zU2 E2(cC]M)P71ܚFY!5ư io);kh.Y`1$}wI,z^=յ n.I-n嶃x',A/r>d쏛WCw` a#MS98[a}܅`!hOQJZvR%W]DgHYFmPµツk2u.ǡ'\ B@R3z+P*ݸ4G S)_@(X * fhPB Yj΂$_1=}1 mj"=)@mj)b#sN [cx qMtW!t}ފ5ԯ)_+(=Tߣt-3TWr'JTTGiȢGŋ,M nSVֻh (XC'?Y%k.CܨX#3OEj_r5lpb0O5e8j ̴PM o|Xo "=;iKhFSG3Ž\hFB3+Ҍ8nyffKf ͈hhFpVShFd9Ҍ(9ޣQ!>-i)(%ad HFp-aHFpdX 8$# ^G2"xiFЌF/I4bI!|D#V Ќ5#b۵7^_6tJ?TnI;*ŲbI;)NG ݧAA<NcZk4V'N;9vNnI;']SS;i$EvLnI%֝[CwRNI֝ᔄddZw2[vΈe'ܲFꑝ3bXtrNGt.H9>}6׊-_z[d$m 5I@OenS!ktrW`tKv[jר,rl5߉Є1KX܊Ɠ)!gEG$ZM`l=zbccvK"Nm(&H[PX{ޢ˘Zp5$V#VV {ZB,.j NpH aL٭BHb >ROPB bXd]TEXP!$BS !,$ߋU;qW=,m~f÷|`s:'̰?+ջ)ٟVemи[CSuadˎ.\ӎ,NŽ4N.$ᦛE 18eB&E|M\$ ғւnwd|)i!7Us)qSZ:*pJ[Nڗ/7zVS*8p$LK -tuߔ~ɾ)n7%CBuE|iɴԨɴ ɍfH.wј6do$}D\fKs*QeWD{Ӑt #="ƌ艀j3 )4槸ť J𿀣k2,+ӧMM(-B$IJ5$=wc} %,SJ B:U,^"ye/8"Q2{q6 c< *x2Ct? idơG{C䶐zz?P>*P½\D4L{Pqk$Y}HU}B,:[þ"q9NITt$^I4dB bWṋvDgLc*;unh$U9-  ;W'*JMRf#w֓WzޛB75N(h?ŦTE 2+ju7Dh+tʋh nQRi4Dn~*PC6鄊Qzjߘo}PU>6*KG+T*_G/GH$#RZU#V1]6hܺxX.k!H ֲ']k!jO0\GVXXx\ȷ2P(K3lA.R 5:{a[w} Fd>R.Hc `t:PL"Joeָ, [s}F#$it˪f"DaYq?˒-K^bR=$t?0L#}vxK ,"Am'Wɂ3m+1(xA"_IAd"(ւ}Ao[oÕƵzzWqwP%;&YYNam .A$ BNM S=0Rp/9)" Aosvd l8NNwSEFsRo}+pJ"ͺumӧE,'ft;TE"sJU.wSb cQKA.f7uQd8E0]JxYP_ɡ9Y؄1j4 W~xAQ]CKer4H]N.&pVm>|H6 Za#+ͤ(G0`:C8{йEɇJ*!v#+J/`وne Mfd8YJI99J^s*_o%jVeE.ifE,vU (E[m9}YU[o\d!逮FUIHm`" ?-Rzjʉ|A\9Y>{s?hpStV[|rӣ ºN"U&z)V{H+)>$DUF5;E96 )I$Ud@90])җݛ@X07.5{F.Evwrb JJRf㕕 &j(`UᄔG7MkB ɗȿj's(h+'\D rvEK̑\"E$GvhD$bЀtB{캠h=@w9;:KTP/m0d98nDq`6IoƗ o~ a9xkHI>+zfb7)|ۭJv?Jp݀#QCi(;gc DmROJY@N2U!{2"nU|3H)T Q(ȿޭ]+E@SN^8*(ދ "אّ{*K)Gք Pʢ - #[KŌfi#AQʙYJԸ@x-HMH5=P'dʼnv<=n3T#BR .&ZyӜ$fԕK2J/_XrvߎSjN"qW&ũbV+7B  i~k)8VLsKk#ˋ&U"ќyQMHd#`=+gs'7JGrN(.'spsQGr5weJ鍗9*ɇuvشKJ7{Єメ|lj6hu$N4;9Ң~i 'KpHEsddžȎQ3],KG %Tn,C'VE+PPg\'ht Uq)hK p%pV3…V:Q< 7t׉'"jprfAEQji)=6Hl֭EGPJ!u$ZT gB#kj(ke@H<ѦOE=*V"h,}-U>!ӕ!df?Xl*z`_е.MRD@CS*rI=%E @rl)#kPU`D7 r,x#7Beh6KQHR KLmpd ' ^/]dIaFî=7TM@UV0dS;diۂ@;%@Xֺ>toQ/Է6! N*N;☖}˹S]ŮV6pOYM йj\qF,?uJh0q)nDPbgIA.۩+*ܬl5NqFBRLI3,ّҺD9+MYG 8Q>DlJ BB`*(J?_]DUmVUR-Nu0jUj)V6-\xD7#)(Dכ%}R<ٞVW-B~H}K⟎lgA**Q,2*Kd?>J'MTPۢJ5XҊʗ5(99jNO%f-vy t5!x:$*\P'n7QY@rȿڷ>h~o$gِmzB]uwOސdx**/~b::&Ӈ&* .9O+v/\7U{))n&ݿ"KȾk{Md_jYf2Z[?Nc8w{k=Xi4)a!+,:eaA¤Qԡ9f$ OwEݮQw02aPR+3t:N6B$\yPdS%g b܊X]8EyxsI)LgQ!t .mQSAI21B䁐., ^G`]] G^%\. 1۔#wV7gU =eu2sDj?i(iRإ:Q^[u岄BZb20l(VGS rBF$) 2lvP[waRS:q>"q>ј>rӍtwgİs0'Syέc.ܴt|>IÿlXqQ/>T&ng v#Gf>'uDf}U1Tх=`HqŽtjuybLXK OC0EEzhRCO4 GXeEƹ׻X+j/yD\HUdgfހIu>UoCWJg6$7Dt!)S4v_tT1d2lq#.364&-Cmo#КˏMT-6|o/2.0FYנX< 6x@k"TTi5N/fOD^ţ'D*EDms40#m!ݱjci!D.Lqs!z-dʗjdU1xw$blGqnITw 2㡹 cUG[jj(UL] To2/U^'HOOjEnTDQ z-S &zd.f1&J$R^0N4Q-klgBɓH~,;"?In<"~.J+E|(hFBk[5'ջθz-wۤ9b2=}yHS DpuƠ 0* ?njH\bYVM,b>WwAAAvR ƙ7$ŎA ΈB鐖qpu3c~IOOw?wO? o~_yz:Ou??Xͧ+ڇ_w#۸vӶ~?oPd`>ol;g=c"?'6RWǹZ-QP^g_z~:2ۿ'_e=~/O?~He?۔_mtP$}O+eK_dI7!\و~s!wJZ4?u Dl0%>O/7*S߼x%Pi}~? uoRGkGj/~in;ٺic~'c~c+?ms}+O??ߝ^?O%cZ/Vp|gZe/k t82PؼFs4yk^CSq~ f%胈e?m7Z =Lqn_ac/2Ci0~PY˟<>¿_ޫ?^O~ڏX=_uÃ!1A(^}~>ڞчH+#v>ä F-@0@Nf+%z sbACʺ^=')ƷeJ\v ߑol W PĽ jlzIaq&vs#ZEpÖ24$.u85!RuJY>C](e>Ԍu&~@#~c&J_G_2} d_ُߤP٥;ͣM@DGE(|yPhb}.-]ZOBC &^h~z0AՅ@[`$_ZD8凴As\* \N>qx=Hx@DȧJ'|맱@cx{*_^1wVl.({#Lz=w}E@1t0 ٛW樕pӇʖ{GI`zWvvVɐY P,jq&T{+DX5@|}ldF Dgq$Ėjmkysi\^ޓ,TJ|dJ*z~C%XkGa]m8H\}/MѩF7ہ5TkƇ8%cޠC"@Fu7{]{Kr.ʴPIoʤRW%a ?č_%=0C :Q |ƞ$}ͤq$ؓkƴF~pX܆A$Y*[)&מ3RE=9EQթ%zCkmABL%=Ց? 혲PyULi/0t ְ%XmmP{- u:RoDS'{1Pq 2FӦW|mPxtF_ϾBQAr$۶>^%弟~xGN틬 pD)U}>p_tX$qtڐҬ懗)zLQ,w;,Toّ NG`~,I2h&u:of,yYsڰw4̸0%¾I7'"p].פf-ͪ}U/O&.o֊jk}5=5rTL’TBжڥQ̮܀}JᲑڮI&S۷m'<0: r.ivpeƊ+4=:"$}ڇJJN<:(% Mܺ߰)Ȳu:[g]Ҹٯj9&?R<~:5IMX"~2d\t&>9ύ3(e/+jL~K[R%b/~,uĬ ?o/$y *dm糆uSLeZ, qP̴z_;íx#bim;Z{a,{h]s;zE]nP;{oO gO 9T((:UG-P|6UW_yP\Ù"ާwȣ61"a(in{:ًp;ZPgu9/m|dzH|}?R=,7SWS;Nzbr}>%0l)C;rh_>dp`2 ɴ?l>}D{!d#t)|DwP@p@IޓH ')_1JPGvgo u }|lͲ~%9Z<i&^dSQ Υ?:x8qZu A6 8`1U!ypݻCs]?ԗ~=) P>("?YPm.Q背7Nm?`]^ 6P >d /(KpJ5<̗ے3$o/(aFg֖[z 7:5vyV~#f zS;)tLrlw M:?T8r] cX{ ;N<;&* dC\lO>LȤ W vSVS.o&Nӄɒ%!F jϯz#)C0'.^e0 Oui rf| $X2 3fc!\{cUiʔi$B/c:8Q B!2{w[~OSLۤPf> 1 FmD`O,]bKm?sQ7@zj2H5s1 Sq%'G Ռvb|W2has6^L(Zp{ȯJn$akC%]0!4˅`E P\}&G"g3{#.K2M=SX(gh?j*i.0>OA)HLʷѧ^g@ W^1,L(J}8,@PI~ Ul&WD7:Gfp6 Si4~acѾelnn^]Kl;\=)eշL+:eTP. ~}pm",A̱M:J(WŒ]N?؛w'|?WhnD:"ٽ|O*Ï; oIn_%bi>6iVJq =fj1U/-yIK@CF!\S90 x.\}e b ^JxErcsQ/@ݡmCQ![Ϗ;(7&x(D0VqnCyډ$2}v|CqP xu8Aײt(WFڦj=L\rCxUJ8%pg(َ߶ nW3'?~jA8k~dkZb|Zsij*wxTӭ[m}>_VFC@iTmʂ%)/m M8²)nj +mUٖwʓ owӒhyΞC7k9md_o aqXxe}c`Lo Ђ4wiaYiTjxtΜ,s#ZO+x#${=;'zzGkJ u_ 6C+/hZOjR׃rv޸B *=a(X/94ۖPnVx7ݢyS^6HOGBW  Up Odԍ=AMᠽ},Kx,Gi<.ͪ"UC A0"Zɠ2H"{C3*Km0\n,ّ=;G++SrVaQ&+KN43>܉BN-Rao_:2ߟAtHt9鴽3A6a~ȏ cR2Ʊ; xհ3W|rRu7$\4wrv6T'uQZQTiZC^dl"ֺ^^)>ct=~XGFӘp/$%@ar\ڏ͓X]liGSL{/%3Ss;RGMnhMᄽK7X;xÄURb-k!׉'#Y [RʍoÑo)2(ېhn_s{a Gm0'#hPS&cGQ!TkE (>%m.V N4_IײBvc*  ng&QMbk?4N ڨ*(<Өy̑|:Ŷ 3#&kIa#jgyLf!iTycƪxA#6֘Nv)w 퐖gdrF i?=or; ޘt~?IHY4 o U(nZe}3h4SESoL/݈Snf!\l,Yke m׻S{ƜԒъ)YBj٥[ˑ~+K`d^?}t>*qHk^@V]v;+8 <֫7Q=Pe\HǚLcSP)NӸ,^giSa 'g)6 ) `y B=uim5]st! g Nm=OTADTq}Ē S\*BMrM7A|"?mS5]^-k=AkF2}Z=o*eM?Pg9I_'n%ux^{yЏ93i}2hP ccA^[ט,1j??ٮl'^'A]:G")%e8E#;&H Ad~\k97G')J%"9bp>/(]Jh&:Q|^{-ιW؁eF,D/AEۂ \᭬!{dWD1ϧJ$,@6'oָUe>Ζ3ł ž3r[񺒏p'ssEhfKD, 5]z9|q^=Ty}kD Xk9*cq]b O67b 6Ks"1EjWĬ^USƾqimJ͆: pPV'op7f LxuyC!T2v?x~ 5z)E߄s[$%UPd{Q{"TL!}sje'-2+J8)xIm#sei-!SFWYu *UV3,QMI>ϼ:"Ni)8Zٸ$ <,QLb~ _JTiTl4꼰}!yQUIc{oZÝ̬P((!=W2МN>/|A sȈk|4tDleY*RUy117*.>2ˠ8p .wC.]# ?\ pav˲^%en@h<-*Ѣܶm<=։2/b'fՍ+K%1D? eN{D84凗!Ƅ˞mGp'SXNΑlZUsOd "ҦTY1"QqƏ;]3XɿވXc8٩onu?rӥ]`GZYN4蝕}yr/3> / L.q;MTNW:YV~tM-lqIU_6Cu <2+YmVA%vZrPگ7ހJB) .n.N ,؂*!6$a@}C{^\s{@<ul(,vwg92 &s6/qTsɚ,g^tH@ zy 2- ;yдв kQ}Ԭ6i*B &3>׉) 2*tE6n/)?WʘPg>c%"%2~dM^Z<{׃s<K~iSI2`GW3L >~8_ ۞PN,Vx0f@ <+zz?Ǫ4"BWlfBK$iTobV]JF>n#ע- ؈8ĉ<"XU|Mp~ uIpUz>’(I V6&{.PTTg1Am%p Q}cT㲫Hy,ЇWQ6҈֕;"lx`PפMu\ daOƂՇ wFMW_f|58KX:Q`=^(tӜ8乲Z3#A>yQ$Fа~цzLG)ry_߯ͺqe6rzs KUa'&/PlPzQ)pKWPWУVtJKhB=fwDDEtF6\eAg^jҹ7fmlzPzSqzqWѯM8<" h4X{@9O "gv @Dnd% 5K>qx}]G!`T!փ{dK=D A-9Ys;B.\; \c?)~ DicBʷ+sN>"6r-E*(Z"o݃7'-,=w%1b9N6GjzGF̡5uFɹ3W j5ckDv ڿbȵX+y">sU7tG ;}y^7<`ݖ:I> e R>8 )w;Ƞvg䀒Us$vk&w c׵mc2+V[n l:7 }!,z|12Rz0L,dCگUR׈\014F( R@ϓMCA, e5"68,I(R~WdteKUv&ʽ74e=;NSpG,? #e0;%< 1"v?rc*L*+4 T^ l=UwA\QA꿶1+$AaVq!UҙUOZ#s )mWXLTWP"N A4y F]U)aF djմDe<0M(`Y0Iފ,YdduGuE"9 fb^EM(^ܐ4crd9|X\w.55zplj7!zVDN0)oab"bl.jR_D.x29kePc}q8pg]}>D=!5]>wÙA7iih1ZTWqV+\(ԿsN)A#[Aswńg V i-CɈhM}^nUʶ?rL說hM36}T*"<4YլG9v@oR;mP/.G*<8Рwq(adzܣc 58,QH_ xם5ǩd(EM GLʼnH sͱ_-% 1 IZgqtD'tΉX`+D7e:3?@4uDnb:O* tbḿOq訿~ vP~+8/CĴC CR&۪ O ¤I?ZQƟ/ԏ~9l#iET[0NdmL/n/BXjJC2S!U!w1?`&݅>W#;Ԉٿ$7jC0V lѢV7$T PC>pjŖ|A 9e;X(6(񉽤Lr%;b(X4^ D G>L"S4+HҬV,o_f½E&ZI56F'k9pSJh.o k$>(7E;S?@9О`4WWnSXC/6~$2h^ x+E<\N)I(XPﮗr0T ejQ5,MÔwlpQw̸#}c ~{|<\ 5vX3;/,ЕC ΃*eHEFܪ'=m̢"F~YQGP+ uܮMz6Qe(UEv1Y:b燽}]δ%h}4+әTQ8Z1 .5kSP㉊Mv8@rv@C X­sl툈8r뭕SIQ6*ޙCj^3"oLPkUx>YےjL+ 9gDۀ-)~ ]aIQ"vYjCA(Hd BI5 2+u6IMbA0#{iy *,' XW|;tR/o@' u$ѳ٭YFAA"TeQSad,6HbA@k+li@wyavo!&*T'ݹj.T\9!9teNUQXu $גKgdDb@+w\) j^1;rӪ ,/9Z# wxyv_cjG+@3N܁?6 1HP6SYꐃf'<΃/m줾}%J:o2:M(\.Qg/H%/cG!G (V,Z'@:-JUQGH~Y)kV QWx4*nGsca;t$;IDL!Zln<ϏjӾ\kU0=pC.(rCn|2LoU;‡ $EV{DND: jd3;FVY:SG=DUU\\CB/f;3CXRnBW>@$Ԧ7@ESk>*Ѥ\KwSARsp^?;YY2.ݝrf]%QKDҔ Y_7 M";> hPUicj D8|lRwSv<XjAQejSvyuNT)4 LJfw“Bf/ӂvh!i5]c^eHs͉vՀcGU1"ƙ h~qԥi'Xq=UEOe7 M8=i˭VSԟK"X@B^Bc%+.(M%H:_uM^2MMj\4ۡ0DW`beo;R ^1.sw96X*t&i+; H ;w;(REgSꊽy@,cO߂`+7Z(nca2P!4/J6z#]zڶ\\$T@)3j㠇!q2Ю[JeL=:|4PYj2B@_X }NҦ*Jx5AlivMj<'1TM7s.ˑOu1U9j8$0wռ.wϠy=B@p6ס;dÌ'9c%Q᮵T ŁՒigf'-u+o[r,@g g 7UˉJr\@ჴ9>ֶgrF[yڎ47)ul4VH=V qP/`H YaPjn4QxVWBgk'99;@efq>),EK`e҇}.HHjQߊ420b0ͪEj&x"V?=Bkc>bջ؎g &] x!Ң/׺YĮAmYYKM4͑_Y3!ϯI6UF}2T;bc$3+Z6b)^R eYшo%+;!RGeJ >&HÒf4"PJ]G_ԻR5X]-ZëmݪCz"p3|(?E٧2z.BCqO'\ |LiҜt$GLp-[+"}"7N+H6VzWgY;VolWv 9C&Ae"bPyHZީZ^6$V!zYrwc J}ItH4 J3&WNrGqyU~y3Tb*H9>38 |]SV-< 1ӘQˆH|X,2(R cɐ+ X?3uKP8}sK:GOFVruBb}u[+:jҥt쎡l2Bd0= zYW k8*l*7b] escq-c)~PFVXʥGB,R CRobq^ᯗ@1B\XhS] (#!R.)v()_SMlC8 =@^wnt58SqN21OfT ?GeXXZШVxIbc%l(JwS ,w6D6*[bp;lqڸhaO_bCXoSRQD&Aq]$+^Cq%>J؏lH2 b*mqNaXf#kAfTKW2TğD9Dj$N:ZE&URoNoPK!tnr媿\}u in\,7W5EV"2n~vS)R6,ng`~..kz^Jٛ XaUw5?O~_L;~Sxï^{@% ˹AO?/۟o|7G\x?7/o??/Q˟~|m*2W&5"=v|Pq- )tg@1AmT m dUXuD_odSjT)iZ:`v'k@eLHSvȍ޲,[,+?]Rq,P< bRP7ISkHhc@bS=^r yAdҚD#)&pR2CØ! /'X?HqRaG{.8W>kRVr: 5"-9C@ѻ}C ֥u#{IdB8JΆf%l=;Dd>uam伇2 Ld]_kG]mF N*۪c~lhhCI,) xvz6\Ea9,X(́,jL禲1Nx5ۍӕ̜tmp*MUu,aqy óEo`5/?* sri\M3[]ΰ95!P)𱷍9,B٣񧽦BKPe8}+syeΟC;֙OeIZ൤,\a2S: XNvl07 = ~DH]$!kmAIs(M }ߤ2I$7Iy\Ow $iJ[ 5RAwohXWP*Lu6˱ U[Vl\bj;ZCAJvWVLF!Nqi\6,0lw{V)oTPZi<9`}hҰ-̇GJؠp1="a*ÂQ-GCT[Ix;;Ǐ+6 UgFV݅,Rƈk! Tfjvi*6Ì 0p %;a( JGR0m#VĪꍔ൞^ ')܀dz-l |b5R:QnÑ S  ZH)@Mn_7Viem -1bUZS69X*&ԂNw&!c'>~6oŨ܆Z*aG_PULOA$Z R:52`Jq4Q`"Ӌ*d"ص0ܱlvEq/ |jʃ۫ 9u Ԥ - z֚!Ezncp:$@zG=,Aq~ɜW!A(HjSGS[Klt=e2Uk!!y] ).g䢒NPR+ݎA5:CȟZ eauRp6j1.\襰QmǐUh7ФqKczՅmG^rWhD{.][NF1xe 7A2ͤf|A+m;BWhp+:I墫XXfz ˸"?v (toiJkr˵ cBQr%PD" vD@դ<6"cL@ Fŀ {| JW(+%("c $*\5Nn!mG'ysҕֶ$bbQ[v៸A+[2'n6CvEyn|Y,I9$bU,1n$Z 0rtK$C#y[ _#E|(HD(:rq퇝m:%=QшgaIJ?v [ ٘"W347YaHJjN7cJXS [GEuL8R-EU)YM@r!euMȎ@]it沤X"<6Ym8/ эo-P/+\xdآ $׀ļAɩHz,Kش_QqCKAzNe:,$ж YڑU& Ac)wuy`Ҵ kWGA%҅v^8|>Χbg2s- x ;%ҨH +zׄB?t{`/,L[V'b\QVesDƮ+6t +]%2 #ްIPl@7Zsq'B=. zPh12#-:'7jDRYf,ai.فuDCٵi:Ce"6*K`F_@lk:٣V^Rc;ݖ},t\ ls?+H q9GǻTئ'ղ|u{n]INJ[W3V{,CEt Vkʣ2y)(wtfnMݵHN&զ&6'K6C"> ZaT^*5濼;ߙ9J-vq>a/{gJ %벫Q(n CnI|~tb˶r zF:⋓\CV^Dz2ԽDZT-+bX JzcArJ#(j*\ WtIRLn[M[j((.>^c)=ź%.Ėx8xTaﰍ覙Ӏh ̊MXqWɯ*dw<?w;5:W 頯niȡ-.*qn$!Y\ޔbﺩ_O[%7Q^TP%W{u;])X|Z&iM JzGp-M g AQ C W]P?ܵL t&(Jv锈G?ܰFǘ@WLIܻ  1-~͢jDs)%Xy${NA>}KB19-;i2ƨu5#Zq~Ru-H^&>=X3P+tZ\hAyO(v/b%*6"0@!Mhuկ36gл)޾tpٍ+DvzLh@gg+sD,:N vנ<)3862$6~_K?oDphHáˤo¶vjE"*ܦ}_VeLZYTm*S r_ٛ@oىhiqH2tb9*RNU+mrxV;ԷDxk(SpSte37n0mW]ҥVV^FDJuc +uX *H5iEn}t.jVKV`ePE~E,.NB.EG,kPH|ʣOX`<:5"rJ ~Rv]F#2B{ޖ8%H<Wַ\z} 0ޥ̚yG @!yQdJj%A 7RZԞ݋ \qV7{Lh K22F; #8E\!`O4HLlHFMGIz/n7ݧ"[[ 26 wC 5+w5HXS3h=86Qz'r#あژή$wneS Z39҂DEǾYZXt$QEriEF꯴ǒf|8+ V⒙?1 Eržf-̀r´7v|>WQ,>e5魌;a c1 :y8yРcI:$L|WnpUEu:-;%+8w a+| XK[/VD,&4֔/T`"2R@t!Jp5ۣz彏s'KANn }MPa sU@ >/he*.soHɦqx3Z=Ş1D4x:YyuSY`gCO^;3qr2 ;awheў%Z:?pZ.<eh\nj šZniPSw9T~,8{saqPR[`;Ą=MEUHl[} 9 W( mZ73G~ft}^#qeIIgv?~1yIZpngk,%H H !زXInē}^6`9dP9WRU T(*& =EZ >#؅q)^]/fBJI*_ ۫; GA;}-yr:-jveQlZrm ^ >^M; /lbQ3T]ۼ[E*3$VPT J! ʃ;D=#a ^9L/ID]V9|+TXvuaF z5u*KDajF`0Ku7d;RGCH5tUQ-ʇ'%-Ը7CGuQJ!ED#6m*8qMXBL Yɪ&%ꣾMc[bg(4+!MnP>^X@5xl*3 ԟoa 7r"=M*}('YUf|l !4{s*]S 8v0Xb>,eG5 ^D+ "w>diU9Uۢt(jeݝq!+FDLH3NYn-u,VX19W5ʌDM1H7E)kD-YZRhyb: DX=sY92򷀍]j-SuqԖ@t"ʭU+ q{Lxs<40Z"\51KnWx?Gz#bWP yXc63Wg^zؽ&tZQq;*j!_AH&R#Z 1HU2UuWjO\IzJ 'sT>⮩&Y,;c tYH36:ѲwPNQfB[ՔYT.!%|MC\E$wSb g ʬFۛSTcN9"4R~0˵2G8öM+_\^HAE^;d;(U& ⷊNL)Yn6b3BH?}5ʇj] Ɂ͐Qx UWX"|P v mT7ePd鸟vC3k9 Q#LJм_-Fgej؉ Sv( K% hlj=e++872 UXSR@vQ0'FTg֋#ErG5>n^P]_^qS6!XSy0ܙ",{Г&KB(g ".zslZO;ڄo>-+tƒAO( 3ԅw9CݾL'%Ä!C ×4|@1:r%bs \;ؤ.f.Ժޑgco7ъ .VЮ+m  m0VlG+Ӓk.r rhTd# vɸqnwJQg|rFCdůn ;ĥAMGV5Gp۲xl7x.{:U;r<(B;*6i`h&WJ(t#`ӯ^p%|k\+e ?mڇ r?YCoB|mS踨Ӓ/ޓg6Ծ}D"L`DJ o !iF|=ޛ(Q9Qb`mTKy8yxs%B{8(#snZkgq"f659-w_ު=B+ΌeՈ&olކzty;i/RؘlB` 饍vTnXr8K]N`"[tۛ#4k2hʒf}04$ |.g\ mh# $!Ғ`N>X|ZR{4CU+U^jVcAM/c']O'gG#=5ɺO>SV>1QIXȅ3 ϨL--Vڮ3  -QS_DḩtRo %֞ ?&،[rTνeQ&/2^ڍI6\VVɦÚi %ZkM #'v5 c-a 5-o@j+>SH$X@3ːU̍_ݔ{z}ml WtiU{;ŧhƨ恅ẑWzk'6rgNCWΡ&ݭކdԽ՝3A2 CTCC􊮄$9~K3% c"̙ 5c" VEi6[8>Dܛ!nB_g)Ez>ɷVhah-࿾Xؗ2 Qo]9!!G 1f;vdt ~ ϲH{ti7Y0c%Wb 4uRD>7mA6l@~l:bPwt!ץz0)L s} ϕfTZ%kL*8t@!Rޚu2EQ, J[VRo"eͽ3!<~Ky_!(!%4 |92jFJ.  J Sg$ H>̖{TϚtco˥BQ+\2Db`Ү"cK56;AݘED[Mlxu)l 4.rS 8~UDk )CO~&+H~cO&%..HTliJ99w؂{,1 Z )k"p:.҆ͅ`P} O| .lyTu΃*G(?<)򭦶>ʃI<`!'jҎZ :uov/4qIWJd1Tѐ" /sJ9]$ݸ* m@q.N>9B&eDSeZ0\1YV1oEv $̼դâb+RqR$`j>NJ&F2^עsC\STÇڲ*at;uؑ i,R*g{(m% We7X=hܻc GB^ġ2De@V`蠗ӽa ՝ZD^k@UW"t^Z[P&&w1TgWb> kxpR)62LE@b4p 9Q f؋Ui7eӨab kiP$>^3RCh($, :ǵ]-"3dD\CuS `k5a;*pdUX[cW[5 އoau.VPUҽ*#1V7@QW9/.DBRwa(#XYarz: g+"%cHU |hlnSa[Ah~h= Z: fG.%>(MH$,sbQa, &@R~C*˸jX{NE]Y0sj[^|PF[BNKd|ojp`ٍta@@\ryRٴ!|ukۏZ4$c߼K\m@ml(ȥ"ڙ {?J AWաNb. GDPs8vȣ(Wx–KU٘)3][!S0&p,iENIxkb[4Xbg$U)Rԥ4\uhÒoYn4>_\ g>IKL@PWtmшћ219F(t}k ,U])AwD1,;Eʵ6WGaQ=L #?}е6SVpXbXzyVYOS 峆Zʗ IV[izХi-s1(` [ey8zȪJe+kۢ6,bej%Qyq@0cYVx[,Qr=0i3Z Jsu@#e\sc @9o"X+VK/f>_ *QeQAV/+T_bBPbT 9eN ĵ}ͫu-6j{ǎ-},Wof\v/~jJ"N%l"tP3H6u&I:j%i\ J##S e@W&c.YEی5;?_Hsǿ)p9 x\ jT~?3r %E̞vߟdV*,@]9b<2 @nahV b 8$[CD0֓,.[mz˜s Fi*f6qaȪ8b$VJoŠטS%EH 7LƬ|4)s2Cʲ^E׌XSf; `s* wЀaSńXnL]11 FVξv3^?ر6k?;$q'E,wՁJkF1A?h`p t%\Vƌ6z^PP}t #o4) J\ZgdNk#i/˙\! ,E:dܪYVtZj4zpԈ4Nڿq꫑>36hijffޛ>*@Yn5c=r)G K㐸{VЦbPNBQt^ R A8JawIu.>rJS0 OJ}$%=b0RⓉxpF~C m;蹩!w=tT7+8V-P:,\k9q;c~4jx$ A$y%TȘIcWR|mۆ7`Y-6 kJ BgI4TwjtrZ 69n%:yyŚAcx*]U10.D[FʊX6tX8F0 ^[y~;Ӭ3csj`XzM`Yf/208<1Y\pu T\öK|eo/@vZ Ttc-Ӓka ɑArA0O7`9{1\C!::PW>4? n@L0^iO 4N`*6Mp-yDrHI2!7-=flZe+s.E/WPZreU-* VDf8Y:-xD;=AQohU9@L|ǬQp81wcZHe)*2GdʇDPv6&` -$o-h8__NE./ M 0{⾱"8'rV`k3KATWN.[@eW65 E'ڢFl9:3 |Ku5`/&0GMKWS\KҼ `T.?'ŮLL4Dzi ?a nD1R0#+8/U7mu_؈`̻}=_l@!<6PVskOBxoT|DhIJ=֓\F&]'dW>gP$Ut]z[D3 /t/V9Ԧ|!KVi42 t⟈F"t)Yu4ud~)T 15T98V h]XF@d𛐵i=N gigiKҘ;e9C$ 8#f]5({,-2Ĕſ~&bg&s+~@ST;A~ V4C[TJ1-CB=Dg"?&$X>nnE8NBP7dw:&Fe AMk޵Z'Z޸H}{I\S3=8#ω{*ګw9S$7B1Rq9>|aAR8ޖrU"Җm,MAce@9AbݙX*E.4e6^%Z6} N[UV-s>ؼ֯>mdjFF"5Hܪ1͗4ʓpD5WwTКԵmճ,(I%rJR3{ 쇉"dSC>MY_k*'&o}m +e`:SU,[v!v e2 shFu#P͜TUQPe A8=u|(W@l~ª4$6 !5#j)b˾n[b)==r#I7Has8FN;RH@~+jF/TeT *&fne*H˦i@nt/FoZz<{YP4̧n04O-E,Ag{]AD1xuo+K_$qq]-BvORuCA"#e2ع(/;Cj-QfxP+%YA֋I C4_ CғS BgUfjϝ#1-m$IQ H6sXZ @/jH#1@`@p5שN6S ʡ(S.Nԣ3rAYڇ`,s*qQ 7~Me~2r2&x3 y/BߥEf<>rT%0p}-L_j@w[azMsۭU{thq# 6Ec S DIxڏ2K@[\; ~4fr.UH׋쓶c&?)"r374]MCNVVZg  s5R{7#9+1b/176o NH'f aT#%OXC4a]yd+`t\לٵPFtX¥[*x0a޴r(N _C"8f>Tiʊ3J#ȾuH"O(„ BY;;fJsZנVwZn%q6PDQ@ !f֦݋`A`YXlvKIТ*HX7?Gr;nGdCy@ofDçyƏ@dAxb4!Iv3wm/֞lR;TY@+`=aRb;\ 1iP\zk!DdXmg/{W@Hڸimf~-53 : dg+1Rr 9=2CAR1Э}> 7+`XoΛo%w-B{ >3Y`cÙC |#n*l"旤OMuzmD VU'"=v;U& $b2a\V:md.e>G&V3v5Le]R5~PJuIvU0O&̈gϑHFiYS"EjԪ|)!<\nTK] b@?('mrTx20naW>]U)o8k|ɋ?D )5N8lanmroGcƭh|:1K7Yq9؟#P*jiS@pTK]'_1X+8R*4x&.lIe 3GkodJ_it"0d?[7lשb[sعw%\ BuZxadžIDn!IȈ/ڏǩkZQU;ˇEΔzI˜zK*s` \<`O+I:qJ@o6:_1o$XGG{3sUikMz);ym]r{=U䌭g-O/5ɛM6>O'1u<;•9%r8nWŊ]O/cZ1=tQ&B`N3&M[8!~$?)4(F]I'xNˋH.TqsS[^.ʌEpC@  i n"6y4f7UUvfbԅMI$p9o-B[MkkG%u{qOUg/CY,|V[l܄WPQ%T3 NN5)С,(u\U ȩ;$Vf–PcSp){l` nWur6@^X.AEfc Zke|P#î`H6;TLjXyd\-^֏x}Sֆ8n_Qkۉ>*iutU}Ek9''-W`57 K4ĎRoQTL;E(WzvEMnx@ƽ bm5n ?ac PXT~|s J{c n.v͖4Rt`4z].frlq(zjNBosh Z6>F;b!GQD$7 @/ۻ9c&,ߡ#zwߴ܍YY{Iz$b \LI0XRnk8d%-aneJ`i M)66L*rqK 7JsxBsT7ReO0fwjf)N#]掿%/m#E<ͣ*%$P̌ ㊑"FmFNi*f""8*Dn$uf?"%fZazք&Rt`Z^sm넝;hƻR&k }G}hs{Bx2ځqXq<(ٚq<gW,ψæ5,@2JDSb#@Ms҄rQ8)&kuM ]KE9;D`a4VYVNuկ vBK/R͓z*')H:1AX ʁMF=KLHa!mBkMG_]n H2gTQy&+yWѫK6Oβ !9Q}`iL?S vui%;UQ(jV(M,T͢|=R̓ y$U D>jfC븮l~W Z)Qr SV+{E g mKM "uDs!G#rWVLiqXtZʛRrZ#i'jӃF1m<l82ԓfL폎5yA9UUa{]ٮ+;_qzqq7aUʤ@QJ}}0m/*TFjf3u7A,wtS{A `+;8ӓ2⨲Fh/#kE>,]HX L^4 ?K#O$>^W'Kr ݤ8x#vT4܆CDh"!浂ˮ@ ~oDDbIy eRO\[(}pzC$"YIUV1 yΠZcYd$|Li; !o/phɬA`hO  >ڈ+_"86ˊ$x=搘*ZY }(Izjbui+aDFk }vriD&]:&ꤎ/O@=/ጋ@#ek1KE)PEW0,c9Dh#/˳4,Q0n63'դ&ŧ({-1B{9jb˧~4D(CDNw: Z0!ݮrBOS AZبRY4 f Җ=2Y~} +NU(cRYoя9l()^izgR>t™oݯZ D>.W5o5JT|P#@Ir ޫ[`V+s@#JŜs1pO+n[L>)Nɜk*햆MQK瓛 oqS[[+ǫqCG2NfǪ.w i愪oN=.2ԛ߱]n"jR\eyovm_t!3hk_Dy޴CX

    a}5u7ʔ /̛R іQ* ESRR^yqV3r WQJwf}f]I &}vV2HuP-nvP4S==_sY3w/\UK< ݈@G)X95HVE@nV.)tH7) rxF:P}w_(:K"mpWխhedE@ CVH5olt`=bS`de}G;F0aU4ȧ &}(ĸW)K\wְMsh+]`pդ\ qv(^`?6Օr[=~t_:ew4tTeyZYH$Dr׫U{[Sk. L ?t6*%eU= OU,U7w8·?"Gŵ^եMb/ªds(y"m*TjE7kZ <&48$Mt/G5_e#,NX:TD M4ӄ5-\x'(Ԑ9y^D'wz UrFfҶk(LBtGx)Icʣ'ݵE5o75m?FA6d{ *{n5E4¶ {LM$D67$8Ӱ>0BYUU+GM96d5-wGXnY% Q)}'x#ޅğ> -c@l#u %*~Ka0vH&?ŅuBAh.YiVcQRVXǻBdqSmiD[#7YDg?'Y̩ZgujSwPփ8&[f_"HnM!g}ni׶,Z-MЀrZG5Θ}zH~6":MU#*S=T$yw}ޟ}+(zD(lM@5=݊MB$Tnfs>]z_A;0z`+nElhI i) j"J-*xdJw*OQ4ӽWhNi&a#xj\[>;hsR6~ zLEmTZyS̠>kdKؖB_v%KX}M QqS+B I2s[e|hF__d^1pI+&^aUVk̭ݕynr$f?%Dވcq>wєWr" \,Y\2=nkF9u"d5& ,Ϳ?~_#os˟~??7/?~o_M~ž{EXކc9ڞTHKjG3@ԍᡦIc+~m9OV/S߄|EJߍz5cy8s&K_/85ff *CicuWtg-QEaT\FgsF@PD Uh {tW0Y>uwo!&=nخ)4JE X~q܌*ZsIt3痾1W5JWO R]ˉr屍zR k豍-ȡ0dѢLqQ8԰IIgKթ3Kُ\{o^U>Ǟc ZdskςJK f!V5KƲ3Q~K^9U$.C(Kt$~g{(7Z#^5,?Fۙ\2'TX;es]ӻ(U>͒e) Wbӽ8s7biRr"ss$=j6gqtg {muZkruVAK;(:!MkNOiÚl$W)2~v}cuubI4G<Ү6wwn,v|/i K5)߿ZGІb"Pk12ze6Cʤ>C(1μ-Rr+!,d%+98,F (-]ċڷV͠e"sqO쿩9m^g AqXƄ(Hu ˲'I;eNQ <LJ7Cרα8C.>Z#HcR Ʌ} ϊs,l)[)~NO>ߐkqRR3&PY:YlJt U][<ǢkRc`G?'#]'B Rm4R)6bgK7y[L!2J&~+PN7f4uk-@I[5ZBtz>muc׫t,MlP7J_?1;vlZ@"^ac/o ۑl&Atd󫶩y(Jb3ҡvYטiY (T`~\J"LG@g ~ eckDDġE7!e) WX#Trl:\AoYշ?[01hC< 5T+Uls츷K)jٽ6|$kLjZV-i&s&%0]]Xa_>…=3n0"ۤӏ=B,6ot?"P9)eӿXvLr;T7Т`豏 .U!:3@W nƐgXB,E[Tݐ'8-ZG0e17tt7c!勡}\$Ċ^N)dU<+xuMf;_ݜ!ژIE/LHUU/[a4F"qFѱ˷ r*kI9 *ax0PW\l!hDbB~4Q@|lHKTJ1? 6 >zSw18s*k Tpp'ʝb*x4*i{eBFD !2:p=# RT%q;g g$FJj}}k %[.B1D+M̑ QLPfMz'0I̶- 0Y#ap Xa"Wmt&ꃛlʲBS6WBR@Vcu29Wh'- y~UanԈE,_dK[v6|*hVT0F@տVuX9SSd &_FԞH2lo'ïb!E!.&ϕ&'LxAöFBNxul8VLJ9>JCj*2ѮKveO[u|ݨXF\?·|C!n-:? tQ`GZ/fo+E!9UB*sWE|5C#a"u(*=j.#c4>#AɎ@^Ŷc!ምh@}*,i,,>{Funi"$VIli5 F`%2jק1M sbWR+yZ|&xZ%G#If&.S.=R>9:4}D86KjfywCUkW#z)I.ES?+|Um><;9cy8үnGTt"=H˩Lx]d1aʨr8 Rh*C]t)*/B"\Qf Z[kO 5@i_lR8}eyP9# .3@0p pMT؈BF0% x}oXAQvl0RhA`W3eH3™* YWռw0c|Ѥ+g^uYykBEqPgaW&wb]lfp6bKCpPmjZ(XԛT=1OZ]G~.فE7  Vziq~NJ֮@^;>Z.>IPcneLQPfE6:snns4I8~ zMc6ãI7g fݙrY#nz[v6(rjU 4'Txvz>Dx帬I RRb֝L$)8% Bq!TG!;2J &BrUN%c( sq`|c_3s_sކT$]<3U9cGV{ d0*կldZTTkզ+Qpț/ҍeq joiLb @bR4e0ar=Ғ<[2~嶥d# 5.46hj]^T=j̀yrm9r0 gsSDhH0EH'yd!ƸQupa3H/X(,>c[Rfwni~L[đl~?QRt aH)zr-9Iʌgt/vQǯ I^zr(r`܌lF]{䴟6H:Īv#O.Ak.5M[jA-p %˧Dr!/1ir4ʐx{YL PR[a >ղո3^7 <"zK6ʾm?Yɵ"f--X'~cY5b"@>gIL?R$9ȣ󀈼gYL]d&nHҼ^ҏwfL2r8db41nDU/$RK:i"6Hr(:Cxk"la.WRk]kqUu>j;2,X~ &aG<ޅmBj5CI8`ܠVi:ObtR;0uK&NwIg-ɨA@lKPh*i(?2}{M`;t%jSQ-;--F#.d^{2ZovHn*\KF/xvB 3۬qAǕͅk:ZEUo, ë d  5|zRLj;QS ALtkfH IԢZ.yZgX9*v=W0SiJQS#j'F)]jb Z﫹RpYF{G9SGh.1~؅^33.ٸ5P`^2(>lq$WKcbk_+="iLz{ CPX Hj4SЁy΄n "ԢȨrI,]pc<{QMrS$ [e5{^Z885bXմI@P<t caXEQ9-SՌaulp3UfR:f).,CJMu}5IGP{_68e;iĊi/] I庡 jE423'r "^A!cu>I U{CU, ]$-?w8Hz,.0Va3ϒ2pꎨT+I?bP8<$%84!֋8{tRel_r;c7qYyANK,OM5|F97Cl c#͎_0j\Nbxx]U'Dؙ <;e^_jz DFw\wR{ m rGNϊH}Y{y#U>} "S>@# d (#}CZ2SӠ {_N.p dI{G}zV*dg,d,t-2|ZT,qnai UZ(5XEw}fzD=q۫$8fftG#@ڽHL(v_*RVX#ZN+šu/{R |VAS,ZQ{S1u5нT7O9@tb"bŇ.jthMrgOo4=ӽX25f v@h&\Xijn V#@ް?>Va[Ce;@/dqGYǧ&P]_Lo@[di'FB=tŁ] 7@%PcB% ʺpճ 3#u溝 }Ty:Z3s&r/]E@ E* quT5)OᬥcéIg҄vwkfm/B]KAoYe"Y+JjTL"-諫]3ڸ\\v}s`T6yEuYUz*(#ј(y2z3W2򧀎$]- h,+#D+yTQC18({^ME!NXDbKk`:jjEشD~$ >tP5NWW#srb47[X+6v\Ԥzș'ȿ2IC)ōxQ![HȲl5{/x77z!8:L*_2'ޘu;_Z|\pbcQL$Nv(Vr-g/taXªwlDewuU@]9(p2QqA'HD(r+p0=1)O;)%dU.! G~jo*:tbdP7q6̄QK;N=IT6Rj 0v%j+޶wVkKWnT83bpc,|O a&kUR@)YtEP`H3/owQ4׆E7ĉ'K3b$"H\vR!;} e]N޾βr RhS/"-I,{=AEaNYoy O K1]"'bXH(Pw Wk%o<ۢ1bJ P؈6'(_E},c&+ӆQ-EH2^`48A},>}蕔is/_s6{z{ˑƗ>Y_xq-;At)72 q9m'1M=ƚb`uP"ܮvG™y8uxsن9\48]P;NE=f^gW5At~!YEfMu9},Qj a7z6 AG%*w?XDڔZژjJ!( G|%]id;|_Dj9.=s^vd{J( S.MKh,]!3؏h7bblо1fް#=/_Hf25̔p](lom:p v<;JR0aPYyHg8Jj,KU[aϐ!0@RGGq `qdvRK 3c676;JG989"/u{x(ֹ3lNRQFC$b]H7Fw,•na܋n9h╔óOY=e(m] ']qhj+c42'UTzBqs& W1+|.p=5B(ZZPֺlBצ!.,nI^:;ڳZRGV4_\[^LHgfO98Ub:#Gu*zcn u"qv_e(tνؓ`a?vdWD H}4kKp4zU ö|t >UvCn[ fPp< ?S$h3Rٛn,WoQ;4l2L9:s5#6ܘ[kVކ2ڹLjQHNc$ #x[6m$%j Žv* ^WRG|sBU^ڐ_&!XfQn; %!0X)wzyx2G;Zcgq:W$0maB",ZXG:[5G@U)6g(EIJw'nYr LB=0fѶuD-kBtc1m)Y<[觸h&6Q ƈɔ.C̠abKIy{UYíS+ qྺ٨,A*\J)P}~i}hkE4wQPK40 dcrw2Y fuU R/MjkxjDwZ$.$*Jnm 9u4WX ĥ0.paO O&7<4aYM6/gV/s fZaIJc'B1uqDh/~E .mԅ 1P~@5Х B.6l$[#eB%%92U`@&YõOoH]I&آmDXt=)+޶'<{tzDh zt JPD>>AxXS: s1a7*A=yscn`l6-"lmEHpM >TfUGu ƗUBBWiQm)]^!I (|4\+eTU]JaklH\\K"G]{ȾLXyDc$X نWHll%AAذQ[d-mvЁjlյ(3Ԃq] OUUfyahz3ݼ|2 o[-NJ}+8es/6'iŹR]q2XbR*s0{#y+^hJQK"g:)E>O3]PmlnE3Vj^K{%Pzq66z.Z"ckHw׌hbҖ ۚd4{R~vݽgjx&Xs0>OKNڄM">ҴnZp U^fZ`E5c%uHJXԦ:Iv7:o Nhh),Fa4qw-bRJ7$ۦK}_qy mM&[LK؊?d) 3rb`(K 2P3kWv O%i9HmV>k"MD)]IR} >M XP4arSͦ!\QePX窬&m峥n/\@Fn-5=-Ru:T iCf ~h17iV `N#!J^gH M/1@qej\n;0Z[~Ω=>6]̈5a*FR J^5d=3m.lnd2x!Z9^ݓH<'as,- }V߀4]lWdѫ[Ky MU4>k%#[]ՈfGovg5 i:vַgspRW;&1|[I8.)6szeUs)R$`̊%G6E#e oQDn6 3b=hY jV̪ yT@7H'̩~޾x[[7VKL# !ZYzg:ݺcgXPDШ1eSW)9WB{ >:riѴ eJ>+% )9,y@sĥ^& @˩D'!ta͝}6,!DmZD+Aҧ }x>$Z C" oꚨ}8rVDQsC  <7-9̱[u_n=hՑ7R C;G3qvZ- 6|ߴe a$XJR.mzQE:mTW@"ci5`㰠UN*ηO-<I]SEH 6Lh}AфSD.KJG/tZZJ6Xn:i&/dغ=_5s Fm#"e+Cz3L* h eSCu\`M+zs/f)AyZwtl(tqB2||4i~:uO"1-ABH$ cYm&4pmr7 rfLNŭiT Vb]l)q\fOXքLaUR6L.I-q#ܒTEt͸ț=al/D\.4BwEV% Ahp(Æ\mU*< :ԩyI@VeU"5^'E'a C'2V !I8$(-$5cUv-_]|ݝq1bkJ٨<"َS6/}<{9wve(h^<6ꅖ]dHkZf(Z}=Zk;]( YӥZ#ǎ w%˦jVnj>2r3@22TV|YQb?Sw8/lGIDrf XM ZcGg#gnA pss$S.:.42O\mۍ鼹׀y б nHWDh q0;rl{*O!7|bQe05Yv?H W15OU)[Ye.>Ex$KH+e`^\ҼPӎ{xDJhz[e:O̹8]5Ԃ ~xJiJa*ɂ>\wǼm{301Vϸ;U>hphcz10 Y2-H;u[*кWY%#Oh[FJ, nofK;(W2bk5pVN+0UW=XĤdLn+c.yXiBDD˨t1FM|z:b+]!-ax'ڱNNsif,7*r3OU]-2({0kqսmJ |msӝr".+Ҧoe5)ܶC:{v02I>Sqw%,s ;ne@x"1Q!Æ 9 ٰ̪#غhO]BRc+gXbeRrJ(-$}PaUEiUo0r5P!$KJgMSѥПZrTc G*#q1E*%놼J_]G.v'*YF|ԊP"j͇+y62g.&Zr1%E~sր9{w{L}* /u?юGnےNb}$=WOv?ug6`/@D=}"۩]9 #a$84UinyX dOrlr^ׯ͸H |N/Vc3 SiyfĄp8?FɥhきG1%I O.u)dc _K1H",%7*;( mb<T4vl- @ϥ-PS΢aDNJ0MYL4D!l)DGgDv+ s:,婱W銪] 6Mt!09Ҭ܄? T4Dyg%sHk5>R!pe*zgN˫!G`p]cM s3@z+BodRˈ@"7L R+O?{LrS?TXQ[ ZMz զ6b  iR42zuïKH1VXսWJ+)j*l)”*_ȡ3 d+1\]@$aܚk!=eNјzb ŬU)iL~gCx=kgv䥬&u -etsW;I܊%!&lN@}Fv~cX-cs 'Ӥi$fڴ|+!sO( 㷊{!j(I(eB^CZ<-R"C@YLT4!5ƕ-DسJUHE唒ҦHQ$ru{p#u_tʬ C'(NhE{Np,?Xm'9 pE?Xc"SqAdH&}]Xhk∀EhKyh붷!6,sD.04EhA'vLB YƐh6pkj ݑ-Hsύn%>?;09e9݌%StX풍}Ƴ,Vg QEdu BE`^3q-}92! 0GAKlO7KPD%F$_?*HJ.SoLY A*DzH`nK;j;ZP= SE!iX|4p|<ߴq0kI)[)mZɣSrm,c3%7$&%p%tl,gƂ HpW,zY _^:P6%m*xTp`ax?-vAun윒pԪ|0n=ޫˇv/ Rmܫk+%IqIq!_՝T'v9ytZněr.Zt x̆7ah=OU~׋6D}+5 *$B PflM(:l"8wI7.b0t Nw[c}wp8 lgDzt7ĜƇ5M_&$3m1E{( 'fK}HEʸI2$\SɺLCx-랦# pEUsbY=oÕMAPYŻ;0fHh>2RR*xRm""*2s0pʋ &}krC(\OP=n?p}}/oq9źym`6f ^}G@5D8q&Yn~@9lfTtr([+ ~=a2b^Bb_9 $Y:XƦM9R D@4ޔ U5-8b:mԷ ZΖkvWd,ކ*gTܩv i7f`y΁: !v [:hɴK ߈źQA>z2H{ !=v8s3>(_48{8#襹o7uN?sja\Hꈨ:eT2yY܎ yFmȤjBLjY>x4R5pPR| HJU0q40"{F"Qe5]B)^> yԨrtcŮUOq͸ِRr,3DYPLvrz{䷃ͤ<C6ۅYITH#vd<ڋ>uol/)6gKrN. Yb{G%+FBՉFt6%[ÒG䔵&kg7\K,#ꚘS]NN#f鳥R,9*UNI-2 Z-f޲Ç[/!gzt<%)J/B⒊@yToJ&"DBGfП"ۉ+ZWwa2]6GZF[tҦ︵fHT&x iֻڧ('`xp9!$i( ŝ܍`S ?:#͍kԵmzW:)xtJr^RviPz%YH]nM3ϯ`:FZ 17Ǿ? }\7j UUy0802k}iBڤ!t4GEOW|˕AVS-I<.{Hs A 1@Yy| $[ 0HN))T'lBŎ i NYRe;Ц:K#uU)F06r􂏻m; nWXE2VdBt-'IVZjo#<u*,+ IAdP>_ֺ)?s P%ij=XWk'Yx" q-/LݑDfNF|U*=,'I+ Eb 6ubYN:b(gh v O ;wei\/c$@LvvН&OGW7áXBuWmmR`};L`.XIp8-#;n%Arḗ"k1ዶ~Q[l A=[d(VAqEEYE)~ ),'0p 8.S&gDRDH=)c|ޛ5c>:;:PoZ>H@GЊVqQK'X=C13u+VAeHx#޶fUJS m49KCn?+HT(* Н0/廪>wrLY+alO]mOC?w9@hBŷܣ_DU -O }Rf:_O!JK̲v眬MpT6ĝ4D5>)OhrmwWF Y\}]S0hJʬ).tpVܽAU*?0X Bjc!f:| c{ j̹?ܵ[!zY_.Is2N]g]^h, n#wH`NY^c""G5&kZ[Wf` ?7"1<2 ^.~{0E[[}vk#J2k &HR!sYDžACV=- iݏыVpFЎ@qiClb<ꤶA2mάSH qy Ԭn=#050ZT2'D9XV([`t#2ljcoCWTaJ Ȉwm뀠FǤ:GA>&ldnL /ME <05TD:y)8 \oo]Kj+PP2$!xǗIZd9;>%|~sϷvyӌ,+g֒Wh)  L+cMyǪ5&o3f-eNfs^cv.*xJdL+OQ4~*;3`lP BfT_B,?RKP~6MiQl+&WJ >6B>}L 9hM(3!¥$ə蹎֭ENňԯӶG7\4`x%_Z#ۯ,L^7^qWp˯WjčEk'n7@ظԎY);1kŜ#ZL^*#f_7c܂Sbdy1 '2s~jbh~1Q\~L)B5~VQ_XAx~LxX_(F`_qFwG4bqałvxf'__X(L\xv|LÉvǸk@Xex1Ãoocܿ*&Zvq^LH Y1Q[}qwo#~x, \ܱuO 7ر%QKP҅#TGqu qD!X!5P8<,-x[Q_qIi UD(]d[ȧXɆC+1:*2| Ĝq~@Bre rtw"STh6<[\c Ecum춨8 c+FP>p+c9;q!*uc7-PG n !@/M3:TB"h/xQz c tЧbC Erk`ÍX5 Ev< Jgo'<^%Ux F~֊h6VD{Xq?q*gyL8! gEqPYlq֢qzpik&]tXx)aXo5ux';-!5FLlG|YL8 *1s7j9tFCsH6Lz4bۍiMXi+:ԗwq?>1y`%y IGu/>Ӝ:iĒ mrA2c tBrMCnWnHI493dY$'vXiž^ר Vсl]/^zwiU8鱒C' GGyː{~Ec񽪨&{lV# ?*!bFF@)~oqE?@ P'EV&QR'LG D-ࠤ!Qؾư+Ti2a"_ݲF!ǁ\kR7v$8Rkڧ& ZTQ nr?JHnBU}oL'*IMjLh"']Lkݿ`˽[ߑMOf;r){#UeoB6xhB5ϓb).Wr ُ۬6;XLL(A*ƾO). %r09ΕRB3ML0C6Wͫe$/( ץaoBؿqms0=v`RlZr٬SH8Eف `>OWKI/Kt*啓d;:V.#]H:T*/ePWc ݇L'ھzv;tZu,u: Y P:mD**PvYk;Q]ߧ0zYוBE]*E0gR$p;9kTVʪnGщ%_Hep2nfRѵޢM'cBc:U'Ά Ў|8t&ط-6P*6_Sm׉(SXs!1щ&/ݿ $ꩃ{I!8WyߑKOݭ`u=&KAqƖ~6D"2;&aB!:J;.AB^lD g&Ln7>Sʢc OȌyP9Jvhd3Y}Ch[ 92mV?89G~XAMy7֋ݫҪk@׺l#9hI]csg,%#L@*. +s!V`|uP0 !Ph)*' U[ADXJv , TZANp  ;=m K8B$UV[@fq%D=..,TBWC=+lZA0"ZPqLo@P0b5 aOZ@xuK=: H k, $P|7GȪ\3i >H( Eo|G>ٱv7sPGT8J_8E @Ʃ :L-7LQgLm@RPUdGS `&_WQ{z$#R2HUvڱy %-a['փgeh"؀A 3B ̫ZhZ\nP** Phx,@ ,P) dRug[P iiP7Y`p,Խ ,T ?EV(]fPO"PRvB>! 1T14h}hg14i}+bhkP-`C7M@!FO͈gK4uJNuAG:d߹wdk"H^{mR7TE:|Ҁ`e9ѯOh` Dk 4rA S>]ħI΅K>#gf@<(JPO1&9`_};  ցVV Sg]6 0A+IC+D{pNiItQt (#g\^1 H;1?'EL"8tNu"{EoF{^ ^/"e1ݛ:{u `G3Xuy+թJU Ȋ*{>X;Z8 VeKĀT5j+$T-#ަ&OO7hē+Mdw@ZQ^;ٔg@vL)!93Ĕ A!ԥ!` miߕSkGCm @T9WX& :'*gZJ_ɰ!!I$U`f' ɊHU DEh̫ m-uGYd_*' әlnFK%m̪90 f#5K`6Tfµϊ{4}%NK-$*"*. `),bRZ;Z݋ntj!cRN Z7(}VC#q26z?従z8rhR_@  q_>TSa(Rn`r 0YVAfqyUa#SIBn\Ob$wnLeK^"I}ɪBC퍔Tl'`&'b {8uANȊbul+ : k$%Qr՝wNbP8H\{Q%#䗣& Tߓ`Eèk \fK6P nw"G!.7>E'C9U(9nةMx.FhW5[a1=r 1uﰖ_ƺ`KPN֍]5-nб""GOV؍DCVV <-B|@O1WW;h5|hf=x^"ؚnffޟRp;{,E[I D\S=&P-:*ghlm%!ېPՅlOіmVd`{@_̈AA^5yAۀL?cA^(e`1C(1ڭPD>[v`l & Bb.@0.%ʂ, `26{t2STRQ |) W4CRME_~1ȷ*pM6Rhcg*rcgʮ\<+ȲQ*k/czcPWsUQ%l&ۮATHi*-@ICI7^?KK쟴 ;gBh4w.q~bϔ@g)4?T. ^|ƽ2/{βMRڸ4&+V< ( 8)$SY RrޘIUs?ʑE'~5P6t{ހi;;?xE<}21TUBL,^άd`9B=bմ Hs=If.F wLψ.E1p[ ˋ`ֺ+XOg@q<̺ Lyw8,G q DS܉Wd?/WN@[;fw Tk  ? V`1rމS,xoWBI;}IXDX;_[;<}27Wݒ;V 6TeMK&lגha)YM 0,Y{LJYb!:o?^~3"3ujξzgBH cGW9p.9QNzSkDb%iNȓcK_?ߑ®Vh*|M(܂;x+p2-&Pjk0Jk^2`iU[{ a)Ei0Q$<xuɢOHnEX;:pj76dw*Y 5zK]B~k;3<]㨆ECt"d+$?1:L@P U\@!E]Z75HGAWi#n5"q!R%= S: K#-mf'a)HXx7cK(%HYkH*NYeT,݋ImF+dHY,/-*zrv%O.M%tYƶ'c#g҇sg8iKbW)NYtr0\nHY)K߶Dʲ/AD VKl6$P2@I6Fb0H\o;D?v˖v˽hy4n)BEҳU6 *lyJ?.%&ov(VkiZUk͘oG?*ݥ2ޜBN25"\SNiL6*pzjkGxջBHwpo.Ș"aw2Oa: ([EEzKs~;pQz_Q0X)J (XTaw0@kU߭Q{"U)I*v@W*]f]KQrAݱiMϡܴ$t=RsQ݋4'5#7>ϣyܴR<4M^KhqN"9-M%UK89ͪwr @J_)8ѝ)鹮t-3NdYU:i>̴SУINDrZiġ"ai%Oi9Kr,\$U$|S "9P{E0SMk^2#9-MNcu63bNMZR1٥te]AjZ))iocYr}̂'ļp4 tmVHz|$P) rx7sD:G$к:;{;,hibF"O]M)9l~0 4!(`䕎&kuwXόyâp n=&V&E@8*HzXD=ߖuwdbXB 0]̞,FL3 PI6J<\J#ӮSJ AB-( K4-[gu̅d"7973UsdbqR"ruRd;Y4Z" 7CQ+;sɷf)MCmʆ&D؅ΕFDU߉ 2ѡUq(VCxtQE$PA1uZTZꊁ+^+H%ZhU$veY~aN9;w2!Bh^60URrsrY>?R<h'qAJ ݋a" ǴJ %ЫFQWd'z"7R$9Jm4LZ! r?,eI#]CGk$)^\g52[|2Xw#6؜V+B{IWRvAaHA_T|^)f2UA$\؈*]Z#G8PlT$DdS xwi5S&[rg+f ZI-"TNj_$a%͕i>bKAuMa0i#@\Gjb(P@0D6owur}$"Rt B` ~V7 ^؊ GRqAL,_>Y# ?;}8g;9/>C?5IxJ: 9f- B^UC,q4b|3jvzF-I@j(ĸ %n!"5[wuPoO͓HKHD[ eh'!\yEj`4]DrɰY"RPי"q*d@N7C|Ф.x Wuwu9q:r@׉\s'N!G|z#y9#>r`>IGOar}}6b{i߇N>t}W=߇U]IB"t G9*-߇J:}>t(ַCj}9Cr=ϩCe<r':e:(Hc?'Sg~GQ~v{vX3ps5BmQl^s2)X;Rn=lՙ;N~vTQ&bg)WW9vt::atY;< iPoXcCZS3n by ;'{v)zV @cu4h߈Rb]vg)<xHG{.Jel(Z b%NMh+C&l crԲ'Xj9>EDZC"Xm &m`M},IUK-`JK]j%ZܥɱHD*euSPiR"H2 %_ŭ²WJQa[R*Śg l.J@ P knFH*%P(ʄ(P4:n;Լ~Vw%C`$)TG7j*d&`k*\䉉A;!@zҏOτEGx;ycOFUfj~4qZqxS.# 531G獵5T\MX%=Bi5\#q1hǍ/i36|hGNIMByz㈐Y3DmI>kvsHY,2ZZ\;ɴ<%@avM O$NƅQFRK:zP](CѪfKf}@чbԔ";:&M !~hCŘJPOMvjBd#FC6(BS B"5H%KhPz:4kn->IE{29 e"$]?0'Tkajk/%+M EzD4げz,U1l&|eO &ɼw$Ix q663EvhW13D8f"mg")q 6vY>SU/P7}Zzz4`r=p6He .Z9\(>2UoXtqP6\R>ScZP65.䎬/\MMv wSw$I064h0< HU_qĎ<͵5 "@|Ou0aZᮚ!\Cjijk.!th԰ܬP&RN@D ?͆;VHD~aZb GG0^SK2_u-BhP|=exޖO$%]nT0jDIަDCL"WؒRAU5Z6q, hxAP\!8-p 1̨eY^%hƖin&ìYUA?,άIU @sܧrʠFťQ$0ӑncd4Po{imcKM+ *lqEoi@~luzL$6\srdT˶]a_1LCh[$M"% !K[:͗H& kjҐWg15KGXt!z͸\`udv1 |e\Q hu<Ğ]ϩ*s@kܞڵߋʞUS sAk8 sI<q5m9z9/Z˼=ZCݞ}2MBի6)<nIbelnǩq*ȴ:_Bq@!Pq*eʄvp؛85v;j5Eb;{ lZ9B5+tbMsM55Ja~=61@˾N re7)3; |\(+,`F QeqXwF { N ]. _k*OUwqXK(y]Z. F$$(iw@;W;#a1#nzbyʍppĠsYۆ؊;4ܷf;Mn;j|h.3Vڢِ:c]NFX"Y3@IBBH45fmsvW6R+q-"tK:>fՅVϑ//E@&3܅x[+^cӈDҟW;565Y 8MWtUeLk0ŖpMtuZ'?;g,VHgvpϨA>Q|f(*!(x1~L3Yj)nh>Eo1rdT+&4K) ppk^5^~B^C&I:ӮCH}%,p!ҬWvf" *U>h~Lfn gT BF? |;Ѵx$Lk"Z[MMPx%Ͽ)#zT}EO9Oγ2&sY6Dʗ ~-ݿ "OO=ruMX_ϥο5;=q}G?vVjaEX}IfzчrmU5\ǻT_6ʋ5˕`lTz:%d˖\}O>c_kI*붩)mkXlƦ&u^:ؚaS~Nz o~=;l?ౖömV6 vFnۨk<7xM^P3e)b]ʼm`9 x80Ŏ"d|WsVUu}8%G8Z=::Ĕ&^_4Va=ߑc;-}G1`|ە5Է٤caSز9 SףKdY\!;flٕϠz=زZΏ\_$ێm?*LƖ=" f/6_muښߤ 4*^v.nm3M.]:b evہ}3Q -ؾaGO^l5n;m)Í4<fRk=l%|< >Dk?K&>6 Mm;:y໴GQ^PKvi+Fz;wϔ* 9_v*xMw/~,F(Ӆ})e}Y}ln<5m0݇~E\c ךqI$" 2P(=,|~IݷYQY4uaWlt3פ!"_J!<Ҍ}֭S.V0?Y+ 0.jIǸu3-^3m00̴.JfZ=4G fZLH(Ju٭ ppӊȈ=iMv뇛f{*~p=M+5A2iu5diCY&nRVeSq%Dܴ${o84Դ${M lj#9hnS&\AN1";"քI}7Q'97foN˷ߘn1;~cvZoLO+ߘnӃVn1=mncz5fFH=nQ\:8nc~5Nsi4&aLN+4fmNKvr᧍mOۘn9瘤oAmsPKnQ#0}yR"0bܴu[;`yShFk>vA8r@Ѩ_hqrPKG8WO=Y-t; zZn@SSj@w$@6fJ=4ӓ0dkVtb"aXKCGs n: LGkw f:Laf8lyaf;3mqhttfRZ06@̄ ;;4bӌh@̴;3#F |a8,#LH ( Zð&BZ0!w^idw=ckj$^kjt+M -|̐,f R5̒/iLTo?FŒ2џ?؈ZQ^<|R򇤆>Lρ0F=fS)Z 1Ə욉䚉1OT4OoJ,;6̊(C+*4Ư:5egJj"4Ư*aGRW9~qI7-5-1~[ 1~CmFcGc `S?C!ZdTmS `53A~#Pp_Q {}l-$KbbUz =mk5Nsdjxou'<.xi_;NAxhx_MA7w,5dc_)Ȕ~i~<:l(**r4ϯzd!lA~Y6`gg+B,;!1~C6Ndy1~ӏYi{9~%k$T-&qJ}+J|)anh^hGU7)1єSOmP&?6/aB }w31$9o[;ŀXDb6˶ v$X)X)E-@܉hՖDcZoM3̫ Ucy{ʯEPu[bmZ1,sZ,β1Ų9d#mAdlgL#KlsL"+lcٸWD6wd#xP2)G%hR&DLD0ħPIAęx Dd Y"&"o"A""<< 4p@RE05OR<(b'fV`,|YxGjdʟ68 KxYxq$~Q|"T8N) N7ʝ,9fueCģy?)pVeE;<ɡvH i1"7}hֱycYY6ʚuL Ĩy4Ve@vV׈a͒v%k ;N0b ;Îy-ueMQ{띐QΨ}~H#@dMFIwbDjc2+muvUorj 5xMg:x:|ud̡Q`. ؓ:a 0:esHFR~}'+tguǝ<ܳ۝{{qlN=I'rO:')t'tJ5:q$t|^'tJ58r:nwRQwNI=xY'Gy[yܣܓ{qrO:.w^Iey'ssO:.wbIN=5踎Nf޾#3O l}i12vđ(:|xdlD3c9r<2<#cK99FƎ8rJr9##cK9-Fƶ_GFƒj0䊙gN;3c)12և ygƞC8sbfl(cpl3gxhl;g09WgΌ%ΜSck:&f3+͇N+:xj38rR qydfNP#$މʨ^Co,TLcqUe8:R9xTP9sƥZ1FXuTʁp!b%/QɚFr™Cn3=Tu/&G >2pd/ p[G',]ci-E hl|"tY `Oڌ0b:[cf`bH=0p.+32p]}ptԬPF&ƙUߦϷVW8.c@dUGP}w@myRL$%LU'E|y6+Կx/W-pe#8 F*SuEBf \ )1";%W~EJ]亚ίXv.-gܻbPVҔUYZ;epBzuI(K<:mȴ&|,0 Bt8@e2rZFT('o wI!iM"+C%?МtIP_M4Lȷ\;U7D7F*(`$ED9~CA^Κqbgr3Ԗ)_R3Ja+DZ+FS]5#P㞯WU=Fz@h=ŹnֆhIh#Q,F3֫h!MuSqAQ,b>FڿLCH8)p$Sgγ@ 0,$#2tW\Y~T)1yyWZ% AIxwIde-zX&"^Ed6Wއ0eꩻ*rO$H4;wH"hz}/w)11SXA8ip} _6/S˿ _NqZE$owd壙_1X.iLK"uI-$ORC@Hi9ScenKs9l #fI_\액5#"@3&Ps#`ysI[⇓ Z:$X"b((z=b(qͬ j%xP')d 2z׺F1ϸ-'`qcv~NCN)w壹_)}fT~3]B )g$@ HC-Ŧs @z 6 =K(LH3C\T` 2|@>)|&+.a. 2YǠj<[W-hkVӧ 4%e!1誵_P׸%kA9"X+4mϠ~sn A&9#&4ߑ^ˎKo!R U`3I:-ƂFKge"iO*,\wQ9Ꜭ$: Y Ӧc=X-ph'UI`lpS>ŕTQDY@&Ҏdeýق3ҩ*F \%`jwa @"±C\Ǜ&e V,zT0EY*O D3u<0B D3;ܿ|4׏R@~tPH7Y8q3ftW/u<p{Gb./=p uYK* ᮀ 6$)=yS* ,k DQ`IWRO2Qch$R!9Es v=r 4'E8*d'"sGo">0W'b?tk=fwPחANm %˽0Y`#o$ Y LDU@ 4H?W 56={o @ X*78p`7_|6a9rkJj^VF`Lj/D}-IupQ );%^ l ;$T]WS[H;#U)jI5auS~\;ɬ 4@f{jR〸F-Ě@$e(TF:)'?QXvT;Ad-{ JGR]ܪ^=HMŤ R>7M0 bn1ј܉K>W|ii|'Ԣ ˒auUm:],*2&A\hY9O59,2~JYg[aHվ'9$|4ntu.|2.ʹfew.^s;ߑK!?,rBZ'%*Ϧ)dEH-^#y4$fv PZ#~քw"=pӓPo+BjѨaV.b<U ,M8MAz߱ 흂7F'%FzL`F< P3iWV̈JkjVD ]+8;|C1VI=VދxcL  f`j% eh%:d5M{Xw$}sXTJ ]|TcZul΃ԝ1HC  0CQ6ȤwKQ!a7V@L윬Q=NayKS;/Yq5ZG_'kKNMiddgӼKb߭HGaՊՓ3s@]nc1YJ=X"밵$"IɦAwP!G?Ad/􂂓\`E!KJ45vDDVtMaEQQU$*<>')U5@lN5Tހה J,TѵME21 Ed6ahf{K:]8r.#IK253zD P 8M>ڱpaS,Dz{[CA`~IZE3Ʀd7;@ɼ#WT:ukK=SuB; ީWGX{L[H7YPY1.o;hc(ofn<'EiW=x(zΣzlvZTQDQPbvjEeZ4F\f1ʒAYk@ "Yab2@# :Ȩq2;5LbBb?) dWR=5mt΀;W UQ   EsX;;4Eky t쪊T 7YYE!Je8h6X#oKPZ Ґ` rJ4&^*H#N,*[GaVD6]hQZdyGiҦʙ#JZGQ7&5Ҁ"@+_3?;H3B@܈$wM1:.sȐG"/mk8JDGGyK,NS7Jk :2tx8qxxPz \./3^ml5~ )ApiE+,VE`[UKHz-79ڐi1"0x3;Ys K^(@"JfLL+_B NVP0 Y4O9Y’j\7"wt4%ƦkW:VJiZG0ϫt7rBc|Xw91 ֺrn]9n%tXA;H ιnLOqQ_N8~DѸOZQ3KrͿեb܇`ܧF^,qr0TX KE^x]'dyJFFÕbZ}(;J44L0:ԁ.$~@Dz@z7 `TDeƁ Uǝ@!f`@U[ oJ7yh2_骞x˟fag(R;VkeJ AKR H=w>|AN{N^=WD" tY*՜G\(ԓ`OQy\.ƼX-jTӕ$Uz)4;H)'pF;EYwV;( g/I%,N!}JI_(P=ռ;j}2b|jõҤ!=3L4IXn vqŒ &EFW<K>*%?DǼjhX\mS?$y 6ߥ&4ONg(]UQ3ib:*z0e:HAۃ IP!UfnѪ_UG]5smռuDDJ\ʂLTe-~&Z|tr}=sFF;րxY@Յk}Yx˺5q^5n J{ZrOe0z*^/kh+6+&Px3L \w @ o ղ퍍ysTdRkW4 p);kSӉ$a~TD‚\Ť1(TYnvj/#tlgb?Pٜ5w}uǓ@t?".ȚV%7:ikUV-"NpU$YIN5z{`1Y%-[ndm-f ; ƢK4nZe/n ;pEl  b]wd)Q!+lᩌy鋁~k|y%PPg'{QS+;Fܝ_<"6(y$/2iTWGv޾ߖPjCAs^\=øv(Ix)۹%e \ zpw}t'`_}ں͵ߜIsz7' €u\lpWIy(sg_]I^$\.'_+mss 1jagGL)0z,XzQE |s'Ɯ [k@CVx u.2;mF7g!sW7i%i$~|ko\n3 v.u׿Yz b+9EMzݳjTvһYN@(O8q`b'WObjo.ӱȂ %3v9n;*9B[S N}ņ^3'=CS6%ED8<\{zE򓺹_ >]45@C]Y˽܁7i~ZMݬ~sۢ#,OڟmToL*-##+HӳE(KnBǡߛǻ5>|,*&PZx%\vWDr2[1/A9:CҡCBLeR̵؊d2* dSg@nl t i {F&I4AE^?to ;: #3DPrM13MA=&g-LH@'@WA=QF~Rx1CsKA5:4C]p6Y%5{^*? 9 &"yR{< bܷGZ=~#ʹ1W&hgs5 EE{ȎYpGT2;&a%wo]?=6)R;4X&߫zn=F$'-zOƼMc,ާބrQO̽SOLou/HUGS (As'Uax1H>-L3칺we(R=CjNӏ*7}Nk2-^0PiMA(uMR z&&Յ(LI9h+P pҁN$)Ƽ_q*_ѤU5OU؄HކD/dC5 A*TԜ:ٔp;vQOV})mSH:~q0Z'䴗E~ W]ߑI.k i vLIhܴ8۫%r#KuSyj'w Hj`RG#@9"΀.zRt&X<JtضLux#9Q pjBb \Sa2kAQ\x"QW%Uj( JHjRCO$ l|x6QL%m'DIt|w)~wdm7͉HO*>y=:_Q^/#漏g]r;^G8Q_G0$Yd'&ZdD[!(P1eӈcQ9ae'*Z)"!ΈG a^.:h 5pN>$' z33 <(EXTPR M~M2aM"͆_;}6;RQVe:LZջLa>e׀* Px*[rm.BDsr6 Y5n:481Mu֛.B#ll~֛RknK/ :6Ҿ}g:z;x).ZNc {(19 Mٸ1Rմ- n;v @i~+x4ߑMOfej9frg"D24iAMlnӈc47z'7R+rFix6wZ&PUGeN9ErYn8٭puC.#n9N׺dWC *-L16fF,ɍFyy3-Bڹ{OuMPW݁goe#.LG6R}ݻLRaC!cA ]Hj?L@@W#fcA;~ V>УF3KgZHXNG$#ER~?x  āuY(?S*XKC]F4@ M`m2B^}MШ I4!j(SYʠ2g>ygMdյ2F4"=F$x) Ѓ7TPNfIheELB%:(Mڬ;|TP( ۏֶ>̙4<#0 ߾Pݿ#5SpigtB PR V Dց3-Av{~G\?H.93hii8IRX2dΌQ~i+*5S;25@favf3){(Q!Df p Ho(l LU@9 8 0esٷ9tg$+TJg.,吞!-}g3RK!>S%>Cj6Aτ rl@ɳ }spmC1}ӂ!pW|@٢֐l)&|Lt's<>`U%Ϙ]q>jQ ]~}*a2W땘4OHO&~kQRRWzK(肱5_9H)C6h'K=#Dä{$T"ZOx&,;*NbjP^OEDc(~S ݮڹ~t0Y|\~`j,$#Pr:_HSҏhS1ߧ`]hZ/k9׺K +J`@kQjdXU#->Et { b&Ky#k}Qqv9ZS[s]ׇQ`M s`0CR=(SV\HHtO6^nޜn|GU]?JwB`wAɐ?IYUͷB<{#.b}Zd!6Re]X<WQ`^q#Id8HIW?\YT[+rudQD/E^}uxm.U4WĄ@ AiZT^KJzE 6E eSHaӲ- <, *(O9E"ˤȠa"j M(Qnt!:ţtJZ|E![ę|j'ka͑Ub]D'Y@nU\lU^qdb9w7T=}7TAS|Q#4D#Kc>kAKSU^$ig(a2O<>.bERVCAV ECFQb`Ҍ , r`Vy'l Ҕ*r @Ģ2̣\E.5YRkQeFѿLNҕSdFelWf۬'.BDjN6iS6KY0&DH: |WIO;鱲djLs K֗dl07%^1K*n8D>%9$f~ec)g9[题nL .?~6sþ 5oow/O jP.֩!a=aLRXG(YĺRX8d)d~U`ْ/QAYuO"Nzi힙 Q^*԰YZ20;]9%,PzVĽh7#w#\QzU)/$q8w;kVBkgs/Z5SAZ&R6w)Fsile9UNZ*/leS{uj2!I, laj>ueե:d3$yg jn★qJTIīGQNz$-mJ95T*:e jwLAyC4(&V <1(J+y[ F֕Δ؏Vޚa|ƑUz4 %#eɴ!u/ADT Aޏ悔Gk_%_ cՐGɷc rLC)fUq桯KyŹǠ&~Z<kh(`CȺvdu7,%l6jG}Fi٧y7s&E7#?QW͂`uZ+I.SC5I\@lz^ d%_b?¡/^]<&qIbC6DsŴ3=*q׏o('Ko6sDlqH6)?x0ep?tX8>b){3_&GpJW3Yt8MT}BvI֊|Is+R#H,H[w20 d >-2u"G^{!1>Š f#TQQ[r$J!:U21:"+X~" ́{OFa)遵3o!C?ۻct s܈c?OɸĔ1 /5V&Gy%*o9?P.);'ڏFs+|vt5'3?n&9ŗrwt5cN0URuBziIJAWau^Zi GVx Ry\:>â[:i{P׼ˡΛ]:' ɰ.עλE]ZI\@8}¤·1gJxaR7|.۵g;}}l+m0qB+V=8kQ>e#&Yiͬf`?bnvI=%V]tdؕ_"#+0#E,JyQ''qI&Rqb7/8?&4)P=:4%HYEUΫI,UZdozrsL d/!=Qx>F%wNr`q/!^+;g>f#s»_u{G7f*>-cm;7Ϯc#vwġxj;H/sDzrcayO+ShLP?*Wh"[xOG3`&CԔpgxf|KNp:v0إZaVa͉fÚ'[v7O)}?LPed7k!{<3G%›~֘Ü~>^Ÿ~]qyb!\W?2ftٵz=¶+|k5:}qU6SrYQ+OtSX)ft9P ytO+,*5.ұ8Vx-G<*L \g Th hiA4`A; @XR&w*АA-G VT ډ%SH'LNgw%i$䠰pTF=~vw. _55`r/ 9U$;u/Aʔett}3lHQ#.J5ի;KV'&|%owwwɚ(G@.`aڂBu HߡX\o?1imtY ;m+]|bh3.s%bL5f{7ݗSZbE{KB>mݥw 8!(]!"ǁ$NeN43*Nҍ~ &)49%pVFq ueH0G8KLi5H6r8*zap7/|mksAGh!u ~A'ɶDI&mԫb(US.J{'>ZA%"$*~%M ㉉VaR"ޕND{͂D=wHC~MgOd Lаwy}&r4LYG2O;RH%p7yXΗ$0Jh(&A!K0nـhPy婟 N^ \TYTm󶟝dK)pCBr*"0ڜyHE "bt| G8i2ͽ[}{Pg ZY(mȰ$heS:6&+ǎB3vÐ1U!7VQ%*fJ1Bn=]д_9{[HP=Jt~Vwf'm>!G2vzFˏ*)W3TO Ilb&N+/wJkVv.hͯ3Fk).n(,~H%)j:5 ' ΋hh e[Yi^HMe(nX.gB9)a*na,8ٚn)xy;I$,,̞(x{(ԙNBC?B֯ƒ fIM:c4(m%-Z~㱂_w cq=* 6| GŒF\z9 0઱.R⩱sm`.\Ⱦ d3a CcJuZfHC6wpE5#Hdm,P@՝ʏ*Q{Y֊l]5 10 3$eIyvSM@p4Yi7a2 NWr&]B&}YMiHjc5ﱾ^c9_ SN!"*gErQ Kib>.VSIH1Ŧ-(f%3S?(A%Ś&{C.Q]|kXh+vYIdfSge ")'f.p?&H!6NX[B2a5iw#bx&S1SRPh<ԣ.DVqf ̒}љRJZsEM1ڙ;"ɫ%l3T]"O%FWE>"g>~R&;_E*】A+9npO9r4ֱzT\d01 r 53Ǎu$ PNԲ%wVadWY+]|\)ծ~?vq+o].a/ /5$F| bg!5X銌y+Du)e ut̴Iu߮ȡֽuHBK[]5m?ĖU=k#NnjG'Dq:@BtGP ]N {l{7Oq4Mtp/_Qį?, Ā0k$w7e3rG3D fH 9g؍\[;r8{3Y+ B$?tND.Tx@YB8^|'`'Xshv՝rH+$,:$s\IT,Rs(I8'~QD+R%|GMI^лd%0AEC -0sL,6znO|E :xX ȔC9FBuHi6fSj')C.QfVLr"WQsѕ%"]}dFkmB#/DCF}ҍrC>bhݚC{KHKHyKwa|qyǽm׶)5ǽidzLqouǽa+qouǵ_wxfgiLk`qmvǽUǛwIL6 c5I;&{t{HA"̖{zܻcyzxshz\ۣ3=16< kgM4'a{ȤOs|d=85bxG{SdHҕp qVp1z:+,&_g98zI8S 9gSʍ8 5X fd΂'%z(%fQ`^P\qBmE i-JXU]Ԏw\U1U"m2Ϊ՝QҝwR>>}?l"u~u: ڕ`HӼɿ7;G?Z849fPYD(^8҂6x!;8+&Ic&]3-X:!YmYޯ}fMdIU;̦4]a󬒷$M'%k@C;z<ܴ^k8dLcwX|e`+_u\W'8hUnw!+*˰= ]([Hko!뇬߿@w;*?-!C])bh:nQHśEW@mRv6-F{&ǾU(8)>5jfq;@EzTfmq=nU@/b*dZG1厣 \qD1Z:"H9$m谅7/t,bḳQAhGɛb D;2H%Fw(GM6:%&}@Z*A~:rd 9o쵹ǃ7e嗫r,k_0PN >Sx䣖̖TƸA{˱{C&i+a6?:63w:l^COAFon/G'zL+V˧ 2vC3]m?R4BdcFuD:vd vK &DRã' s^^?2adExliĀ[obY7 Wf\p:c,*y8?14m^%Z91V{Odb5>c_tՁGc:A x3nv'sbr?^r'/Omֱg\!Ǣ^6?da_ԉ[p,[b1Jʽ+kvǩ>{& 柩A56ԍ,0v0/!n|GMX>\!F;b5PIO  N*XQjG;DmmyYy"؇-Վ2]BAku!.eIS}41pO?pq1t)oT>$! @! 9\Xj}Bci /%OY" (xJƒh-rg ,!Rͺpǣ謂T~|GYX> : +]j~ojkF#WKy5Susw'%4q2n5x`%D*XZcm%|2;{rck= {{=XY!@pՆ$DdxUUr\1l2Շ|pq< ,2EC`BEM}S_דּVQOttU)l.oJAaL w+S?x"ʠ*ġƸ,o~ėWfs%.L!%4Eꩆr5jR_Qω(YV(1u%jf:HsS&O..*vir_VlAҝyabbA!xNTʓ2KQ~얀ķH-:B6P/%zX7Bϧ٤y?k"Z~} e嗸$YxOtɗģגk+(80T{g)3 tμb S `~fx{ kϞ5orP۲Ca-|nk$\SEVju K5Tt{;7Kt1i$Q3WzƦ {IUS@pBf0P'-,\H9щ`J١:.T)W)}de?d^™XCgE ;16,5j'(7Aru)e9I~*}ܟ{ͫQ7:[bM ȄBȟ߁4A;m Q߰ a[ۄLqQ7ZEf݅'YU85q-hu,W5 gE6y%QrVl{ﲈgw*,GS 4{ Rl}+&ImCQOv q)<1 ce"%}o{h`z{#DqąøY)ۻ; Q_?:?i|"P$jF6tOǏħ+6X?aEPww;[/O P}]LyLYrTƥ3'@T.I[2-  :@Q4) 0 ˌ}MQvH2~֡cؑVA22kw*Pߦrw]L ڍuI 1z\Q3jdWfn|GY?J&^<ٳ$ɚ%тU$ihm,|ϭ %fn,nt5ϖrCY%ˋfjDhP ʽ8n e nꃥԙy$6MJII7ieÊvpaBNb yGjե lK,vE'hVT.;'jD/ & llqΘY̳Dҽ;;jSF瀒[DeU„ǃ#˔ Y\+jcp] -RW ۵bfY C]G]3swv٩/D`TMdm0qyKMCD% !8g3}Peʼ&EGáh\4R3obՓx5eC>u~:r,>6EsI r=#ݮ}ħ]iJפEtQkbK,bgp@8>Oj^o)b1h tjŪ΢S 5,r. fĖ|wKB ہqUY|L/96*UK }YAOf4$8˽@SȬƹE-wKNݓmh+,1t%:UEl6*/G >(;k&{2w*\(oό& AOa]?G3IuS.a&RYLϾ(,suY:a.۴QO!<; [ZFإUHMEeܲ f`rTfA6y90Č󝯵XDDytb&*ͨDߋ!)7;#4W\o'ᇻqI4A0@>g8Ɲ&aЈ(9f2&e]%9*b< ;Zn3 z>H~ *15J{M5$"W5MkHDPR)jQiOHE)f|!$556bamXxG _ǻ}@(1]gi"{#^J@>Oj'XE'0GzX<_a7(QG'^j4{DSĞ,'s5{l93(#vfPY_u>q(lסsiϽziXN>Y@w3cY:Eތ08ovLp/^EθJ8fj8G+.78.w;;yY*p/&^ne.| 2P O&5\ -e墢y*/HKFMKfWKqU(]zGY74D,!pw-TLU=nT3XÔOg4$t FMe oǹ+]+J}܊/Aŏ'}.9 buxkښ5˪ipm2o{|Gm?ZѬ2]>?T`vݭ'[C, 9iKϼ4; wG hz]V!d[?q`85O$8Mv²Xޞ4X #Zu~Ys4Mچq5-چ^kEV[$hi 2#jm|saz<_~}$=xo}*p~VPXnLF wC 1N|^}R|;*JLٟO>9vaȩ/&. ͤCo9@ӫYܖjۡ8~E,ӯMuQ$OIw!pG~"4 &xI=嵉WQ)5X6΁d{VζQT4 S}8ĒΑ[.LƂu !`_9jyY>h)L CzD xNZ2W1FiZT69.X;qPH[RJx[PQF 73Pwf+#Yλ{Olg蕹ug$oTNف$h)I4ľ)9|Ee2Az[@򠜹FTYڠH+*-4 cw(5`?+<ו "ӏd ,,KDR2d7貜#$).Kbe7$W4N7b;:T~ >[ RΔ`$ok[ZZHyC R_̹z }-}&cdP$Ú%ݼ\ Xn0>Z+NDGA5 Y8A+ c<4*iČL+IQJ2HkƇY>W[h΄NS|Σ[|NK,L# \mTZ -wJ㣅/EIeŻFq38ٴ{G)6h)RVM^У:+猈ڭ!3Pi)j!c7ǔ sE-19xi-0/"B bs)SE; |S%Ѫ6b"^,Ny\㰗\G68.,9\}ag#(r[\7E䯥FeR`'!saЊa}ߙc;ja_KugDx=CpBNvGװ{`7pwoQ5=l$z?$axEG"wsyKB#C${tOBK5 [Fu΀E6#|/~s7"FO8CO0[V7/ P/ S#˭ftcu%Ϸ'G9?Y}rIqTD-Չ) 8 iZvt,MAՉ %T@j=nA*y@Dd`Լ'Q4ڄPg"f5u;4R ӳI I/;X~6ݡ /vQ'0= 0.] Y&O]ѝhll}ҋ>紖h v髒_=;0QbONNXd "_5(њ7Zv 5AnzwA3W ^p+0} !NOlHH5>;Š, 9pW] )Pr;p 0-w3w3 5$$natK|G8?Z>2=Loy SPb:ݲc=tIt̑X"3IAF=`4^|NلĘ-Ύ}Q^*ɠA=wBK\%EXPUM{[A!~HvBLq%Ѿ+5rB!m@V~o6wõs Jc'N+]+v3Th #F F52*215F6Jj ?* #ï.0[iSm3U| ¿y'k𳊋\[4٥E3~0|\X߻A%v,}vE OW}vIQ W}wAьۻFeIM*оQpϏJ4dH Ǎ)$xAaTc$dގ\ILzLkp&ľCSRkr i|y%k3`8HPD-\4D:pbZIVT7j*z 2 ) Y!UXd}\Ef{ao߈ Qܫb hqe( Nhz[r-f;HZwC~)erf6P=t V>ͥ2!$!6{Axx6._K\yoΦY̔_ƽ5([=h^lF9:lFFyhbxX8de6{@ Z=-ql_&+eeJvU&%axI>N% :>G 5L2tDj$n.p R Uަ#=8d)ED4aWu*"ꐮik?ǐ7CH* LDI+&N eR9jGeG])Պ,D7V9g;YLi(qArUUUsw;;94Ǝ6O]^кl1(m.s{0[y V@, XiYʮ'[,˗'ZLOPߠȏbG ˾]K63؆dTj a!6*~1BH!bPYU\d/I͍(fרr>cd=9"VtWQڵ%=X0+`p/ &H.r,ٖБ(R0@J8ໂ`ϊ/[Wyn|>{WUKJ7 mLJi yIvWi= oeK5=U?5 ?#inHVB+!. Ϊ( ъRC 3MEeMfR.S>fŐ5U_h@;t;WwMEG&'3%#`U9l^il)sR@%Ș%V0*9T9L;S_ Om"Fzuq_{t[~C?"xeCUfQzL,a\맻& P)n8F< 6)5¢G뒞0Q(&8fY B`86sDn ]Q}HRdKaRӦn.fŦ==@ES/Sx| !H;DgC[Tw-rjW[%~(ZV3ʡ(8i4+fSD4z$`q!/F zp0RFi=窼O!tV?j!.EId_qo7T{|q!@D(qriwꇱS0@=hʹrMFEkxf./%wEn"C5ZO:cs['P|TR'sA Vbo#9dQZ-.<_5Ec@sMw |_ OCdyLf$?II ^F$@h$QD2Zè{ݓ9PV#;S)9UOSAz镧Q8nE)%SqE+\7@$zXXrQ_zo:O|xM3,x#v,j՜Dگ._6=Z2 On(xOŨ*.F +KNOx"] Ԁmj1/hT{:?Y|WvB Qe_ Jٶx:s2.ΤZ2H10DM2MA Y-j6CS>@K^?#01AlD`3~05..+Qn#kV˨ -̎M _~5?Df$DU:) vfBT'a?f(9 0՘P/HNiESE(ӺQd?46I#,4Eُ>d;D .MZKI)`[5hOw#Rp SQƵ_&ԏLTܡXJT Xh!/HgUzXj@~_"1{+OcW{tۏ*|" \Ru.Mr{=Eu&?>D"|9jo8nWE,FFVily?-95ﶫ=}GD~hVо81aޢ}?ee~C4KiӿHw1(]!n0W-FȔ[;?[τ=K7--wM|@i kƴ8_UIԠU"_[gNO;K.]+y2`ZZ!n!B?,4f\:5KW)sw?Fo̩6zs'7kѾa̿ =!n͠:P8LT3ϠFʀD1m-Rl -"y[j<V/"?O@J&Œ|ߓH|RHU0r-*i3 豂{鱾ڏ9V`oks"䕻IJV_~2H؂4mѣm!VQtpl:F5G~9a^-:8ۂ 1;RC-ݳd4a38uU&g8m(GI' pܘ.x[TIvxq\]D 7j `|-~h6Q+Qw]\WjgNQS>tY^ڪ]Wc̕M 5s<UC% 7#3 hH첑4N $8qp(#-O>联w}ѿQ iogĔջ(dvv쥾/< ߶tw!/e\~lt#Gn[ן%4ԕA/CrMKpylLs9|w9C`UnV|D2'o 4)Ρ`@؟y;ۗI1)w BTi{'|Ga?(OևU8MW\>lOb[;[evw}Kk!r.Z+eԢќF_Fulֲm㮬 _o w1.aFw bRt6߈ٟڴ}l=L {>F !S`̨=>Q<3l4`.LF3 U}ÿY;"+ ɢY5QTudJF, VW+248+c3 1Py%s?MW2WD ? ѼU)o@dSDˋ~&4tGVc!ѓ)2l%QCeY~aDs(8yeSȐȟנcj()⨢Vh|G-\>ߙy !1fDR{ʙ0l) M֨oOHh\8UbUcI!SCgF[&S#ܴg^%׼ (͂TL`X,yɧAXJI[ wvD,ua>~Mp(krV#qh hdX&U'&Rwf)>Rfh^+[qs=zwT壕>yc"|101P*1p,1S.;֓ciXP,35b%fA}Br^=撺WbleFm:>%o#:l~6YLN؁-RlPk'b[c8jb p8΀W"X!59`Rtu 2b)J\g>-8*:jLR88;w%b-n]򹑧 ym-:7i3.sn~ HE+F\SV+RQTNB"8 N"#"ƭ\Љ0/ `-'wZs^$&a<é,8ӵŢTnyr0`=nZdU8̙YYѬYu(5)!mAȤR+R~wwa^ӣk޸M(ϊc䢨\vTƚ|sϣp!Jbzb:K{MTwu.T}3%3- EtѠ69f\wRO$*̻:3E!88"=Z1<ឥ7Da$Q?SDrW}Uy?Tc&! Jc]rE]vSWZS/ߩ-2fU!c*M sr3T>#S%A^zWP# ];W f;ݍbEa;j!Eve EB\VJ=;EK%9]!}ӽ ?ӠVaTj$UUD;uB^Efɞ2wqaE!TC@gOSv$Ow;Y 8Z,{5>~͔ya V| Β`Pc e3]aAg&;: qn%[(Ϊ٬8biwω1wkC^wޝ.fI_ a⦔{9#^=y#+=L[u( G帓z5b޺7z|a.Lbi:_D~0U6R[ [/E*L+VA|$wjFf^Yt)Z3[Nl2[/Ot2]/HE[^6M>qiN*ތ6"m"r<Y\~6wT܃d>%ΰ =L,9P"v?0HovN[T=۹襰dB+'Il*ӎ>N݀UE@wvzs: }S]+wpGZA\IQ5W0fLX/5 -E6MrYkYp<ZBǑYKj,VIL"hr喸at8!,WXԻwV/Ҽb %j5l=ؐ/D &⸬#PJXbF rt2$G@&8b8d}&(@.\aO\UݹaQ#/Ls^,=&aNu DAi5%!fE zB/!;J.l*B@ '{insyY5D HjJRtG>l%vu|ZVY<#Ra D!KK+MMa*&.?C{cO# oˇgtlr$d^Gk6 \]#ȌxUՀz?X07uv )zXV۲Vmy3Bnةѓ ۇć sJx\v_/Ɋ5q9gzIGĹ:^;jQɵ/UXj w -22жJBƐp|# !jFjpg=RANeJhFm=U.*_;;4, [SPMIˉi<b~K! 5.|rv*DxQȧwo*u|uY#aF7 F ]vD2&%]$rAes@p0V?}}G}>AԨd7=D $Eu=GH "yΖXE>E2a0+Jh;Y*@TIwyEFfe)rxac6[8;Y/L^Yi7nR n_|G?cXQ=Wz]4:=8@-^X" 3/҈٥# 88EUɰ%9Gl&s Iӧ>E 5~tˏFBS/fBvG;oߙ弘0:~W]NY@iPSIG|FՌBy 0KHTW8xֳH_{qlh~Jh!`RɬTN+Gswdӣ9 \OsEO7KR=aj29#~ϷlmtRsxW5?p˪EB)h3I7[.VZc+~v݁3RʙIHiKG4с&m KtP0@!"SEJ+H ٜs5^!l݆2{|Ά$إ>|桰h*WWyh6C#ϡ W̸ˋSϦ<*P$FL[C>%{pKEI^:=E #rCRPRC|#ċ+hq3UTsm5uq鍄_D=Y+Sc7 U"oj渨œH(]];J O˝y>OID7Skߢ~c03@~JgSG,|KzFu7l |vn7ѽ357;\Ut^]a|rBC21i`CG# @b#$fuQYħoq ke[&A쾧ir ޥ͢ >_n -1Db49Hd75;si\mkzZVH)af;ʙRg`.[98`䮓;; p*pw8+9d &:yƖʗ#ߴ3iPI]M`nNl[Л-A?w; Z,@@̙|O@ǩP%k)B#Xz1({RK[&P |85 / )XI10< [>Rz4Pc:8[,~295_!~iF67iЁ:(G5H[IcPG le#*Em*arWxBϢ++ ewe!%fq:DXE}h&njp[ S]C+B9=j.=_1)wmNؒ(4GTmF"r3ݓB 5}1ܵN__!7ݤL9x$" ɗ~`y4Cuhl{~V,p'd4eU!` Bq:ziH3ȠR,mOf55ӧ_PRGi)TL9"īE|$eTg,_\&jB:C9\Л(2 \*Bq`ZeuxXbU~^r(^˶~AW-eMs1j8~JO~wLT3O[EsoY|꺞y_pn-w} n>]$+eq)Vps}.x]yi{R;~Vݽ;yӭt 5=M/1H{HR0K&8ڡ# 0S9ݕ\ w'fG}h%\;;8OkL1z]Lp:bj!ygTx.gCJD1Wa 9-t1TՈZ9U+no_UC "maC./Oa[aˀYѣ Kp!ۆxU͖nPtfKbj8PTjwI ]`4HS~iyH}o]5?˵=f9Fd%LlxbˋHpFyCy&U(Y{TʦXlC'f VX-ҏ)aFLUsb9I[j q2 RE늉'R?r S?nO8GE3Q]74,zYGB.zKOA|hp!]"Qs]Ubj7=y L#]e+%|^AW{yݽ&x%4;%ߓWB{3@_7y&f#d;0Q sX"'7|)SP!dMxŰRITp}¸@l_jtA|mp2ySX\7Pʴ j:1EuK|ӢyH?gW(j7k=YLLJiఏ Lb.>f##2Be@װcRUDjKAS^!ejmrOBa4fx{<\s,i,z:zx\DN(92Sc,v؛v@3|yzmO]*6aX13Ab:+*;H㴡&gmub[HM3rs+zfv{6$%21 #- #kVB&pmT7|D#'·u5:Vfޯ|}Ku%K1yXZQ^@L.C\tx/?:!^_}Zx6gk_}OO>]k|x!Lޞ x:,/QHJ6CH>4ih0 i62+ 9֑k%O>vf Ӟ^ͣӤfp%hB(C G!a:Ո;`@d"V?qDf)I'3PiOeW^D[.ʹuГĺYrC8{ҽ[a@Sz4 2<߉ppcPPלT3(Y&dePRDw8C<<Udʋ~]._r Cү1VB4lX"6*ʽozo@ XYcֵT+?bs(@DbM#RYA}q0ٜJyݥɋ,: KQfI1^cɽ(v L_P OU{ʽ7IʉE6%t^~W;F2,ymXR~@je2OW|ޅpI-Y 'AT C}X˟\cyH߆3.|)S$EJ,yu0tyeht[AL Vd4,cɶsg>3LEp ,#Xm ?R'9M$>x ܘ"{q0Ƕ~2!$ Rf&^5*3>I_qс^<۝t%.LpeG.,%5AoTK+^WO_}di~~Va@# =kG$Q8hBMB6z6=BBƫֳyhjy~ب&Z^nYr$.wjYdޅͶJ!ftJ ܱHsO3a r6mq |>{+g}j luY2G((EH6T{&H&(ljXQ C52#Ʋq!556+1kMe< ȟ^3do3PgvJ4Nsr1&2{aAhg6^E^3a4@I C s6y1Gta5dt UЄ j ҷV֚$fNhЉ'gv e{B3q*xqgGn>2(Sۉ}ltw.[s;={_7'VW_qp{u߯6??/j^|Ww?\_7.ޞ]޼[x_N޾ᕗ7wo6?F{]x|y{R{cķO6 twӳoʳ^q7on3GSryyx{[ οv_ oղ6:nԶnuKN<`)W']t_]n~ڼ\p۳KϾpsg^=g?|{~qwW뫟~rs~jK]wqon~gx–O!g]~w?yg]|O7gLM~hV^9}t_~\cW^i#vN|;|7gޱ۟/tlzÎݡ߻w8"BͱWG_>?YkMƃ?۳o؏>;KǞ3?cO;=;&pn٩=ǓoD3xd>cn&9Oޜ;뿮O.oLۓ~gr[;wsNf[^mue~=nKVOm*.swaSGsf>nx>N{'dkbmC}w޷GϻN34!ѕS2ۄmx)m-%'.et?rYtF~\lO˛aܱϫzq~,[ϘgF˫7ҽv 9]^]]oNgނ_ەa6[Y:ٞ&lk6sXm6!bz,!w-uU6>mǡr,v/Ƴ\vۺy[֗g{{_mֶSk1!-:BtqJMۚZro.*mkMmܒ MWIͯteֶ{+_4kִm̫/}&+/f`_4ek(>2+~wW׽ss{}l\msy۳ebl/л n:Ö? Kcw ۳=.~>Vr)]r.; Xf7z6yN-m.RHҺ-ٲV~ E(5ˡ6ʡNvg6m{ȱQ0}>jQ?QIS;ߣFRNǍy{|H܄zBztydս}1m\LCmt5{ToBkX7wq:tbm6rM];]4Ӡ֬͆r3סߊi$CZڻ5ܕU۞ćiWݥu&Q,e:-Eo˭iP{0"~3e7>ءzXe=`R2ܑ؇f7nVL PF1m7 URK;9s̓ID{ qM(4b6-g%z̶Mn/1LN=-!t{^1=b3[͞{+[(ɬK_>۞?MْZhغ3O9}r5;{7/n̥۞v]ҞUUwn}Ž# (gڸhj 3fKB䛄 vąX~v+Lf/6OW*IWnKm6c\' ɇرwc·7y!w/+&GY\̠~Yjkz=`ͥ[3kI/gG|I3>Ĵp~Gz?war?.R#bU!F۫i!}K=v̧i#_<8,w,qש;=qoCQ}x5{>] [󰂯딶;hQU͑Jt8<9kbf7*Ѐ9db9 Քb+`ﲞ?!nS Ssʸ̵g += Vd. &_! )v FY)l#}tfCkE&odCV0bX_CwTS l?r>qIzE]fj );.[v7. {'Wz}؍0{kޗ9P}OA2DkІ{,huh.m{蓍ݏ y\'l#.C@!AOz Q?F7ǴJDaャc v GψQd?~FĈG%P#Z6L C>U]jݍ@|OӽG)?a ap*GOq|zdcCG!JLQOQQT2Eq=ee'y;`ԎَAߞaSF8v>Sݧ5>`YQHL@.w˻{?0?K{B QeNȹ&r6i< 3!:M7[_RI6ϰͳ {(O :{6Die0$1_x0Mb)Y'Ϯ`,뿀 93Y>8R˯v['{ |g{Q_6x4}05u4S5oϽ6SE24n[9r !msJ?hewͧ{M,>`8/47H1sџw4R>d7G󗠄~5~eEXկ̟O }R >p0]w%tܞ߰]C-T{ﺉ[W\w^F;*[xqr{nuT| s$gl| q |$'\HS=ɌpUa#)yQ|.Ä2a8Zѕbx`x_gdؙM1j| /QA;G)޳ Qpޡx8V(5}!J|!J,F9ܔV(5EzYJR(52R﷐zƇ0\>U FJ'8*P)5yYJO27xɔSꍢLï[Zͦ_6UY9W|?ct3Nï~,*~>χhJ%'/g4?2g:Ukp8倫#_pgUA[q9ΥYUWlɟ~R?`SRm<=.e[j%8 ۣeӷ͡uUZ?3?9~HG*[^&3@R#Ckϥ?k{mb-Ľ#Q_"G?iul56eO~ {4?{#z[9DBz69< D݉П$բ`߭(o 9EgGs_LmqXn3`X9hH[}2̬_͊0Ya0}i |fXOg3zH=!9cf?zz:jo G?e?n9}}kr'MjY$4n~H"ɛM|{=X#c YE{ kk<v҇ sִ?j{֞iFzVG=+&>ju3 K;-7:̈́?@da!;us豦˷R`.N9ԏ8|{oׯ.M \ lﲿM/Mקg6?Gzc.~~W뾽ͺ@/~%\)ص~{o*-tw#cy֯ᰗ{}`΃bw v>hU~򝂝/1;7,?g>te{ɷvg˦ڪ{ѽiOAM>"5볿wP{ A["%(pXԷ=l4R8 X+4ͿJ3B|e=R|Ҭ}Gu)5;xR4{ =拪2TUg8:3Rr]z|z[l]mv-Qowe,Qo1ovToWovOSu Ο +mɊyƊG//Qq?28dQ)U_l>߆bo)/)XlzXnl$jG9+7~1GCхZg$ǀ&sX=aS3L3l<1ra ^gD0]SB3<)$U5VlгL8yVl|Fk(U(n浧b:yS* >hPw7_NT9hrӜ3m;;lW e M 2'ܴ!MSU?UCު]uVX{|nmL=Fs5n1\.J諰GnBB,X=_LP Ɔ6sqMfbzu ا|c3k̄H3+ʐˬK͆ϝ ]/2(nbV i1Lce^&hj昣} qj8h@J)%ohgcH! ݑb؛_4\\V]vr ? vdOL't޹}pI0 vVAA޺ܜ+@V勇w?AqWQБ\\C7gcxw_ܞ\4-_98*_]\on]~u=ڹ#r.~ߞ=;߯.v+ ;ήrOC;@?0cpA5Ϝ+L~o}'/W|G{>r?iޝ^b[3LKETb af2B m?8 24YSNԗY:S  T%jV L3LP1Ig, v5]doE_ :$7!!Zd6ك7q9@Zn `sf&p[` N9knPGd&=n 5H0 ; 5W"&A0ҾJ?*# CG$W/Gq;._ .z(?Bez yzLsu_k`˞}U ;/+>E`];ζK 8+J3D;#p暞mLʘZ\AȐeȖ"pek~ly[M]*]3L) Cۈ_w6VSn{ٻWsUfmYۧȪ{4O{Nq";GL1:gg9. ^~En4|#7pf03^{>R]lH'baPxoV}ݫփ;p74[{@>?^ܞm9}{~ONi:'o.?q:p!5ȠDxۏbkl{ۄv~L;fo/mTx붭`:zF[pﻏafk$ddj,mXFgB;LW|!morLdRFgRƌ5l7hsW[ TT% q{ǂ6&Y>.nW @_fUN_qW ږQNZE!zO?k~3v3&KpΟg#!WƽV{&~{#>u7Z⇵O٦vD+ѣ?laP (Gfp PUL[ˑexe[C>ĞTH{ h.fό݈w_:>W+M)#⋍3n}[#fGICDMzX4}Ť鿶j ƊLxHgx lBf{] Pgʻ#ЛcB;vN2 9g[j: rvHc3qE`'n@]-C![hGodGlњelWnЖMu!b@R&Vsfm"9挝-ղ׆MɾB9SRL(EB,]dS/m蘉ݲb(]CƢH/Rn4+Cy;J~-qHj/ila!ee[>U>>Ȁ)\̥S܊vvpLdBx+RB-I'BKRDK@`+&F+CR@(u u ]4Vm혡as+z̙LxAwוK5)DE/'cliQ; s%~sFa5C|iTY.P#v)JuP 1U(:(TM;P& ʽZHV|u 8aCydt\mX͞x >-P"Di2'DVШlCu 0,֙0/C@xl}<|s|)f="Ps5cte&}8GkӾ9vy)3IkY'nKK(x.-Nrrv̠[?W0+H9>QFR8ags:; wRҖ0 +8׼ԮHHR?kB[ 0X4 ۨRWUbS<Ԥ޻5 ɕ`[02r[jaX0!-" {lTK@iqaSa=X+%cֻm!#YFeSyYaYom3A](R x(MH+8έm-Cd R#]nzՋKqsrpr ـQ~phEZri]tabBɇ# 1%RFCVz[4h8 "H4l+؆KkGl-fTI|@ L\G5E++|VJw''" n""#U=.}0ՀwaM)@O/&ڽi4i2P6 3cIjjZ(n# +B\BA2Xg#A%Jʬ4yểUnGfE"d*4ۨ͡6ˆbಖNF(;2N-Ai f*gN JQ'h`bU 9Z%O:H28062"|0CD qp) m&w 7U &puGT&oW1:Yeۭ Wn1!CO0fa }Ds2\W" 6堦$VLuDEU`'"9@?-@r4D)2а,$GMbJJQ6 f|*cv' +UH*jd !}UXSxQ*tA_^CA rC%}tg=Gw@x6\PÁ\bۗ]GD6B.UUb[zĵ5g]Ō$4֌'Џrfʑ^T=tK zxhep \S$R`#k{y$)*aJ}$B@m yPEG(-W8c8kuJVȤk+<[t. $?z@:мR &&Q m呠rTthR0zbm#nX>5V399k|+HKNW)aV%"אbrXȢM0`4>˄EȎG7I>D>= o7C10H\qQZf2ؑvqP 0Z9׀'ɷb}ҲDm <4Ƃހ9&̤SőlSBIɔ䜛qż8([xG@TDaUQ+GEQ4+ z0)lG0)0sʯ!P2C HEFNH 8 טFD5JC=!*+K\V w8;<{zshG6+Wmͱ5ů\gG\ `%eBQ!+s[ H 820bsuzb8=PH֓ElR#: p7q6Q2ܮBZʵK!sۤ-ZxwR36֦$EFm$"0@w*7a+4E8~FCEy(oqʊr< {kxH^.c«л^#CeQp;)9/,kSPnF2sb3݃Hlk[8- Vf (eO^+BGdh!4# `iZY 𯉃]69a -8397g{DδnI\~8mgF#tE+FQ:qQ E;HR3اS<49nsIn%h`1VT6L1#\HUz3-~xZRܥD׎y!HSa +p{obHz*`"- *V$IܲCf$,(0 t \Qd m@R &W\1 $ЅŬ寰IƯ3yسZtNrTF=^F4)5L@g#!+ih!Z .p<3M}s5,;Bc;U\桮DDC(L֩$ce AESw!is@btDž[PSt vB/5ie@. $ d}nfL hA%V$<U%8Tv&a0g"TdAD3)?C9xr0vq!ptKb0AuYGN{'QnӬ` {< vDvҼ ʐyoҶRsM k_% 04pДL3!L =xJ]IB.^6ov#h“hMգ@1N 8B`BYEQo !4Ct-kg"qiW &<8ʩEq Og ps?7X,0|nxGh)j10LpEE$a15'!w5Yo+tW"¬F$GS92~\6K|f eh$HDN -De`kqES~V 4b:-mgeK*ERtmC|l ۟7s~lN*}O{/Lct|( qCEWO)[{JjǂZ1ŊMmzhmD  %ԇE]ôD/iJ Ff5WHO> {Ԃʙ#mxBkd 5{Cm6JP'5\ahF'&;l j~ek %@z\ܷYޛ0@PG*7'@Dq81-W' 6k^DX;U{40L &OBBSa%('3).1#݇ML4qFUT>.cBuM̝ʠe9OqciDp{L t)7VrNQTFhEqUJx613JR$, ӀIٻBK[Aqxj rhVЂPR5 I $ ǙvYý9<-J@c[E[!'\xM,c`a,Rhu ,˙V :#&\Ӭ>}ASQĦ Y?F rPa Ck+ɼ ڇAbgF;J?0H*@*DLvZ! (hj&cǵ0A^Fb䂓́$˰g/$+reȕw=cQBEZwWNQ>9zi*/tޝOGN˙SbH[Qۼ|$B|ii!Rb. cYET:&%LJ,` Lm[wÂ*(gIHl 9v} Ci-I͒p-v/t 2B0!:h^e?&agMn>ȯevV`'~#rt}:zB9.L93 ;3ۙ9N`vCo$k"PcfØ1 ,(6&lIVJ$w`pW Bm ՕE>vM:-BlU[08l9(9De!)dIT8fLA'`&${X1 |DLT*|ؓ2^Lݗ8RKcoDaWE0@ %m|}$jRV䁢##Tf  { ¬B۬BARyclu؊2%@{2die?Z7OvU4IM iU# 9JǨۣ0$x:'EL}W3}lt]"[ ̶!el b oiY~(U{;iP!ҪXC# 3U:fJ1Y^^Aod8ȱNyD+ۥ]b(7N19ي e1hr1bk:$W0 X9UΔ$n4ꃳ[yf'`4fu%2F`3ɬ.vL ]qIa415fNq&`! { iА SkR1y̤sW&B=Dq1OP&D/fiXcH Flx-vҤlKBaP]ɩWcKBAM@\ G& X2D5,Y{"P[:5Z#<;DjR93PUL2"x)?G GH=ʗE"EiK Th"؀+yAT+ w偿D:(h%NX.4'72ETPi,†$dr3j&pAX>7 +sKʺl\P_! x YLBNN^U\?w+0؄4 ŔsCW8*,0fFZgY:tAq:*r^q̌fpuhhfyYCq~A %u8A. 7Je0zf4@2R06uz*Б\"nPzHaI  < &m6R|V9wZk5 $-C%j0'v˱Y"ׇQ i'.86öޑ6J]cR/&{2F 5í'&q`DBYeWu i?K[1y$+J& Z_rJ&<+4 G*6wuQb>2 GDҍfN}.Q; gPoBPaےY@8aӸ LWI/ !ƊjrOI%̕_<8RͣfgՉj+ю} ØT0xzfXQdB q\P'K4,Qd%6Fzzy@<`4 \[sѠM=ŔMi'=y,LT@B W'C4}HȜ_uINof9(ߔE#(Ԫ D/== I<~Aa % @I2N\ IcV C"`&Hkm0Q/^1D# [])h)Eb4(ړ{.v20s72oetm<^[qtD6 xVBJ(͂*{SPePN;dZVɫ4cc4 cp$ԋR2X#|b̳i`1 E 9 _f0X݁M51yK!u6VwНUh$D4^pY02D;>8XKUtR860đyf^6n{wήf/>FP a@;JJ7$Id'}TU"H,]fuޭ+E$XCNxW3˾نP"- fƢyq%P]D|P&FO0^, JVOOUˁ8#p!*d8iXGL--vЌIG n͐=z&riD=X0Ҕʪ#J 0>XUM` 6&@0)fdTCd9!&eBTp7 lfWOr~iۦ3 lEz`ifLV ı%\'Dch0$2%aFQ~e,dӏB@bD J抭UdfnI˜l#z8CN;WYމ@vE$b)L& jP3$"j)(厥'˨o96xkDh8 aM3%A8S"~J@,|ADxcHbD~q }ˀ'E<%,\"}X21dSɦGȉ)&V^%{bt<\~W2x$sWC.N6}ثA,!zY8i$M`*{.X.>| 3#VLh+˓ Ĥ,'/7U=3fLM&fds*g6n #B=9 +e-{A %*!"* 3AnWƮej>VkKܬ>6&2" yJXs3ÿdX(f,]!T{$!aOgdG: $Y {xsHѱƆΞWďZ7Ҡe">As*wF9tb嬼# "Wub-w_k7g A $)4"丄.S0ĻЇtӠ>R !aW; "@._8YE}zxb;AzyP9ZfǓS#V`ID+ 3q]0r8Kq@ !RqT^4h$ ֈ`&2%H0mǘ.fz9Rf(1FöI0 iحʗ=e{T4~\U;{@CҤ6R)|@ V_qM-G¬<(~*ڙ#$$lx.ޓLěu3! 1:?2]z~݃(Fz)!W Qu G{if(QP=a b04͹-yX%&kXfvCѳP@ x0319iM(j@[:!,0Q0]$?(e UVdV3NI}ź"NeA6}[*-QJ.BE0TU/ c }싻\kyPxAUiO+TzCY[ :]N;psȲ2d W(dWNT0uTIjyTT\Z4E L F|XHivE0ȸU%i;Ƈ|LM/7E ,YGO'UKab Ů%2 "ON5m%qcxZmJwy"YgwU^*:m,- 2RĽ`]Q4+ `qγ A脕D3,u)C/*#_2KpdErR`W'"F9`DmQmTӪ?Ĩ"~JFWt-,F"nU"zWZ燢)j'D``{e XntSo$=Aު-oUD_Ý飡_e%#(| FI:R\;Լ›9(H04_DqH;'ӃT 'Lz'2ӧi6N$nS+ Ł%x\G(&f;x05 Rv N ӱe H,4 'Ѽ{R":4yV[@wl:c̯6_y tzᓃ,!F$>&XW{ U Tj6^kL6EJzGpЗlnӏE2f2LZ*"ڋĀrh`+ *RirkGmfíF!^s3Jy0C9ĕuDq;;UA 䴧R0uUONGJvd6rdc hb>l~?mpΊ6ԅ% \H+ @k1(r٩ƌeKo~RwVʷbc.QEEl7I>DZyIr6pn0lg&8pGJPFӕ*wx@FiÚ AM`1;Y$:vif>>@r[Z%Ab*ʘ["aA" xGxjU5s$JuRbىnY4 .Q58BG]6GN5v=FedVI:PT<eR%\r`){) N5^8C(\FkoZPߠbjlW%lg.(vZ Mfju/ܸ;S˕ _rT`6)DdN"TVTTU*HB0& R8̾f,Xl EB @A\y=V=THj_f AVWwhJ E |e!2xA4KN7 iY SѤ}x/F8aV,6m|t5m ߼j0xAf;.=x՘%q?Hh0tƼl3{tDlۚ~9(E % )Tw$ o0Dӳ#_ݱqA\D{F5^IH@5hq I5-ɺY)Z;(slncIڑHZv$4(F@=qZ0\+f\#K.&1AûQ3Iq ʅsf79 N.RaASgMW ]sxц&_n5d-"YDF4]*r ɇ'FlϻpX-걔 /͢)'`>'TVfGHj ]DZY&!JI*i!O>paޘY\98h"ɢ(-H BSQ7YRȤ0RABP4-yĀl`iwNOm|Z]hɳ4e͒ *}Ri dS.*\H;&;d8v uU"Z5,dv7#'NW8FQjdJKþg<)u0t18` c6@('~mXg_T-B37j lpR2sd6p3Z ]0itF7:$awggT_. ݓ?~[ݝe_&, <, -S&9Ae UĖbNϠ y3A bz=R} #^ݷP=dJCei q%.WuJJ  MߛaOy9.~$KxHHj]$Mu x@6i/iFm SO(tÖT)P ][3QD+*mz6j<-Ěx(Gr!5u%PL$ ucQMڊʪYދ%9E*փSrI:  o}4ߙNɛAut5{sfl]O U<].zt)[5K?uf\%ݵ%X &йXA֝mHIG(LrURq͇.a]UVuGl𓌁FY倳Ӫi2rf֣1^fwQxr3t\0\ 2 rڑa0؟.+q / dCb66g՛a!lҿL?7>NWݡA-'֫ 25tKa=isdC(9Wui,pѯ2(Ufˊfsʳ=) ʣ#)\5Xy:q0o 6꫿ -2}A]&, ^ڈ N(zɈ,XDtJX|Q&pB^9 *KF/c6ЧBΦ.5¡"{A?}\*G<R J#K[()//0) {4MH(}F0|t0W@@5ij"yh j6X5 8Ծ9NQH@2@d?;:=vEM{SyGs R 6PAJ_GÀ"BP9 `ڮ*O3WQ78su`eds ]‰CׇGʉNj46(aBs=@ cj>1TFqvL!P[t#j8B(G>SyT`e<0K/>h5G2XSTϞQv܂M4,.⣠Z++Kх>8n^ _DP[9 *#J٩ktlMS]܀YEs*.”Ӓ=b7bQ5G5+ _A QUP|p\%Z40(3M$Ls&vq(_EՋ|Bpf[w4dB/3rMB ETJ:(MDH?Bټ"bV(Y<(+6cG7J D䑖FvDj5*$#K,BV/hohf5r$x`IW\Ba'nFiyqRGD"&(0=uO\fQ؃F!JF8J j!B!m ȢR-.s;ר1woG?iMQܠ3,678Ԓioer}QruZ!-!|Q{++UJjE όb,S# 3>[(/luőڗ+f]yz>h2AVmG$ ,^a LLؽ4G; „Lqz y:XbٟƝxBu o9{e/.a~nbm,RPND#slWZD0C"x,!q 5 7\cdBRRF_ Ӭ6Iʒqfiomd1j38EK+\*ϛ7d`̫y@S[ǑJOtPۑ:,TiЋ:Ey*'clBi`*XaiGkJl$txfšڢS` >Uyx?qf?u݌_2'B2J-nDy^ "-f!`@;Ep.;!0i'^pHR+n#F)&1i}qnk&։DY] :uRZ&4x9p?q`ոyhn(!.+w7v;2I xw%~FӋT<=Xn-H)j}e,]7lF]?4Syy:o+2 vPa#谴_'g瘨IDoİ|VwBƽ`PJMvtV̊DQbrP#WAIDa:nʡ<~bvn46zXT7kd(!Uh0ӏܖA]cj# uUdl$=-^:v }3 r/2uZca tĂQ̲THF{ EIOQqE2݅!!8M@F\PU Yn1 anD!Vuڸ,g # wKq3!crStm3( 0d5!570#FF_5)}P_;9g!U}?iFpoE%fKF?9i4 vҚ zt |@R\IZX'@"CJ!g嗬VI[}h &C)%$̎JA 0dʋ{(ԳS~^8NkB!Ek@\HC\.-7cbu^[E6xQT(6ʀ-žⶅ"XO$;j*'?ڹ~تPl8U5q y*JDY[Ǘ (}#W!:H`-֡l‘ yv˓ҍ ?E7lj8e{6 `P1 1*QyFyJ7nBbWsGr,ޑ Y2|VmWW< Ceo@zZTj@&k UtIGƨC-1!$f=`HW_wHjD8: ҈a͐qō<X y% Bb\2$B>+gDv%V6`Tc`rvy$! {ׂɐd(HEn; VÌs8;_NJ'tGkC9X(y@ۆrV1&X7LG+¹3)6ن]~ɗg-]*#F`ye]4J~]^"(U^.@/1㗪9Aٳjdmp Fp5MS_faeZY ġݵ`6aU"P3r!jV򉍠$$27/B/,WkP7:uwhl|w^\|{uWwD8ۤ?]:NN5L؄]AE?jjcF&AtqK5"O= k]]W,}tslkR(<E$ ?g=JX?d /Bđt,%%rAi ğ_~TAw1ZHGAA P I`H&563$hU caeM6~m5 ytV]0m??srpjd:"SI .e6K ?-g%Lk%4A+ iaDXU'K߯l;f$nt_MIB4:mb_BH.}cX7*E-."L5AI8M IB0HvrRҏ%?cAH1y鮴uGo |ه^hĊN*e1Y&^¹z^7C܃OgdՐJLe3d?ݚʜL05-/B&  Hޗ=Gf $PAEw\<1U$H%3VCgwCzkEj_r8/Q ʙ0; %ںj5B,Ypl *B lΝl>I<qO ynRmF¨H]aM>6d7B3;=4璬8UR" Ҩ4WsMO(}50]E0AX*LݰB.3t:NnAcO/~g'z}e13oi8gMʤ; Ck'҆<~I_8@8bٜU@mG-uKI5s(Jk_Z ! TNZȬ 7x; W< Ah1gI!q/#:j={C'.!ĩ0,>˒ܬ,9SB+GLB&(^DYpuU21%h4٠Ey5򛪰Za#GR쁃QҘz!YW]>p^.Bee,+AjڤZ Dm -viY#Py4Y]q(Wd%qu')M*4bbKO>?*ul4N_201Z">*a1zh㰋]H?ed7ㅴ1ߛ&#uF`jCF2,8Uk&Q(PU^F] UHd6d~\ N9V޷=..a(צ0LEnԙ%S iDFEr0r+%wI{7C; ;@ٰ#pIU/ȤnK2@HmΫa/#A`جfفq&}lEh(0KGqqcO̱^XMɚGaʠF)"&}0/ѻ:wƢHј@2wsFOBS #y *0@!o)U0!|4L qTΣh#{Gّdɮs_%D$uzC@@S=}[̽De Cp77{`ڰg.D 2/eA#ǹ3J-)W޾eyl†6!~ F:M3G$PE9;[6*e&_Pヂ :wb:y,7-wXdfÛtT)gGѶjo6$) M,VM&3e, bmNzm„¬V#ԯM׈ nǍaqvx!1,<=+fbݨyٽ 6I$`Q|eͲJ=Bm 2ĚM6|8>XB{35 .#&_}$"wϳI=b \#{p:5"\*0=ࣛ9BCC]Od٠>#OD# k6"nBo]<)]-kv"JL ΧQF/aWFI)Ěxvu w$k`+}Y zqY &Lo lYe[ :ѭ`7Z >--L H 81~6!9; [ɏR GTyY,a2܅p0 %"AR+ hVh<)"1>v\%c5[:ĔG!d0s~uxg D:bpO=,%ns^ʃD;?|s_ xSIv%;y2W=Y-9\FbMr>¨r}gSDBi xPdE텍5s|ӡW4:T:öf&JiFax9`Oi8ܔ5NJWBs?}3K3ں3/tȘ¾@ũ"Z/; VpCGmLzmbź趍́<ܔ޳ҐpƄȬ˓&Of6J>L7_NXtKGOhbw~cɒs~?-䉇o)̀d> ks$#4M|6I7S*J5LM[fG4ÁE IԭxjJ/rH3q(O*GYͣ!dؠ `ӃKCf"r\_ hI\RKaS¸zp_;v6MohG}QD__^.iG m=طᡪDG~\(:g$!Q9 a!o(D `֕5EftrZ*_1$lCX 0` 4C3;$:nϥ43h#SlĄ˃4ی ;;kSꫫ]ADkdM`%d; 13gv(ҙp|̤$ "ka{;Q;5 xpCɉ;瞗>{.p~C X氥CV^vݚŴgNխ5UpgN5܋ E@qcR`AQhXE/.̺͓54kEDsņ \\8 nM?R[1ݿpjU\b0 ݠq1p/j2eg2y> u9}Afp? sK8'rHuhEQ5"Jhwva-"(g!`SVRujXcS]p=LTGٽ;Z˄ ԌyJ*+>Jυm_`whɄ>0"7ٽl"j# {_y)Zy=lx$!rG IfQnhj!>!Ge1!%jCBfRF TONũ{}?!%>6Z$Yn<.#pUn;?]1R%+M"XEw2ː<0doTyP*A9|=}lZ-Dkxf5E~H6ICgukD7 j~s`yL!yrڤW&6l!G|8+룄=yyxZ8cͿ +_G#ﳠΓX 'r6gPၿ.*AO=#m64IǓilu[FN<3:)IY_ʌ)3M5-WT+ÏWs@A3r $11kW:>/Ozc7V&sgD`ᯣE^R,acF鴦rtkt08)[@ *[0嘪N;Je:-_?-VNldIIkbI,nam;kiW#_K9Ʊʈc[Lttx[c3ߝ#5?UǠlF(|fGQh42`?v+8JfghXF.0vt1&Rbb#i{*QZnjho?{Kئ^VdGu^`2WHYQ i )i0N M&&4 LGL4Oo$)J]4ry?G_?>&20%AiH+ # 2Y=ョ' \jA(Ao[4q^N:44iѼA<3DX2gBu4[Ug+)*ae=\Zhd6 Fְwz#wt{< M3{DrًȨDtp&(Ŗ)l`ϰEgctds ͭQNv wV67t5|!o3gOigW 1)5J3u>CԿt@kN\{L3q䃝΁ v6Q!JRsG7K>BM$b(~n GƞOKKQQoam,I$k]bؐ#l  vخ'kƠM#L uylu v|l3"cy_t.d1nFQa.Vt G|z>[ m췼=kߧyc~wYyOA'VM74|`Dpا{Fgal"7\QQ=Y;RDkSG 06<)?jxppU2+ .(zfzvPv!9Pc55[رrQ?*A^Ƥ,3(UdËf.^fYHzS_Lmld&7gO`kg*/g#^KW욉n^67IA ǵn"#|N.i@`uٖ 2` }Y6mZ!w&kJ%*Vu,W ھGip!OFtnPB&8Pkv8Uv$ a)nMi2cԏ(!e]#6æ_QՐY0`Ҁ!jSe#r)U2~v3c3q+r+pG0O9i@,v#H_Ңخx;9 XImNyxD.ct`)m;E1|6ߕhye\dx{SJI?Vxc7*+9`[: OՊz&4u8պNRM* aM}Ql5(p #s0ut_l=+ Eݢ<+.=Bv 3Wq=\:MAd6]c{a:l:wsق(e~!L]2 eZ:]ya L] NCbJxVv {6uml{(+DJv0wT-y rXiӭ'qiq:G/c^pTߝ-lt&:artzpEx6tyS)id# j;r^7(.OiaV3^pAS8en<6_vab]Oܶbmߡu+B3ۙ=JOS ,N ٽ/jl2S}fYL-1C6U̾X)X$˞:T/ tve;su08ŀ4E:\d0U9x̹<;Ȓq6z녳QLAam [YNXCo1ym"oZg'㤇)&Oyk&*l5F$ /f仲BN fE,FXyz c[Pf6k,(<wmfC!hj?6=Ek/Q]oNqׅ;h"L~և1C iI9bߛ Z7&9d6OmsV5d6@o%}Txas]=-黻]}" {7͟+{.én1v2GBұԪQkde9Xr;INqMzՐ,^ǰ[^u6Db^4[䥁$-Ol ;p_!e$ "I´Wcpˡ0h\sqG%~ [4=&Ơ/l(jS:s͂WD_/y}~ܹW.X*" ]qfƳ? EgA˞3ncnÂr אP=1 @ǟ@F[I^hq4|VJ}Ӫ&tbB,ʧLn$U΢%?UH- &p\QVn}LLf*ojZHjզ{V:\u ȫ0lD041{de{\vFBB]NŤ[ Uv}&>$Lm %˂}#*BZ[u%@j0)h_۝E:M5>{F&yZP$ql"-T QA̢S@wG{¶ p$8?ݦ'|G${0^M46Z4 l 1ٿ7){Y4j#_#K߂]Ln xH۝B;rNһ,QuUPlZmd ^Pq߅^[Ln H]D8L7Fωǰh=Hdz-4ǒ|WtzڴL1^Ж.se{De>?Y~6'!%>fjK jyodd+k)-+iSЄj١SWu=%NֱiCs]By&g`wl)9='͕ " N.@>pJuS?_fv\xwGFfFbuD:ɹA#t} Ӄ[9}mNi#hw#+g-??|,Cƶw8B,"", 2&IQقcD6{(G"g'Q;Y*[O5a9U Og7k±>'88O;G}IaP$BZ[|> {̀=k.R*&EZhBSx{K\Qs|9]YtጢΆ\~\Qpy%Z"Bxw W-Q~2A  R.Nwq 4rƟz_Eˍlg ̐m5$,J^uA hNpx5'_ ڳs|ļVV7\?\MW<ћy c>s%ЦEν]-wq}򅹅 jqlV sh\!7vmq!V(0*MhEzC :i\|G[eBLpm88aek$jјc^ fiQ/3s`ka>zzR ߙ>1P|s7/-߇ ӛ"mSx 4g:Ӣ^8juZb0 ؒV6 u.Ѡ.u@es]tΓv1f]ESr[{O biDDt@2FL,Q;W PIWyCv\%Bѭ[">Z;wԧA^g8nclBRSA5@M7RÞQ(uaop9Rn(FX#wk9A%y7h6In+[h Y[<;G˜6MO Eσ62{)k_i.8',zcEC@FlG0DuXV=~=!CI6c.!RzK-Ht <(l$O.!w Ť'E6Qq D+&T1'Ӭ݂Nc=iPѹr؁UN p^o0ūBg[˓h@2#z6ј9/;EJZ's|S%M6s-i^ /.OcIoVKQ+IzڒM,F-)wOtw˓13O텟&(: b`w4МmM]8CơR@s-<|W^`;V֔pN p6Sgmb Ă`Th+ae9GUQE|-sf0IAa!p ᰈ6.{Q1b̥D$ܘSճ3 ۨ:U:C3!+6ƊnD+9V4.߃qi)2J-D|^$Z3meU5td) nGP@D 88(I_2w?E!$1ϧDlsfT$s]:JDcaZg;")ufD$sʗR^@~2uZ\Ë}A$l#$GW̌g_L+?Ɉ, 7^VbǑCs %^y櫢Z/<֌ygv5!g/, T["P#a8LGNCNբFˀa2 i:vB>ٿ/' ',5{)q"B'qו 7aK-<ƨn*X/ Uo(4xYq'X$̸#wWZ[a;DѣI4v#@u#R{0Y.Gl$:"<y *jJ- y\La:'7Ŀ!kHz=ȷ}H<?g RwRF(6w2PH9iR ceP [*Wf?8mfJіq~pώ [}5g2v0TR7H*n t咘f~ef9JKFҤ(1ZLEcm;1k|fwӜb:'ZC5O>$KS69J$zs{ -Ijg]n 3nsoUكkmi~tsE7mv+0ש2y# 3=BĕNn7`yFOD=F8WMVV ˠ圷ØMpk1@X徴[yNeMގUS >M> ~ AqN4aTUi8o]589|%΂ќDg똏;i ߒTNPX ۵m%3OډZ ۫-XY fʁ% bY!S%అ]tBˌH8eQaQ]TL %`r2mʌM Ű&U| 'UV|KfHOGhu2ATȽ,ɰ k2Z&] &ǖ Lu; v?+:>E7_p޸*tíg[8%ֻ&:.*vbqZTE>^ 󋱌{cH9x0qb]fS}Z}d#ekwԩ6?x, 7j_%WIܣ)l5 xKW%] ?ߝL,jO(]b۬IN ޞ4<"<K5-J;ٴ9}{Aw?ITK rއa u#^osf3v;)~ϧWO~܋G,(B>m)RXY^"=[+Zt*QE%b o.'b.^]ky x/ %"LxUA.[_'j]k72W7^wSN"m[y <^4ym%{`BEcۭYѼrRc1A:kd hjcwp"FѪxS׹םC]&HG_P696ڣ;_bWDm9"nt H潑L갈 ?s[v@=*=ՌRIbC\Hk4Q,QZLF8_ Y+6.#Q6\^/SL]6c5fORf"rz! |l[6|Ϡ01Ӕjf9Jܽql/0+կ Řɇp9 Iue={uy ⢞$tԾo;#QܭɎ[ƴ**kؽTx|Z$kUʰ+5>YL3;}c{͸3xAc5'_׊J7l?,dSM3uP2'&J$@d3`0'DEDи ~g_}~Ryqi>08xPOKf3 ]3S߉$AM MT]{Hx3Hk0V(asia/c*ED!Ա<44Vq.ؖE5,ҩ~vgB#w(Ea\B W2|+\A4 psBA'{MF)Nўt7NVS+1V3G PX#pk0Ú;%?I%-W2)X[[Ήq!Q"S0m- 4 tct?%I(Չ [d>Cr#j@56~Iڮ6x̿H=WcE+E+0-VPRA]>A1svL";kg,|ے3lks4 "$ ӗZSsC|V~I@TVknKr:oe4g~lA ACe쯏/C}>(,>@" MiRfo hs \'K[9 :f$ +/GJ<1fF|֘d'}FlHӲfRmECюy+9{^b|u/1_~CvENg2n0SG"* z<m$,yʝFsl+WN Ti:H糵丗caa*`ɃKʠE3W hSaOgRnlNVh&f˲tX=?9\Un ӕxts#-39i&ij@NG7.CHgO$Pϙ;UDTx- Mg2ӞepkSHH%>ޝBhUQF< $5fq5zG(Ҡ-udB`6as7)*U1\Vn眧6y15pN[@vе64UN5AO[H]P#Z0 3$5:󍡵[ς:uzB]dRquqp8] D$EBZkRJY$WMtHsm#ݯ_DžR u>4V^}ums^wOg0k:TU ZkfИ25ym)W/— baJ15|:DP|0f| bѐ]ۢH9gr o7/6߮ۈ$vCk@~ot2QIM*,;?F)B8av1E+Mjozw]tb-~ ؞!,{ hǴ}ڝgTV#QÞ*xq]RC|Ĺ-`S-bK^huv%IgZÑN9 7%x='pc!}#{5"Z $)LzdǼfN{8ņi-fpt,B $]lkg)R)C|C$KAd:/nho}~rدUmey(s۱[U%N6+84AxĶXq~-QDO(8֋J%APZzm;_sabg\g+w RW] Ir# .@NG p#ԨLmk} xݕ_uƾ +4֐~}1lC66ڰC/D[W9il[$k/]{LgCQ[ z61R B͎^~UZ`uA13ǒ& w>yԫngZ q6)qldk ts=Ӗ` 6f6)#kޯlyp~uf{>ryLdʹR@1-;͋ 1,+;Ta^&7cY:0ZJSL0 p!7w%`XgQee}A>&w$n&O&&G ΋#nZ A7o#& h$w# ΅3-f$2<؜$ e͵cp2Լ=Dݣ[b$[fmB P g;9n+S,8b nr9GhobN3m!>Ԧ)Ar#U!A)ci`Yv0.CSOZ82<m-,("oxB^O-&ӷML(&xPr8j 20s ОPg$Ioxh0w 6 FUy<^#Ҭ/eBtN!Qr%[ nM,PDFA4{h |+J =]G!́初3s3yo?~q{\V1ՕyF̔i5$ĦQᔼ`Byy~]Yŕ~}O~Ƶ_Cr5[$&bSM`m?A2vqYun>#7fg4\z">mmg?,C֦V$%K*Mh0UP!չWXAnɼ&af"jw}\lnjAWӭ%4XO fIӫ#A=F;ph40S#I :SbO\Q{jI_IQ↕ E eTG%&0;ޒiVIݍ؈+y}YoCCxpU4KsX j5{` <{209n* GkxZ}2G$^dmZG_JALvV_-3(gkO Uv8A ;{ 4YL6/fGAre}ЛN!LHqf$57/Niεf.ЈmbA]hڻYip.{r[.htLk[Z۸)wӫ)<@8mnᕳ3קfPb nޙC\N<¬k 'I*~wOq ˂H]C(q`0f mOmPnMb$$_b*D̒Vs';Yb_$~Y#J3TN),虤!S*)x8 Oe\ l+[q8t _ v=Pm( ;kqX=R?|ytcevcB )6g_K)0`U+ t$- +/ĀX[_ŋN}!m-KcS"14̑cIr8296s>c'5fNI@ &hWxQg`{"r3i-A7B}7R{/ku]ZVlKr6ڮ4鴩[1ml EcDZkiX4y4(mڢ;δzF-)E/W-ssmУ;:ҥbLOǨGAAS̨2sҼ:"E<|nh# %0ČfZ>w.+ޤJ~ Ѳ!Z! ͞ڕvK6SL wMrɪ/.$#,^}SWEÚ(eXPJ464u qdO)_af{V.e#̈́B?ܰB$Sk[}2A\A}fް^cUE! g#i'dE(m=VF?&w{?ړQq-Ou_g皠5:{x҈xU_mqJ\p[h}OUUׇLuyեYWBR6ɿwUfFuZU6SE,{/Je!&Jvn PF ;h,Nm$tARFgD2 ?>.ʰZ*4l63S)@D!mcelV- }SDAomy[:$Hx)6akfiB7FO>%aNO>ii*ЦXP "̽|xgΛCv [xS퐃z~jqV$^v[k>p$҂( oFXتB"i.^,Bp<>@qmy-Ӻ1Ol1*VB5@ 68kN}bD6U,6.V,odķڶ'}} JSf[wUWP ll!ą#QnZD(eY+5N<͒ q,LA'V:#·OJΏ~:Vʹg<8K(),ެ_Q?6j=W}ev}oJ3ƙ9@\n c_k\Zo<՚LDIuwŌ5hT*LTE*FT9-fe=c'6K'u&> sJ|0_BOwNhFEҙEEa _M%MJ D,B 9ѧ/wK ہ=嫔nlH1#nf|'>r;?_ =)n֮F؊ .隱mȚ:]iXbƗC,jῢ6!F`n3(Jz S!abO*"%层Wz9f"KXY ;w_& yfU tU}Yxt;x|rI˳p?~,(>Mt*:Gzq=C,=͕ "@e{+"=3qf2 6`|pѿ'PU؝Y ԵbOj(ŵ 7qbh#;|&Pncub{c r2v&'ql(9:P)mS-y686#9P; f f@yGCS3o-"AЄzU9ڨJ}g5E(=la^&}iEhtϠy 'ˑ2 GZ<f ' N2VCTTn/ 53{61ϫΔ+jל~=r;!mWt}#/* mF^#| )kzE3'`Pee0v$&԰C}C !+rr%vf^Oחy^* fi^wS?Թ;줍^Mq{Cq83+d[{>pYV=z(ӣH]܏_L?}zvi5F`$[tZ0%26,XFyz}=j9 ( T 9E\C#o489=8 ;1%{rd+3%1\^%鸮iog֊-fVX5uTW&W"ܯsk /X/L]ꡕH8Vk6g(q)/E5YB.%hsÛޗzH *aȆIgn5K3ď9;[\qs'  Wd'S53kk˓t0Lݞq>b|RBJHύ^ML?)K'j0oT8 Q坋];T,I70uG/&xTRKmhdk9Q2]MGS%v9.ǣW2xnα16_U^s;,Eox2e: _ROV}rMoJ NJj[5 TJMމLFyb#H3A5|P=c>[HBf&dN~^oQt._hRSl1ى_y((I, [kk>'7SaC. CZf.}%wE@YY[r#!^='>Qmu xpo+az%? 5>$hoW:n[[p͟} L SBq<³ik~8\| _#n[ۇ$] Q'1m=7wI ҃U܎=^⦣ڞpAwJ!=|- B:=eS)_Jp*pQSbY)w%&"i.-*վ4ϤyшwQ=<$:=q5#\خBǚbL +F[~\fb*y{j7+h4V*}#P-WpvB0ŢR@z ˭5)!̹#3AHϷm&0$y0f1x |q Pƶ$ti3l1af nξ.JSԳL rp0;;/ig ~٧ȅ a_W}9iA6GnR|ĐQv1J#m@w{Ɏm=w=-bY@h7-5W`V(춛|P3>֚ulK"B_8KNrk* +T vaJZ'}/ׇ6 #)snc6bEl\tngь*d/t*QdQu:DGXB;y}6{"ـB`rE78'plHY 'ӄ=-X$_BzP ;?c,#أQOQ!E]91Lym wmd3Ow&N sϊ2BX_J_ AjO,qA\l(!UQ?mсqxwxO-X^v ǾyNAl՝ɶQ۩zmH@V8 i?GV"ٻ/-2/nu0@xrĜf k(䓢e|@rإ6G9\xmm#-fo>m=Wg1^u+)rȊabvjLֵmP%&[eDh e#c0漰-iLm0y "X9>&>spLԤ&] te~CmsTׇٴ(A5)'$ .{p|C=e_XaEkٗks )U:H¶ Q]eN57_sy4NE-OŹ}ڵ`3!uha» 㵚 QS 6b0ܔz)ނ_QnɮOKV'׀pRoH9Ҍ&'ip̷py3-c"cԦRwbo.7UƊ=)1B$(vQ 6y[D/DaA$JyC٘Zٜ.^f&s55ɽl {EWP2Kn}UHI7ScФJ1mҝk&E G3!U"BNv%JH{[Xij890jR}S`2o=tqϫP!O8/'CQ L7]IN#_~[ŽÞ3}k !1 UǴᳯ>>>LH8i?7>}}{\Y*&`uGjڈڜd\ctli@T;Nޱp!ƶW,dTzvTqLglPQUl#iVQg|m5>_mvpط۹DR=c׉Þ|{ӀL: [~XG6kGjl}tϮ`%w/TՐ5{*tf TΝӃ]' -@<԰P)%/N~@pGTxҸXs? (#I@uBisLK=iX׊l}^/}2Ko RRчfD]IJeHDޟFEMzLE;GkR Y""Uۡ rH?!XxS.;ܐ3SCKtf¸ ()^ꔖ]3-[`OYlaGD=P4}V({ ˔%LYO !@ə? K~mx jֳQ6`oM 9.ŵ4EXZ-_À̬~a¤#9`݋M|}`M=fFсhڳNKvS k&8n夙&]Ix`o윴mZ7t,j"р|gJ?ȶp-fO VMiRZÖ譔e' zBݖ]8tO> J v|,04^CO;].d Q3#q=_h4?K+d.|+u-e>j[&rIqҘDA7i&; {3IYc\Z1و 4FG7OĔYWP ? zΓ})i:1Wkmj6"ZjǃkYW卉I:d%&jI2>0y , AzT?mP!!jL:>:foo =M d˄SP{0 ~B qHm?|ض J23#] ))T9gU]|7z8ӎߟD8GaaKvga4 &b#R+Qauu^,’'?6=/#h!c?JmM4&nv/rOai{ %/g ed3EPopcw2k`r8sc:.;|}ZKBL< =ԼDRAC۹'U&NQiBYZOn~urP^TٚyFcB(a٢9VqUb#_=2k;\ڟ62m$ -)Ǫ|6 #ÛO/WIIǭ gn;0r(įNˀp@vP 5-Tealp4>x۱mL߄`j!3R-^8|ig4$ۈ@%44q-&{Y#mD`vT%'=ȥ/4>+g}z1#b|pˏI-Շ}& bZ a k D܃f$₫yBE JWS8ç\5 *3AWxd[{&h._ONziq/Jz#g%q@:f;j h8:Q!\3' =%+@M}`I=fkp3:mɾِ]wU$:~iDz+.Q24sAn铉-uiL/y4RNtRxAx$r@Iȏ瀒id!I-2l>BaEq0+%*9x#{z"|!C[p|5ēr5;"Z+{gktȘ&j]X-6ۺ.x'mW'4DfLQa+ p{{1M>SW!kE.}ro{OE2TmsL$Z)b!d}>=ʥ(2?T%`ohPPNG@\•OP+i,[ 4GBk&l#]%Yxr_djg "V޺?)u4fi.MES۲u5a l1(EnT@ 5`"2O"R{ @TQQnp>uYT)ʽ;23+j.YK:91pZ=2Ʈ5Щ .,kaRgc#Ym|{OX6qG+{]$l7,46O7|0?lTds`Gw+TtMIHXjz^W穐[2\l)&;`ea{hވy ~f:ZDZ6 MT.dmPAH yֻA=J8a'τ_h>2-=2g"$YY?޾O?C|;fm~aװ%S./+!S1pj?`b|چ^3ޞ$Bh'm9(9߷76ؠ^^IJlKZ9:Ft7Gso$*Usd#E|XW4[3v ;f- אFNfd!^QmTڛl~ە uu t a nv W`dhG8:b6/hrgM4@H[64>ZHƾ*2$4c1L ;4O˜hc"J|}v2 l?2w)q6 B(ip_'ΆIxᖢsX[I ,Lt$Xg~]4v:;=l$,6n(-kۨw{vjf>[ sx똑j1%F+~<ݰv7QҚGyt;JXG2Bf0?5mk˽2_Հ8LfZA_%&s$ذ6c͘7tӥX8GyЁ05nח`BaVg $s\}zm5yXz\%#(zbhI?!ou9#Hk0xO@= %OӒ'=xa|8~7+ M9.Ks&)ӕtۮrX3k ;,4f4nG{:=;(۞D&>5]EEd넗y.r`85Žb,e D IgJ%@9.v,Qػ4)#K92.Z3 +'HO,kCYbN٣Q3lx#Rď |:*QH$sߨvsUwNt{2|d;SL I y o;~:pE$h7? [iL$|~.H#A#,\AmH΄9]jZNxw$=d>Z|wV s Cu8\*:G9I"V-ß.T-y29 9ݐ&_--Zҡ܆b_ 3R WZ` 9IWMFU{LI"Yϔvά6WQ yVr~tj&poN:M>r M>~u KGf$πÎC#Qe2@IQUbh)nً鋫$Щ(́F3[L7'Y{ġIOA{%{&eH4|Qk'R5 eH:|A)yHix6Uq.j߱fojN7&b1EfXoKlE:NP y]o/ !SǙ >DMAo:Lt\ uvZgr6i xEBT&qt:*L%1JjS\#ݶ5u=O3||:Q7-2 ! 7 ӤƦ'sSmDD&U;GWJ:L\{"u]送Dz(zz\N#6kuI[K-H+Rsn*vwY>coLZ'3"[f:$4/{>VvzDdx8YM$ⳤ36ָ5/b , BVH,7fڰO-"N" 0L2~S_O 8Hn',$٘:mm.0=2R&`53TĤC"KJؿ7O%KJtRfbBNpC`-߯>҆/#K%bFf܅05/DYI|dbiX_ VGyS-uBpfW蹞ӞJdkfcLzlñ SS74w=eɔ_䳄!ě=uћ (Dn?}4\|*OA5aLPiv{aH=7%~D-φu*Ij ՛ʰͻu;':Zf$NpΤ/n]6h,O3i!FƋ**:6OF6u4;n1ālR%\`+)?ۤ2 [\O*oiMlab -CbhVP*4]X_1 ׾qr οR#w#X`׶R]f~)ihJ,AqFQͥ;KFTʱbySř$#@K72bFlb38г.v!`ﱳM˟OOYM_V{-5<>ϯ#Ok.:wbjs}XMC@YoT 󆋊 V՜!+4$i|븖$I'CIGl-eן"^u6 j6b6P /hbȆ 9lY Ci2"?n .== J@s^~Qzd=Rx<Eo7ŵbɠ%Rc"TfyU4N| X[ȶײx梭 Vz׻uۡY qvhi.|z@tR4PNYgyh]yځeB¦y fU8D3вk6 L{9q"'1 !S6Bf| B#d,v[n|9ֵض{][|mj̋%U_ؔjԵ9(;sE;D|nGA&nLr Ű S1V5 WH)"m}GN s=wc*Ns+jtXmPEY0ĥF&"ʥvY, n \CjܾsY\bJ#3yOM]]w75w;i+hxc]`vfU;מsPlz^88LxsY.S=xm7/Pݟ2FwOeJ8{4ܨG]lLIZeXj3^m{آIif=M?vV ,@,Gk|*e]>0`I D m9GvԲ!:zdUk໽NiKd@ד/޻@>kh]/1W)BNk닳Uvw< 8xi-4(&+;Dl0g .ѢMdiPN33!T"0S ߾A4 hFe6~ R6N+WA܉]v؝ (2V{ g|ިPz#WDܑ =mD -d'{OkajS%R`O!Q &ᄺB݄@ =g>>xM WUK{c8)QK:fGp6`h7s LIAVYė`Klc^ Ze;X*+((!\\R3;׮_KnOZ.d e{{yǜ=;Q0 19r# +m |\kΧ T/i<2ϤI =jdtvhU'jD_Q鷶x\+(yqұH:6fx. :Y+[@hC= 7ߵx:^.S:6f E0ڱ%LR bu$$%~;>GuY5ˈ&"f)]x!zQ"X|1.:9)!w83]]k;~ݫr~!PJ Y';)mNRY^=_+Pbh(N"sG3laR"G䆱;bsvg`c}mtN-2!%+"@daRBO_{)A*+ʓ\m̔VKn@&8*QO * WoaT.d[ h-}[=cT ?O\jc &XƃOC~[}Y9%'SD4SJЍaV V5rfiMmx#'Nm(.0L=?$![].ax8D u{|ssh2&TحyJe\m D6x-tiq5+:o]י8R%V/D6 PH(>yo  DY]V~w IߴpP|%fĀ͈-M9ods'yAg!1W`D p y)+ XD?JLpX_OS>ᑩ;<0+2A`47 Dvk8 R K!* H[EE-}93.2]"B%Ђ1y TM0·)]z+}Xj6їpq sAϪ8(@p3s !vހIZGFe4lqbz~-n䂉az; rXDDXx-d4܇-l f|%Gj]$3fLsn "=#7WG~ |^-{,HC1储:\ڎ^Q*;s7}qI D$Kt]Q*r$[+:H]E"?Rm@/˹w*2py Im44$G(m)aP5Nvk3,?an- U3:s-.MA(qK<g;|ZF/ NJHD5jQ *n8TpƦO[5&.mmb:mM[L7gKݮlA3ΈNе\M<6eq5K'8ČG TI)П =s8u3GLɤ"ppl}'|e K5!ڑ8ĊK_⩏K$(qM5Ar!v =-o!VZeeల]oŧvQfY\M8l@׺9͎3CXP[ k:S@kĩ̈́G/6irC3uJ)rW1ߋ&qníM Oʑ~T\Il%,Nt@X*t1~{ 5!Qns<ۓ"L,  n-̤ΨL#6ٙVu?[Z ]EhX'ɫ R 89bm\-)Z<e]b7%#G(n5NzNf6 !%tJ67HdYm;GOR?&JoQia8^o@(Q%;D i0X`)GDBxu:9 ;g۪1|y;Q3ȐR'ǭWpճ(p$ћm,ɝN[ȃcGFJH71Oby3:ǚޏdڑjQ-#MFA_o 7/諂c Jgnp9;˥aר?}3~¦?b[x̿k?zקx_S?]T|'AS2OZn)=qSb*~; 6ŬɶA۲@ښv1aCqpvk1 Cn21iRx DmwER '["/l,u3PuzTEѹP8;^P1h {B"+je iTܙOp KZx>_8/-9ڍ2F`oz+[;T]`׉`g>^\C/!jlm:(`Xq&LGh4BUjkNb`Ճ9 |܃onHA\<ߒ[{Ȭ|ە X㷆QrA9$9Nu]rPV0bL%+%b]ճѲc[De, uy0(yNt&h R*/;QI2ң$:qbmTfkԨyT@;~"jTpyҨPjTNhu%G٪ 2|<̊"~$bքrKH>l勌 ͋tB݃)ye+USg|n)dy ghe#GHlδa;9cDʀ&0 tIm *u] >F0ѤHJ`$ON5t.b&#dg0S.%rx]~ھ-4ӫw d8ȑ0H,&o !fĆ 9yY+*5ERsmnSjװ~qpub%иwځ\Z>3Q*+T c}{O_Q2mVãݘP%`vq2ouy4$%=NUI܍Ym>SN2RL;Z#yLv1xF=+0*>ޖX#:CHc)rwtO¬Ԯxkޣ\b4c*uck:Z]cY k;ˡwL?06]@æ e}$=Pciw [QZeи.o&Yjy vx>|vx&vHMI'$GL6*Ҳ:^_I'+~bSVJkvk|/`9L k$ hs K}ZjusB Ar|B8l<? <_[cyB3خ1٦L0 Of /~Czc104ӊ2FXF^z積) AbނQhPWD&댚a'߿ J CӘj<Kֆܳ$'F+%NpZѰy#GqӻlCEAHVC7R\pl8,0f(=(|4n 29 '5Dž[ʕ.Mn&ٲ FNC.VPlǟo)G~H΂*3W/Ɋ訫%9@ʼ,tORGYQ3ԝ =7YU%#qɥ;90IMJspܮZ-q.ɹ"- o!x2ltCyU+#8.-ޢkgѼtcUiMiJV!EZyj7[9X`nC {f.^& X$hC%;w#ԃXnhxW 7C%8Q*hq)I-tՈ.UF+'q9Fm00Gx;[MUDƳnN+Z}E7SA18?d<^zL {0%gl nRe W5_< T2p5:sodNn+T#0,Jfu'3x&_kOx '@u֯3^TcH|$`y"x,@e_po[7$vcYY}cd:TCkwv&ia6E/kG~h L>>AA}>@l8ߪ#kt 'gh9'E"Aju7>d㴨wDrE=cQÀTzx1:ԇJq;$/O0VpZ:Q15 (3G5-lY$pTSqyʴ céTb 4sqPV*lzxnYRuϞ^@:5ZH#ްBͤxOS%'5CBIّ"imI=F[\8"ņzoKhgS3EtI(){޲0` nߍ5xaspvUwK4Fݩ5˟KTk;"FC?dIښ2|XCK}/ԏ[Id(t^אG>"#2A˳r$bBIP!{WrT6{h`v!A\"6w| J($װ__Ǐ[:z]w/yR=+a~e$8:hw0|RtAnm~x%(ى^]j0-1ىYһӼD{]ָQ\kn;%苳뇣WV`"XJOe ( DAIë0Sv/vs7JW|>Mߎ[̖6x_ , Hi*+l=\:ʧB1n>=^<wWO@ߎک.]j+2D-"D-9+&tJ\aLyc'U YmQʼnNwIӂ~g 춴g " =^K`NSUʃ4 FF%=,5Tp gNU27(.,XJСaԌ>8|l6~'Hgeң=@JPsO\Rp"Çt YLV j?,&HUsSST Y*.U3F(ObCt * gcOSMa{D^N^e|:63T=ϒNJGiq XJ:m"}r(<\.[ݵB:mpF=S nq\U5MLtn1yPt<ٟjȃR8(-Ӣ#df-f3RBG?)= 751ceb¨d'S6,4$CQb{;B?VfotV$P &]$(4}[ ;mGJ&`Jl?xz |&ʡ46_K 5}[ȏ>Fc6(g"VuSj , kp3H?A|x+_կި,-8_Dz:p.=M1bc]VOH"iZL^w[p[]+4az!6t:8\ݺ@bzqs "F=Ű@=n[XzXm}t:L=c%p&4`aw6m!t"~8/92#lb=Ok]RXvsxE?~n7 ,z~_ܧ^ں;Ox&ޙ.8d8*bRlmAӾ1 ꔆ0!+mVQMJT1ާ#"NFg l"):]s ϏFODiHV Ld UoE'YOm"b[KBhS;JJODvfys3=YT[s$ݏƛ^g歬^*ַwv{#BԾZZ#0M81`xlD#GLjחToҤw}f:VU1_ &ONZ2'Uݜ#4kE.ORd}B8$;MaI2&v8BOw%lcĩeK\)kC' Q❐Ca 5)qbAG dM `OqH=5LpDAiRk#2q(al$Z\".#i%-^/߉knc:,HF5dwї.PW=˯.6z![Ǻ٤P9׸٦5R&u/Τ\#/d"6ܶZo.e"@qX&hUcV]a7rumg@1kR9dAټYaV"(vU4-"Ι3Vh@9__m#~zCtօhO#sɁL+/R#Gz n eϮf{,>cBlOTJp_ͱhHvz>qH@}vu{ZgՒգbj3d>)WV&Nsrưr XlW_ff'!(bv1lI a\mm|K(,AsoP넍3;& KM8}s/J3=%qzEQb7ڋTE <ʚWi:H@DRhR*sc# U)y/8GWl+ N.> >jaTqX&(/j,agP6B`0Om KdGFN)<;dT m5^g>EFbl&eZ H/ !'PIm9w V 9{ {b?i%W-X,bVkwDLrnytEd0$2z&'Cmvcib5v^)*U!D NB KrFT?0"5pKHa}y9LEpjp"S> 4a>|7M|x7|,sOՋ)bbL5z ̸("*JjJоemlK 6vqD`dL,B+ lm.S H ,#(?N|Wi{ШS y84"T"(Ψ_v$[$E<"㊒+ʕ>7˽]u7Si{f(pm%JB_i漄Tn pFw*1oM|]ɦ;墷eJ[Y]xX3p" ۵ƴHN܇s^yyl|jQLi/EmytmA%QBaHj֜Icf\h(F8yR H#_ślĂL7A f5qOS!r=yk+UxJ!t)pBz"*gNp~l"~݉aJ}l§ ߭\aTMo`xzU/FR=BNmĪ\[TeOg5>aTfNE#[ 'gE<$/MpRڷ㎏vnk?߬Tj_iaA2Ljˣ5ڛh L+-PĵΦB%#c901.T;U {VLKa9.8&د)\Ztk@i(,p6jf˸ Tiwzc2SVH{J{j8lEu#d&da[*?SpޯWRI)Q+%3i0(7 a0(zJw"$jn)*䨪rDYuH9ޥIrdA. &he(0Adu<[]#6EˡYfj5:!y# oϔv׉,oЎTF2 #D 9[Pe3٘ ,! gi,bZ d؟l)-Pw vFS~ ڃ3f ۶86^<9kOH2u|<]C|Ϊ>;rgK7[LpMKɁ ;mŢh6^͚o@=aV~ّ)8n>G1: }{n {>xbMC;L~jMDӽ05{8zϧND_|P lE).c=q>`"͵QG|By T 5^};S ?kk~hpu~ˀkZ55m8]+*92,ʤĂ*mEi #jo-a6&T+:eKXd,qF{$GΞW q\X8f yeE(eD91!׻Z1`n9MT0R3?r?a]$P-vJNޛ.ddcfNB=h5OT҄|:H0ڣhyVzSdF݆ױ6Ϝ^(ick<}[dj卾5oo"i a;aD'?3Cߌdbc3I49iV=/(2!σp09gZǣe4YHNah壀Adx/b@F4{{kfh[@u.eyEؙ5g{oh9Cesf&u^Ta~~hۿ!cVQ6$fMdx\<rלDfalg B>ҁf0P{mf#dx?_oǃ/H"wq0Bxo*SqG_/ʸ"}o<_?/?%X yy?^8j~?n_P(\Zį\Z [^{WJ3/\_n~2"VI&m?6Dw: W+駗rLPRP 95elGTZp87ϣHeAGxp)26%1 PI2*'C! A>5!}2y<ʢk1Y MomJVм%SnTGȴg7B c|]?-?Dq$}|#?/׿??C$ſOx׬b}+{0C_OSkek slkIVazc$tUES`F؀)ED9wo#H$ҳ!ɴV{sjC{фಛߵifpEE>gghse7gXkw1WA$s錴Ƿ`gL{!Znx d߫D |_fdonVk^::"Y%u*t;?,v :<ݻN"7tE<_:_Oy s"[aP/bB&vpCvV*N5g9~!'QY|zLsXo2#c\6s3>JpGDuzu)[(zI^n.a$P,Oȑ^K1dW%x:?6 Jlmdἦ =ֺ/Vbk'&6S+ؤ<"#W5QL~`[7"'µSb`$mfrW4)LG vjf`.o槝?w DN7/O0V,Aܲ`nE5[lH)iQvG:03WʻL0~NdǬ>oV,2@޽6ѻc3(k)`SgyD<ֱe˦UCe#}YKǁ!1y':|gdC9x}+-,TBŴ E%_7OOw[$mWENxRE`)s5꼒m}th ;v&:h & t=ۀE-Rtx ꣞%6,2_)(%Or&=qǦd¢,!< &c^jHzlf9B0S!(Ү а?@K)ٰ Hr="oquUqV[ HC[ (w@"؅dQ`p/2:#L%;U`H cNΦMa;w|xEUq]:o h=Fݮ3(f(#M+x 8vLќZ6E;[eBd;g/]hq$++ăWjq S.(sPiaΣv'(|`b!+71!1.+X"N)<b($Rx;)h3EќVK3p*BiSփ7럧\$כ]Mj3T&< t, 4sNJӂO(- ߥH*6P48fd,:u5= VK 堩59*!]af[=Ck;6ƱGF*Lq<% DVU|\Ⱥ[Oˊ{O?O_J}1k}8Scc1et؞>m^)uMsvA݅wek:MuBvں;d9^r#2q.M#Jęzf+Um(Țڿeۺ\vWu=ґ2 F `W{ ,.qG!I"Z‚8W{"6t屩h p:ݩv zz_@ՃcKV)j%G3Jsx搨jc,ϞBN9hԭ) clq]iUS)g =R&iyX$*y[ AEMy,%r5\28B!b5H!%UИxm[jBv%mM!fh8;¯&X((.Er^>jY(+J6B.co%9% >Kl|R1aIVe2SIұxךNB 'iJ5[pT-p?$uIտKt-"I6F|8B핞x Ё /h/鷏)< ߙIc_d99Oo(n'Rדi τL Ss ҌȤj_R[GDW v& 36YƯR)o8Fk|6t G"O. &5p#>.c=fF8O*mWt ȱ۷XTyG Ok4dq2DڦG+ε15 L%JC)}C)ӛoq:TЪǐK^F#3n%MJN) #=(?*[!883 OYWݡaei{g;YU~!OwCa5|оۦns ]ug^we ў}+|o^1 >_sxm>s#Evf7pL:zWj⻇KDLJaONPNE˱|%~U[$l#e8C·00[K-֩&c r/Ȑ)憰¨{u:Zjb=MpDbӔ<5 {s񐌼))EFՕ\^g[y֊rk&Ԯ0j /}\&_@0&S`VV8U=J?4 񨎳˸V~c(<+rS'QjC~Ow6~imYLY=J؀9[K6 ;VB5)z&Z閬Ѯc&FIfɣ;v9hP+ Լ"Q,)"r"b\D}/SJ+kˤZ֫ac;ӳ$J0`[36%WeGH@"r$o~Zu]",SJʮ.iۆI^]h=o}E2Uw4Ák=0ms\sC29JfZy=ӁԵf4y0c*X [.G 78 HPN fIx-EštjF}Ws,qN^t엻)daR.~_#ڣ D %pSe+Yζls=ά.*yi?mmT[tP'tAm=O=xf nܙh&ApHC-bbf6<)&Cdv'̀8 Vt@9vǃ|{1{83NnPTgKyݬ*.9wI۪tl48װdͺBv:G$u~3wr=hphAM[giۡcarՏ-.v-p4f 9eUxt3x-0GƵٿ1r8LT]~P|*\k~&q*zX, Hz<b.i?6͆PXE|*T:n-4X06^\e[0wƇc-$B ֨snz̨y@d=9+.&UOX(uyi @nrl|蟡t#hmF䦮%z0Y{AIgX:( V!p`)AQP!zlzG'' Z9EKA Sv⓪9I1Y Nk_K6,^Vf{ѵን8rNvY)XA7.#"fmܝ$3ǔq(-:nUm o2oJ99:`)+1D=#i"WDT=NZWzN865dvƒ 7@(:)39f,vaIR A[n 3WY#&x:k̙—cD2| 豁Lb2CҚ  Q=Ϟ\atpFj%X[Vz3&uD}+;L%r$w> GWPs3#\ 原צ4ӈ`Bk{^'5uAfP8.m5c6`)7mDZjAOlVOf畉Y 14FA5tL'=I0;$ wxi{F.QApo5:=NW5uGTzմW}Qb4R׌=M;rPDˈ .L VZ;KchY"$W" j%aN!UE mq@(#>uӟNuGDoOJj2X+cP[I!6+)*C:ae8UhbԐb'm2ec^<\hj`GN4+ y -+7RE ~2|hDԶJZt^ߍCXOK11s_p3 کQtl1Ll-*C0[ad̸& )k`3d[ɋtW| T;%iql3|M[$| 9ӣu Ҝb4zVmA~}\8A2jzdSz.`B>٩7W#ʽl6tnI`}v(kaSN/t,ìmPBT)EIw~(cDcN,xt`}b8r"͑2G_;Fm򙹟tۈ8x&UH3lmTYĬemOk98apoAGS,b8Ǖc5 $϶!:4i+xm6CpPS'mx:N Xv5w7z,jzV82- 4Q-Ti\:B&w&{" `J9@t@ˈ3 i46ПpfĨ8֣p".+QVࠄ֘x79ȹ=_0/ҁbk'cr e8r֚ GQcz1 *AKS#vO- 3j&8U!wҩЍFȢ<;Ӯ ޺qR~a ) OjTÆx}f{̈JD_8di1t T ]fxL솉 ޢ bW4aV,'Jc5n;n!K{ns?Ld?sqdlu$(nM|jj:?n|mf]aۉE7wok>,v@U%aKp$_vMaK?N[H-p39*fxZqQA[l&4n4fbTcs ' 5\pm+Z2S=|lo[RYs=5*퀇v _rANWG|psdìlix#8UNJ\fathbcDtseyJj\}KK6aCjfIBR2͒Nf^z8|QyiT@r'ii4-Oa9'چѨw,Inx8\vUMFoDڈI#x; 3Fm~1 hʼn|(p]p~[h/!ezPjo.˺*4TNZTe<7.pۂm[^YQ67ϱ4RޓĿ c}kh#q^nf=vgXG5iSLT!.;]%SMtdfQ{P^޺l{^uE\#k54G̕Ê7yy ZLd$KxC[-k6W|-&9W'=f.@gt蚌N$ى:ʜ'rr#7gRoJ }n_L"VdhXLdY6"A a(&ss.O P Fqv=BNr"s)vc|N[o2#kЎvY RBB5cIƧH}%9~,udz %f28Fӯ P7[$o3={>/+,^aA5eC, h'ǧ+hgusfIy8ޝȡ$%\ױƏ| Y6ӑ9oPh;AH;6?#ʫUQ<2<%qq("àJ[S OB&(촃Y8&'}&Px_15WRzL qebYd(:Ld(68W[N-5(@4\ hw 3VfD9P ]=v4NXNvFq]uLt8F>ѯHΥdWƔX5xFֺDH$c%?q!ݚd4[&)O|eu9d|ͥ0.w͸X&#bi`8y|=~ݷK?챪k| fZ7x]ܺe^Y$L?~wWŊ1O7'\j9-Y8^(" Ms3ka7N*39X fWaNPsR}E2ފ3d:CUd%0 ]`>DΖMEւ{LN^:C+N],/2QQgd>i!sM6{SgR\Dl{^<=*\=|նm ҧ9m3M[5.Г&c:K[x-kM#Ʉ("rd߰Dx_R@CbY*\MŅBYmFuͪ@>,;gB72ȊFf>r,Ѓ%ZAt%K63ɠ=k50òph},kۙ*n+}Z^-6HO8-OГ\. AuO Ũ`>}mgE-%U.Xzٯ͝ӳZE`$ToHb$Lc٣_$H,Tꜜ=(L톹s}3S1o} [(d~f,`-߇l<WTᅿ~w{, #CX77M CL Pf\oJ+^"ORaLW,ӒOCD޸!K^Fb;fk bsk5 Z!D%٣Ƚ{=; KA]cեɶФ,{}'SGuw(3t`/KfHiBuXwQ >l绝7K\p?P&|B{1O^Kd-ǭ cs̕myU9 ) 5b>4x<ŋ.]^/~?\_O䩌Pߛ*ֽa/I]C"EnY|frkZзg",n(3!T/hd& ]$f3(y9~ߤ5>~k6e/:럱uCaݐ'[qzp #W>45!ண*)Ukrn[v4q,U<7W(B_ekdjtrP]~[I\g?o>ZT.-vCuf[-V|í&IkdZ.BYCa>|dg*kDj[.*hG:9 9%ͽ4vAsFj,;K{=d`=|S'w^Ԓ.K}a<~~]qFKw(ka?IeQl*3(پ9߯/]"J"Ή*O3QϘЈ&١v^Yז,puS)S#Sw=>GЧ6 ~e=tzk)F> q5;_jJ/t*!>Z^Tp#-E+u] fp*7c5iF$w^-Z-?݆2%dwS\U!E{v25[^Qft}5]s}|LCf) j1NOnWi>yDRIjsݡ7֪Nq|% sãwL!c}JmH[wu,pD0W#f5A7O^gĜ« @}xt5y> f]akd;cm-+xZ0LOWr&q! Vu7=9˧T;tGxWgxxN#$Š 4B r<}mWNfۮtfne"5U5nO/O#͈/o~^c~}_eg!Bd7xZvaaG-'Pޖ6h)4*2 'D=Ș -|@7\6#H QW!4KrbGk)Y=2IGfh2>?&MJ2f* :r$jLL$:wV~O_]*Yk`rp#1^~vLQ-oAm_c3>_= \T/W ¼2unvɟL"߼ljR?q6sDX1cT9sLNsjZ"b=фćXB~0X_,r f/wR+ ,yJa2׶faV-U8+MN$7Ul {\"F㷾l`{OVv}dr(,,v0긅.JtZd0j _3pݱ,fv9GܻHeWvb^H̱"D)YFeAz9ZXdY&e--\^{9D9CYc*} r 6k-"$t\DI_qOvs6,C|E%u+%^ms:L8K0#JetL.ngIlP 1xW8E=~w ,09δ8^XH2'Fs`UƢOJEdȔ\<aC/IolFO6 GcUg:Z< E}OJ-cU16W63ɲ۲P9{6!uXv_1$Վw &ZrڳJ"I21P=7""AL.ջwFi`R|by>zdz}?[W>e9.-J5.\&? i$޳b JϮV*sF@4\w1,qyv+ .|̌YWcUk{;~?ߎ7\#/9cz'C]whi9w+GjΜs"\s8ITSh탦PWjK* JNV⮛w+iS/SqZ=aպDw໭׸Uetˬ#CVƼBlu%mn~ĸdxouUzG|F:n<0bE{9&UB}aNEG%Mgګ g} p ۫y~X-y4WԤnґVJ5Fe"C;og7whiqѬ f>fˬ#+dϑ[ CyL՟|MĿf½N9)xb:ln{{er_Gk@L]"Tg!2U\VGeqdj4s@+:!)miµ뙤@y<+Յ4an҄wkKھU| g{x2[ȢBO0q|ז< Jv 1鿜woKu.Mi.̎& r0I  '4MIIX)zIT^ <vO֮d_8u!1#m8ˊ~ o^7Ypab鹚}k/ BU>!laekg1ȂRC-8$IlRSyM7#jIfp9>u<߽N}r+ t韹t2h;H| cء5@kh*~p,~§ݽ tОη3eGS.BO @g$Loaf9ݖ`LM aMUHwUy|(fe -"<&° J]uInk|sH.}V/:Ml%qI9/ѻta=-19-<7"wIQ&WkFA Ato\$,/- Ep$}%i,Sm/uZ RhfMSnDJCy*Mu(wV|6Lˇ_K}EYGK eYTiGSQmV$?kY6wUy:ܳJ->#u([`-ֿ񵏕+p[H˵14['Oy lP @znf|NEugDP2y|Xy?x漍ƥ[l/LW T3xv2CVGPYc0`AT>쉼R8Ju.N3,ᴨy+q\VX7Z5Ԩ4O|B>RaqtD|j%U=rj緘/<}S6|UZB2@3uX36KMaAtN,:q˄NJpS~ꛫ y i { 5!Y{Qh@k`a_I%r !/PR0\2#bQK;>jW[MO}lvb *tXe׀6em%p`nM+ˢéC&VKʲ &)o &;+&Fz>(e -Q;ygjflo>5j h0)sͪGH#͗0vve(>RʷܘԎhO l &~i,s"۳=zlL򒲵vȭ#-#)Cp$u*@(wnp WO*~'{R47+VC ?>jQs)e5>$QFqʸ]fǸ.BUQj!E􌚄F5LZph$= I<:q5pI9TpwIW`HagIYpSq: 50Q6ԟ>vUO5u7)6jcM>"=BCcoS,cdl'$㤢4UnGg!Uc0ϷV^^t|Y  aualq0HU65mAPFRO}&w)|/?9_??qg% ͙hM$$yH=θ!Ӕ/TIjLӁԭ<cU7Jq5b&NB^%*Ymu$hѐ*K@7[ (bem}Ԉ`w}X= vwҳ<]o*`YINR7ٹ?g@=aOZ9`6\06QL>RS}Bpfbj^4 ӵKo6=fBH:#8? uR?"^b Jѿ-)ߌuzusc 92[تn 5ʑ7́ۙDU]7LKby7?Y8ŧXΉt5}Io4NK2Jrn 0i@؊/({TV*ԣ fNSsvZ<؜EMylyR4qXȳj}nٓo?m|x7du≯'+I@+ UHx+YGTɓA^+cUp2*p+ʺz&[D/q@< C^[p,Fqv~ k0/i=l6wfYCr%5l`*ؐTwATM3*hӐFto]dHi3Wty|'ˆ}?~_>g+׿?_/{˓w?GT~?GϗﭣMߠ|{ Kٵs:0Ԕjե 3j@ vΪ[]GGh6#nM!7#[ Ց[d_ja<~T6u 8$8 ~ڠOG{ r%Qhte>4Y8~y$3G0-!ќ̀B뼺mM\Gpu]wESzN0_C Y9n2a¢iuazJ5WyaYm` ل!6 أV .T^"l2/LYmMP:aWDWX愜[jA~Obi[$T+CǪZ4l$/t$h7U0zWP tرj{.i-aiI*VS=3.F_XcU &ȰGGD?55=Zqoe|+1LXe\tbW#/d qJf;Tbӑm H۴H)Srt3#WB{[,p{a}t:lF!Ej1, 1˼@=J<ȩTZJ1C"8NiqN^Aϧ!́d1rGC%+1>&΄(9K~{F$#_&6m֔{V% !'ö`ye<.JOP%Cg[Dk]g{AYYlDBbVt%%yeۙl2>jߖ[F.9 U!kWqʸg DcKk[}f”Y^wvg9QBM[o)>K25|,MﵩOkvCžrTK(\x,";OT7̑:;@TBTJ0`,M =%l$I'VGO^-yy>e p#FíI[idhk94"O\ZUh+;KDj_tLƝS/Ʌﭫvw)d M,ޝMS1o"LҝԌ*S LlT(!:nJJ3o0&3xdR>ri5gAG\!Q8+dzkQ/w-[ Rz~?NL#{WqƏZ1dt LpCXD|bks "ڙR?E| eqWl#%e?9HIk7>jGH9tdS )~>%;L5 f7dO}([Ů| =A]o#S{%D17_Хuv1aUS&4Zo*_bi[_[e5uƩ]Ž;f֠d[{RVsq7GdD<{ kdSTb*2:Ul3lDZ Z B>c1M`3nLz mD<__no/5%]s$\ȴbdp:^kVpz1#&)T mftwwʉݽitԕ}!wU,^c Aay2H jӝ64-;;}J[<'4{"/=k/w o>sM}O_9=#n-+0#jinvY,\_Y3cءqHL|*l>v&ƪ=!M;f'bMS^Ӣpn,-(G@L~5Y@mrXUy+ =U}aU&sK=-UW"s5-9đi᜞xXXl@sX<cl-$S5m߅dz}Y}_G芿J8k|k=̐$1Wр]D^uJPÇcz-b6_f򧞴9%9hזlOXLMް|FܐsKWN|B{~C+JNuw~l^~l!h`?-SPz3k5pKx}$Y]3nӌ35m_ѠѪSnXTpHʬ OkR~a"?[ҕḊ -APFrota zB2q': 2+CNg}1q,jݣ?G?TS+֜'dPKC;9%zAs![-F7G F+uPB0"nÍZ5'QKJw^WFf ?[5BxT a;'JĮ7b{|Un9y݁ne빙o^5)뱈_&4qz,X}DğD:FAPݏlK8 XlvX8{Cj,CAEV"y̵qg |=̟Dz''O!QF{R2{Q4 '542W{tnf,mΈL4P^)ux> PjGZ-8)|@Qί~,g>gSZxF})tZjҷ۝ԇ$AlJ_n0T-A%JI}g ˸*JKf9NyFy|3WpEKxXy3G_2<\dY[7+]pr B89򑝎Uy\Jv^&"WBa7UXV:#4lF+"U_p+-KTp) icwt3>dV[Oz ~ym{ix*ё-$0tIgX}TD2,ͱ>>uV"ұɁjH_Haf}܃mk&p9SQk+$ qrFR1H[i mJ/}O!sኸh"8Y&Hj0fC.?Byu1Gj!֓t 8qq!ߤWӳ]վKj ? z`kT GH땋VeL|6}ŖZZ~+Ɠ4OmCz_9yCzu+bRa,Ӷ[ПIO5"?_ڇS`3۶F5rgԽ *ҔNVDF6vvdVnu[;)sAj"Z T0uCvhd?҈؀[JPc)xhdWh]38 Q@4"b:^D`Ygt,gjsg Qjr@B4|ùVΞ;5_\@ vN0Ms h\HQXE>Jh=~tbL#$G3@lة#c( o9m7Ǹ.qg@Uי&^2cB&k$ݚ-ǃm e@4ǣl_6?}faxLЛL2p&usX Ԭ)VuaՃLv13VȂ Կ=F5B涯yFYxӽ83'"\Jv8q>YɃn-v&Pr95bEՍJϚnuR X_#)FbȀ)!QffszDz";0tևկ,r:-k{6x#2 0L*:y >lEzi hknҏgW3 F.0̺[tdg ]n@fL-#ڇfM7tkxfy{5'?^|[aZ-Hy&] .g=dj1/BK}=r0b_#/_ـ SH:J7^i/ӈ{gN<㍧4S}ҟ Q==n tc-laӳΒ0=nrh]H 3 @3Nu[%nnpQ\O .QWX(ˀ=\ۋhvcC>>aok;e4!ex ֧e/&?k#Kp0{cEymC.{>tsL_π`F:ix^x^Wpg}nh,X1|˄5,1j_廾+K>pC(> )xIk-{__V sNj{qQ3PQ#WhӭUDvt5 n!aDӠy ,:c8A(ځdPJzi9#4xeӤIa1 ^(f$ܞiԢ1vE,6-o֫Ns IF wF|GY*E'b-͌i϶b[j1M6-YPuYE KqYCTN?ϖ|4Wi ~!7W;BN=~dEӐp2fK89Hp<Aڑw pSF hNGq΀*QmHTK١WXw=wS`zCTcBK F4h+KPHܝhbzY[58zB ?эtAhԈX񡛭n=B`_?*qfHFQay.zW'ilz9.RfX?ϼuk.^KXw7o[iS8Krpv Q*^tY)>tHa~#L1̄9ΦkTp Aw0+2;wf'َ$$>ҳmh}PI1RE^0+ xYSCJg#]ABğ9v_RC[|O`grC -Fa hˍm~->ƌQ%Ayc!#`lm5)L&GK,x~kdeC9>_A @$сօ)Ъt*\'Ŭc?=aB$( 2f7g, )b2B'ۖF*6piFۈTAFfj3㓃.#;}JapzW @3`}? s[vOL(RnH?ҴuB; =wX-?͝unrx[p ؔƫW>a>3JW׵ĖWMwQO;H'UCNhy0[p(6#JͤU8?#TM<y>=gѻ2U5;-?34ZH3kypUip֭'D|#{mVqyry4ؔNn ֍@?8.FD5p1 L_p SZe]n, =%vn(Y;ghAKx0ua^C٢+widఀjv:x}_H:0/z=-N~Og.N J'2\hͷXg*E13w~Ex]&`pC^@tV?͋#..G~? }A*Abc9YҾp ,$ރE9ͮ\mJMԷ/ԀTW!W!0Ի#">f,zv+11WȘ .4ex 5iV@H/p<@]=QL0|Gy:h53DZܞ/OV ݒh]ZHv N1x28M]ƊCOBx<=7'XP@OKuZ[3/,* @eph)aQ!:|H]`mY5˼KvL۾ETLnMpI =4&^wMuC>PNO7I#*C ,>m\X= @{5n)Oh#N` 7W\9{CvԻ>Hۤ;qEGSɸP-]U"vFc7u/W'N!V8ra|˦vKx 0NRNv?Zlj]Œ,g7K[*zb!E_ 7~Ė<EZKk (8;fcS=%1-wZ4gZ+BC. .@)W=urSakdm^h.qﶬGML3+5͇D{1i_& Aӭ5qqZNRMCJ.zljΆxR߫!VtZg_캳 ,9iȗצ' l#//@EY7gؿX/I>QCbvemTЏͧ`/[sj1Kd}pϷ,9xKT+0 }W{yJt8^c8(2c4`; 5=C-7N/ހb7t6 x*'z^pܴ3 qZQ~3~DpO_/۟0O~zN#@;=γ_dg]AČ}E Lqh8 "q6&{ÛqK&ݚ%yE/gyq<DE/ ͏[8M4T1[xHCܦFgǸAGc `?Wc4d܅m&ynFblBxkב C%Csq@"]7uoVZ;^z)*ԻsN {Ls hkv> VkSUbF7?D4i쾢L_q1"W ei,W㶲18X]k33w9Ѝ/6uNH(R42EVj>Y0KO/ :_Q[Ւ}")"[%@=g~b_^}xR`j{|OC%Ae1E Y8ɭ|Pv9jsf|lnRTHXz,kMqGtPǏ+ԕnM; Nl1\=NۼZtf@GHZa[fyp@[ΛvT@ӱavt[qٚ&@=X*+rz+NM#fɱ-@p4ʽ}8v]nZ$dW`{WIޣQayuku6Ɵ.h;qDHM]:eS~wx}F }얅>}:*?]oByRՀkX+E8{\S@u^z"|/Q \7e?`46gʈhq%ͲQ>u,f)0-5\zDVue&bbҮd`ԪY9 *wb*d'ش*&h ǘlVp;)34QPF-\ClՄhV~<_G#YAfA[?}vJYc&,T )'As/8c1L\f{^aZGa+UR2x'>6p n9ޛ^h<\ zx#: g5ʝRi%E(:7 SLKo<JC>dSA~~)'4l .$BڱiUz;}կ=f\=WqȐm5%:EAD4Yqxv<{OnjFZk#ZL,:Ϟ[znXA-aȤ3e=p8:B̷vfqu8AjѦnQ6B ǹģ-rɼ兘2]-S N85:1_ n0&2 7 xLv 6Vm^љ'׏Cp/jF}$"-S0`xn_[mvZN %n^跦;u?D4fzV kxxSô=d=}V?O6~#qg<\ϸ.h%cFonǘߘF~8McC8c8"kx=*h̯C (fSX=]0x)i^vtCIzX=a #f=wb`N0§y7r9? K/p8FLjjOE2 Znmh iTWZ- /VC,MAʖ՛'&jdI3nsNGsК3֤*pT )*^.qԥßc@^h)>I X;w#vz4gS`*YBl(p9 q%lf*^ #6L !+S;:[اs~u9S=egx6G NUkѝ.S!k8Vw݈qkh J} Y{(x9|E)kV~SWwߝ*jgO4/(\._vkoex[9Np3C2֮h<6.TNɜrK~t9܃}~r {xqUy0uq3~f\?R(]mWDQ!xOWĔY{Ͳ=iÆ>b)A{L_1tjyp~$3w>Er4;mfȣk~G~07Z|1 .67hD+77UPi~4'?"!-_rs=oY~htxU̝].dGF4сu/u F_޷6,וxJ(T؄`QUy UM%4gdyAV=#w-ɫ„DV8ĄF MP]Lv 0uWDGdFl"J[Ap3[Ua/(*f pMm`o=G,c{o5t#6"dj]3H+R]Jb5C'7F%p.{…* H ,,t:j{0ڊM-i!mq9P)row:,gW sOUF2Z$z>;Y|f(gۻJA*-+ilOlhΰgv-Wp"o쓛iH!mLy ̙ #N[7Q6O>%]ngə;a~ٸmm0ats"s6"ar}nx5Y? Kw>ϧi *[]#BȚ{x"8afHǹB"/|u 3W6ӣp z%uꇣ>9eyZ綏RHqT5tmAx[S{UQ6"Uk$8&Gs :w#ɦ#W=E>n0W `Q稭^ߗ֝KyUS`ԓmjxo¹8CIZuq~d3#M]Gѝ_^bY7z]\*Nױ]N7Sj3 f@(YV*}⥝qZ0:vA4x\ܛ جk,T+)2Չ'fdВXʈTiF us@ͲPX5~ѻ, :0a_U՟-'~?קGƓW+vGN}x(b0E]4|B'$x8QL?c=<7=2 be~J,+IDhu]~STTN@g.!SRB"k }dpyNzWo\|fѣIDEE3;^5x`Σ%ewa0/[?8 8 ["﷤_9Ͷ5(Z~Vts<pxEt[\ qKR43hi4  #A~Fcį! cZ ThRCҔI0sTV ^2UgHL'M2NellDұPڪ9vj[,d7z=Uclֆ-o=8wҸ!wc^Bgu*퉙KM Z>[r0)[l-vǺwfJx!Dp{b~Fy;Lg^?r-^3l-\@nA- !Z:SX4O ۱O_>徢O2uji*Y{;M)^vLxAtk猧8M>2{`Pҡ`eY2Ja?H{p\h퐀~ޮ.P(ZՒg2>bsߛơ.&HW_PDK(W[%(#҆YJ!dTA:GELq +=[}m~: ?m6 +`?4BD; /Q̥H 4ey:_X,." Q;=U,b;ҕF9<}wu (9fNpKT~3pD3Ӹʗ-Dx*5z&E{̔Vj2[=; [ #`y*"r!ٲEﺍB^{aR {tT5UKA ͫ9*JB݃~PRʱ15ӚpDuZVMKwk㺦n85>K .o,1HGfXYT_D~^ȢZ25p25o^[ +4LdL q|i{Cydי྄<],5˰#|LLe9EX/=pQBYd<J,w;b830}g^EcQ[&NkhO{Ydb ]_j6d۶ *ЃWN9;|dܽix2V԰rGX.dƁF 6@ !1iTjf\hč0hiP%eʦS4sӍtk[ ND {Nni_??lPPF<s2UcaFT %p_c6Q\XmWp0(a,ͥN/CQSQ0`ԛV:F}XJ׏Dԋ/s kmKqNb ߙK _(i}/Ce|kaJOޞf`K'@,n @>NYu}:|X*"׎Q%G4(7A8}ybWW㯘y`Aime=`rIPi8yX+5=_W_ήLF2?{$`.l?+ 5#/\!o;XNuZ~P]%۽insGpdV8٘@{K=%E1JP8bt ee{>5\]{zӕyrc!!,f|zNڪx6 FRYSLC *(Og1 2b:ݫ@qNb*$z'(XsY_C@|H,oS eNo/e~|8`nLHss4ۄ y5_F2SɬM~d{mOVaHJ!TQ"ez|K> u0^f|CXc,KJhXndjAs+Gbŧ2Q_Wq5,5Fu^˞[,fhWjaٜf=~Ujwk5&ښ;êpx4 9^?qxH>YߞԬIaGm@&$T]y =rm93朤RPygAͲ.#,~Q5.T'&j"L:M=XpPKYqwDTZ7 Z~nw y KX8-{7'"(\IxLəf"?!nwle F 3vvlN@PȂܡ0s ">SN$s݁^~:Mt*7}Ѭ$~9}I{6:"%N8Իͼ&P԰7tEQFhNj~hr˛6c/^bk[7mɵ|4?ds^h|(N:QJVCs\;Ӛe B"_7>7] 7EC:pj"bξ꿼`PK2?%b.§B-ᯟńTEC*~b]w{/ρapb0GIiz^=>i{?ٞ!^,[hWyFAU:1^Mx`ޟ=ܭA{l)i{ ZSi gZyNOÑ^sR7%H_y=;p'م ц81W0@/ѻPKAޕ8kHcR p< ZOh[؅&.Iٚ/0eHe=䓬_DžڌMEO~>ٿkOV[,/-a۱/! freվ[&nW'5 #Q Ϻw(}4=/Pj^. ۉʪGȖ^^gZk.=tZ5WjjMxNU":S}:"VWCHøapՀ pcLHЩk9΁+ AY>e`Xú6>Ÿ&%B&haV7׶$>EG7|(ʭH^e^[W @7)z㸱hħln1`ᘬpoWR_5Hqxyn a)KI+p.ϵ[UIiw[,S1l'E:<0=ђD-4OccQsTbotfu+jz ?ʠg5f%fZ# A]F#øOEu4m#(z^Ep9~Ya6JvpJfX3S-6UM p~\zՎ隞>ry]\ + ߱/1:ŋ0,'NB^&5|7mp12cMGTQ p`^l a!;v.3Lɟ &{ wl]iFL,6.GœN"'fd2<ذa#Z@O} 9 ytk(8&Ŵlij?BpN5a-+t7aS clC [/~k]}F2hP]N[h]-#"BaY81;r}~aS8K&Z4ӡ@faڌ9xetb"W'1EK8$w*>ܦ)A0b ;.ːZ;4jm,k74vK%g=pohi;ds6Fyû3Ԇi01MnO v"aX&Q~Q_bn׈4kKAaeEn ZBYpF <*(ZjKqp= 5AG9bRtk>SlvQ,FueG0ޖ9:&QBlJ411txSbZY~j][xk#Z$&bKw&b11Xێ`Fq4Yo#70Ag4\jv-{ȕvR7XO du-$cJ &oVJz~$ȪΔǛ~=G$fiZDY9QCWA}vD֝SoCi}a+ڮݍ؈0o%bdhw725q@Ƀ;qyģWf,QzVEwqFwϬ|ʫ sMS-ls0Hq-Nk&Hy+<_R $nog;A\ѾᢦۧH51}a*wn "|Dh68Z22QZY;=T%dW DG@~,bmfΏ`?u[VɵЦj:c[']dYݢẂ޼J.W~֠% DlmhLQ.WV=^c bk$N/W &dz`:'0]T,nF$XZ-ik5XX.7IC^p]TZt VU NP0VQ ]Zx!/DV[ Q,V[JT7k;~8%M)~gcnNxd]fw}YƼԨڧiN sIQsy~ -`h2ޑ@y\idZ{p]ܷ<i4L{GZ\ۍTw3Җ* ?G>㗀4ܔXT[g3~;s{6lq,rVyJ0QbdZZb=r !%zJmp-_뜎B*nǟ43u6 "fom=򫄟n{pJeCO6A3yV} GiSKkۚ~"ݙCH9P_C?_]%[325K:S2 d-`H'v+j׻ԆxYHڜ0N~QٙU^G"sGo^2ݘa(1uu5a9E'g'M,HU/@IQ %>O+ KN}#-i2J[?n#-Hl9T99[aNo! HSMǢȯ`QWᩃDj -d+4B}_aE&*ummq~%9:hks?l `DZki L$ /Ŷcm,G-)Gl.5o.og+ =j9 kJOcy|r6>F=0LZ0yCGy]/hZ }'0?DF^ۇ!NhH zg,fx$|ŊM9)]A5l:OsSWŻ;ͱ4+s:Md0G]?LBn Qiƚ>ܨ±$)#:df5,O^JBIGɊQ=Q->o <>07z,ϽTֵ5Qw4%rLWn9cyIxU ` Z GcPMnp.~>`ٓCNBj-|EWZ<#0uxZ< Fh&&DĆxoq5ECc$i )=/&ஆ!L mLL%-M!ΎgGhK{Ż9(#?]x=رBqfq,HUbMϬߥ)zٗqmg`TzܕjQo@LZ㹒ebNTqV\uС]Q6l@ Gjklq-^}jha9E^cRymh!s͐%)pߖ^ޚaH*_1h3N;S$E`#*b>`ѱqWc "bkۘu‘1Z%Vpی*7`P9ٖOkDRܰx#fvnv`(eKE#3"p^~5w~#ژCxOs 14"2m+ xsf|Ы [vX6EL GMŸQrH$>AJf:HǏta1ܳ)e0h..TRq*0CiϏVB91 5b/x` h]l/7ct9Gr-±iCRFrwxlw3/Eа}*O˶^C^>"j!XulW ,W-pW;0S =r#:lG\ʮ0ɽ3OE_˫^%Q?6 UOʱ檼8J09MĐ~y_?[[6Z}V w9@\f c_k3\ZeݞLL KUwkШTZA}kT-rrjg"yN,mx'apjaAs|GZ7 ӉS CaZ'AXd1 ,*jW{qi&_ $l"ǩkѧ.7ceL`/*G6c~>훧1]nǯZ0:xcB|?v[Sc݉b)qC_vAk SօK=٥*-0=8Kd|9¢9m)-@htjр6Ɲk]i-l] _ngJKO Kl^B%E kX;'4R34P\sFx1Mx80uj;ң~=Gpre]ilq ݪ$ze+&@^e{WDzVqfFKvTc=9g5 I8\7N$\? [*I. 2 P@@̩OQ/q!5Fb+ݓv|%)ڨ6+}\t}5&VCa#fӯ.bg3Y yVW9ωuᄃ7oK}j)>jv%p-p`;4(-$s4-@XZ+ 4 oxBi.PAO'Z{(=@di@pk5NNף'2iԑ7?h׏F aHgnTʸ9c8|=ScGNxS&\ןEoysЪKb*![{ҝ gXr|[kltW{Y~u{~"a-Vԅ|+>M<@X<)1"MP >SUY m$jۯy_s^܉a>%Stky BIZ~ocj k)]Y ԵZ=*\s[9}3^ D] _>S% ,6ãgJJӘZ, B#msV=Mf&Gam"\&@‹'P{y ?"h,O(jx2xN"_[ۇ όӟ oF+۴p }F wB180 (t yp]`>oMܙ<ߘG'22W>  /H0݂Ohǹ]cAu'_ YY)I5ߌ/qVZP2}Ou=/ (bxIdr[<>*Єc܍WsW P.ͣtUΡMǩ˙(6WY !$ۋ,^`a"^w9wfIҭzE>P3!rF?mlBL;b1oZ>M~]͖@168Mj59S]|Chco=G1ǽ1loE$DC40O{Me;Ý.PӰ 2?Q̧-"A\w]丮^}׺a+? 4ac0>k}kgU 0ՠLNؔ4Ϝ{u!n6jǮW{e-۫uݤ/m343fԃHN[-E ad'!**&53{6193ǟR;SO_Qo!,\!m9Wt}#/*V mF^#|)kzE3&`Pee0$&԰@}C !vm'ڍ:y)>cǮ=VFR^#6u]|;#NNԫ)qz1zfYlr6{mz#RF+cw/&ϯy ҾPr=4#Ƀud-:h- ZDF fӋT,gb={WMU]rSYTȵ/ TǕ@F4A>SD?:U3ZR;aė xGfBW!&tN_m "tc uVOÓeig3@ve,*:gff]s%HvQ +emfy;Kz01ï," Y{Zf%c}8?d:?p˧e:xc}L(Qb6C_IzSɽ`%;d*?`=sTnCp|T,_v7UC"m>*EAaFyILh o|-ySVܾs{"hL_BGQ\ְ}spUK*"ĦZpԞ!ǴUD2ID)-+1Fr=3\_O^Yet.x#f4t[nmSÃf:|mCMM. 'i&M"FANDP"j=d$ ^3>Ru.AZ%lر UV-ӸދprM* WN7]8XZ$ACVa_;/-0HƇZPG|'{z~Z<|?_l-xwǣ9碈~B`j w 9"Qk_elZxXVVHvصPEh:9-d` Y5MuT0@R:7A;l&y82xHވLjX+I`pWvEbyG8%S}ji€sv 3cyaSAtF2ACMs]D1/ G"b SY X}1y5!YzOEJWf<r#u+țUxq L֥'Ws ]@9.veA oQZ2nvPUT%xҏZTs'e mz.}WQ Sk;YNk.4@C%[Qan&||PR %Dnv-$ QvqwC8Όo̮q:G0+ ,lK|+>WF&G?%au"zw$0X$݀8y qJ),)]}%t^l4ۻ,>$3:;q5#\خBǚbL +F[\fb*y{j7+h4~_de|N:TT, h轄"#F9rkM fsL>c F=wm'@B`rE7&lHNwR3yױ[HT- 3$g vzˆ )鄞v  h#E՞ Qvm'{g0C(#o)5;ۢdIJ'ɵ̶]Ga'gT>rޫdv 6NdیۨTd=6s$ +MV{m4-X|tTݗv']Nz\_j'LP1nYa  hn{>RYRaF b#\[@E 6{`͖?f~q ut/8㈹\԰DEHCVLE 0em|/ 7ϝ+!Bkf!/=huf3Nc:=o}ۏ[W랣Ck"?Ԅ'>uL8 ӤyLd6-*i!F?q Irj|eu/VXu'{ѵ5I9A{G|FBC*|$Ɔ(["2@ _myPNC-EG]O}u;ۘ  ܝL@2J ķi+ #/-ꋣɮϔ,??3jd>^H$ΜEiF]0R[0_1j);e7{} ws* FaEcl!^{;~ y#@:f#T]3(⥑(W߬6h R2r7^:3[ ?ӥ ٝd:5-~^$ + 8rrGլv[9pk#LA* {F\md6nFJq}p%f:f88N^O_g\W{s3τR\8O+ЈO9-wƺ.bxB gVV]|Eb H0"EB/UȝQb0$." Re{ y^-7VТK0:y* 1FǰK4N`wAf|B;,b W䛯h (ZQ}Dokl4I/>ȽZN%\o/vҁܞF DwL}n(FdRPQ9|1>1'<]CK}q5^<\5dre8 *Xx]Ѳ7mDm`s1dr:4Y XAqWc۫X. aK*EH8V&=Ll6G*̍42?[}яl>BD\B1DaO>=i@&t[~Xk6k^u="6wn׃ f:L߹SWCD쩸-/PevNύ0rF#il[uJGs'g0ΣM E‰ 2Нԯa5ڐo]+Cugbs$ {)|0˴`0-bTb)<.ӋӲM;7)pfD]IJECD3FE4gyz:N3P\)OI3d[ݾn&Tv*ceVf7wY()c@mCΰN[L-5 FwgKzSZvTBl!zHg!io{)˓[^yH./,d~bq'YVLǖǠj=l 6޿R\[HS%u#_7/̺FIO&#^4(n #sm*1 4r\F+֞muX󓺯dx0g^3xv+'T0!N{=I ٦A~BSA$RsL+nQz:i=ʰ)MV˿ٔL-V۲ ԄORCE LWK);@ׄ2ިx;k`mOϤ^z= _f ]_nQr4)?kHg0$ .\|H0i]hiK̪wAX{Cqhz4]/PcmQ0OYZ 8$X_eNˮϳ@i6?څ@TCK!w}q@\>#V0ZI Pact,)b2x"[t |[n=^_r:]3%:R'j5w0BpMT~FS$RK]xpM"몼16)YGD-I2'@&39d!5X V*$/@i@[ǓQ SlM8uت %ڷ|q'ۿmС8W#AIffi`DJw EYߍ^m;JsFfaqFk@.6"%'R(I5",y"т/hb=b8#֔Kc";,ͷXXᰄHlQNq`Ufn#ƘKhwhܷS-GD5or" ! Zm*A'4!C-'7[:9@Fdl8{h#Q! ٰ}T@lypzEUww1?;^{_Y}5AM\ڟ62mJNݦls۴ /LA<>p}A^Hr]٨ S4)^zb;/+I!~u(D@5(ִP{OmǶ3=.U !՟jGDK=s!>F*@x7k1Og|Lbx䂜'nq@ǓYߦnGj=Ǥ?2ՁK^ψlҠ*ex0hpS%Zm}l>&d|1>dx}~ն{6:q˖a8L5tP51Pn:&Z1}2X2P"߰cHv#tԀr,_ LE-CRmHD\2 3V9,2iX;gta~|{Y&5b(-Bf m*\ Ek0f@,9fLaQ=n9ǡcQa0/xr\cݧs`) '] jE<čI7Qo sT#tMYF(܆X:,N ökڜ`iDz+.Q24sARnغ4& 53װKO&p{{1M>S kE.}ro{OE2TmsL$Z)b!ds>=ʥ(2PPp)t(_qw j$094kJa0%Bf0 E`;.jÚ ۈEqV"޶%?+<^cvs.ڎ"3ΤA W]`'a/F)2߰JI/!֐ YMmr֛ˢ΢CWʰgV՘m]tryzC2oI0Nʫ 'yR1~AȶJ ~B3 YlnD yE6vt7IBKۚY.Tv}k| TeNa4s4kN| X`{8^pL&*IviF6 mXjҌ6$A eV^~ jaV:3в Nr<%\mj֫-^ ə6)p3x3`mO>z3IXE$}5]1#׷z@u9vltRȃ‡ 7@-*jME&K^$:}t:&ƷH%eqCrbކMGF;Zib2R90ҥD8~Ů<ys)ă!/CԈʘn f` 7%*Sr e6jY͊m+-lXןq_lytGVd390Pš(:4jq c:'\PL2;ݵa <؉.o@dO, m|h~操eZ:2g"YY;޾_G*lvŃ_qz5lȔ-K@JT ܯ3&Ƌm(\cFiK"}V3›}y` lz,Tpɖh5##νiD֓$~VCfmҎIP=ja]la6}!svkHx#'3/樶zDK V*n6e@dc::l7͆Cixńū}0{4X{ z# 1|hro=x~8!mˤ9B􀠌4e,V$yf`՘qA4̉.,̷8W)AWz}b]`;xKXUrΎU~lXP'on)>ik@ɣKGB|'U_{NoW(3ӓ ߔ gt޶%rmN`ٽUL[g0?c9a HP5{Nu߄~<հv7QҚtw䶎d.ֱ/E|Ri/9+)U)P SAjvkQR'i9]QH" l#*=، ~Nz>]*e=Ռs:8:0#5}G1:PX n8 >gpݳ\;mW>?sGp^fHO&ie7و$&M4e9O9CX;-;BLyXz\%#(zbhI?!ouj-+s NE5&Fg@1` 9z(<͖M`T̜X 4g2]izL̍K/ƚYKAeLvۻ2ce)!?!a u<}LŽb, e D IgJ%@9.v+Qػ4)#GK92.Z3 +'HO,kC(YbN٣Q3,x#Rď |*,Q+8簟$ ͋!U268 M.p3$')(I(g>#DG4t'l:-|%FGQ*p +y'l (Zqw%Hz,#JbR򊼁 kr$%$;'YNj.{{?}Ow?}Sϲǒ69b\BDd^E.oܤJ.l8 SyC P]T*IvF|1e42Q\_L8W|\J&l`Bvfcz~![v փ;;z^~ \G1'ƘD0i}3fFk vjxطFuT-yglnHx/wCݖ׈uh-iPnCxLޔ 3R WZ` |{ⓇM~*K]5$DagJ;́'ά6WQ `Fr~tj&p/NMH>r &&1~̑f>;M/QB*JC N놽Ji4tsuFDQ"4mRD3vB-UPxs'OC~~!k: xH͸ a⅋k:_,8I.۳rҞyc} 7ȎZ5C8f?j[B330quygqAg1fzlñ SS7npzlΟ)g CofE/+L=+>)NS9Yeׄ1AU?n ^mzluo6Kl [0T̕#a 7aK}6j8 Q:>|nON f=`T3vWxQEYTGGM.͎[%4&8M Ql%1ubk-FPA4{&Y0!X_14o`+(o*4]X_1 >qr οR#W#X`זR]f~)ihJ,YdEmƷK"pҴ/V"lN|%aWZ69)A4\+$uqVQ ,㕘b56OA($ZhQ!:ƘV=G0U.*uRXų要YWk^x|t)d57R ZHHHU&. Qܳ{BM&9X??RIV{euw~"\RK •Q\?PPRIHB2]KJ"XX`PljM~]c%]8d3TB03j=E}o 13XVqe#!Z@aNFF=u"}#ƟI.6Yh{D53͈4/N,FtQlGB/J6stغDZ)p@ENL4LhfokbTq9S`:gvCK gsNEeB۞C+Ok.:wbjs0A뛆N)z A9CW icgI;ӢZ $SIU{B0마W fM5Ë9Z+`h,`6Y Ci2"n .== J@s~Q:Gxzx(o%㵽l[Dϸ%Rc"TfyU4N| X2ײyx梭 VunY qvhi.|fU$ i0C>C:e}vuk6}c )U@٨' 0ĉ(hJXϚ2c߿[!cCܢv\İxp:8mC۵wѦƼZBXMκvҕ9y Sq䙐Lu*Nj_FO_ 4# 2Bp?JM'ɣ pVJ;FP6e<0&7>֙OFU?;&h7}E A;Zv=)|~\lM`HK^0q.ONK'z&bT vDp쾴ok'p:j`GXάF zbp(D`% L nt04t틹$i2/ƼBI9!bpw(UGPP( B.z}}-,@] Ȅ}Q .2sD‚|)ȶ5V@8m/i[ދ : g4ngR$e2:YRU5l "/m[<<8bjbnJ,-hz!ng. /.S:6f E0%@@HHJv|ꪳjMD.;l 9Cv E<45bt\}SBɅ+pf:|y^l$W)r~!PJ Y;;)mNRY=_+Pbh(xEv?ŏ0T{SN E(c wXti^T$-VjAȖe -Q" 1{)^lA*#ʓ\m̔VKn@&8*QO * Wo`T.d[yzl-Z娯پq'wuR[?iR̡>¬Ωco"|͉qW]F0+^ُ9&W݀6']6]+q7?}s7w}so~:>M$u>|(49TХogTsJwu$#8\)w3Tda`zz(XjoeGū "Ո+! #vb(*o|oNM Dd[;jm<wrT0}H(0q4Ҳ) M-a NbvvA2}]1\ ,G ѦV+[C):^a0 X(ǐa+va bT֭aMl>lWA` vt6k8R Ka?dNf3a;Pzrv0!v. 8LmRbØ5fڊE LUo39.`ݑ7̵i@pXuj~b5`^Y/$$0["-=lXzzX>֥eV v/pRvKi8:  &0I niۣ-0AKC5= cӇ/>\g.Ý2V V(4E*<,w۝] S߱uiXa9moU_PqfBk+m$F#n2#B>"G;@)=(&YYQݲ}~A2cv4a\9Rs)Q%ښDj=i_Rg!U1Jd:X&aA;[qA2knʺx18T՗LtEIN{M'=.ͱ#G]$hjao"rKSnP[7HQSZVSY\a@3UoQ3e5#0N؊rd )[ y;0y:Mow2!٦24326"hQ{|tG̠mPfw=1m_aM3v bA) ؛rA֎6UEW'P^[ AHsf~-,Caaɯ/x⪟k:.tq=Z,_"'XUNc_o&n2+:lv!`D6|8hN"u}u=@ 40KWd)JŸ{%e `5/͂iA+˃AͳWdv7ZU>x1F?8 8t#8c`p4xlnL&SUխٮq(|vUn"+LQk^ŚPRɿB7eqӕU,ew2FnxKh+q 9e8Dgl"# z頺GaFRXGxt^;ҴøPjI7 2FEPo-'bQ(1M ~\  (u5[Qb[+=t9Gy񈏤hjT2Z}s)N$[7G›>@XxJ 929ҙ%HVns<%Kb2!`/#FIy@jVP-]lSϡX>^gv^W }w.{Ѡv#߭w.DŽ;oy/iW4ҩDN`g4bnG u鄂X .p2oVRhI 6H1)Vb0 u]ϩ4-㨘Yf >y^zJgzmdnU>s1]a_ {.a¿ݜ !6@L2Ei\*q"|Wz4*8_YZFWbvf۠'sϼ&8z=X/< ;$fod9!FճeҎm AT%C }ШYқt.,Hz+c{%NZ43+BYRMTFքJ(*V eCDፒΌRW|u9q>/Z-0rʾEAgɈTP*a;vh&$tfpE0B TUo l4v7kJS?kUl?kX`TXϮsusk94yXt߻jC(\q1'A$x$;TW(Y؊ &j=fK0h1FA-&y"jVoa #6/\~e$.gT+uRSI?NUDⅦT!ͱ *^v!")>1EVS s;!hPr Ґ]:Z'\[y=0zՎ#ȮŃKQ0{8@:U/ #*Pl.Y@fz c0nu`LY-0r}tP32U7^DZ%҃?nz[w;;3K0r ;-xHglDA@*tP\!1 Ba\mTc*ߡ2y"l6"r%*Uk+#l75v*)7{:;,R(w+OYcnBCMN4sQ-ݡIi7Ý[2j Vۑr#{NNE hBP)L+xm3CBS2aXkj@e =8d <@<{FY橔 !ӷ+WìAjӳs3fF|O8qL4?D,EMd#][\PNpCk<\u^X,RK9)FSͫ @ 85Dѕ06\6 YUiڱ9[#I\pRQLG''own*pI.=#HuU}"!Uu|WJjtu Pz _* fJ`HLfp,.X}ޝAINf -@JYp2n1u=i|BX=^RC-XJB\r݆NħҀ"wҞ]MTTuvnL9 ='?`>U sж+E$=):a@NE \an|:F.6n;l6lk!߈ 3?:V{撸JG"YP؎sA} N (4Y/oZQNBb-&pfTɋeF*Н.p~޺m$Ym+W!x&z|^R\ϰs6)61eNEM >}XS<>Ou>@l8UGΜٮw ]Jp`Ӣ3AU #30D6$Ë)>Ř,OC@*AsC`[ײu^SY;nakg0@qS=L06I%Z'd99z`T ͦ7IO\^tde\tZٳtYF#yiv^XT}I|͐P;v$xbA[FsrÃظHV4F3θHaAx:ڙL1w7Eҥ?<ʞ# أ7OTr#.BG<\<ޜv|z 5Dwa0?pm >oo߉е"FC?4>ښ2RuC}?Y%<[eCZGDz`2hya*[# 6dzϾ땀\Ɔ<*؇DDH%H/ɝ'_ZDx) >5x/9E/4B;g[1) ֕02V};Fp>}t[iV[P|mOE00ՋZ\m%&;Ru8#z.Da}dB*i3*I~sd%0ii>8|l6~',{eң=@Psw\ռC P:{݉]ݜ;sռ$%GT*6HL?r& ~<<4^ϲ i7SU^ltKA8)M7Xn'鴉IpR6JձoNјRpŏNAUsDKc-1r?cv,N& .BEb6?$DYQivLWLdʆ_d/!v2CX4 a%Z_m{m?m^Z}L]rɦ?"Y,_aEz"/ȕ2&4Omf-WyR[*]@3\6NfUJm!~Qf8-yE"ɾ:ir T8V-,)M̮8hwkb;Q}F7tZ>Hp`)lGoh*j9f1sm֢AWZwf[G(ߩ=u$7Wd+ FsoBڮ~94|fq?qLgw_!_ƹf/TV3gxI1)&.('-.gv_%.+!؀3! l;7`y̑£ L̞E5{é'>Kn_RA ,z~ܓ/2pm;L 4_ѓ+Ѳcp/({*?3Hr[QSxү$۝(Զ"ɺg[5efzk6In׼]p[6EI툀;/&eLK3 0<Q#AoL\lׇSSҤO]^^[j=>鄫%s"mY1Bz""4'/$K5Tab.>tW“/FZ.#v qa@Bx'PiBMp[B9iG&YSRc GQPZO-ul[T5cPeGI"{G v8Idus<}\+ɔNd8#}8IJKh . ܱ5r1E10$7SA(eNI [Uzi_ ?Π`|OCTƮTX:*k 5`6HXх-r!ҼW鐘O-P\a#o ɯȂOBi*7<52ƌ {X~$PbqH@ v nc=;-\:+!v'0T(KNQKhc dDk#0t\-̵PZl n#8-%%lsvKBgUKr5Rϐ\"4m6,gg+*:Z0uŦ{ef~R!"fWCFİfվ OKt]47vΰtbDŽU r`zRyMT2 ; +]{ꐳGYUZYj:GE?P#1[3HzJ >;*켆Lj†ȁo50*e;,3搰3Jp?PvY.'d^mI KdEFN)<9dT =*^8EFbl&eZ H/NCNX'E")6XM ` | 8eى5xO+jքlkNq `9[Z#bR4wD-"!3i8}?Auܠt~)V80löcd N NŇ݁:{=OY}&Ȇz';_2֫Sbc0qc 7QDT!Ԕn}h&@8l<uX=Y 9YX)\uUW:V/mS H L8uP~fD[f)Nc Ҋ2bSgmD ~!Dd;~؉6Do#(W5kގ8⛩X{f&|(pm%CB_i4Tn{ pFW*cb:MgIT.ކoJÚI=&\kLԋd}m1q9畧>yɝVW*'<&*)eW=پ.U-3}aE.a,!4v;iiΤZTO~|1U.4SyR H#_ś~  3 lC1B$`]o|ҷ 8[ɭT 3Dw~T9S45W&R(ܝ4dijR$ %~mn; =87! D`~w>򶔑TFf-<=֖hlph 3"b)[ 'gE<$ʽLpRڷ'ǁ_o׺+#Y^!wMu=4d-Gc!7>FK kMAK.$F?p`3QVH#MWXEsJu]pLxZ%BS@23~s2(tL~6J-LS…>8ƀQ79?J>6Nk0X%BzC\pK%E?yؽٛ~3g@[-#7t )B&6~Rk+abMU(4 'QMMBQ tU۶a_ [[]#DˡYfj5:!y# oKiwubp~,oЎT6F2 # LPe3٘ ,! gX~ 8:R[$!vmh2L2:H[KaRp|BHy 6pgvRsU;rgK7[&ۛy(b Kl5o#1h} p0c`ΔNÔ9 ;mdh6^͚oݍaV~)8n>jctG/ϭ/O=^),,ZwS14h,#L#->>s=|q`y _6O2Dl7uEN?7ך[})rq\R2xQ;=k~htAה4#iTv}J?#)sb¹2 vC'l}@'0Ow'%,32 w=#gu+\.exj J Q3<@2"m~hxaLx61!׻ZAכ|0C_&DSZJ?-WJ ƬxEꕕ0 iH$6=fo!YF2JИO'ypoU-j^a#/~o?m>q_)wa+Em&3B:e|馮F6@Z\l?SJ(eT:%Իz ܜO߶‰b[YFn7O^Nݼxkg* v^8ݶI/g?e';g'Qid8R6g;[KCfs~1(" RA1([O[Hrߜ&C-oj7gn#FcDGi 6{l-ùX BSd,qNs[{oZr LN/MSv]1(qT, ^`[79FX #m Xfxl p>ҁf3P3nIJ}|Gֈa'Y%_oy=C_Oo +6 @|&WVD3A6_Sw3-$rKp$/`F⥢@iHWXuߪ@֝O+4Y$J. +;,PtJK%jpt ]Y Y#kn[iZe>dQ\J.U6SwjFk>v8\҃OݷXD >8^u/Z}C:#*{b\&Η6#Iҷ-F{"Wmc͗W7_c$ډo v00i["eY_DV3Yu&eb&Sd+ jEel n4KjGcp8l[.B\"?%[mu].n :_+AW[!cK[yu+>Mf"7♖>ܟoZmJ[]-VxDV:$Z]?lQ__>ݶ"ܬ߿o\ȟ^Ǐ燯d; keeZw~_?7||ݷW?~K=;>~i?nW}||]|oq:x??~?߿݇_o?}k]?}㇏K{^k=[!lV?*~{ /Nj;KA*r˲]~텿~o]_O=?;=ﳺtGg5ROOץtk%䕌yӶ'L "G$Ty rPdZpzI6ANN^L]W~o I6nrY62F6LV6<傽M&H6䈟pdiIڑLh[ֈ=Ŭsx%mnҗJt"]UJ/翶&qUhXP"rm6CW$n f.YFb@!bVaH6Uioz1#ӻ3u)*!={]&ʈL4tNߊzLZMuOo=7$n-I)db k,ux`ۆhl"R vdx&F[*%.k@ou;g7Vk($Ӳu͔@znmui6#sv`6,UiL׭i?޺ fY.x}}mw)(_Ndla2 }bg~>i|',a33xʵݾy};?}W2zx]÷oj?|?_O?}i=z/ྨ.6.:گ4?uJ7X8eb "ΣpxI 4YyZ/z?K/.˶8S zmM/?xx/z %޾o?O_,nϋYP[2:QUGr?O(z΋,*5xYmz@7??82% Iocsigenserver-5.0.1/local/var/www/ocsigenstuff/scalable/application-x-rpm.svgz000066400000000000000000000322171417255654100276440ustar00rootroot00000000000000}iodw2xɛT/ja<<ۘf*ARu-]榒yJ^K28AOWw7߽+b>9~݋&X?^^\{q}߿ͷi֧Nj?^vNN>~w'/Mo~~X,^n?]Jj}pWE_~/~^\]\˛T;fo>Zs'ʜӠFsS3~}{(NyXW.AA[{-X|;[śǿ=l|vGSr}z==[ߟNjŻ^`|& H)Ug\Z]I>w~s~ }s|jNVh˸.Õj4O7wۋui㿻g'7>[_7g`wyr}ruq~| 2_^^>s25:}{nO緘W) GooYLa6l\ˏ<|n 6~¿]_<@P__~QwW߽:}oGZRm;=)j˾)|Fa` =~2(+у(ʬgo˧6~Dq#>XV+MFPP 4!Vh]jL\%4vtrN< :>WgxI'l,2]h78:ӞkOϷo]^MKm5mJ =o_@y=?vk]sӇwMrJY~@BkLf),jfUzјUeX97Ư JegVɻ[*-V,ۀ`eRZ~>/JR{]a9˔Ezg;Yy~ǦI+ Ԙ][E# +,'̲qKzWЕ -;څ+NXAZ0~u1ư5x*< C!lXbP˦>4|+ߦb R7|:X?w7XAe<:.h.Qt{sY[?(P^Y/Np7˫$\|! mS [ 5y@ҭgИ :7O*)egpFӘd(iaa$U+i/(h % m^52G=T)]Jj,vAQiLϢscm_bsT[\)+rW7;LX>6dCnk>>;hfJLЉ1drᡮЁP:*ͮڝJU>Ae=.+`p9S/꜕[ )(3tK-4(^/(şʟ[Y kzz+RL$THM?B?+4ty&@F p%˙;) {vgRIJπuq[cµu:ƿQQ01 -؀߽8Kȯ[*,KuŭӬ^Rz4X;wg`yXm7n b܉z$>$4@>FY At=R 4^*E54p:_!dU*rnsp[xǡ ӌLBi+`s mk2p:Э0M:gMJ3 =~CєJE: Sihs!W18sDh<̏6& ߨ(Wgm>i D"MN;MNe6 $O/9HgF`9oJN@g+t%_&kK<ߣ\8/mЭf!UjQh #F9вLJg{>h0o%p07M9ߵ9wM=x8L4;|Y~7; NF|tdr;ԶUg]P 0񁍚ݍtГ3fӝE#Fw\>HXմ̦;e?rN?q{ۮZO->힉:n~،vcܖg݇Uh.W>h8<\[pSc$f3 U4gcpa 0yaٟ~}|3;Dߠ8۳A@w;y *i߿NsЊ26>퍫λ.=wa je]ca(|K@mD|i,3;0h6WTaϔ[#F:[B;϶>=m3̥nES*U<ZqWGr{=݋=s.kBWbJz`o 0~ZUiXhһ{\?}|et8B~d u쮅۷Yz'X\R!?ӆZىX:}^|O BPjJ 5Wh [:Q[! fۺƞ^PdrK&|O!J=}&hFaެo߾y 6ULiц[-nn$qK uf-FnZۻ?fW#})^ڿq{y(P%y(Vh@9(GoG[!(w.B 6 x)՜T+a\|2n=T`;1*@25L#a <֖HNj6ǚPz ބ#uߵ@YՄwo;x~;p׻OmL-/`;ذހCZ|g pH blaÚxQ0m:w^͆qq;9rd>"p_/} 7w/vSi$77C0~ϓ|D.؈;F6B3Cr! fn693ކ\,<}Ɩ)|llS󸋍APC 4Ծvq<> sCڻ0y4[QS;Tcȼ_Pទ{lf8Tܷ)jf`ס=B6wSuj_@Xu44{c[N'wJ.vhf wT<혝7 V|=1)mۍo<Ċë{a9Ggwb>9.A]$fU~` 77=CrIc#A`aX?.%(1JɦVNLJ1v2=ݡǓ22bަ}fJLv1m}rDC о-ϠiƎY 3h{> GY3 < GY3h=G9 >a6O~FR$汊f3l t;u' 0! + $P)ē<5M0Kdz`Iٰq֏X1‹@aBF4Y(v锁nd@cqenz|>ljWZ/fn|a\ۑ58;B9-蟊Z/AI↥Qv\j ì ɾ(봉 |[qGT-< $IMN WBn2VLȴ rʡfS3QyHPR`~aK0GYEeT"t>eg\hMɸ _=O?_?noO߭=%SZܝGA=}3؂_힫Oo>BN~RO&ASc!lr~3Ɨo>CY6^pw A@஁ww$݇>ino.|}=>k޼45t}4nK-5>+xĵV_6.oޜ^iO/ŗL E_ebܭ*~x~^|׺›w_7[mq!> ֛>b-1Aۻǟ:{v ppQAWXD}B*s}-[/9?K'y&#DG/.Kv'u]D'-׻X<}T˛ņ6f+`*_»90٦*K6<]a\T} XѰarh-q JW:~p`mZ&%(SH J*%sf!$F6 GI?qgyFR !6EDTN* IRw漰T M,T(7MZk&j*l I&c~ nJ6&QY % U5i e&9k/;ū۳.zr|*Цr>R9mh /n&ȇ{A`04UnT&o h˘PeDAexRI_.lEKn:mmJ,֍g,I [RJ|/T^edEpIJ|5W =Y}_,v\ L#a9t0:E6LٞT.H•*脶FT]fPd@.]Z.Er̉ OCƊ-CR@7;d) `L8Kbd*7|0@ɏf[*\ڕ_Ҡ3I_ %yQ=3+;)"l2i  ˖Η7v5JKI0,Y%G]zg)02m>vgWKa^.\*՜W lLh`RNA$| d>#F^jsR=|ah#E4 t,V)% h#+5)ͫJiw9Em9Tb`fF^RrhX?&Ƣǻ+DN&Z(3eCL49jg ^ B39c(dHJ3Z+C.lKBK8(|ڄȣdft ,̋ J *,S2*.<52fô: fT9>t` c\4-U,e]k9+gR yn2PX\#@$D\K Ӷ+R֔LI߅>_j,kbz%rpY^z>I:ѽ譎_%meID4›< \}%g0:|r̖!r$!Vxn7BDH~=ԫEC GPF{;cF͑\^Q5u|jrȆٯ<&0 B+bK7,i| ʦb3p\D1dh֋h߀;tcVԡ>.aHπ . !gnC 8x\/0c- og#X"0X[P̀eꠈm='9.58NScgrZ"L4g0NT"#sImj=)BAl6 &^v'19L$[A٧JPNo!CXC%zaF0k<< +і^]`./W-vs~zs A ;sc0KC;Pk$#:"`yYQEZDOx 'lJ`a.DiD毶~* iTT T(/=1-Ja3SexNO R~5- w5YJyV ˾\PjjrXR.DG %Ft5 gl;8KYie&}3yM>mI N ZRy#/n)Ph@tSoo:oriuniGf/]-q63$[Q=F%VЙ+Dx;wM#_ox,סJqNkKblzb \DKR*P<9]CPYsA+ZD3"cbuZ].ZI i0 z_Ҿ&Ah]3V -wqijB:u>F^|UB'l$!w5= ",d^J~SO|D,rF1tڮAn=l$.qm?n0U.#kcRl0n]sb5 /)[$(mKvDQv Ȓ1rۢ[,>[C8mtTX-.q|Wc1ID 0#\qGٔ eɫ]Ecc8r&!EąMp]\;[s31XK#`ev.`fs2v1?zafIqZR˨h6X'S 6tai73GRHi 到4wҖCR4@[y޴P 8ay7^@ƊV̌" yɞj1V#'6&7Uv,z\ƫkX5ÆݎPiNVvz)xF2e#,  D3&iᄭpFVgX3☤LfMg*=*LA0%RA3ܐKS , ( (LPn4Jk2њfH:8]nd6Frt.m Qs5A K#e;%FcSGblʍҠWYXbVީMf}{䪾l`S~sgkb `~횾5Z+'%Sn'T4gz+G/u /t!"vPn.0cMXH#Fÿy2ΰQ[Cר-6;XGhg{u3kBǯ-Z6 lJy4RS#[$03֪wEZ6k~mll9B"xN%:{bnJCPnmQa{sTεWВ4]H3lRՇ P))BsMY2.ٞC [T۵Z[B}Z%Z+w YryR*-_m6n[u_V6ؚ$Z~iTٕo'W~Co%]IX>KHE(W g |"$g(27^ztCB/~]aB7,Y{[8TDe%E/Y,HKA$w&PD,6 ٨m" D)C34: 6Mϳ~3(Ɇ 01@qĆkBqFI7?=xs8`mޟ[jgmbN1vE \B n!ɹb&zȱ;.R4ݺ/]V011?s: '!F dَ< `|n`qO QKbmb_"ew =%(o cG1 %?r5%4bgo;cVWviJDs߆G[4XV~9XgGtA)^$Na%> _ёڏ nk옱8;ca# bTXvʑO_1lB'>glVqQ0)wM+ (d544 wHhr}h2G` MӅ&Ф MqN%_YrwZɿ$m^!u(ky"miTţä҇"lfarsAg ڐmȱ +/{ݲ=~(p+[6v,njn3'+_偛vl.:{OmF !->q΍,t8΅nӠIn3w6wBq^6~* nލ;=j{k|(bLq~fr6(b0َu\s<|wG%W PQl:Xp@-0̀B5®`ɫ!}99/uzCb0&,Wp;+3FpjP!24Aa%4ڇm:Zϣesd[j Aތ܁#7}l- itm1ЯJf(kTH4 x9S0kh!o obb\&Fnzxts#!Aʒ'_ϫy"uaFCseʀ?1c)j]^O.NFee"qp-#k"WI_)4|TPK`}ӫϯtf}'9iZVjJngo/ΤƴӃ5}BkY|ra nG]df02V3 -gStuSטvsU};KUq$[^rHln2&IQDGmgnn7vAR8ŷ-W(V\.BcJ2C|ZW*-x1 NNc4̜t-m#|2 BI8$'k <]BvX9_1`I)TIb3L%*Q G1[W7"caRSCRp,G5Ӌ:e2@a8 BL 5xW5}[S4%5Q[Iǫz80fJar-v8b`ci+NBUJVT7%^Y!(JY\=x3eנMI Xm]yڀUIs2œb ^g_#M1(`vT(t{ܐ(jFQ<-ˮ1L$}WVAͼ yl9(?@\TcfNJ\FĕfYKLD][/$T\$2>ߕ8&,EaK;5xIgS3J%9(p7ܢ7N#t 2жl;tl25AYit"K= 19TdAE ֠$ ?rHX@ ꤸr]"Q<2źnsP$قUkM[y} ̈FS)P,3;| ƍz,(;>h6\m&7S@ɑD`v`A11q{@1[Mtğ\Q?T̉ C sS0VCu`j؊'Pb = lI~ 1"HV YsJEԦ[^Ic7lXS/"j$.kxbxw MJަ`q0zdT#i1/$| 3V|H uc&*a4#)@,U 0|1f(=] ED^L4O Y1܀7#fWӥt)1] t*y;!T6t $#\pGPvuTE-GlK[e$8>KuA;(2kKjɏY`"XbHw-K^-ō(-rШziؼ3$iEPrn)7aPL>;PšPɽJxt&NuEUXC ro/S*"*1`b6: '=Cakn0?a%a6 nU)FJ,pTE\#qݝEf@Yt:">oA|G3O @ƼIaɑHjJ`$O/DYJy9L Ѽr.[O"5sݞg%/ə}KjrhxFJ·tI`ެЖXd+<ߖμ蓷j%bz"I8cVX%E.+qՈ׹znp0@a"d4oRg*'hω(F-yW[+w%J8#0}W i^5=r3Kp/T`#0$OU4 xӊ[$(2[v0PLYF:W`$Ӎ]1b uȥmǷyRcW]XJUoK &ȯ^d݈%BH^hsYٍyvVT9`m5ɍt?(l:swAh5at!<b%&,OǗ2;>xQD[7{CfkÎfφ68xJ:p8(9_vBMˋ;bVocsigenserver-5.0.1/local/var/www/ocsigenstuff/scalable/application-x-tar.svgz000066400000000000000000000253221417255654100276330ustar00rootroot00000000000000}ksDZwY;ݨ"uâ,#v~s P~̀k15Y'3^ ]ÛۏUz?>?\_޼^y?jvuz:_|yޝެɧOꋦ^~8y/Y,{}͋慛RduZ]ߝZ諟Hj}}'o^nP}Wd9(sbLӇj*8QJY_Z.1;#O17[=[Ǜzu~V>?|є\^nNVw'mgpIŇo^& H֔g\6ʈF;_o^\^aCuz[o>cp.C^=jzq*DO~^_Nn.58;Y?|.q'xjuxwuzy z0d7&I>`S>+|WXa2l\w]Dv 6~>4x+ejnO X޼:x=đ9TM{9ECx7_yBm43 .`Pkу(سk6)Gfm+?1Tȃ gh.Š3Um=3ߪ~- A_&Ī̈́*d_I'٠GA=B[ y^涫|厓==M/Vq?;6i~/EhkڔrQ|mE;;6k:xp٬ XjY&S{er Z:Yo^T9 S9{|mP7jm0%Z%o3FRobIRKZVI/}>/TOa=Z|΋XN,2%EB\,c4'+R\T@+I٥Z::XXak2ʡ).E+3Z;څ5ijh[X GۅVCt? u)Q._H-+0`;ێK>kݬ/ p+5^w_%ʫ6#_o'yuV\HG[yfU AiֳihLĬSji;gmZQ4&Y6s+i.IGJ ~KIC(WL=T)9% w5~ `~rӓX798=E8ee\Qj8YULiM6ֱ6>\N3j m 78֊eN$ u-vITijw+U4PN***,rS/꜕[ )(3tK-4(S//ϝcc[e=)i6$*FZ7B6t+ lNYnCe%hJ%@E: Si5C`׀18?#zNdmtyr1|ۻQ6&lQwC@Pxc5j~X^FYz>*Ö:*8KracZ[(D7F#fK[4 OP4W6Ǜ1"ֆӄꬍ&"Hɉ@cC x߉=ј Ԧy@uÓmK&3ZlFwP@SЭpJ8E']ɗ%ZQ.iNGtupHի.)?>Z? #ahŒ`Ì-v4AAa&mHSzhT?o]{o'1fƗ x)߫iq4 NPxY8y9-Ug]P 0DP,pjݑͅuʍp#ε w85vQ@"ovZ=Y!MSv>:vOˀkö8۳^M@w3˼'{ǷňV=m3̥|h)F_+#ڹ}HkvGWbf}7oVեjV=z{^dxmt8B~dsiZ;;p{qg~4ߛ)%!4 j&'N1u|Ԇ~['j0!;zuأ.wCATxs=0=a= U'YOE^7 fl߿?'@m*/8Aц[-mn$Ϗq;@ufFyd?fW $#}P^ڿq{yXQT3P%yXQ T~XmF3}O|A>z8҇:TtZBp߹ %|0*TsRRD[#j)ՄN * IE-X RD F#eͲГ'nPM>񀲯w-R!#W0??ܮ?^cWd(.phSpA&3鏄@2ضX[~ X Ie/:@[kOC{` N?@܆~ffWGul fҎ-^m0ilZ_0gilYo!$e|P|–5?< _at1a-?wr|E^nn^ݦ|V|`:0s8܌yF>OVa#rqFo =L.!ыCjnI oCCNr'gc˃{|llS8PC rj96nLJڻ0ظ Bh|j>QDeOP᎑#|C{F߇tG SqߦS-V_ۤ{O֩9ЁdgoƖwNDW7wTNﻜڡ9M<1;oAf߷?`k3f'~{r΃̔v<}1mX{xu6~?|Ņ8Y;jH) Hh9vYPJV KkNHOM<օIGnTBbؠ.NvUN !X y`aX]LK15Peϊ!LAMɸ~OV\>}ӍnoN?=%S(5ޭoW 5m؂_힫w??An>^_w[ &"LV=;_}5 Dznx{ WOK tew??} ~\mf}qM Njݎzn05Ʋh܎m;j16.bi4kt-lՒJ':$=ALBbO宔_OOO{!ܖ[=N랝N߭?b w^wqE\%A`Th\2y_:=ПIdi>zqNh?^4}/_ >lw+H\\/<]h~x—\S`LB%TY]aLT} TѰaph-Q p.+&er5- @@*E$dDRbΙ$.NRl_Hjh!7%J>p &}JB%|Ȅo/"SIR: ldB$F'ya].w(Y]P!nGoR7iM.ԔlL bJ .t|k5jDњ\8ιTC8H8˖|^]A] w`f ݨ"oh1ǽ ˚i +D \hi׼M@1{Ǣl@^WJIo2LwW0BU! *f$_MUB0o0zb[~,32:qzNFȆ SʥI7+p :¼HZ"EoEVݥⷥ9$@Xd8Թf/&a=6&X+6;%#ҟY" F0|m/_#L,7 dGl\/NiΙ rZET #F#`4LH R2e;Η7ȩB6xJVQY "LLM+3z kMFrɅb.J& 40T)A$<#e:.a{Hπ . !'B 8x \/0c- f#X"0X[P̀geꠈm='958NScgrZ"L4g0NT"#s$6t I z6V䘜 $[ AJPnA8J0ue}> ECC)׭1GXI  v2,3o]4\3#@T#bLj,FYqYm0v2d;qK=q7Nmh0$K?-d\ew4M Ld7[M"RrhrDns}mƖCR4@[yf+`pI+B{ nSBlwV$w<ffɎ 01@qĖkBq Jo~8`kޟd(v2tˬ Āb#\r -g$_C';PqG[ř87ʴ&b8f+pyoi~[jLȣAOx;i7Հ%\FdLb p\rP`Y9vT P xP:#WSO#vfi6%QhnAhڌ_t3DQJ"v**B3>`9ގůH`ӎ nolXg+WLwȧez @QTV5lVqfPw0)wM+S m/dfvM|d;$495}h2g`wEDŽ&BBS{dhχ&cBfLM x@dyy5DVoI[WmAjg{jH{ho3HaRiCM^sm0Ir{9ރSAg Nڐmȱ +/{ݲ;~(p;lv,n'+_N偛f6윽NF#DŽnkOS= >&:3S4 Y~6(>CzMi7t8a?MS][yΧx"wkl6%/;߷?->N>H*mnZ+8 .RPFuCyil_n:=!A~knjX$3pRʤR0|(ӿ0œ7COMz\^O}L/ AGyljlK!(<[pd ̀Yk+cڮDkI- mTh 5cv%Z̋L;?b&+{PߚtM9dtQvCJÆOfwȰn;ǽdF.]zh3/$PӯDo;VeѪEkyvX=1kŞ3ysPdK^ )[?_fP hJiuW(TVV旗jgr#7SϮ/ήn?y?T~{տ_v/xo77ݯiZ?ۜ]ܼno?>ǻ۳RlgForOksݽ⼽+~۫siЗn{<^ۋD4_$cυzT+g MV%xvWλŧ+ޗ_1asw|wn7uc%6cIۻgۻM;/`B/w_^| SN8޼}Fti'6bu5|I;97هWS0nwwۋ ^nW7?|y00l3߷錺}Ӈ6.A|8{~uuyN\\m|{vu&p`'7 WbL3D0Eï`ݞ]\biҕ_Բw|hg-F?5߼}{6]^ܾn]~!@'^dcVvLug7۷۷7˜nu,vTJ3VoVխ/t+{;ߞ9oBX|p7}=GgW}k__n\ CMֻ/!?mo$=}gBJlX Ah}{}6^e>1SҸ~RhㄒٵhBm~Ǿ=Z:J]=]p e|ƫ((⎙{[AYzBo򛠝'7Acw3٠ZD$7X2YV0ZO|8eR>+ur;*~Ȟ뛋qݝ/kmu׳!9?pQf ZJJjcWbmfrUĵUnpFD픥)5kMwDPRRVV;<E *4rm7>HiJlś,'ָ$F8V_J~(,=G V^xCoh,,PULXha^ߠ7I +e7XuWVRD;"e0|6zT}Ү^t/k~`c ~{r)MnKW|vXH(:vog.Ϯ_^}-jD_/]kaͪ 44&ĨՒZ(k`.DH ZVhJM^6x(ih!'H DvQT!1%+FAl~r*":WZ{?`z RuN:Q(cY= [\m,|6',֮6fzyA[7}m7 ʯ.W Z|H PXHA#A k)\Uh@eƋvE?Y)_uRf::^iFK/Р"}2[-}ܫ8U_UVIn' Ti$+fL|]vi6N0ZG ֜9:zgй7dmu&xUnF`oq2CBMZm֒=pĬRQ s^Y8a:!%{,%4֐/hP7i}'Fp\b$hur-=K5-ns$z@GQpGђ^Q㻍X*j]+ C~1nJhH;^(zSMZ)bƐsKj~]9@]ȥOQY> #ME00#0c 2 6<(I1(ɤ iBȉLۿYڟT~|_R,b8Ո/%x{x_C%Z3#N:BobHj7 d` .3Cw4OrK2n =1zoi{O뉉;c)zkl4F[)${^@z,;֖SycDEk ubU: %;s%BI5?{͈˺qgiOKQ8kFUᄟ͈Vɴ/uїie&*yׄ#xpFq ж˷d} 5h }51#|kg4兛#1Ҍoa3FXdz DZ-#\fB&?5hB#R/vqܾJObi}<~Hx  j{CH7yKe4Lz3Mz;"V_QͰO}_豅OYz'R-)ZJQM~.NNY{ - FƁVAg (-y&^0gxQMklyCNΐ=?9,9n~!$}Ī] EĤIY=o^}sV*N mj~km^D:/C={;0aKhI&:4SGx~xr,gѷ3_} ,06G{/`Nl03O {iӺc6?c;qdjKLR7NA|I(Ð~Ds:rŜ~”3&䚳p!8[dztғ7 ՄqAPEftdTGclt40ظ hra.bVFyb[G42tH(`BX 㼸6!8.<<|.h5SkC{L"n׏T]]ʠFI2M5i[hCU7z67RZ/)BDVaOjql !zc:2۷7plSI<ڹEkdI"W%XHKQ tޘhّTRjlwsq~ߓ1HJ=dxHzoDwy"v=Hۅ&dI WJ:w<@`.mI)"qן/h'۷Ҝ•GiaJ!МnEWH c=t8N,9q#R]zNvS;`֡; &/}qyƾ읥d;oӡ8Rb16$K  :'A rӒNOdv|y$Z)i6tOvk@E\mڷko)%lIBcҼ!fUӱjhlXiaˣ&pyf; M"UF'ir߻~g){G1xI׺^ֈx)k#.9:aL8rL0߳}a2#{xxgDa/K#=N# P zʜØm9,no I_|r|f)AB|amD@'xZ,W$^h}FD^V3Py UK6;xWpT"Zx`(rao庸w$qGv׶lfX q6!8XnGD? "_&XJi::gb J.tZ8[o\gظhNSI)j='tH7 f!~}TF,*llWCU *@vTSf6ʊr\ȥ_.3t/L^!𢯃ǕYHMŻe3vu𳙐M{ou.8JEP̂+%Ո\ =@ǁX$^u1 aK90Vf&JC6ڵ 4wy[cFGguHv%iՊ\HԲvI6]UW!f![hiltm5k[v\ȅTIv]ƍv+kvK-{k20nV.je >m!P5. )u\H|sPLX#OPp6%''(8F B 6a3F.Սvy)~R/U r3нqũgmd5q׷uL{9=vŔ:ІlR'$;M|su~|t|_rC,{<];6󋧳lHNV@s@ǖQ@O1X#B$J>bT阜+$7)H%a6?_)*wchUPlV6r: 0M \z Us"a.vMY'FGTa?[U: Wx%(4[<6ʆGغ9x&!0ag&x, !)3~rչ,8r-Y:=Δ1p~B j<քټLEDj 9Kی5__L80W'HRϨj wFf`y=Oαh-,GdJ0RH`#?\F:|s&~b?4雲)'yf{~?JUᔣӑf)3;]/R&DCI wPAi]WlpNt|`4tTS9 _?ǏXWg7wf*ggǏ`;kE '/ “+<%q~kNd>20q##_*Cnt sZ.V<婩 +Q[*'?Fh}2p91O#_Nt*k\Ín =(}TTP=ihGD] @!&PX5zn/Aᕇ&'7yTߍ>A"ac$t'U|whWvܺMvSvZ09zr۩eP@t3fRkx\k]ٝpnGӺ ೸pBjv_ qjJ]ĵ"~Bv3|AO)oHX 0~|GgI(kڽ.U*өfBSeKA3%Uxh"LL咩1%>T/$XToc>Έ9ytt W.zO3}8@q]N]{=;?ϧԙU"j5)3aiMuqy Hf^q ^D/Z˪r\4!e|QpMO\`NO;52zxJڑǽgnOsɇǴ?G?).A|#UvU7vm]\7u.}*Y7w|ym3,^.jLWش; Z[]&èrKA! [bdXtL.ƨ֩P&Hx* ?tFf;38s]Y2ȰqX_@L~T4 ۷o?]t?SQֻgRqqXcġs1F%޶.b{ ^|E -6J2ei!B(.Wapji9a+-tÍv3p}?zvvcߋ뛋[t~~~~w^RGtD"xcVn!, ̈́ AJn謠/(#;y֯&(^z҅UtYV*Z!,Q8a!P%5zH@W tQ:ZS0֕*w> $\][ ëH}xIuI٪+;ů%v?2I=?6?9S.ny.ʿrvqdxon fg^^lGUo|*5Xb+vROUǻջ7gWճ}o߷!j.M?޼ۭ0?vb>}ƛw4v;wRυEBG.gھliu߻EZzywjh^+ѸBjs}Y+JZ\ K6z'?]ʅlNO2֙%zdN)k]ɕm_:xP_"4P >;mZ,o/޾߯ju;@%jd\wqp^"z~@CbZނ>ޞ~o67KC;u!W>fa4*_7dozbRonnVr(Oo>~xիT¢ hs"*ɪMy/7Jϳ4/iV@f#|~6f񂮟Z?5Z9ZtfoqC`;sR4[]F-Z|W^ŀ;0CGb<0ɀ6a²d< R8~OP)VkNܝJMtb6MhD6,x_ut`DXN'Axʱ b~}'ցdUr#w~rKDңb0VPM/` 6H|V" 6ƙtIAj黏JM_bcd#4|iPFkׇr3\ NLhfX &`-Xhʓ~\l5  K:ڸ?nH=gۂO+O/Z ,46D%Y&t,iT~yi f'#U _U y Y_ !;KrSSki'KWBaq!cńL(EI'TĺL#k#'ڌڬh㤇*YW[m5UgD6&4Ы& ebCHJOC8ZHm7߹\ۆ`*Kě[疵T*SIh谖H@@̚2!֌ ZXNX|y<\ }}$܍F@7B7r\#DEVf[لI'T׃w~@Y$<4ball *}B IKrU^5LKi:,prJ:H=$G< ȀrGMQeM. ; ]61> K% VyiC5Qf, ,`V R>[XfkKhI(<]l~ƃ{H ³gޥ!1@LIze.=#Xz<~0/;IMM$J $ʹH8Q~+jS·2Еnxawqw{-z[NzY'CbPnH 0ʝpPE HR\3(i c LUAIZUdg@W 4M:7@LAY*aH]TkkhZ`M 3 hF85DjK]lx+1NJ7ђ4v$N $^BZ!"tcj=INTj &$ r)fY.(nܯ,TJ9R F0k֡"1PI 6eZ{zM;p. ~Me) 3"8Ut*& s ,InNϲaw`, 8; 5!k.87PSt~+ke-{X˸a/Tb43F+=2 ,|J AmZ(dD ֠;@r( ^KŹ^vd`j ta-ұdf,&b:6dT]@w,}JrzP,ހ|B {&9Wǫ[,֋fe|ӱt_xߛ7T/1oWi]]rv{{'@nࣃeG>84ĽjA^k݀u #˫ O7'D+kDn4}k J4gGʓ,Oo6N׺m}t7<:n_c;hezov{_"*jKXRw#R}"%)4w*R1sp 0t)[B{it-cHOH]'$n) Qm.;ӓJ#]:`WƗ=_}zO1\Mc\WCZE:gH0#8K_kZ((].9TD9ʘUZQĄ tzc-,>b(mfapֱ6` yOa&rͬ,Swg|AddaԍH+G`b,2/T<}l=049~sB%B3vo\tHh+d MФMcBۯ} 8#288/QWy`o5$m^5zi Z{C ::L(ҋt[ #nm5z6upVFnP YϨҎK[Kq0]Wѿ1w"Jl՛0?Fd9n*"D\] 퍠[aWPm)O*Y. 忷sd a8:*NQO ce Rc؆_&^R2yF6LOcު$IP,L bvEQNW0rcѤAK{KQG%gsk]autڲޗOD*тIѥ|{nTK|WP TRthr]^ޔWo+C`]oT8蔛IJ|knRm>RnevJMÔ`"1CO7C' ז8-MC]=HgՌɨQkCf(^\TS#uqn2a(k]ݻ燁QA\a*GzxNMw6ߨ< (St+Nob7>s)_ِ;tnm"tHݝ=&\GMԚrhm9A;tbuY*#ӯ@aOIo,[z.YhT M1a[ TϿg~#d!k#Nlv_ ʬem_YB6P[[jxϦI5<+ *B8LT 1p+*͓P4aVTrf Nu0Cޚ&UŔ0pLİ!u̎.z *89:eRXI-)E*{XMC7ʱud$t>2? X]NH_4=~N*6[XCQsڻt*DaMAD)u 7cl4( 2hK:t2q(y}C)\a_KyaF^NqѲe`_SiwneTd V2]g!0w9)T*L u&ڟ2P͞&Ր*ё1t)nO3T{jFRyz?=~M]pM)}`!"2t!tM:ҭa__ZMYJR)",E/Nr@ .GB<9؛Oy{,e-I*\. TiL(9'9}_YIGWGZB8U~SLQH@S/I5T|n *8 橗cXPI$x?[*NտB.jV7[В`eOU)bm5xSUF. M!Il'ӔpZk=Z #?HOA>iG+F_X0ǯ|ѵc\^;ڒ2-|2Eɺ\ >D[v#쌳4r8ChiQDiGLQz &1>~tYJ<َOIե+ʼnigA֍x$G '  Gvk1d=.uu!Tg=ӤℲA}K| '$Ēeg>Ɣ:z,tm04rÉL ځ4Pv ^,XcqV,XLX*TbC+qh$و1WeDaR;iCph6}zƵBAV&ܙ< ,؃v9X|$x$8*%N؂7oKoھF~ /vc+$*mnقWZx/`MrӅ\ӮfZ|o{(jzJ"u.{uj[ޛc:4-;/<;F^fxX oxv%ʡ}3:G r#̀ϛ3Gx;?Ԗ[zABL|2AoòÍqh߲㖝Xvze4i ;%N#-W'?a*U?P%awj:rv]xdNGN/g[|!z]g Bx;ж ,ydoIݧl"  >naߪiwPz JIf1.,jکe+<v|XfxR!;U@k_e']v񠘝?݇/.O!hzI"xJ棅fJ v_Uk=i-Q 'x>}Ҏ0SY(mAz09Yd~ hr11y"~z,CPn`)О*1bĵH~sF e$//xh}l'یlF%CK+ld3>ٌ0혣19ALo xlen4Og31gbS|lYxў Xɷ~lƓJђ2?8Z棅eylV9:rcps߯&և@aUY%&#Jt9Vthx{ 9d@YODל̇4?Q pp8VlHgZcJ V>]*6GM })~ZRx@J!uaU]k$n7—qf6dO$\9{v>֯V_4 LQ Jj\NX9`֔UKA(ʸ5i̼p!{$r ɿ%Wu:b[aTvJB|*1]tP)ןn4&bj4RȾ#s#˃#  yr~ '}.'}#'}r[9̝k#irlit};u99OyGn%0(  <)'5Ġ hӊԂS`0w򈩜pIHH0I8tѓ Xx"' 죂KSVeGf|\0Q3Rf`]1, =U5EػI[L;v%`DvLBh xIN:S0gƩP9a6^ ナife:Zvu]r?(zD֒+t+@$_&+8$'&M!5$ނIhcI8Z=8UX|[HL &Um±%C}r6t4-T뜡 d"?uU?#G! "D ~OBn4fIVY*BzD$qCT yE%RE,J[; l_1Е@Pc@>ө%: ܖrC)]t ͍N0U~F><#Qd%[ +kSʜkV"uR"= -;1Qs%PbEiܙ,/SP,˃Ly $}4{}\Oq =WJIVTtsV0]41fvvJ2IuJ>?;0xeNE΋T٤h)"?N V:v|'H5V9E;%;Nx^etͫQ%x $[ l3kF$yTײA$gH@I :1g$%WSFk|Vg/.nl7Ww{W>$:(,;VWp,&4pѲ0R& +$`kFXG*dg}Ǻ}ª:ȃkݲV\OP'=B2@%uy<؛Xৠٶ2OP=@X},0pJIZ $ q Mx%:u`V-ޝp҆uJ lPW͛&^3{6A' 3m!'b?B̡ 2H[˩] bG`kާ˂ `~dG@.\ A$%r8 ,jX#2[୥M΀Sp+N)j0;T2Sl1Hh^VF2SuܒY@ ɀH,. S%q>@a#!cƑ'慂J)'dW -o"G-wyښD.uĤOhSR gd,ͣ\ÏLXjSv6xKa.ge9MMd":Pl7aDP S)"O. m8ͮ 8,Bp}PZlKpInN)x XA+^G=` IhSajRf@H"5QD&~U{O^)"[5B0V#a\V If&#<mVyR3bщ$( PJB |i}XAp\ F+Y8 .P up5gp!_db@锍>j^Yۮ^XKnU1YQ-Q'%iY>$  YA& ZNihd|Jf*Wf!Qf-GOl\ 5H`"&y4fH!h' 8 #+=9tmUr.AKhnnfU%,s IЭ$w0Ej#ۊp%.p] 8 T6@j "Fѳ5f"$<+]3bLH&+(E}ab˰R_'uAy) -=iZ2JF<$ udiDqà 1 R,w UAȼ"7IyB2{C8~,]% -" 4Č>8e! F9a9`Dk!WP*pH@ r)b5S<(12Ԝ 'eeiOLӒ* -YRRɍT8 |KhR-JbAc,JN2&e}w&"|-DqZ{y@ZyrX5p-In%b يb$| 8豪 P;\Dx~$<8^qXr!S@BB%i/J14& T /euVԺ.9%NLP 1ƨIY l5DZ7N4vg1Us.)`RY)FFU'o8w/L&K4Z,FZds έsk4-x0 )"jg]v8TG܊`:r3H :WnBD#Wxeed <8Wyq%lrѯc4 ɂ`==ˊnӿri:Tё?P@>/goJ$I>oO [`5A/ՐR64f!jy%O1=# [5:t+֍ngV)Kyl:Cq5iHNQ@ǒc cOhl )YUJ/$fʸnޯmH'#ΧI;ʤdHYp2S1;GM)C. #"EwQˋ_^P5S/2iy?/LӖ5@N4Zuqvt^wWIVG%!))\IHBщ3UdtmCJދdB2pv9;ڒhevM{HJjZ^a˒Sf 2@Mdz5+(AZ e)%S0981 šlT:< ;WOiF}9WØ;g#WOԉ`&ŞpO)6E1ZhX:aJÜ惀 /9#-v#kӜbXw`Szi2c-k, #1Fdw SUnmhɹS"r|022{H}k1kLZVj33=B9oI7L@{͇P .L 4(CySFJkZbT-5]*qA0 n [JJ-,dCަhItއ\5`6|Ib҉6,yg E#F ZUwD=a'|{S:jH*`d7Ȉ TU6ʆ&e!ʦRvnR'J`iBX_zUa^rwEmiit VGʢ5r'CU.gTW5sZC,82u'33# GeS7en1]6BٝG| _֌w~&RO?k4[CλO!J7'pAdG;Mc9J#Pv6QS4m7^KrsЦY%A[聜 B +Q#5*&XI[)3Mjpz()`P!SK 8aY bcҞ,!>G P$ mtx5ei:5h. P Jpl`[)XG=a(iO?K+vUi;0(!MPyIƗ: )Vh0#ar ۤLkJ,dwJ:[H)tI}kNhg3wߵ)fŀ 2hANEDQ6Kg'Acc,pMN @.G Eh#6X ؞|Op1$>BS1u7"1LeJ|KHfUq$92-;& ~ c9"3+m1#n bPx uȶYO[9|H`6%JT #T7J̀ p,jZ0MO7bRHws󕋣aQ 3wFLT i͂Kӷ8p?(hO :O X."9nޮ+Z*|U5O[ӯ_^Vȷ|D M%mzH ygtpߠ3P ̰ 78U"dZem)'7fC4 NJ%R^!sbl8wN/* y[G{I4y(#yV&X8E;*]OO03_{TVH0*_Ӯ Ism c/&!N)q$H{NLU @׾nГ-+-2j 05 8t)21 2f?>Vhu"rܪ E-/ L|q/y-@‚O:!`8imliPY&ePL1 H&C8)_Z'e4'u2`6Nֶ&f6Mȯ r9KUR5ziTNݡXL&sOŨcUmCkluLPWHk=ֿqO2m{I<̵\i}iFR]]rꠂ>`Mle-H0ku ^nVT2tCO>#ݹԧed@:kƦO'D^"Uݐ{NFPNџ7IAan+h!-&[a#op @)4z/!k=@ --^T;wz[[,%T^hV\ n7ɍ㳩qkLNra"h#(%6J%\Cx3I7DݴWPq R AeZ3@3?.s.#ı1zzO}R2;]p ͧ#Phq֎µH蚛:qJb>~m7ayw[{V8vrq 7G)̓Oc~vL {!s?h=>rw <0l6FFNs>UWN#}F \&P *u9 ѥG<@[UF#y>s?Z#c i|Rfs4-&7gqZaO6cylC}#FJÆ}J8@PA%2&D़%73_;:h x)pP3? tt}x!~:0'lHq4^~laߎMz*zo|ED.$H9X yBNdL F znXr4xz22`x^ D؂'OS 2pw¥Cj_-nGSۛۇO4 jH.7A+86IpOTw_mNQ'_G |Ӓkϗ"Z,Xo绫y~כoE8]ݏ1 ׹?QKU?7s,]4~߽pջ ~<} emR3'V|nVx:xrx{3L/8,r͌ h0s#Q|Bz9QNS {L6"PIw'3˒OݱmøY^PBnY o(}جK1c)d )M=j=[ۭbN1!sаu,Trkدf"N(Ey@; 1FN muD#* Stebƙpq 2AFNQJž]%e/׎٪Ezo}Ⱦxzd58 &=NϤc}=4L>_|Rhs k%J J9?%=ϲޯn^~w}5|Տoٓ㴇_K{q{9gW[mqoL 1@1R| RrW(ΧlʇaΞr T.o_Ji]P%^o%r5:<](N {|I֖E„׸${~D% K" Ad!kv@'#R_oɔ=]"7?^'P)TAo3z﷾Eq5:v-tosAs=œTnޣ`/@$Zފ1a q;A$:V6Ն&o aEsÑ-AcCM?2seo9LOz"goTx|j6"u`H2GC^Ll-MhSF; Co{q7+)>9럽'韏ʭH/s64M <@T1xF)@1"I,/ $Mn_0r'9y4y6=܆L>0e3 n)] 獖Y=Yb0>*#0@r<,e] ~-FKGm CG֟Gi&|nvl׃έetRK5ya3^onŻxyq>ݎfgl}qt1ɻZW'+t\scjԨgOuQQ:ǽUj}Plml8]Qs7z8?.o֪|lf1v;Sr7\4|j0I.?Vwg>TE.H5֔׶oԨjwRC|]N.wg~ }讼 _T-5\`t?>WQivt~?÷O'q1;<} 9ߎoG1 ɘn{{$ݤ{+|nW5]X0 I.i4y:}JR{'h~Qw>(A{*\]F *=|f2} V& :X#7&zYoVW\ct>TFWk=fmm6+mrnw#;#fcOzwkMw]M ƫoFh{xiy·#?Pv)&z^$l4lQ "a:~#94PM{!Yu_;K6:6hVdPѭ(4ٸ")Gfmkn#[.]E3Uc+bڨw[o„jД *D|BWMA㗵M9@2X3iˠ!# nFkvI֞T_{X}q3Ç%̯w"XԴ):F6\'g;hwz5{wwɴx~>&(Ge7oaq]Aw[3{N9ܵ|A^k<0.QPt?Y1K ?gGͪCW?goJ口c hR>qY[CPjASGZ|Ls!elh|e$ݚ6 4w]% %BWI;AAo(ihQ0!{J"KIJ `~rӽX?樆龆SVܯw#C}5mƇ^}A}qѣ,ͺ6=HЉ1dPWbt NJ PTt\~ HC9@Pd*34^o꜕ )(3tK 4(^Ys>[ڮNo@J5mRFZa5+4tY(M`+lO3E#JL$!ڝF&) <|q[cµu:1JFZs~-`=b+-؀n@(kE f}hX,I-O(㽂~z4X;]n>ۚWsjtq- MTWNѰƫX!kNZRYnMe!hJ%@}dSi5^C`718xEH!HVӯiB,X|zd7^V%E]y}6o>!‚<6 KkZN(mo_}]O\r<3Zb28=4R Mh2D ;/*Z:5!.5zg9?7{?lzYEv1|n/u Vw!  :9^{`մMA`p>``Al`o-st보VŁ9DG5U{wAFmLAjc-!rDТ]Œ2 !yqX 6-%0+m櫚`Wt~0ac 2/҃SmRL*r${4JgM51E ޏzwM[%] '>4__vhmTu6inD ʪ BLB.h5-uprпO¹*?6*(jj-B?W4[Cj``T7(~_~Y$c:$*Z BJHΦd$Lju̾9<;Ǎ_xpQOR ;~M^w҃:grKz* [xXS{D; $CMCt_1mkbjYkɭm"nii[q{~#=WekE3.}#]ot8@-o d@dn15Ա.3ZSoK2v ^ V8|5R-JUR=k1P+6mV&"pWJCawV  ;caT#х PA3ɫXl:A{k|,Rrjeʻ}އA0 G3(яյt$piCvv[-@)̍._ǔV5P4C-[ ":z891J)^kqU26CǘMm_0r;ns ^iÉAЎ8J )u9k=N%N{ؙzFko8hĶކbZyk ]4b7-B|/LE3Q {%{q"`=5msj+掏&bv& vPsǠhaU`n9eX}1uA0nꭄKC6W.6z!K] _2rqC;Ywv>ME;ryJ/Tw{Ш:Ccv{hܱaD9cd XmZlxcɻ :ۯH^)}yCTs}l4ʿ(RIiW驑VF5n5ٍlx~ qV\S=% Ucn L=]uia_uo{͠Kcزa}DkYa=t߲V{߮#a}澶CrָQvs*Fuunuq[lo{c0#Mٶ mwv;Ӟ0M+Z{wԞ0M%կf ehEnI2? nTnI QN .f`O r"}Z]olILӟk%Ä t"IZyv礀3՟j3uUTX۲gT\P֞(n򰶛'XReO0"S f/> y 0p 5&oL̡rD䊭̻'ND= 6~pxFү1Wq0<ބA:L"qU3B@nֽꭋY?*#Yym &E<QфA&٭{JIǭwayD>0`X2JݛuK5Pjl6p㫏nM/XaX7rAR؏(֗`.]Z]&`6qub" t:8E llaGi tP8j/C2&B2v &(о*`cyJx)yK0MN럟:UՓވ] 1R@)Ɔ)D?*r=!:< :Ӑ8t4k:!pjL ՙ%9 2&>@M6f~[`h=;C1K13BYg7^&g_;v4MzEchȚ[&sh`wslQ;a0nn̩Wvcm6) FהծR$_SW1KkBՍ*=Y=@mN. }\IE9HBhJը+igN}KQ 2QYKIp-. 4/6`Qǰ$;@cwnlcLgO ~7A a _qX&Wt;w:+t͑_H~EtN tx*{&Ut F8).macoˆ'[{,xJo߮-rx:k/r|ws*J}x;8}fGh)Q'tq+ȟέy,4lr ߰~dr+$m 3/W7_sorrxYd?m<8-,ruPa˲هɧ)a8Zow*SlsW?yi|}\b.ǥB]^šxlv7o&7ή7m>o_F= KHϛ|gg\i:Hzܓ3[N?o9Y |0ysϭp咉jt{N?Lzܵm>g7Qky} 5lrwy^m)grC5PŖ nOfRZج%or@CB mjK tO[6A7i=IAwOcRWoGp%% zA˫㟖od<'ԻxK3|~| &:}O7PKkhM3^%v̇0 i_:~}/m82+;_ \]_G77Jor4gy]}畀0P/,K+&Ց_+]v&8@a$*W96ޕaBHELU7ElS$uU^9ÃH| ܯds`ay`7-g8%ktexCGX꫈V-}.u`*@ kC;f̹TPJ32*ȷcSڨyKZ;`S?Gr ݏAiNFP70TZ-MY Orו8tcߞ3NV?0,NmءEE{-{]wl~ 1d0cvb)BC UXT6.;|3^E蒧,mJ,t;e҂$y_o*&[%ӽ, WF)4`s+(B5r i]*By;ɚUT 30#DWx|OmtU6<;ـZ>#9 T (BT(vCOZrٍ(q@&?Fu/Nc 3?2H4ř**>hp'E eB1rB8C@Br :IR^d^d1EE,m{ {?|J̓fJ!f&@r%k, IBe)H .,q~`,vG.9z,5!zɅbeb$uIIґC&!1ܙu$F5DT'G3mڍHc%p-V7C(b_h82Y yW^[92ѨD# $wL/O"$ZmHʣ`oM711L͂wgҧn7ۿ'( +v:*ZɇzyIʷИih̀:AT "%Ef@KS E(OE^CϛH& K@ovR N.7#0~jsLdYk2Luн%̄8 ӧv l_>2 iU3Ok0od.1`^*̦@u9l h-RV,ø6tl$|uNb>+vvrLM%햚ƭ3dTZЫXƳ,;y\%&ŵrlBp_B$hnwEP(#S΅]r){35۝&[ٳYkUC{(RE@V1J#ґ&d̺ߴ$0';'?~pV@ҁ#D ;0 N[ xtzMK+jrS_4t LR )=x 'j}>?Q  3jIL5k6HEWAeO97"/!(Ci:p \Nwȇ-xQm̍Z&GǕ (D(W3DN_vo][)&AwBM%0=MA6 eWpyYu"(O#0ʻQ/ G<7KbQE(!g3s$hd_M};QS-]P뽂ĤZ3+ָےv"雭8|$U&H3! { ˭t2Dh18E1gYMo4܎2XnQ SB.Wd!wJ -Ii颼_LfCqvԘg 4|oBblcY6`]CMr)5pWatB (cmd/,*=ݯ c9z =Mzt[`7r!DMOd#$+:a.5FjD餆f g ØK!<ˈRj4`H(e E]+6(–-ҫSeCȂb,6h]Zt-SVh D$9TPnC8\j@dt ({u` ieX6D YR&>VgDS^o2Wi"EPldHէy9](q_o˴NYIjzď1E;L,W +IZ01kVTBCMufJ](: Mu3vz9\Slnh93-p;b+- ]ޅ rwmY38쐁bD ڭ|C x%_OMp+(ð)%k 42&1Hm`+Z' 1A9&.[5<RvU]=)_0:r=b ll)o㡔>(1ʉ. XFgMb\$3cgl 5 Y8X! 8G!SN`pkkT*C/GL^Wֳg_A ><&x|1:ȸȡ>m ]8EsSV+%%(24YIY\υJ֍\0E'MZ(A#AΚ )A\&K\Iy'NjкqY \"Wwˁ&|E X&y &aȝV:<24jS6/bcr6藇h82&`b ߮"V%!G|k^(S=3i AøPPsTtG9P:,,Yai'[N0ŔE:p D& 8F;-EYI" ){ NBFK-66tfﹼ]EARcH <4MYǓj@& X~`L-4$-Rm\|iGɂ/`.0z?S.H ƻb,yħ %~T}q">ճ9W)h9ͼFٞDrLJvOwooR㟷nQpa8?o[+u@~$}^%L(icoS_~ݟ21Kͻ_~_?N|t躡_~Y/W?ٱ_&! @0 O_㧿^z[KQ_fm~71\7 <2ls>_!Oٚj?WK˗1N/OVw4/SV_>??W 3N3C/Sl!a~w~xa믷̏qןOqT ]q7 Yޛ|;,{]'mevo:ozdߜplgq9۞8my} -ˋ?B˅ҏ,q ?N+8E -LۅqMmu#~?_ 'r_tݏKOzȲ@R%=ZzH˲vwۭ߅ ?grzMSɮ-NEej厷ME'*ûNfя3p^!7'c2hx"SiX}qY3pd\ *[v Wis8it)w^jS˲=W=1EE'P,ޥ?N 0ʰEyq(?B}f=@,B1/ 1ul4A ǡe@)eEotyQ:L^Au5R;YEמ>v%T(v bQC2euڞ(ACee΄]Sm{2*|ϊ,&. ;+wHɖEIc^H=Ml{1}ɮ,mH0[:c '4LpW bm+;pʚǫsdGh[q&ͩA>dCA3l?>gw/\ r䷯7ҧ|:jGb̖-O;fkrNQ`$´a*IL]0]M[)^Y!:Pw uf93x1w F0ecs۵=,|IZS^$t&ry'imt2}>c&rU砙Ҹa v3ɚ+& *?r*LO-5k#wD3;p] /wӖ/#[j og* dx7. bN%۳VDS<}|0rye;JySz7{,ʲUm>AcWY#YM"&$Һ&%J"9]܉5"jrP93ZxYt4=ksav\gaEoZٲ~bEAץ-0?Eȩg|`߇ + uaAx3Dc Anޡڰt7G:IM`'5Er|w`}TZ/1w#ȢnvΤ wyI{4)Pޗ5׋. ,k 1vNjdiZg^V32@`C7yN.Yd(:kgrso4[tiN>Q92gs,Ho3Xa:#ibTMiS.=~{#o!aSxS@UDS)V[] Tm1%=m $g]5"#AFGMV[wm| tۮQ]ل1 qJߪʀz w,/`,e:.@vРRu(_ 2&]x8 QFQ_V"'vW19aȖ >Mk Gu?`'&&G+jLÜ͠>=6DkKeNtFU\'U:>{|G4Vt)e!n4QNQp X#>j84~q1+@>.4>p >']dhv%aZ% H9x1ie@{V7;yLC9@G;:&Rr "u8LS2;# '̥; Pgn;յ)ɱ? òE[T!d=B#_UohLxfK4('Jtr`뫘~Zǂ`lYv3-i\d g+kMt'§@?XW'Z%szJRv^!!cOm4q Ċ?%q6x㵾 /dσs~ *# wD0:>9JLhlg%XT~%wS,ΑBM$ ` Hm3),]3v?cxb/+{KԵipZ(A᳉a[3 6XK?k0#h%Ŷ--8dPJ9Sm3q?'"1YtK<_Ċn磐~}(-,h;x\ܼuck9: ;vN:_&qrqɜ%#QʣN>ЛjT7t0@5iFl ~;j wJc/\~}3x!˲LiCӾ%@{wrs?psDs*&Ka<85h[VtqO0g+x_/ɒ IogA[g<#B Z''/|0_ NC# lYwtT_;0n+IIAtDE764 NHnh$,m_eO0?ySȜa &6O+;1Eݶ*g$WoO!Vv9W7n&Eq G_ǜr=_uTﶎ%(7Agܵ.㾓:X,>=jrn|xDG2*}CR6y6KQ ")r|RȠii@忚zOk|?Xjv ]>c}j^ 7KՒ:T4 3囱<lhgҺ>"t~uNEw!Soe"كMB, Pa,Ӡ('6mH8g0TwڤWv} .ߢ8>_؊FPu ϢNbTKmUvjW8.:hs2 U[%3)>@#;a`Q^5|+)/?,+ãLٵ 4}i234#6en(M[!=*W̚/݄&ysng2peR.WMp y*XauxcƑ~k2+;mB=+<Ԓ{R4/ ZC_B'Iߡ''rJaQFbxx|}Jo~BU0ze!U}dj+JDž 0c垮 `-Qb m3k"S[ӚS^*4ͬ׺=VqZ jޥw}gjbŨFȐ¸gy+,w{!\k>}/dbN\sDaHED!6#\;H#|ln.I@|ʿ6XOl׫;MxBL@?|a h`3]§"^[U keԾQwD-X /T:x)]V>P' [* JNIS[eMHvhB-m޺NMED W2Ӡ5O#F745 z?p`i8$6JVL|7i(}NNټ:ofozr(>X+)B'pw^}&ިLY"+hvzxs6H]u6U{G~)#e}Ѫ+Y"Wt=}:B)*!?\G/7-be82nSЗf?,Iw>Os.Z)!pdILj} 5ﶾib4t @~S̿,щbʐfyerˡiLȆ.FbVvi`$S%9}&;gm[7{GNZ R[=$9Jl0p H>Jkqՠta&3z~ͮh:Lyx(i8ax>#9- bCة'.6*̊:-\[. Ѣ)XB~@Z/hzZXA;yJe"eCXSۥvo- fԾh.pȸzY:Ǭ%=科ޖ#z]#q^<FVr➏e0<#C40:!l n"dj<|TU dx/Cmg@~wN#~crr'E)Jj wBҸ|d` OAB@a\ZM(Gʋ _1l7GJ&}&Cx(fYPaɤE&yC;R"C]wY&gH< 4{EAK4wP ˠmdb>Hґ!0 5-Hxu=vYowf }ZXB)uL%h.#$DZuC~> q2-(2p+4x\ӨZ%~x7MUM9RQ``anNM]rѫpT=-p_n{]7]tȜ3yY‚-^3nsYXJrngϱT2dtbGO?l<r=<s{(m;C؃vh͊ok׺ `4HݕYBE_rG!o) pIAkH% #/:@(/\ߴ#=b*>Gc mYE"5# C?@Hm XP{-þr巔_%9{Gm=Md@nR \>a;̋ N]iC5T.n^Q1{p-5薹EBUe" yT%O82Kka^rVγ qڟ8lE1I.d >э@ƲkUU]mٰE nNB8C h,xw fh)d{|"R"z5]M-OhW*J]*8ԷIꪒaߏjm4'ǃEqMsԛ*'"{ZQ n0IySXCxثF׊qT>ޗNdxJk:8;C,k9AͻR\3^7qip!kp>cP)f~DS.u|ڛc4H&C`k,Ry|Țr`*14:`M| 颎 (Jӥ}p&KS.aJC7Jj'q&Y8( -KPV ֈve]cl276ԓ&+Ƴ&؛ŋ-6B4Rm~9NCx@pB$}ݷ^N iPOjaDuP6R0 i^NtPNn S[9Z&WU $M%9HD"N,"~| [ӱBDS\+DKP BPtYYh_Z3FPVTk 񖋟]7cCzws|s|GMcHɨ jo/[DEk*Rfu#Wj(w WE&]g. ͜s?#Dmo,>GDRޠ}e'Tb]dc%S/T|NB9#ݻ7s!1h8R6xy{Gx -S<)*W5C>B7qs:WF(UkDtGȓCs^a|5 _ E8%] 0FF=-#Ԡ*Qs$QM\'a]w@ݶF†eIbIL>X.?,P魬xsny-HuOrwÏGQC*b =d3hhy aU}# mrwfso]hjSXPf 9ѳXX@oFwm@!m~|+\V٤j1_g|fT]ݵ ۈ eYk%ޕn!}®(u5+>)ߺd {= ẛ[IJkv9|j}7wYބ۲'=[˂a'Fɕ)5.HX=K.VzfF}х @NoK9%, a*'ʂ59oQdB$y}4cEL*^exN۪#[&2.1 uZk<ƙĮo(1n 0j_`)Oq%L({b7vNB.)CiyW{a|W tz^*A8Yj -G8_e^-A qI$=nt{B!-DŽz~bN=4϶sTt, ]?ϼ Cݶ vjLuYEy/}c7} zC&"EM' om9U#t.xH/dJ {Ґۀ+;{0?A39ʼ#(.Vh)>ܩBZnsݛ,P!r,r+[zxw_OnrP@rbur"\.N; n. |pȰyb8uxsxn!A'lr?n]U`HwYD/AU#oox}o&n2Lح'ʣsB+VRaS,Kȣº ZŹؽGhH'5|w07}Jl{(⦯g{ˎ{@oVHNĮf$=vϫ #MU;\!1</CdћR{ǐjj?EWMKT|Cl_uS»0z6?ѥN64{پ$F2kMFa-/̞Reysss$ 8|(p gw˜ l_oqDIXp~0٥k<*|$ۘd)x7eQm\ .kŀ~L9›ɿ]sm2 -)Ow7F+`+?y8~Wg~YOn@ve`<>žF)T9zrW54[[R8A4[AMTe,m?co-TF02;UUkf~ki3bM\x󽽝iu9\YYw~ԮSP WDS)MF=69(KшHݹ)PL, {HOwժ"gar9ڳ_Z8s, Ei ZV?oÿ_XNeW?g}B )|Ru*Ljr1x_-:R8 M/ЮwOkƑYQ`ޕyL?dA1|֗.?@qc"T>׈ *|J'J #Œt`o<EK3ST7+HCG`Y $]Qt@L=LsTځz`2㋉aln]ouL'Qڡb߁d˚wUVϫ_MEyn!; *]psn|ثu>K)F"M"74X@﯋+w6RӦT cfwħ|g {2HigϮ_~f!2{x~+1nd1k- xrUx"o#TSr8ΛbftL=/.\*; 45 GO`<92 -nHC\{kľ/NUag`p w4rDžXLÔ&Irf'xy N[z+Gނ[%`O굢4}'zŁʓe*(sSoz=7`|i|llųYd޾#ZWy+:Ӿ]jd<N B'8Xtѫa05xCN7]&"݊Pl/}bKq>q-39 `pUEֿ;X񎙀%fY59iayEgvp.Q&s%PeFo@]z #b6Tf&{k0ā:Ea<:`6 FDYt>9uRady ZI 4Ǔ`wm4mbӲK!ېnעQْܷbv1z"sl <~,+,FƵI)#Ȥ sܹ~݄[‡o8xG}Hm3VE mDVEJqe^;[fsJk5g|qLݰBAKw\Cj .Q VYn*_20. kRy}>uR|mKVe Vxn91ڜh2W&Ύ^nYLj#S}'Bc*4p B4o*çA x8wv|QelS*ro٭}K^q|WݱZjY'6wo"՜ |+d$M# &\al.ҧw$$Vywv~ ᎙~"0LhLReOUk>rϠ؃(dMF8S{IP PlKL )󗇯ꬒa6 \BՀ/-OT1dC渖p EMUGV@7f#+4FBhah4fix y )~@f~uϯ^:`[{ExŋGt -!ֶ6ͦƴeJ][a`q+߼c@TU#ihy"/Ӫ=SJjBxny}r0^UۑؿyH콆ȼme:`ͣ87L%6 Ü;|qݦ[ruY?:CEdʅ8'U<с,#|^r?;eggpK|fU=TNA[H,R1n Hlj3jdDsF(hDGf"7ߙx"}C:nxy8~|}~r}~;Əu#3(M =sFԮDNf5 l!Yca(Z?V4W!+} hV0@rZo_gtmHLi]ʅr-~胻-mjsϴMIڗkmFx hl T"8P>.sI]ɼ!^qMXrJ>b4,/?Ī?X.6Fypzrv :'oQ5asPs "mAzBXL7nߘ2!gF1L G\L 74/YqGs5O'g豪xtT76ԏ/9NR;uA5lo&q{\Jx.'5HE#0~ }O%dVaB^T\88ԭ,B-/Cd.Iȫܣgdh+v{BG<";+ =q vy@쀞$'mceQM2pǦw8d%٣ᴄǺiSZ*ϔמcrГd!'u=Uwb%3487Hg 5 *~VCj1ip}vx,ug~ z:IF:eדL (őocc/lC#d}i2 缵;eL֖BJq,P8;Y\@,"]^kSPw}7i-[ ZR~)WUn-DP  0b$muلOܾ_=*KH(b}5Ȋ WqR.8DI x-cI.6NИrvkoK{:dFcoMBy3Z ,l Z0,IY0u>x q5e;Z_'S}zIZF8F#njNk̈3|U7S!IE9^?]mO n1)?fK;u#<^y^juѩKG4$:0=nx|AoClros-(Yj l|z=QKp;* v9K9$W('D]tgK|ǻ{%Xl7 sXĽ/D|eߡOEł ቱsKH4.c6Erd~J9磅@RD4Dmk; OC'+a9z`=?إ#ax; kMV%;Z^5Wj>]iCK5J>ru$3=GYU.`eutZ} ߏ8 =VuNG ۪x~ 59a"0*z8Zҏ{9^ȿ|{@Jbgn!\_m\+%x_| gem?^!*(`O7^ɬsj>DU|Flmz\kӞ4O'Z}ZC1&QE8C68ۨ~T1OuwvƇs%)f d'X‚K3q.w)|438XRژtz1QzCm"Ҁℯ~h49f$VʕPmY51czUt1INД\Ds 2&9a`"'-䭕3G#$unlu ͑~M*6b5r=tM4"IqTad*n&|ThIәC=+OGٮ1nl냣}XӴ} Wqi"a,ɰcSl(+p FnEqW( _$Kx|a{H:(mg{odL@FB#4'n B^7Y1C2"] φ.ͽTk>ߧ/8N|Qqߑ'{Tݨ*Ti^_٣I*. i絓2%ml|mr'|MeCi%ЭQ]Kc[Di`E=3mzh%QiF-]alv[%T*xd"! äh)Oӄ"(H~dtͿx JLwP7 j4Xw@"l&.KņŚexKKkm1|td,L.$h\S\K__O4:am> i LX*_9,BuV7ØlRśG9/Te^ oǨ=ʪw1)3b92܅6M寯5+rxXдIKeX!Jcl1[A0T|{]2k4{+N#@gl3%SzB4ϺϷqKiJ:RR;g?jA9sC.rc86H5<>Rb-O 5zG~9o$X~dZZ+'Xb#7{u# 4b^_WӇq u& FFh 2;bj^RIlyS5^V-*|xKEM:5x1Й3EWkHNDgxDPjZ.2ӊsBו8'IOނg $=P{Z Ͻ\ftuN+4ybKGf eԹה]`^8&t?Tϓkg}nȄC7mQ''}8i4M kZ~My~UƶXrݾ6^&ݾ1`ؗ 3! -Bk"ЌM?haV6X/WbCB1z6h&qQ@%\8!X~$ܘT+yG8aJ'-񕰿Gh `iwzrx0{{<ŻݞRq<*R-NtKmɭ)C}ƍS;F|6ew퇜daQҘE'PsWdu3/(qUk`kv'7Lp-(0OP}< KY"-\:OB9K}tW} 1KNQ5yf z46ܣQ#JϷw[rO}Ո.sG q3DHыs$iݠʰO;#N$)pz4*\<5R.Uf>kȊ^4Tؤ1RPLEMTvݵ zd_y|Gҁ%y4h:Dt4mZmVN.QǙw>L9 rm4}?:/tL&~d̩|:YrOGZG9F+(T]2`5'{@z9aa~Q=JUI`3U+O!"QiE柃|s*YۂBǀ :g52Ql4C{cf+%}J|DhݰӠY0S9Ds)x׍/k6}n zoq#Y?3ӃuNR+,nΙhV&p*S$ټO=2S3JI-! Pp;e 0zQHBB7U䅞qQ +׳4K#Byfʑsx$G -j]ԥدEٖ L?c6:9lpѱv'4 S+#I~lfc2" TC$}~_Ur82E zP\s<-!Oɏ! pNl J0CL)O|@4,i@W#afj"6 0 z#-YF$POo^3^.GTc t+:!ih䡲x]$?/f޷cӘ!<+Qk:&k1n 6mgOU v+~&v;'ᇊFP0e9둩he0Wr-hl9axeU}BǯLNdTI{:­: ̑O6]])wЙbhA}fDk5;tOz8kUzx5b9k&~VQf@Jʈ~D_hqo4uo#j>BؤضSUNv9I'ZH,XQd,Z@IFDțGH 'LBTstIAo!oP*Uޔ% !|xF*SI 3P>_MLcZޗ(Ƿ/e8Z6?}&qx/^ncI{; xV,rB8z!c,,QP RD]k~DƲLx‘~([v ?dq(LrCҬOgo퐿9W!RJ: e^!3z :<==<>u`-ː.!)_PׄUzE؊4aCDm:3U?+X~:A#^p9Cuvmk>-l%h^ŒM@k#|b=d"iC8iaYRܮ1zJAb!okS` !@(IVA1#Cf[JWdiz1{LY‡̴X|sAs0oP[VDҚupx@}XmTaDvf"vngQU{Dr>eE4CB Gݧ,~8~A[s9>-M[&_pn[HȲ{4|zh:Ǿ>4~\CT9>ئnd3{-SwSOOtuc9a01v*Gcyb7^:MpQ̖g m$7g|i7zz^5JpV50^9xc7{-/AxfiW\$bI94&Zʅ Q?L~$삫񓭏Pq : :Ӫ{a$/K?Czl=5I"i4n9BfC1I%|q;Lѥ ~: Vn~Es86]"l 3ɻemKj+zKS:vֈz1KU2z_=ɿ4F'px y(%ܿX$o6dO”rq3XDjcydoK`c;qV\PfCp g_ gVsN7C>0Z"fD~eRj>^J>8HyЫt9`Td ^wW5x 0 FRj8ַsmK8Vv$7~4k*wTb"$+lt*.\ O|& H#fxG B7MxXܿH/ ͸szƶ,@'X| x3W_9_6r'So/ N1}8WV}s17u@T֮i S"%}EPEw`Q,$LCXs>2`^-bTKn (`hWp;'-֍/ ͆tR`v˜p~;_1>CID! 8Hj*)6_wuE^.ό4ޮV4gT䍜ޱ%ozÍ =yމ)Xpᗁxޚ%{|t }`CΩ`9&N4ڈYH;|jKAK\yH)7蜂lĂK>I{Cz8ng>\ +ZB,v!#r S#ǒcYb"0sjUŴ%sQӪh 6WV;l-R&|76}4BƁS2K CUiLI<}V zzx jg- p Ȣi>~tZ KD ]^fCs-۔x7F̓meƹ= L˥7Nџރ@d{A*u S(u{:YV}r@:B"'ĭqn A"IOh9N׮nj8|R_uz:mZ6) j:l{" 0t**P1F'^@HPv*:'3e͜iQ6&`8H2i&(01g/ޟGga_b{BʙB!˰ 0*#֪BN@&ygzwV }ԫ\}QPM_e0N lHD< LڷƾT?|-b[F>.kl@Ixa.n?ؓH!-Y;lO$%=p ]j`fb~8^Vwu>'4Kh"|8Y%/{uB4GD)C? 04ޑ O!<~L^pzz q94ykj D3Z  hOilb:ADsADPVfw̋\%}K1=]R)߹^4idA{T'I֌Xi|1*FrɠOoOw1`Sj]= Dd,2& s7n-0M)8?|O|ssTC=mVv īɉ`S_OPuqL[J.}VcLfR큠 ~X;k-%RXK Ea vFЎ*Oھy~ki: -}˂,Y Q 9; ΄PgKOb5^^T j3t{@.Z8F1ĒT @z#lf)^"OӒ(H6d!m=$"q-ٙ)ϥlܱyROGjFrK9pٌKz%_A A1-Є]nbl\7IOv_^B[Q o=XĴ61N)YW_W| =G,̩w)kafƤoުTNӿc9¹"n͈J$18٨Q:%L%?h21vs3P+a/ډZ0R*]Cn0ayjb,u)T:%2;6rMvzfԞ%%pdžXRfwܜ?NJH\NADcDaT`ۧͲ\?L&SeM7;8a@>ۛ9b]dbcH;zy]{_1P_ d%=E΅FUjqJIW"{s7U}޺Lp`a7˖e ʅRa´ v'wJ (DHL®|?4.IZ5)495.UF+3]?Oݿ_?wWVW-42hVM_!D2o>RʿeH֣'f-M p(5W-y}فGX8 iC Yx~F!OrdD ΀ƌGFCAk S}y&I;]doE'v:,\Kh׭|dSoBD̷)ˊBdo1T~ǔSuT4$Aq_?}M!QoxYR^谫\fls7&=(H }qpD0@0+= 2`M|&rsϮ^oUa*f\ J?*~qٱʼ:f^戊}r{1Њ$kl,Ҡeư<ä}!ONJEy:mg:Q%`?K20a"&c"FB2K"h)U݄_'QW 崝T?<cHrH8WqPєe}LfișVu?],rүefLKTջ#d^{c%pyi\]^13-߸w\$ w3(>r(?d  ;Jt"[ʄ,vنd -9yk{d 6is-^|2Հ01EdƆ ˀ7xKWL#:ǂEX¯A -S^/u}RMNYpa31Ի4X`)eQ`LCUV;O U>2K.vK(LŊX5F[s4fb_Qஇ&b_b[sr,p95Nf(](CyAхB-nɢ%[(/Z{jeڲ\YҽE/n'OΆ&Oa^End٤? f֎Re цh\ R,g7LA ɟTG86MkV(@ӲrW:ǽI.Y[Eq \\0)X7T7l>I1@UM-c%T8]75%o~6+Džt][痣 [_2+k>EUb@7'*zxEtnbds׃ƣENO:tM(y#zzWw?}9o0Uľut+g[viIhh׹~U9*Q{Bn0!Mo=NB;KyCbV/(.ן@ih{= Vzi(yMQ.-btY_dhn"L(zۡ *ȄlWIl?qQ&%lY(zLTQq kԔ7/H+ EY1:1ki1Zqo$KۘxRF|B]/'e5;cHc_NHZW$ϖ*Np '=3eeBO,'h)]?QNgK$vgY:HIV`yV%]I>;A_)i7J5eUrۂ0\|]Z/OM@ӊkpȇCX +{ݿtO1DkCZfv un6G 2̦7G  9e6zwv[0xae~Hi6YSuvxC.=nH#B7XYùd_ghvXKi2s%dP`NioHJ'C8DP+K\O"pP\հc?qBf%='U ]Z81AiB߿=8!m\ MB?ADT_#Opj'^)_Zg 9//on`}Įt/W0nΌE(no 7޸1nO!N)*!L%r,ai=?Ζ;|\/* x%'um ~TG84L67wzA]fд_=C ޱO8no0@]%T)|<Ѷdҝ. KD&m@A};2>, #w4S ޒ@iZʩG% ǒr^ЖF4e@y) %ӄ`%lK G,ʌ4N#CT7Bs|@߰;v$9[-_aBKd)'ڿGGPAʥNu$*ЧzrNEC1^4Kf_:O 1WQ}tt{+!$⫝̸VN} Le[X{5eњ45#EQ`yƚH}T#R5T o7PI>M/gMH6aiw_ցjƵ VA| f`d[__ RNw dPWV_q~2? +aI=SΊ%ȕA nDg1אhay87NN_3H0D8VyC%XcJGC,ͮޣd0D:|zEY#L}j')qoSr[w1XT$=UT.[%:d \h3iΨӣR@,C_z{.~ TZXnmH !,$u <' iFBI??;jD\4n17F, +>67ٖo+JVs6{ !6't*iIɥ'>l!.aۃ, N՝jk#=*M5Iv1ңg(IGN5Z]hW^TM|`f)cB0o,Dv1|>FGӧ+^ >adcv63a1>'1m&@4)o+&:Sƭd`-1b˻KYTr*\r̕-el>QU@It LMzC"< jU\׿B9@/#YV`o;{Z.]O>~{[tTճnFm9LicMb0 W Ю< /ˉ)D9;LKw%ю@JX1*wL.ZnA=x h a戉j~1NҜ~\\6<(\;G|*1Ԓ|QJ-c(d +'ibg(oNLY1zMX /i!_ǹ̫.UO>.?oO;dbk^e@7/twhv؈k5%z%kHlaS`+2L>q2tq3ZD> d] !Hxfn}A߫ ƷUD:q Aᛞ3PYO%uYN{t)۹ eԑ/rEc XIod1*T1]}eǩ%oD^$DM.e}l̎E]g4 aZ0 q>+xQȳO5ovo_K8E/AfϢ'63DnE ?^ґlLH$bj@ TtJ'l_eaT]g|IHzHsyQm/8D I@$ [S?gBGvE&] P͋t8<ˆɣWsjWO3Gʂ1oM^xީ|+_2us2bG#^:_ U} Zp`_Ŕ|5箏f={J!n//Yc털q`nZ.X~NB>hf5d?a_'̃P 6Vk`ΜwƔ(!.|gç~;V1ߏ!-(<3̓zb-woKkѿ4|j6$^I⮭,Yd]IHam+~GtpR**e v40|#L&Ǡ*'ҍ̉TH^mN~yT9H]tjY: 8)m4yop̖v7Ehz¸4HWKJ`7/3WvT oHi8>tX$̀2FF oN|~-Ѭj9zCu>dƄK̼\,j_kWPG wژ'#$6֚~tu8cĭ>O FW ִ`esr2(ב Զ3pY1ٿ ֖>x[_Gy$,nPKo8Y1a.wʹ7C9D?7iZklTb8B@p v'cDRN+ȼ=.F@ٛy_YR( ;}· E dj%l#y@EVʮhHO—''QޓBYrHĄ1􂌗SzoRRqL te܋ygW+{\uHT#:P)%,uqlSc뒫QM9M##}ua5^w1n>~w%,Z'Lv t`I9%/l6d3 5NA>T6/OutI@9'E_Vߘ73sDkNEMd"a\9 &Jnd䛂Վ q/Xݞ 4W}zɘ MNajMGbk-nC4YE;T4 lD2=տ2?3]W5hs)ލ=l kH߃R-8fШ(fЈVV:ىFލYb6_Y _65̋xrSגItߏ5kOÊBr.//l׬/M{ Ԑ`Irg^poOEs(bN:߯A2@_4y9:S_( O"R.I5rh4HʭM]8YAp9qq&5iO6ն_Q$!W@n&*ٳ+bh].@7@Eֶjfm)X3#3)iMy v$A̯ѿoadB Q{ 4ѩQrXH &%^JDf!xu cVH!4̀R^_rfFFsfM6 `NU0B1MO\/޾H!Lz n=|89ɒ"1>/Avzdc+ ,ٜ60I4|C,Zg/dN\sDNp&MWa(s s.K+yLSοhzaH|D gجi2-nzvQ>N(Sk_hydrJTYD/E2FDPMow6_W7HLɭ9G!KPG̸/>vhʜ4 (:>R?qiWXM=V@N^xs(B+anyL8zk|CQoRg*;ag|!.DDUi}vMGOL_F,P$1c@$.XD"!|+i^=_((LEӂ:_̕Hn@0^&g1{_Ӷ L .nNDGbv}\d|r WijB3d9oX1HB=( Z2lHoN?Q迋d[Z$ڨA~!12QS'7 fW<&{ "K'3wC=tpDOnKTH0}T#yyh|cFž.yuq\^r=9vtg>7hDK iӻ%fws=԰CoSHZh6sGF+?)#`.hP2@·VnoujW^#A' `le>f$PH. tChqiWb EL/2_VFԧȂWGfkGhe:QU!2dkE/ ĸT)T L`$AW+\颇j>"%  {ZoT7cy|sߨ̈ :V9dvNY!"s'Y|"U UzzOr$ IKQyQ&^ȣ!I>*] ̿ǧ8؊^F;wjny"IQ!T.#?FGo ؓ9R0tH}mߣU4y7|,i-sSObKQ3fTsX<֏K*mk& Q.oߪ]cQc{,eX}EmmSA[UFFvɸ}%|:}h|M"ѧϩrqmT 8!>B5d$}s#&^sKũNùw3̧5:2;dSw~385e|f.I",\ ߃R:li&0h95MͻIH(Vò߿L Pu0%f zR=sr]e Z".֓a:Ì ow I[>Wy\'6z/X9#7l"R/3z엜mܖ{JF)d8FFq@Oм$r\߲O:lPι&2@03~҅/ԃ㍬D%= },C ~!6#BC+ ur!pnCLKK2áb XO0.5y}nQ_i;FBzc CJBi+4?rпJÊ2|_0+b>[U'I`Ќ:g"s">%+;3ρSf&&џ2% DE9.w*HфA<\& !ʨ'#]{1E^@Bw_3"g ^ɫ3Xj@QiFb%IYNlT6ǁ!_s#ڏ+PΊFw>m0ĪAhGmضqLY%E^Kgjn~0OHj`U[284ضJ-~TO\ - Fb6 ~z@z|1E_򹉣3g'E;Cb+.bR;Țzq7RR^hCcs A \htH /4vER5_uo[óL11~5xA#cϤ\'8Vs>y޻TBz\̢oz`r|CrRcw]K_$RmSǷ-9WUo(::B'٬U=Lz>D('dAW y+^/9nd[,y p>al1&.(̴lZҍBҼ!BsyOfNܿ,z " 7im%tYlirT|_Ժ5<_DB>aUtyFmS/wRz^)<ǣރ!;= eF"41_HA,y`Ԍcͫ7 'ĕ\QM!xyu~COv.rT_Jzu[7gOzd!-EpNQ?L?(`o O軏Rb ij8QōCᱬ(F5.10:%AruK?zN}P ]X_Z}sMHE lsBW~Ǔq&[砭^U †q0_Gƌf'J;Oן)/8Aaa%yيZkD}a`BMzdYHޟj,{(P]⑆#؆۪G$mD ]%$V\dT% 6 -OsUc,B"mC2L*to'h}y"\Q}]"E'mۅ]\9W93Mj_kc$;ѭ#7^1fֿ 5I0x8V)|4RprK|%J,'`T [2LD'`h o{;QD~!>Gs:׉US1Ciy.r U/Kk˱R\&j(RMzUBi-[_0n!Kz⅙mبo.fE?`'9@ PÌZUS5l>3;7yg,*o T;SW"Vޘ` 2`Դ܋'iIzN&6-Yd.: ˶.."- 26H"*kn" *֧s|cxoU>O}bZ[a3G9v4Ccu/J̦C4Tl~ZD$|oPkX5RXFWW`C/T_ta?b :̇ L1CHjs1xM\ѩXU4ّס Mu WxEaHwm}SVN~{O~%t!(ToUl&5sq5į$qqbǤ#!;,x,9b;D㋵pcA}$)XXL@P2yZhpR2!lj+~ ?wmiGbɭ46M_baĿ =cieG}t ^_:VoV"S)bcUj͂;Vޟmߌ8gz߆,cz҅n%z8 (i/VJ,͌;4SNXê̢?Ӛex+`gAv,]_ ǥNau6(l:I~5].Yɱٿq5vz0]tFDӑGF:i u4Q sX:LVWOdItԈe3Fϭ=?q bo8q# {XcͤOZL=<AyJ{ˣrn#-SyN8%0%ܡD^]QĺAtp1 W[TZOf&ZJ<"ȕR;/ ^s9ٹIΜ#&⏢|7?s0+LHhar&3fK:2<rB8N*2-k\|uU_nĐY<q9kWӴ WWs߯zqdmc}O괈I#)O3ah`#UKXdvEoRKvZՉM2T#_baPq&pNFf>TVH^1w#'5v I(A3Puj輕\(+xb 2GXaj{~ͩ I+FIesbw{y]h Pti_).0~xvAG2uPBn#'5sz>lҋFi,x)Lc6{\uݑ~J Lc˛o@n,SDm+ĞzLW=1tGqJ:X*{U͟s{š&j ˊ_w[Lג R%[on]D딈{Z1=}ih?  aɔFZ$j~jΏ :1.)HJ}<*W.k~-b F=,Dm^hW!L:fNuF.vGv9!,GPw2S|,Ph."L>v,PϒRE2W+u$+03/`GTSgyq->`Zl·2̪$ӕ1]\3'ķBbO$փ,`uyUvjI:ir`a!=d-oqIЍl, Jp2 tjL) 1)uhNH4{RYLN1X.A\* ᗦ8lX}%L!- +ْ>5,HAŎpa\:3c$ϖa1|4+xyo_Od#Epc b'GwZj}.',y}Z'Gg(p&z8 B-dfc/qbU%<4bb}'NE <>t#@dV7i+hsS H"Η'rsx[g&;o/֤Q5.D7~lT2Nn94b;˦<VpCu}\7NDpf$/@[( 5VQ(No:XDO8ھΖXe,^Ri^qI>õePYCi5*tꊣW6=62q$~}Edf\y3RJ̰}D;`rjhx,oE.T6䶼4e)A)VdڰvfN@%^*/q+fՈ"_v_bx񉕑W8ZIn&L@&>/Kj1ObE\Uz2*[줹oήDz&hpc cR-E)x#N[xKW_F-5]82 qX& s@۰\Mn%x4&hʤ{Ǜx_xX}B_ʱ8,ю.QX$NzgbsB>{5y Crkۋmbsgy]cNt}gZ=%JC}YX~z^ XPMi.@0y#jnt6*Ͼ@wL  *śJK1^ə~?Qs>VEvq_2̈њx0+"y(N?ZbLnqD*xԉN"kn?КwJrG11ӵt yߩ% :]Ot@u x'Ex7I,e;A;vK nM8mRPcMiWqD8- uhN=XC Kau%dDKhf@A#A_VG;WzHs'dCb i /D@{"xtU`$OD~A\|mGH7;r L_I})ЊJ B6C,]%0,!VM%_HJ!ܿ7u܎:_Zq3ݎǻon^;_Ҷ(X,Ƥb_PbIyYt#Fϧg$M/,ޘQ > ˤ6= )(]=DsP#bƏˡS6p_ w >&fؿCTdXQyXn'Q1A~iNc&!t3~W5@PFz!4m]8΁43: 5nuJEoUTJh2~PI |SNwhԏZF#'TH .>Z<8iLJaIsR Q)v&nt5L~.j+/!A~sDm% VYQ' \/<Bd[k랤ZKtv`U4YI! Eя0Z!QQ,JKY\Me%YXJJedW(2pa55E]18N /Aהּ056YB-Pk+j23waɄ_{+gDKյ*enWPIe}!ltХN1" P ]>[uJ2"bW~rrEkWG [QoyPl2nOgY7߹᠈uzcL엖+a؞7GHy#/">d{VM:_wdogKC-) t6,Vc$!l. m15XyzMP6#*e]~A_?/S`p>]јPqR֚;MK:561Q^]3OI*EMrm|$)P TʲgĞ!֓/CH޻ BHm}Y H:_O-`ʟxF x:i@?!Toҽ :P~lEuH\qe ,Ζ;);X[ V.w==G[Y-"z>wowzQ@og5e1FK𲺯 F%mUU7`=C?U-JSbk |3Ì-TEIŚ,2hAis& gNZ #/s|$6w|E/73̽<5P-ε9Pw)EFڎILdY~ 5ǣ7X^:ӟ֝Z.;nm n8AP:B|4JV`geG{`%Z? &`%n W3ȔKEj~XL #|Ih:ZakDdcD5kȿs0t]>on-(0+tI8SiFNF_:s\g{p3 ?"%'!6e_Ikox},20 RD%+73P}nbхmgkX(Q) v_Fx,d1hyʾP}e JwԤ}{O`&KJ_d?GY>ܲj!yj$\f(ѤJ ß+KQn]'kR`0a8<˼eVvA~anu*BExcPMj6XRԻdhZޣs17@Wd B.~n;zglΟ9/HdΩ /{{03wSC{7bz)σ)jVH2 1*KMR I[ 0=  I5+éK [*uDv($&Tkm<i6D>q=(yYʢ4]ro1pcnKmUP24 H $F.t!$jDXecl?(XDٌyIګCK(Xш WJAY2!P{Qrsբ(ymv+eKe:q$JQOƞɽZ](R`[|p˯NIMU.@ uc*K+ 댰/}'ۆ >OޏM64.wPF#c{uXC{B]Q%_,PԲvyٳs3 Z0/bAKe2gz Ғ~g^ ;"rtǫiYr&p#cG5Xݑ-'{XTx׆kE ވuVt!x$Լ/;J^κ6uGbYV VdƧl'⦈ sg%ҟOO6mg:ɏI{NoXPS4㋑ WQe -WIZ?D2tH.53L/(^Ck)u/@j3h&%5 ύ&ʋ(yPWo-1eыfqPNO^{/12r,.%JE|1Y+^ՙsw&pVJRq˸"@;}<ZYAĕ8ncCqQ:e+&Rux>S)WPɁRa;8Ǿn"%ԪУ}}nqq5ŋfq)o@#n} ރ-ϲ&>lT+IJ&UE>:_kd- V_^V*7%(ʵ*+ 9nVqoZ->T6^Є3TR+ gQLHD'uCF:[ S(ҞŴFVڬA%:>mpP~`) Ӻ2p.]U>1v%OJzJKD٧Cku6P^"ڋ_}6ŠdGsIR]_e44*5[_4d)ZD!_W(#A~/-0A :>ÿjrFM?Rϛ4!AeP{Zg`W{^@ZO jփ,%%uZuH#X4qB-k佫ؾ `6(SؖH+;[},%")L|zIs&Xگ7 Z(j qVeXLهGp ,:Jrߔ; m 똇/pc7x$?@[%˵uu}A `P9@]@$E.+)eC›cfkY?Z8DҧXFZñ_}?IiP:&OVH_a^< +!u`2(wY>lWY.tl9k/3z8ֈ=@؉\/P&`]/1[~Lc)=T PdT4$͏f+9rE'/`=t)0)ꙉ))uK Fߧg%}CN_(*V/x1#+ )&̬SYlX]0]U+,R *:CRr,]KnѢJ~@5Aɦ}U` ~VN\lK[!~; (\eyN>)S__PD4@C(y8|r vǑM Jh˥ JFy_A3SZrgSn)(sÝY*qڸsZǍ6I-?-i$33B O9rYQ!5MPC5eXZUkou Ez~7Pe&(Iv[3A"Hn!XHUSpLM5PURVyG`/-[Cc B=5Z<8`ao/ ]L |tzB2:Ǒ|#?\ɽ>e*ۮRaf ] Z#JmS!G }CDEi)ZdCKaGb?jLo;0ᅨ*0=zvBgK\'ey,67o'o 'V7 `Oj;PIJYZrv&nܯʚ m“ycg)&iErrB!2={uY{dM]nG^+(&7kBմ&CJ(ak*zvܪ&tM+M׍bª~F! PkXplϬJO.H=,~I (sURJcioGF5(Osd &tPoFSˤT5`hRfkw>bc$;,'GT`1 īY5ԇNXxNS LUFVASNEb+/B\G&?b"1d+e5!k.wP$@jP+8p`yc"ĊmSs׍0 t`:DvdsǕ\s#2sK9CLS^@`A $oG]Lgkp7dT<dZ8J@΁,+@~#/wZ@鳌gf,ah/x\ H2-%rWMEnR<;?;n/-{NHT%D;pso#@k.SVw=*tpűMD(\\Dyqvm,\B/oX"Ρg59n "wӾҞY-ˤtpu)ٰ_:t-LiJdܹt+$:q`MOU-_O53[/I&P`3jV<[kWs̟J^Ls|ڰA+z^<|bz+Uَ,RJo|P'um8LSkx-Gѣ}Z9=_xg,hh04=e\S Q!\ $>\UHpW~O ۪an,y 6c}tZ^N\Ԅ}S8Cy݅XX AxqEG!m0yVicLq`VSĞ.M@_ZrB0Oen%S"MoTu.P3p3?4 ͆GAW 7I5+YԤrXܡČHes5 6RK@/__Ju˷{s%6_Hj{٧}CH^r 0c|E49|K,P I9@/[}pԇ}liAϸOx.y) YMuKnLJ~s'H>w" CNt1*F{2*fԮB8R ?#yP*:<.'4ط>Z'?i^Dm>xZ\7&Pg_̲A" B)[K0m.u6Rʑ7U-zxaॅxWaO.v ɽF]#GiۥmjěOWKey5?%M?ֿ|c ʈ4B3 c+:So_-~!n>Z2Voy/?2**з5ۤY?j}GEl&feH3+N dpFGbRsk x_y;6>]Ô;4ňgE?ƨlm;̒ι$4͢("}eDқR Ͳ| )kΈfr/YyWoW>Ņ'6CbBi㽞#..4lQm#eGmR|8ZV~3aVrH't~ćuڈ,Wwsa+>H(V>pmk2K 3:z_zQ˷KY#._Wd[pȈCz$K] u/#6qhykl=.oY鿃+XF~̆+RX obl4H׸jcnQiŒ(r*).TĈ!XCÁq7[M٩V-,9S.QS/q+Ji)m"ʇ[]U0pDr!Es2NDb}̖:N) V~-U놀|)jMeA)=q殐lj6o}~_m#<}%8kuJ.[OkDQ2R(er#lM\`#+6j9i`뉙\h3QS@\݄ȫy9 (K^xEQ2kׂg\a֩Y~',N_H:c8%F[\yXxg1,ǀ4'+J,6;NF:]BR|!Nj|d|BUU_9g؅*މ$/;麊Ѓ:-\;>yQ6JWuqB(cYg( aX,M SIV}k}6XCp=oܽ\o7>cQʴe+6lUυ_U}Og)٩~Z_a?ZmӣP&TА2SrIY_є*0 x9yv>ˡRY,„&-]2-ej&+C݂0>[}A*$B`e{# tp>>:ϿD!p/?'fl&bS7Vg5yQ-ijlmI1활RzS#d]GLz-Q}h6%AeRެTV ]+S"Q/lEJwvoLu顡;Pǚ--:tx`%L3U*qEw-2V͒P#7hE'8z 肶VUub ߤ(F"#ZU#:|2ȭEljh`?jzgݍ_`6,H>5SDr͈ؿoqfGA#.7"el}"#Zc kdye ݋tOLޣӗ FQput ^j"Fv!/qæVvCz֏'ݯr9z61KUz_FH3>>Ka'9H H}? |GZp%T$FEdNul= !ܲC,-\`>y ]q?GmEP,piHbCZm>u\{4hFXg +s8_p}fݺ*6uF^*쩾4h~.l=C=O' P?p7ߍ鵸O‰S$-8z87Fk)~-:zu,e*+Ƶn:)Ά+c#wXir]^-Zula2@[^ ,KMP|L~4cYvW ZeŀK˔GǚvU% /e@}v}Ϲ$# _ê`D}~>Ӎnʱ>4-E $5X{oGq^O",J#dܴzgB"}:8mbXT`;ϺP`x ExƸWm (hVwgdșf{L AY[hwD TCu1G'^}9טY yJEh=Ai^%5cyH A߿HQ{ B=!9;NnR F+z+3mtc6ʾ'I f*y0hp42Oq+J[v/[~ |HjteFlb&ο,&H' ~n? cp9d &.@K9R;8;jr C1|a}5RtUyacLnfEq7U@?r^Ò̃~kz* SimnQ!=q%3ڹ&.@,|\AmI)CH70v5a@ =pi#:5>3R|7 d*cǭȘ'iĀsYs«U _ D Wov5?캬On' 5[IygIT ٵ)jӼA퇻&JrjH zW'lcABI<"f7uN*%1w;ץQoINrZEwfCF<}$GhY} @.i yrpOQ=>T?,v0:SCqwλqW(ݧIJrd㍄׸d^<Y/>@@mE,d-^N@Mן%ҨUUixd!W> &Qɱ'7tqgaM![&iZє:p @qاW)B(? ^Pq eFtk*B:j٢o\ǥ43E\T<y@0G&f h fTgd1|bysn_tBΦ쓀^ߍ3t+?qTI}!꽁)Q|3#{C;϶Nb~?8Qa^CPj}@ɋm5OڮWF'l/m= ?J/1Ot"Vpg)faЗxa^,_i۔`% l k?Au LV3ȝHl-PmrDs%tOO>[hSu3 HVl;"ʠz 9HlWcr.c|C0|@m]s_u]-yvcňmcS+LƘü}m߆ n$ã"lNIi}} ݈%;[uc'>@0-qĿ4]eTܰrCcbj.=WJϊAVG:iwĄo͏qmAMG`TWh>zwK~oA5+ ]{lf;c \y &6̵VBvA_8p1 dlrX =;u%mV$~9X`qj}U.vׂ4<`lj7:O?7dl.νݧ̍.>I,ۇ$O-o}vET%>MvPWy_E)_lEoWK@*WK[EtyT%|U=viP"w$KGÌw;,Gʚ ,Gi]kkmUޙPކ/H;!O KRCxW?*}yeaj0U\哞qQ96{Rb_c7aimzыaf׊k/PV-slEqExa1 i>mq,yBc~f({lOnWiGmV*'n6zeXG7o߭f`}=xRYi<_;vؖp-kҏUGn|%zx)BfzoKO|uFG֢¥EQivX@-nQ?LLKu\_z!J T Fq7ߪ!0YneB$%}-5H)/1mmJI S++Fxwt<ʇy{D3PƂ3ärVY< 4zݑ>0EnR@O,5bUX㷰)J PDfw:ǚ2.9CJt VgMXZ-`S6y[Bh⿲X#됝 bQN7AeVz%(.  >yS>6!7΍:̠Tʹ8]jIv᩺ EM YK͹- OR3[9!A#@%ؠUL,T\O!OEXD7?YZ&ۆV:Gp b* dͳk,&S=n6Z3$#ǻ?45^]v|<' LӦpʰvLTm̔։&EgSIo~DX^%jJehaiﴥ>h_.Kpk>s^U;J|J.^B `uaz Ndu?o" ??g"d BtJ Vf[hged(^_Wr;aNe2Ae2OM*ھv3CC3Z3lQGr_J] GgZc{Mt`F7QXj7^ B]CN uqFie&x2I:m]bXԨMڞJO@ ?Y>L>D)>mYC:]7Zc|CxIDקȵ(]Bj}vBq-`$.h<;H w?kͳe t%VԺ# nFbIY7نJYɮ|'pƆs3YY Y9MT =a xDk}uIE;~d?- 󺼀#ԫ(-8F@I_:U%t96>r :Gt7/.1ViS=l`\.NۈKz\+H%*$毩y#}Zڽ[T!#庽O`v,7`,e6hn\>Aq`8b ݈1l" z4߿`h,匛pT'pƦ ¸oI>$gˇkd`=RL@QF#2r3n0Ark{*TslhɈFVJ@[]h[hY's؅h1imElhY9$`~a+ %h`F2y@"wJi? s'е'bN ry!f0 ssǃ5ȼnͬ{*B37p 7HqsX`{Ho!> |D@qHRHy|@D$sIQn)i8W[]6_kZbTPai0e쪦/"vaXgaDt>*Z.fV,ߐWRMo[:8C[j{tWf*v@P n"doJG7s`yfVeJ ).7wJ ) J?%58TkqUTHg"ЎII/Ywtq#p [M'al\$2ڢ۫:3ۧijY/) Ys 'ꂖN)wR>|D ,JE+1_*p"|E%kmnrzaf@\tgYUoɜJ r؊,9R4a #ɕq=EZRdtwy汷_Dd&zJ͕Gϛ|\GjMw& YR9-L]9Di( cfoif8dž C?OUpV؂mMV-UHI  -L-v)j:6 L)#OOOLȷ%I*7?`Ⱦ~#?Ν&ջ->~1:r3O,۲8IXC$VfgUDq]O'/IcTmYG\dnYL c~\K]^~a+Z[& 6 1ɎeRyL ۃm[M&)X ҴOX+f{%-?i<"2;DE7u HOdݔuYdᣛ{ɒ4jͭb]; ۷ m:]/I~N.NIc7kŷ277E0, p W}^B#F֍o7݌H&j29N7@ h*3}@(ޒe8 1{5뛸8co[ hG|WdRe(0sLy{)w,,Bh70o#~ /rON1m/~~@rSC"yfI D+ef0kNo7o=ՙ{]ݲ SXe:e-7~W(T`C6y;#M* S+9L,'/1~p ONgXS\ݜM]nOXķ[;u Hda/Tإe,ĩ墘h'ҵ"DGwiAʁrbNLx>~[/=2HYx;ϲHb"`U < ?撼%fɋTzaو{W .OϫHy"bˬ8d˦M)ȻW^Ċ)/%JmwLYsLG+~į&^C3Wy'+gܿauuϟ`c[RZ|> PAt"Mo/qe ]n$hƙ/Y~6'cXf)׊TI~WKz:90\~d"AKGrT;\t\Ny2QrY^ /5IZp4]DZ즬!JW{;hqm%]͕^?'ckwfAU~gtzRk227nRŋĵs+ NT\>?cp?͕Ue34x^e'T0mF87`Y`S o4#-Fj׮(97҂;^GK1ٴ'ܝU8] I$#Bpu ^dž'66$}368=v ҢBKN"?e)hmzcWJi}h2|Vq\H &}HtR^BoꪗG[\ kT >L%feTfibl`S9Yz'_ F*%]uLzx.l}|e8ߚMmH?bSFr,fb}f9*8Ifmus_q4 ɺLL语.Y:ѵ~*gJP:뭉~9vM' S6Wm=v뫾ρ7Ǔ FuGsMzO4O3}WU&2lA'|/|*ˌ6rjrh[U\s֕4:].&}}TN,yABOࢼr-Oby.!&w҅Ox\)tf@c (eG稽{*Ȝ<\qK73k!_%A,Yj6`a}/e 2(b@]>WL<}$GV&D 2Ɯ"z@9t{c7YvUttK`ixA[e6wf]΁a}8lh kP-1YXҿJk)snCSz~F0: ָ+ Mԟ1._j҅\-~ۀ]));82B{NA9Ȕ}BCdtPH#BzU5К4ﵽ/a8>k|Gfzg}8EYqH)9z%\f/|R$!XayIh|.Ia)i/Dc=@x}Vpesl錟gOMnC Cm.rE8-bR`مO-C~+T*aNѷ*L%i51uLuY2ߑ<5n@,8 Jw%#|n=Z>|;]Ͻ^ޣ8 *I+scw%bqzbo'!T9ִU>Yꕻق{20wR+"lcT H&}|F!Ҹk{ty1^q;5'-A'v; \tr~n;ЗO IPg&Yp(PQ<]NmD wZO~Tś n1#@n4z+|*,Sɔm $Mq )[۵-F9|[57yq,y^IU4Q̉Ț)®k^bj^~ܷ>.f ⎭Ts V&N:qD û^)6 Y.1Sk׌ZOM1@_瑺RՑ5ކGL |R|usy-AâC彎?ӖV{<襵t~G7/88x.)PGN`\`T9^dÌ[p1E]m̾s=,9Fqgi>A~ $bS<:p @1Wt# h!Io .fA S,=?]yp%t’xn"rG$M:7CYôLRx蔅fRk|u-qe蓦~*q575P9.]1EkUO\_>}k**ܐ~հ[T¥UX\T ^ Α>;#-X|)/ī fƼ)݋GmYhVxiu-'$vzKۃKGFޔi%*u[`CV$G__ΧB8(Nrkಢm*񖎊z.旼[M*k&62 7= v_Wh pU m#:ܿE^zf&yʛT c&/C3R#}@Z>ye;۠=PX{G? KSm?[i{R)7PHS~gn&t)l>wymKkgX5Ttg!As/Gnd/~uҡiERN7a(P 'Ukݨn\;<+UR G;0؏Q_H Zps_yČԋڊ0@WKQڰ5Z%R$pp-jZ{6;o8a( =UಛX B#GɨӍ&|>d!KcmNtBr!V? hgړ{LXJb<Bzz"x2[7@ $-K:tFX}Lq澆@G5mߠ-IENutۄ>( :)8l4joWI@iE7XV;j^R28nVErOx'uHcO`ZM/@&[j. 8l{~ ˝MOny(M}oGSDLl%ȪiI HA3M>(r8~ǡ^2092#3a欦ͬn=&Ts#o4K64rCقN 87fdfIjDg Vdg6{h|΋wuΙJ.Jn1BҚS-rɝc5R.(Wtͽt!=Wvʹo>J`k^UbY h:8S# ZQC _ﳴbPE n+ hV`ǔNBxWAsu%<7k'URRWb|h椙 l{B>ͩm/K靳W|PUR*xt2is3lv?)vlSװ=/ -e.DӚJaDeoɿ$>}?6'Q= nTV^Zc]L'pГ56-{::zEMU;H#HEh" "XLwOX]) 1َ2/ t6~At; Jes*P88"2T G QUݥ);~ję`$3]/n i=eA9|}]A]ο: w&wd0gI%J7ۭ՝G k ( xI|U(ah8>% јhIQ0h/J{l/QִNsDR<CH p?xyv&`BhIvC$BV*^(UXl>b9@*])W7# sBha4kx v?XBGxR מ:Pqf'iYԥPeS0I ΈfX:o-g% 9^@2a$wo0ٌ]uj]UXv-}ad^$)_o6:ekM}G>Ej`;"x=hOĦ5Luo87 ;5|"ЇjxZFu/#w:'_D[}0h5$VO/=7a7{,ʫ=RQ# !|T0(gWA-߇1}Qh #ʱxela[djf?2ȫ\CbpxDKIZ/ItyGyRYrB#LbTEGgI6Vlk˗Zo$L{r m;[TԒ]m֢"Gqw?}9^8/WM7uH {qWdJ);.+XNRx/̽Jtߖf(]=mE8DVbUfP ݯ6Z5(?d'VX^WK@^iKTǗێJ6&^_OqDžǖW6V!ROc0G g/2zOu g>ZXd řG3SsMß\8Rɓ McQ:%4b~M)`S>mُ8C֡7x4MUjQ3+&Z !e̹z!y{b=4_iǒ, SSv(c[P˳¼䩜  QVb_KE&QR_x3p=O_*IM(7NsO[m3 dǏݧCn3ԀƦ"$z_-I֗l%.-M5+__9G(84?G+M"劦V#oقjzEKXbu* ,eXpyH#}MR("@ [lXTZu!_@<*s^7|qNqk32Potsw}c(yů&b8 0 טPWHiDT#Td-^Eq᎒ՠ fZcR9F1k2׋Gd)̤uz0]+o* >nuM60 ~JvF},85Q b/0 HP)+vmﳊSB]yñ-iAS C5G^P$jG)h_J5V'@H;#fpOWl;9 06y˫F'$ĻU9II|X,3iTb=~mY|+쾽~ǝz /WiZYz|BٴS AS4o~|_gHwƗM֌Z 768~KaL8 s0\˷YN3H[/~3s4/]A r8M}>SLEǍR0^g z={̻9'1}0Il'QG'^ ѵ"/NDuݑhݲ{M11ˇ(IA׸o6څ_bŠbο9~>d6uW ˩$ R'j7^l05ᘸ`() <ü7@\W)(kI;8y$ C9i׬ײփ+4["WOUI`~` -AYCDPzݍYƛC(TL4mǟN׺Û #"8ȫOn)VB@)ݛh)@f}Dv/Tc,cEz\=/{*e0r58V<ϓabGΠSP. 6@ e=)o_o9H%yA`Fض{ҬGwBx;(_0Ee^߾E+Er?̃?[[ J%<_s#fw/\nɝƠsi"#4  |cvBe~uٻ}DЙ;vh2~ǡM~󠥰a$>^^QHцIVRpj͊V]}bɑՌ^~H2 {9lD'ldr,o((vk'?`ԁ_wRjTA"PHplO ֿqOY$3,> *b|;uw)1SB7X~gk*y?$i)Z/2n xd4J<9H$( hԁ˔%:ߝQ i"f[_Nh !٠J#xSǢSFa8e{qu5Yw_ 닳B+k< ;9D/V_VfF*>ktdƧa~%O,} ;bg7 ٮkSQY*] >̏E&C"iB04?7~}GTT"%Ng/}#LhHSه 6]D?[ g[L C+nwoX_V"/Y$WGv& MAn)O x}[@.*} v5/]!}lz}!7]}x*bWPwv}Q }B+~'p j|`'\xm bhꆠy=cһl)}[`mQZm߸lcԌ 1B4<x뜈{&Yd洘Ķ)Y7|.؏pPw#owʗq-M2nU/?ХvXA"C1Z L|>"Zo9H,+,fKGr`7KVs2C:AmU6d\wiZnX}6֕t4qqH7vO~4 }w8f.ugx++z[a?&Tr7T*%[0yBQ<|ɳʃ_XJ$.s@|y2FdiW֡ig—9)8} {G{*Kn9)aL@B[~N˟ ͗hD+6CcyF,3em>9X{:KFc,pb~`ىܽ_rQ$R79.G5@sq'36ǃM05NZ忻i^iaWu| z)a3a[D3{p"GaS,{1d  95S5h~54MH٧W7䯉X=`:p{ I:bu`~voJ d~Q'TV*M#n?kָO:E6pt#O [/Kr' |ȇfa(^J[Nad:sܾFKfO}Y]R$,cXX uZ#GTRխ0Eo7ho5 |0!Do]՛~i%lDGƲ8.~ rͶKue%ݤ V G cM=VF4{^ ᐺ{Ӯ[ ig]]ܩ#تi\%5 }?-ԁq @dԙ>8Mn5@][Sv+2}_X7l.gfwu<ֹY4=Co c(YQQ{/e?LRE%ۡiviExN Sm3t uY): B gn()Y\'Hd -%#*)uLWdZ}}k"U<#<ފ?-Fi2;o7BNEM;q )R[Dڒt@K?Bܑ/ֱ @,}䩿ih gUd}G"j Ʈ ׊$ ;ʩU9iy#R*YsC?WQ|xiZKbz1H/ݧS+{7{>%`'=sdecy0ql|"SLa89~=6v[3bm9dO-Dbsin2IOwsߥm'h9>X/bWڹ@Ds)~Dxd/n-"]@+v>|i i .7*̡=H$YmlM2gP gj' &A%wlo֓:9d_3<.ȾSNs~,y(f7*i$1O5%4V|;j g30+_6yJ\hk6Y?2T)`"55.Qt_0I5ScP$$d:>G6"Q5%NpT/\9 `i6)&deޘ :+e'Cu$@c }9)vcAuD[DoKS|#k)a{>.)14cP $B}c2,al?%>z~zZE :/(C K0H' St 2PG^X{ '-.aJ]OJ4)]5y]spz% mCɠT<g싄= KxOFTFiPb 8h-~#߀n Y.*W/8INT"$_nA="&>l`ư$}=NYh- ex:PE\E^*d#ԏb^oq(+Q2Mۍp]ij L3Öw7i<Us>q;Џ T#(^L"":adrO'+\kxP:Ϋo{҂>!<^>tW>ڈaDSQSprjb)l;|\@QL}|ʊNOCދ"1Ql&ggHj}LC߉z!sa4T;z\M߿W~s⋕.<7)0Z׶ K>$*i c,tu|lOo="SVgpQ''7Sb-U~'zj(X0Jl#:WSkm!J bCH,|S_츯nH)9/_@jתKst' E2, n/7ᇏź/0f8$(ΈsbPԄrͮsPR]]V.;íd-rD~o+|Įv譸:7B^FI|a>L&ڞ^C>~jXn4wHg>]UIg.U]&^r?uz2}'x9z=fW{m3֗j G ϔY%YomqoS?-@ J[ûح p KP oJy4gw,(Enҝ Tߣ6h/)e7gj@xrŜTJMX$YBI>jwصAOYV~!lHgaUqqq@n#SnJgKKۆÒ쯅Q[=4a{Go+D=z-Y 7aޗVb/ ~NE"5й w3[6{^?SIh,h)V 05ۢFىZhN=M,mf@IlnOu{5pd>uoɲ)sq1S@*< 4#+Mx ŷophU ٿX:8z <6ws?GGMf+}>e R:CU\JqK6d)LڻPz ,e_+eP|$#ồVX N ^~Wzйjb= JjKIȎ|x2 "oJ0Իx_ 8%ڈy]rg u:"NQol ƨAd|8OA9m&t+$@ Xo#seZFυхUL[0|{%ޫ*fs=i6sCW`7OgS~yKDKCm8ߤ3DhY\l|6`(KN;ՈPQg2gdr7۸^ؠ!TuMcMΨe>q5Bt4VJWC!yCRR]{m:L(8*7?5bIR6A&SZn) ѯͽ1Ϙ3(;Q{\ՠ0rs{òsE:AbSi!ct"7%!M3_eޯOZ(OZ; n9yOa7i޿˘(FvJtʊ_yPk~ ^U/:DEz+LhЏˢ{0.#X\ S_}{#Y[bgdlrE(SF*y}fHA|W?w_C ޅ%<1عq_Ƹ3Nn_iii+ wЅdhh&Ab>ٜGڏ B۹8{gT򥠠8X#>`oͫ~G^Ykul\y/-|C"PG-o.=ưQb`,A_ {5lDv[.Xָcþ:İ.G2(l}"}Ui[+;?ڍu2P<\]\"-nɫ~;X\ zL ƴcF07Jz%dJcn6&EAo>!l;/CRHơgDP!KfuX v@{lgr$i/Y8<-C#FO jbF_~v*jn Qۃja-6ɻ%m5c݁@觿w0}$a^{9&cɅv"Gui R02z\\f]YĈ&ߙa=8O)3Iھ%:@;j7TT(Sz7XjVB,#JeD4^m}scG#²`}DkPĞeuUqI3r.:1';h[cڝ$N>k5#f;BߒC2CFt XEӾ&TJi> xeo8FlGGRgv iXrȪTzҳh jhv{ej!gk+-{;W|>^9x]|/FW,_=s%BIee_[&oɜNP^O]-V6Q*5Л! [ul^"֒4i\xƈQu M)mHb6{w(,V~P` 1Rw-OyoJ͔w0UR;IJ`)C]cMiβt/2>.Q{CmF#rq0 ^GljTuؙCRa1c ѿ.X;Ɯ1Y$ ɹMΤBT BUͿ}ɯ{l"ؠ_Iu鑧]@)'?mjT}ZhI(]ܺ,:'.DoJq|nYgǂ b*󏯕!*-U1C4E$p%.,hNVV"S' H#m]΁-9~uL.a?=w7f&Mq^/ ﭽkzFόDCG<Ζ߱o>ҬV GIWBJ묄͙*w1tP3}6h x~n{ !GLAhUY h4~xӒdxbAyl;g*"BKZ>?ޜ,I YTO}d㇈^5߁GB69V"C$8N-́LDrH|_)n߉vhAWs0 aCqm> pI6x6cc8sz]RLm5Y ):ˠ0vWLqϥAJ2{el[!]MsC B /L>J-f~aO*q7fYc EdacA;Ob_CSX M58#~x޴CmzX ?i C=+Nk%`= ,bͿ.Ǽ3l2ůйu('Riq\7Gz$y1m) I٠JcO1`zJ'>V3H->&HsԔв\l>>%O ;۷HC|Ć玽ȩ4U|& ~YL4w  /I$ޫ<:{=rSj;AQ 7IZlछXQ<+'3t%T^I[ofoExc4QT=Ԑӛ?H՞Vp ߩB1CSI Wu .1:^PgJg/?_ٙgq:9`6H^%p*҇8/*%l.y 6'%c~Cn^bOopސbXcwQdEs~ *KD\6#\l5w`y9Y Y/ѷÊ]D?p|máM2ih&Rg%?”Ŀ: \;ywp;8{ksb*ӹև=YTZfuz`%\+t}`GȲH^/.~1aV :jh|S┗%EAI]y8S@@쉩D-^^R}Ӊt ERv|!:XVǒQ7^ 9k@'hCe |XbN/Uy;_M/1ekzuk $kYC=076>7 &"Y~$K LoXcꩿf͹.*d8ie)S]ʧ]_S.v[bljWk( t~߈"8Mݓ&#MzI2tI ѲsjScbGh3sˉɗîSS}WZKfbuXOp]@Бeg|ig;~bLO~Qm`9(M8lYBr:v8 &s8ԟx>E|LvC[\ 'OLʄ(B*tmH+<}Oxc}qh{U8b8wCknşjdv ݿC 2wGHo^Ⱦhxk.yWE]c*f3B}*w5& =CXLM-Xm\LlkS*z~kq71tHamVq4؛@B9<7_yiPà ܼe&Ѽ$p?J`W0{@o sDq E2x\zIl-ED,}~Zڸ#Zu^ȟ>dhJc]JؖWZax>T(?b>?r"|5H:ߙ<q:^s 7 *Ui/UBl# p`%F77^w^)ӗ]zU}@5#[mla~gȷe_ep[먽 _ _Js9(c@k|0Mǭ&R?xsAN^f~Q{Fgcwkm fJry]AZc}%B-EW}m @V7|)7ңo'_ SI1ϫ{$<ˆ/h鞆Q^nobIb<*+u4j\2م.xP#Ie Us6 c;]FieGroF4v]fJ!yT2=VV07v-3*SV9x`W(=<]AgNag8Xǎ"hYNQge"VM .XC`3d ȏ~Y-Rr|.ׇ(65 d]/,FaE >^ nE~^yǫ{k 7}htx~@{͕`BOŏYZ]9\G7 ^DEpbn8;a| 禌ZHG~}IK?qI W*w=7>X_ݼQ8ጿ]bXOYh s6Pw@{hzqkM\~jhܦ䶁K@QnJF{kꮭ;q\Yϯ`Y `I,g-@cml!IO,R꫒H3)Kk;PwQ(.kUqǦcy" zw[>+fuzSY;w :\Ͷ2sƪWqz޾lǭYWmSx>)~%zL8Hl/' ;~j1Z;0uPSja pY*tpW\UPT%16:anQmCyi+fyy]kݼ=h\yw2E]Vۉi<0'Nگ4o gFY y&̔FT%U4 CR^l2M.>/΋oUk[P=Zjg^tH_OW n_V|nZ3ڎR|9d[2htVe 3G;ɥަkʠyͻUO^Ѣ_6Q#i-g1o*W~bl5Tش kJnaflzzmJm˞=?ӭJF6ua;c/{A:)+YvγUyיS4G/tJb3V$N&3Tm[ a"P+%wjMz-l.ڽWYbN6207l/i4mwFFb7]ӯmX}?DF(egfaTWӹS^CTՊ(͚4(lѪUMb/4f ņ^CKmŷlPŃ]y*9+4ǖ5ƫ ;Ӭ]vKؽV_|bZM?U-5M6^Kf7*th1~[3<BY'kMkjg ު,{ 948/^R-V}pv$jfföY\ng!bY=ϖv15P2eݵTf+z'F~~e4ϱd鷶Tڜcj eo:k 9(E~ݜ3a6uR8eF%3~nߗ\ovb<^%,R `ũvh/\5:LʙEe^(5Ud0słiU:AN 3àvjkX|AE=՛Vm+a6Z(l.z1{K~1GZ^[3Rw|ΰn 1ތ fFc03MkkÍaV1Xheri}ii53|XR\σiUM2SobeX&'["$/usQf, *潾L~`M\fLS{RzsYeKnoƊx]YUs{m-<ӑ-kYƼ?M}7GoJiحeݬO/GtoA-=T Hz1h>Qor Smg|`4A&+}QWrXֵ~mf^Xu,OS~+ {K8VYxo/e ]o0U{;yud[WY>s3z<[^i)|Қby~YO*vbSS4gʲߪXg^wb:B~orRꭺeՖ[͒4^ێK{YײzZ. ,Ny^$wWT;)}尋)}z!b]<]ԹRL3#:(ms]w{U4k~`obTyƙx2|]`%VcWvaSW`s(f|Sލ՞o\ei:HU +=_ZMo ) )QDanP~Ѯ):U3/lS]۪7/D]01K1ΒU\I4fP(w^Q_M:ZF'eQ5Y)F%77D6w2o|{fVp\-s`nٵR-^-fLZ*`aR+A=״N 2%vC˝efywh|'cחlRtai>gE6՗캘--2·}&[ΠZbR &hfFj6Uh*xla7p`HX7mEIhyeߞ AT%3oњ)Mtaӯ9D55Vcųuv=ӼmWmJW;A1*;F//Rfucex3NM):{jV&-{1_(;T=*̋4QΞmߍ=ozsVRω礝WE[%-3w@, v6f77 :3b2ZVr^8Nf ם6[Eo%JYJJkɾ'[coQ{ a0 b:?md\sb }7瞶Mgx@~\M# co_Һ1{xש{1wצ Ex8&{Fu$`A0i!݄͌4oZS`B Z7kv@?{0 ? 6Xഠss uaH >3XQK{15VsX*b 3aDZnƞ^77Q])y[C<>x}po78TwE\Jǎ;4OcUPf+fgmٰ7~c9 %-@۝,2?/!;-RÛR9C}ٺ_ػjQ/ (zQ߫wX>7}Y׏%G7=3ٓ0Φ]V `zr&Poh,i,Leލo@t+Je6rmq\5%{e!~ڣ(l*ÆvO6Fn yiH-!J̈FG%p! jLx ЕxŗrDҢA 0dFB=T!C&LnyGM$ !bU~޹hHz'0E 7!ö'@ Y>XeT`eQRe8r .; bt!>K򚏇P1>R1 I JZ+/4ʏa#a3ڹw c!4a'ZÛ(b2dD(&3d4tF Q(@ 0#vN!U@`AW>*S.; ,@!A?KUSELR0V֠DTzvyJD90U9( ]c,4ujΒXk$ͧD I@"cW.b XkDy`Nx&H40Kvb.]DBPx@ P F}'/X`i7\RU w# ⾵7ZͿFSt\9*Y랥;U&n^s-gyR;ݶΓ^ M­DHflS!?v,ݸ,l$%5UoׁsǞ4|xVeP 1&wL'(x:~H ;߇tGYiX2g{3U0hC/l}d9p֦7yNɟtXW"Ѫe G 0 kdscY! 5@QzaN`BT*""EbODh%";@;Z'$4 &`QfH4"-)p$C‹`ߎ1`DT J'҄!Hp$Ž -8<@eg\ZwyK\//G'.3ɯ:VvʣSS} k.^M ?{D/|*3z/&6P]f% JKppޑuȩ"Lʌ+$ EHR Aa`dKp (>k)0=W.gیL `cj\bjPFeXD(R8<^00AL%8F72 ?g)="@2 9&ߺ9qC㧲$'K(8|YqeA{Q(]|e?JTǫBC#K:(dypM~.rJao%v}<~[cwqN !B! ClA4/3&ለHi,fB7ZcT =\X 㩡ѸFQh=xu|mV]:9d(-LSnjw,?ݳm(d,n%N q /rwmN;)+JkH= >X*jXvرbLW <{'7DHfG>ޖEUr}dK+>a;&+Ŵ[p'vaB~~S]C?NWSd{y"@}MDJyv7 Em6RnIzeI$􋲸V뮎e/}3#,(^;_eQ韞 w h6" 1\Fyy 5CM*fZlk@`0{sR8H߮@ӓ_)%P93ɗ_#=orC7pw}U^͐t?F8%G9KJA`zSce[ >D_v&ͻݤyv=~;fo ٍQDU MU]lU5Ƚk6m6uM]u3(u~upWEgrU!mFߝ_Aeoz| vB2yW@t0s 0I&ZEE%~4|ы2c\3 !mBᢜDLuYr̒<O]^V9)ں:87X qBf]a}Dq@/SXlӛxT {1uڛqDgG _^.{#`40~ %{(PJKj3"|[}ѭ+ Gzlh9tcIn|SWD#9E s7>^k9{TqV,ʒ}fU~*_v7y=\^.XMS xZ Y_7'{7=We>t%RgsRÔ3ˉyÜpᳫ8=Qw”$8>pD(X N!_7x8\MRӜ&#ˆr#bMJ$l Fڙ9wDbxBG;QN4Nr9tL9B)z.Nqk}2Zh)ݴ"ZqEa|Rn 8Z&&(#Rs<Šυ"*\ů_|nBFRGt?m(?_”Ke}2 quzo*Y 0nwGׄux\;L2vm ˭}.pI)aB3u VJQ mgtz_@<Ҏ_1I1:MI]ACM^L˚Fzɸx@ @(CdC>lҦ!{G?!Y vSÀcqA]P;1 SnJ 'QE,>kwu8r]Y!cW8 &?ꑾC^C>"$J@y?^يbo[A nhs+Eëjve62&¡r Lv~:|@UP~NbSPWyXicaZRḷnvvZ#<U>= R|/w| ou8y xKڷ~Ѵ0kԜq*)c o);NMRAc:f6ͻnyusw4&OϋwwOfx\-WWo?-~|~~xq?o㇋&ٟ~~d}_-x^xXݮ>.^^^7??=/~ߺzs5gыl)¸ fbyySnvSK?VO⃟[j ^WƛWOk/g .݃rn| bZkJ/*&C^\^wvnf/vz 97^uad$`˻nwNɇ$;fubl+wbsۮdeWUۦ#ֳr\vtj?/ -9OPHF dCm.yz/X,2aqu-Vqs=tq;&4Xxn Jg<.آjW|wuuX̸ ; !.>5Y4-gߝH辒V{hu^{[ag?ӷ_~i1_?nȤ|JɹLjOi~-OO}p>Ŷ~2ljn<Wr,'fA<4ν)%,)]59W&Of_$MIѤ;lFJ2kfnyF"Y@6@FXF)ndeOT ,eQjj=Em`ЗkU(r)V] x>p ^ ݉G͋ o\Hf܎S5I-ĞM#Gh6jUm^Rs/=j47NT]vPLr_5!C5T7qRʼxQ<@0ᗶ㧹̡Q %ҼXh/3Pؘj&&ٮU5V6~F颴u<  ^ X2toL_!:3&$wP1P?/odg^ L[B{Ʌ gz9$ 28xD(j(}4q@Q %U TtDAzU 2^!)ث.vY`a{k9n I;у^ǝȠxem\xm^{Lz#&20Cj}/nd#ײ+g&gZ!v" w0$qM"|0ٜ=};6xf-skW(kztŤ b%~wnkw qiHt^jmk_;~ TAxRaP%Thn'A[+E gJ-D.kR9bkuK]$kq,rpvnymhFN9x97W~v>+#'I["'ّWFNz1zs!'`9aUd<.LjAn_.i.(Rd#Ź} mǣ}_Tqj,i`zSWֽ}j( W^84#B1M9aeP9u_0" Ut^__E7 POy?$riVe9@qXh%F-a /PCK8z!aRȞ8D7&l_~{z*1VqE$!~4ye=®I%}-q^XPƃ$i0u}ChX"牤Aۗsa2m?TK!7PZ"APVcWҎG_/Fb^%qX`ѪӡVО 2B.yeD CE{z(aPLxƃ7C2WcAћP\9E|[f0(hDF0{=˵{#WC[l?&(/%n/3ǘ`/HqP/} ,WⰯ8J«(ì(@Gj0 |Pa*pqP @Bfa |.CaJ#2$5إ8AAPt!fEfx5(B_`Iᐗ%8(a]Dž d:( t r^ yh!M'fHbkXo@0<Y"Cl@cn,{_Cq<ɠF%68쨸t9hPo5$hhIUt>dHy( 6škxaSrDkږ]r)uzmnc{\}͚ Ҁ2!WυaNnGOr7{G찖ոbp v{$f,0J̃F#G+8 d3R9Zk?rHp6}ݧ3=W l߀BQэfG"'WFv׀oFށ{;Ww$ţĴ'NH␤peL8ϧh8'3!erbYNGXNVJEۉJఠDFd/ ɞbk:?b\1MbKjGhD=m nnRHb yZhPd;/>yN^` 9d;96N*4xAA8S:֜֜]sT(ZSY-mk>Qu!HJ7:5BuL9`V=ż)G "$o2JU{{rԙ[@ 9IjLS1Kva׿^{V@#,<! 9r1 Ӹ]tu(294zkQ@4{ Ȗq tǖ"6C b @r m%EJ ]yV eIǥ09<VBrqB> t9\{V0ԘT46Kǩ1wxݘASl˽P@F.y(\ G3paC8API@8]zl ^Уߡ͵ccz8jqOP@z3 ds H<1Ռo hQ5S":Q,u_vMq-s5e;dEyخUߞ12UAMOc;'S7̲4.=cyڞtcjS܆m*8-5N50. }<3!9+v+,)ig ; 1W+a qC;p"t7<{ vLM-5cK(Q[bΙqDS[>ZF7'AH7 6{8I밢'rBMYU5f;ȚSnn{^o(={֖/v~$'q7@;n3Ih%-fЪdQ@EBCe_]8!v-j.Q0TN'{ sЗKm%z$qVSDBS#D;L*W'kf6|ŗ^Z~}~˛mn=xGӪ=qO7W~fmqV^~mUrVWƎ|tx}\|7o~Y]l MAn}#vf??=ǕW7wҁm`??,?|op^DKIv/=_$doZڗ}{{OO7O7@ŵw ,^uV z…RKsF"oĊd P`ӭP|ŅI5|h~G$M 6{In2S۳9X+2uϋɦ}Wϋb++.n?m:;N&`qy uWT,?|]<x ]bbOKҏ/.>=?&7ſ?37i67y]Iyu^-XA?}舅 2/7?no'{WFۂ͞ѽ#A&#FΑڏ=|k?qbMXDn,'<σcq ,XZ6Ib Å 9Ӫ,&uɳzc.EJ}T Ho0|e\D'$)2 ig0 L Flf4[,žgUm>G n3VX: {8|["ƒ(S'hO@t +!Apd&ouX J4ۥG7򯯥ɓ3ϱ%SVaXvly_%XNEȹ)O AlTZ 006[-1vh$ -[u~xTҾn I7u !9vB{A˩LOB(ߐOML6%  R'A3ȕGti3fZ('=bU?/z c*eJ۳N1H!'. ($լX!`G4(VzVV Go } PTo_zVnАwzp `]#p4`+X / e"%q?>tοK=t)d"J0@;\ iV ZBG^ '߽,5v̊Hԧ)qbֆ"_8m3P `j;M a.dG5l-7ϖ %x߳r3ȥlW4,֌?]+lQY+6#7-e/Pdmeza @a۷t;aPՎa!v١oBUdA:k`gr*Z^Ŕ ]qQCk̀ta߫Zw&64ٰ7jӻ)4.ӟYpmv@**}T@J<-| p  7MBq `j4 1ҫI %$'Qt`JhbacP (1iT`aꎡy!mQ{@.eIH6G>xdch$A.( `IQ@ۖjh6M{D_E1N0Pn5q3@I{VarY9eVs A>[8|Ql.S q) Dj pFgt5QRgg0dWˊR9;Oǜ%db!3GuN99$+husZI g7~-ʄA#/4Bl0craqCG$sz-M{Ϛ}"n8;/N zpʙ%)f Iia運᧕2!;11(8^<$bQ/C1| Ь.7hmX]:,MC٤Q=xNR,ba{<*O=\=64Wj,R 2D4h; S&X-OjĨB:h90C)˲4b1SrQhcbF۲,&bh;+6Ha*Ѿ&_Kzft.D!g\cnj,aû&d {\qՊ|\Y2!GݰC 5Y3ӐD Dbʸ9P&"E/,7b٤bF$vBc^1u4ڗѸƢb<߈q`YFO.Om,X01nr}ֱAmT\Zw--dUcS۬5p8$ԪgxZ°@Zc–&ސ>j0 jRp?89BXs+4пV1KR qPuMee`f VEkv6GZqs5'!v ]@ rԄsPxЕmS-R},eXæc5MsZkjmmЪ!j"CJ |S`u2`V?emlry@.YkUZ)4,놐9:BX+Rx cbȭ=m+jWQ9}p f\9'P?3yh21"LXaI,sQxr86J08Qfa3-o!C$1 V:L 0(rbrRQD } 9AXbEW*ՠZ}ȭ7HSط!>`uN-~4b`皵E,z)beC,tX&#ÆFLG1RH$-p S4yB( ly!XZ4#=^FC#87h14=4گ@+~G{q4o$< 1_r+]cCc1Ѓƃ؇xL|bO}4cN} vFc>FhFFGA A#)2*"'.0ZP \Q#o1&ZF3&ęXsLFyjz+xV3Ec7٬+2`42'u$a1NqmeC Z<5Qϱժ'5Yh(S,NkydfF6ieFZF/p- AXyY(o]a;u AL&‹k@4FyKj2 O8hI1J h(Xoy΍͚[4ᢶSYʃkZD0`9UF듀'@wkCŊFjcq $A@`h |V݊]V!A!Yjj;`FBѩ*ۣ!o(NČՂ0ƞD5pj bu zNNEWI,NU7Ne53βrhsJbN55C% ozذlV3f#Y Sf:P볶nBpBX923Dh1 Ԯ倔Ik?ǨAc_AˈtcSY4GJJA~:= c7Ggh3Rya)R @?x29l&Ft--;EG !LIg(.47eʀ}4_YŴͼBɁ_=2"eGy S܌LG4E0aVlm#`չYqN)K?I N@52Oysщ` BxEĚrx`y~FNg tVhΐkȞzQRT ?'oy*WpZKaÔ.GALyXIxh m\/)WLU0$NOb5v%zh93Q }^b  aļȉ:+֢1fryLt> VQΘf2Edlq be 鋓;\gtr];w L[+F_u:Ֆ;Ȏt?(] PEIi9'>+u/_'|Zơхi>+(Fk{C1,Hg WkQSׇCBRgoysƘTd1I ތJB(jSgyJ Vr4OJLJX9Ue"=.0xUr!RD%Lء`.M3)ܳyvCB{iŽ s9Ež+c P+~RUeEC0Z:d1k \F@D&rӉ0:Lt>a_ngQќLٳh 3\lSjtQ,ZW)bDfaKZsDc XwЭ#2gPRԎxFPvb)IӝD62qAKQcgˀ 4L#P&% G2Mu]H8zB62~[@\tp=r0Ág#!@P{u@ThMj:) :,_:ɩ=y)&5W\۬Tj^k`3V=0zvbn"8V%2^BA-NukRKqk;)kMFE;s ՕU&˽sD%~̐{!s9esdm`|Pa =qS 4ԙu$/bq8_ &^ $طV*mU0Ųט 3ѡBʥD4S^g9|P6msuвuҾK ϭu^'0+.s\%=/>mڙy58MPml+8)ypa>CƊ Q :Xl-f/t*KP9G ?ioJ쏆t=MaUIe[wDk},LN+KXj,#88][m}AlWc)TWMOI!3%ddYg&_[U*H+ZQǶ|86t'GA=a괂ӌDFRв|5fkɖj[X5ct*)}H/*"=ɉX&Ha 9QT'P0YO(Ai21:t˗]1GI3)8HHU8l]DWT -z3읊[k:d\@W$W'A@C#@`צFkў$LNcLxϫ#gma S Ex|k;0DN05fK,~_v ;a1Dsh-h:k 'bMl4ȁځ[:L+lW`/9џNUEdSHM|#یdO%ƈn֐*+6a$I`&*%VфfJ֊k\h#ػES*1š ` wD(!BF/B~z`fN=qRA# uzP'G9/ùx۔u2,Cq+z9v 1UX4KɠWh|%r|:;2\("J:¿6SM*٪ `d-6RgYL #AXd)zSMȂ8uss97i$D,d3Ԫ>TkQÅ=_ǜf~]۳X+g 'Df@f1j' iN#Ѥ(PVǛ%:"ڱD- 8N>o^faࢭ< iH?W3Ȁ%Mw_a[`E͚Dg$Cky9,k rwb~099|Jĉ12ej8:ޒUoIDkܑg,ڌƃ"52 V5&EDwC4ǑHƺQXMZ"s ~qOz! 06G)QOpԼ2S=nWxR*gok-lf^V'tTxeS ^GG@Ϛ3 GRc Q[kX eVU2Bg <)O`9팀B&Ktu_Deh l_t!D L,ztn6{8ma`P?{Cd9h2=T:Pe -CURUzP&d2Ty$G*~p۟iQ@O:#O[kst+W$j߷+@PNócZ Ep·0|W&-^᯸$5ڞ=+' s!w?Faƅ)l_񑹋Yw_1aNe|ɕ9hmaTyY)ON˿8R84̋)4/ZG-^jcjFO# k{+2_a}dzd8V% k?q'o%p26F4=j( _+uAVZ2Kba)k6G6'^5,7,RuohKpF^Yjc64/,gadJԓl=je͵:$fZKz=jN1Ht9Ft /+ۥ"2רc~Zk*n֓hW&,t=I,{p&0db]cBUv3v2 Bʜ g >p_5{h y[=褓/fOc8S"۩jL%b}4ocsigenserver-5.0.1/local/var/www/ocsigenstuff/scalable/mixer-video.svgz000066400000000000000000000173441417255654100265340ustar00rootroot00000000000000}msƱw ^K99%JܵJҮw ).K@i9:!&0~g8o'7g_aWG3?/N.._|f7׋t폓\ts2ZL~97/&˛oL&݋'_ݝp|)xzr8_]\cF?_\}{yq^?ڧ{;5^~8/P|f[/_NXw'EXo?U ޞ޻ݮI.o7W񺼞_,zzcaٛoӯ~d`#HL˪eW ׾Ir?=0{vL_׽|w{ŇBEFUO ,>\]^^/Vxvq|uvQԾ,;'7Ǘ>Y\N ӎyWٲ񽛽xԇӫbZY{>ctJGd˺R[賘_z~zV%5@sY7Wu% GM7bzhJ8xXIN./_nauòKx5i &QNk]' '5v,kscu(|jb (?@2,j:[]^9+^ %:zO9R*lț\/nJTyه6Ɍ|Y,Sc髣'eOJ);%̍(.E5eވbK}C8-5>,>ldvvztyA_s.vq\`~M~$P5(MO ʪkk7%Ȉ޲Dü^yl~wvoy I0?jn@$r; F#hI;fڮ{J]'O~zQҥ/6oCrdr%a+>$̭X)@ł*5?V^ssXXMMX.IU8|Mt#@7H$<ԗ}G#*w` h"{: 5ۛ`cponb_[f/GNʑ׫=2|p, |'WwA%v4RDn!ϜXP;HfmϚ!h}'c QlX-v(U$ 8 pH|y9I n#TЛv@+yG#o;!)"c5Sxy>'#!y4byHYx]) vCheǬF8D&\!NrH "RC f=vrg(2a( m(ߓNtH;{dFR5o|=C=h.hibq?[%^}XԸZzhf6|@G<{qCVGcaGc:w4pܓ!AmFmFA±G椬'm%Qhcb#01'\v 8'$7k8XBHHi:d]45e;p"$੉sdʇ`#Q)!q6YSm./5K{Ŷ4>ccʻ DoD)Ogđ$P(yc"&Kb+=_^u{Sũ3vvfd@G%_Od|]s2v)JiɓjfkHƊ >wRɼ %Gpo+,!L- ɄNzBcr *Oz8:?$A SNDeRr*KWIZ*gH!6X2iF ~w雃;Jۗ1A; NZJg(F4='{M}Ι8u[Oh tFT-$O8cw>r)vHȸɖR$lT|H=zkbQ5rkAHd[Wk?Z4n4jr@l;&tʹۗruEh:}M2Թ]ː4kxP&ۯmۀj$|kbP"QsDMǾY ;:j֎Y6PSNej5HRՔ3Ѻ֌6G3em:#NɅ+~}>ss[w緋C9"F h5$l-dj ~Kb}rv}r`u83W'rԸYkhi;C!ұHʔeUP}`OkobnBj?f!f;kTfJ`<<=\L 7~,* ) nSމF)8^2zEr4ӄݕlȉZ=㉏ptz97v!*Q&ێ]s~yK<ҁsqݞ MS]m! C}+|$lzw|r'86cInS@S˽Yjpyg{t}O&}0t7O ;pn!RdAHb#mi#C]0>h-g)yhBpm#['' 6ƶ} ^:Zr5E QA+ʙ=! 8 m#;ڧmf}L fH#Mgɍb؈f2tuu2ŀh UB()O֝\P+t:i my"?C #HtƉVܘ2XB}xֿ.R ^!;pD}W4Bۈ>* p$XQ}TOj!e7z^>d/8cUs*'6Нz'V$ ݒl]i4.c2Ijq}sUD/Ľ{kŧ7gEm%\qW?RK^M>+SX ~AL8ҷ½{CljЛmHyݺ-* f=T[TAҼHp C m)-^zݷh<(U7C% %?('Zv`nFx8HmP";O&Y>a? ` ߿ϙa( sI\z$p.E?$Tmg.=KY3p\r!.m.v.VIv`P4̠]]2 'XNkc=2Ty\VQ雑2,0r3*oזnmN_Yl^8\ Wueba"Fyf%Qd.)ۯ cuIi`W6g=1E#E/J8<G&J]v) 0o@G`woGUm&Cfl ?.˯b3ɗ5%oxEZ3Sst_^/k{bZ#{1/kߗoqu ק_o ?5X|W:g%wzF>y?>=h W˕e7O?^<>*JoEoI-Kijܹ⏥Z;5me9Xð l}v :~wxx(QjzվH`_sʚ%%5b#ː4Ssբ(Ejݦb/.=oȐ$SD;wFϢ`Q5sKs)(!W.{I _@֖htԟ3gMyS_TンFT3 [ޡELjnX-9`/,dr++jw݈7?YE;2YRo> Kr;6/CT.Sm729ٌCS-|]P Ɋ_u9$ l?|z3uNT9bL`*&o&e_48yh$GbdO$SmR)n*s34c\l)S,J o3dVYINJH2y|Z7*;laGc7{I)k"RdȔEnV 8)N2I>pɑP H`ZzDBl"w`cM^^3#;kR m L!o| |2Ed28-+JA$܍?O  EJ-k;'+uX0lQk|STd@"Z #^>$l[GAR#um$>`|Lh z0'%#IĚD|>D>D56{l9-Uf³QOȉrD=(2M~t0CjkQ(Shy@2Tp%GnRVʊ [)sL Jڎumys om2jw{8]ZȞ+Uk׊g,fYgئ&Ĕ"X%BqU*D4e:%I"ժݦIb40rjNm]5}uWo./H5g1D);oWJ,2}3r'((ں$#'g٫OuZ%h IOEkrQB0SVz,dA>(W8i8+O랓MRHμLOf1IR0GY XeLHmxA0+{'ooI;)>%VuIdPwWk.k Miˎb(N &x!aWB6/eqmM퇥.L^tzg2mIzn?=f΄HrdšAh$] c.~ }_ȊHe{ޙ?(Xf{[ dWmYֻdΒE޺7לX-w_)x!źt^^^_?w8-4,Y& p 1Z&a8 LĈSK(:ɞ2ORFӉir/%T53,,Tɔ|9AF+r()|Z@4daj!oV)hhܢ{_?SILocsigenserver-5.0.1/local/var/www/ocsigenstuff/scalable/text-plain.svgz000066400000000000000000007007521417255654100263730ustar00rootroot00000000000000}YH nQF}!hC҇J,Ed*##2#f*uZ177>sw.K_V"o=n;7ܳ"[^!ҷkCc!<\#(ڶ ѿ!ww?%A`ywon85ePsQ?3?+>w?wڏ-ȫ;?.S5-P8 ,qWymwwOomu+0 }.RR(o6ǵCnx*x5*nO?a^=zG?IvW'+ۣWGPgèol?vOE? 5 hv?AUP:ЇƞRߟfewK,C,?.ax~P %K } ȷK#6=z[>zz+c䇇VuqXKݧP>;ĢbRXAPbѵwjnՆ߮T?ЧoH%wqw|!W )`ϗOѐ{ "۵~.E~2ÐCɇCK,џxzG*/Y }Ͻmʋ]78Or#Gx=Cpc=ޑpR#w{GߓQ8p:m|G wa,r$>\"E9p 0{Q `8M;-!)C{8xo,#/4 ;)Cs8C4 w=D 4480gȡ!X4S,ww$l w}%{fgamp}-A!{81cNd ק akmwȮK3{H| A~T{j;ҩH!++%zUkIUf=Q즪v.MySWo?r'CFq_5}~1g}4u^;0@8NTYf KNCO4|,`S'M'`夡ﺑ[R }QIlܱYb*tLD +"xU߀ӷ*f9 w=b3cu/4d7~k o ͗ޘ ;D,`ApP]A/"B.!#X#A?ıCpH J8 ~9#߱W3#8z^ЧVRAƿ)wG `}=3;-GAE!!볆 sMCy ԧAhrcBO+Gܱ#)}վk# =*pgp {J hm]y`FW瀀|JAc 1< ؆hlH=dn4"q ^"h돯AF1;Ѱ >Ĝ8 P8&C 49䆡A=E`(S]25ih |ؠBu,%h$~O8{yOHn( d8faZP/՘B>p>Uȧp!!nP{ *̷J=)X5pU"@']y8,M!A۷6$\,xSÉ{⋲]|%vx.H?rZ4د5fϏNҰԭ)Z蹡Yz8>n CfuZH0|^^GyQ:HzQ1xhn.l<ZvԇXOMI:x]˪Voam ̐¸ߍRKH &-Re!6fH/!-~٘!^7F̐K nԟw3fHr ) {I`එ1C {c%ς3ɰ_ I4Ǜ{&0 3|[fkuv?3$b6f!f1C{ i!ۤ3Cw I%n?3$gT1C^"dJ)!o 5I ~3I bo?3wdah_3$'#= 3 a9O .bfxkK8w'q7@>0nlF"<6Nfl(Ncܯ%%^lT>?ץx#3Ϭ|Ը* 8iߑ`/!$CXKr"6q8"ؿ`ct ?K^`R I)s A->(}4"WiӾԎ;VI6`2=NA {,,(!&dO.2΀&:!UM"=N4B`_?x/i/4>' !_gp08‡@#iA`YH! E8zH@] B8IPIEB!z=C-U<hXX!OG7h525}yEB8P}G=rKa=q?{zȽ>/FSjOpK~qgӬwܭղa,7R*ݜ˰\Q)nMj)^5䁥bG\R8hJ1؇~fYfrǰà]%uhh dIpHE9%KsI=ք//mli FnyUVyinqynfy.D4wL}ƽݮDs_8?rᄏFԟ?Fzyw3X}cP%˗2v^]p#樿 syE>gc  ~v=+5Cb''t?oM?jO9>ҿ;v!ݭ6u?r.nyϝ|Q#-^ŚDO5>I!yK~taLc  ՇS^k,տ>+"I{\OdTNG~.ҷOmy{Cqۡa!'џ_xwELv̟\Ŀ'n, #v^ϋo,XªS^Np^ NJ,N!P%@5wG@w8,M"`7ᄈB0 % 4?A}HONAB51p@߁@ I:ld,>sfVa!IcD g;A>f$闞$ WXß?Mp{* ߏf_sӋMq_f_$Cəw <,t6{L*_|>;h}\ct$?zN0#=C4}ˁp˻Lq K8{\{}4fj~>)`{ ҎGLS@Q0#Xq"k ߾E/ Lݐ#DϱRǿEzD^7ce7 in!Ǩ/ ^#}I?^w4>|n>´_w VQJO-?TB:ß-a_Ƈ°''s7ES>|St|3kxJGo?,O~90kMB}c<~ Z=&LEJ1 ϧG'S_$2)t峈$Rc29ċLL6؟5,{oL}\<.骁 ~|wqsB;7N[mN|>Xȱ"+jh0nq,Kz|>A1)~8sPا+UxK.oowUz25WDX+Fɖ?H@<`Ê{ *T\| 8C 4{dT !@x2E  OC* Qza񂜯t= \ѾXF'Okw7(?Ya?ƺS/ɚ~v ۇr.; 9g/`CZ]Hk9`qQ aE|E?:~م a} >Hh8#7=GAx"(yh0%^2 fI?Ҿo;}3/#n$C!?߾oE6Ś׾oﭿ|z_pNrZ;_wV~ò䧻HRkw| Q 1D y6_:pӝI7䄿/dZ$xAT੬ F_!Y-U>63쳂ïܵ5!7M V jP95d)4f/7XmF=_GBa$K~>w8 cÙ7?Mȼ~ JՔ %t/7w$1$.CzOs4_L<$;HCk̿tn2=俜c٧=G>]cQNN{>/I 6-󖠿$xeVvU~7PgT{#?ؾw {;▾]/> eE^!eiMo:fv?̳k۱+&ߡ\3Hf)#"lZwJr3Y9!Uͷf̕I2Pbza>GX6Mh&!jɳ!]T{=OM?Q\`mԬ`Eq5Jˣ ]kwUK/h;EU{]kyu`Z.O'rXkcd8.q+]skh\p V`*&:z^QB3Od'~kd3r;B? Ik\׮ÜgSc9^2l@&vuqJX>G< ْ&FU 69rCzDt(ڐE|D/W3aCYJڹR=q^l_Xb;U{1bb\?^ x$r\/]|$0Xo˙VۛѸt+c%Vu/Z~QE=$_.zb\]I36bn S?,g, !*ظ;*".V6e? un olu+“ Hf (f/$꣍4_IWUtI14'_qxIMn{uHyTTaP +g_jޯqLd;C>$*W,5׈Ui* Agxϫ}gKvQŽef2>,M<)YNDZL'ᘖ☀"y!IӦNK+|(,6VȻadyHmT+(/ŵEB t3ݜ;] BLFhi:k22CJ % t]1(SS:9O]iKslؘ{ܿ]Qx5Qk0rvⴺ<)/,N -m˻4rm:,=#P"4\O]ql+"#DZ=yGgoo@k(;aN9ոNڕ"h)O&huQ'Mw Ֆ.~}Qsγ8p@:T?cͩ/XU\>1#B 'Kb=Xօ[izsqME䌙͉FHO7d%5|Πśmt ֣j.)-4²~idMoqVTZs9«Ou 8+Bm% `=]Iiä͙|e5n.ebFjRnf M%/W8Ŗ_xhnQؔH`ƚ] cIZv':Xw!!ܮK'Vl-1ϝ\7Ig戦d{O\v:RCK h̅xg#"Fu1W():٪5bUݩ_m;:5FۙiUUZPQA]/CpVhkjg_%SJe >ECŅ2—ZiZfdא );<"\$G#Ѣ*# Z$SLH91EEsZ:֕8&-/~\YXN%٭4KȾZr.m1w1\ *2MZ*GJ1 ˧>r3?t37_QDŝ_;m̹b[ w4l V^u09[RA#Y{0-Y_dn;"5XJV̡<4VِW Hra+!&@TQA_^|2Ɉ5Ft(xŖI拍^NV9ew5HE8۷Kr,֕]β.Yы8EƱXjzB=-d\r(5h{w|]EUψ.$#iԧK;5g׾ȷy}\q}H$4Ah,w9sS\?lDڙNzj͈){n*s.:!qsiRX=n*_҂tIimubAvx~z؉ WEVhF/hdɗ]6^PLӆGR,`st - /b5fנ4|!̨Vz6}]Uig7.۰*IEFHN钱ssb+#8i]4< *mV3@1K٤pZsY =$(,AGN+ ȐtD3*֑Jvp2 ":13yȏz(@yhdX4Øz:w]:$<YHGfCp]n]ҁ3:_0Tt+d Jcu \C<fdl-'iB[gѵYl^(vռ&?]k'4"w6 K V&zu^dLQ5:Bgľ?ښjXVadix9T)൵HȽgDj&3gc^zN\.?0S4~=?HbDP~nO:BxВVK]SyUl2~?A7#yG9ޑA m vE;P:jXGPgpRXS Kw'p3<)ĖDs~>krYpn4%7cbUmocg^S I:]Wͥ3#M ;5׉IaCw6L<ų!1#yX'ixa"쮻Pgf)Ysi`ʧޤvS[ON]٠yY2$|՜-o8ezΏXrO qk{E 5֧Do\DNAjvSz ӜugN3L]"f9 =jqT*Xm,̧%(QJ!Aj6146NMNoZNCʧC|j.7vKymW+. 4es)2?dZU?+ąMXM5:XH Ĵ ܖbGA<^6uܚOWz8O.K^97buNk 44tfVӑ#K'܋GbEj;JoBҬ(Z|=!)ė h[J1mjQhi2GʜƦͅJYI;R܌b5TK=ɰKvݮ4/lb.8Wi}72-!JJB"NXn:r>@Yf=FcVRlB by@':ܭ"M1ݩRKWьpeXCfΫ>u0i֘] q鵪8.Ï!J*ObZDsi%u{/FxZA~ɣ瞌\3mQvuf8kf{~$(]4=|0T1EfD]G9wbՍ/$E.w\VؙPKJ$o$qOᶌ,qw [z[63<^T'UR~"~ ۮ^t``3sc&~ɘf$Ozݹ5oТLeө Y,YDYS}=睢>ߺc]0oaOTF0C8:3 ǚ`-|E2I_Йz GU4K ? V)"ӒnR#=_Z*{2eĨt5!"-tA$8ʉZ{FRu]W6w^^>)̃)87EbV:(.lYN2=!dֽ<+&4 ϖ2/ϒtў/v rC9s=$}\5kM_;͘ ;'9}.b]6cPpQ=6Eכ9G +8 @il`} $GtSԮx?$:>:,lĵ} ]3xas4R_4T4G eL,iO􆇼4vW,=9se8qMkWv^3DqÂd)6AMkf;KmwBbU 1ss EdBŜJk]6\Ih+U8)(\=Ne1.Tt@tXyV+B;Ef.WL3sԦwYx Fe-C[>@Nx2bf}-G.*`ctE1$UaC(fu坨8޹.28@6)Yi, NfnN ;l%*dՖinG m92k%8:ĀF^КIA1Z0B<w'- fʢ3pmN}ewlWLxkYd*BMoqC %r;]YLEJkEۻ'u,xr`^X =t7>V^庎dS(iqTyQ}Q~KezexE{ FM?/tL.\ϏV\4.$E2x93xprNL$M@:Lęd k&4 zQ6v="il1,I& 1*TzlCd1^Żj-w LI um}-hdEtYЯlSmSč#zD~kNsսQ*UtBB}u lV5cQ2}"Lq4E:l|f 2sSh{#]p*[[6t8xw{/:fU:f"xKm>*;x`*hfhmEhYk4q6҅$11iO ]؉ᱛUaAiWWE%* gfobd^εNC*$ėT|;Y[H]K[zhf~E2YOyY,j{;PjZ2qWWR s(h sݜ.p>OGAt#Vj1hUG\H`%1RV ~Y*Ks2UuAVhMIq>oċsFpVSJ@m ndδPl{ֽI:Sz#ݐ:Pf OP:1IFm$9@o9ԧMsz Ҡ TU\Ja 5r"Yz\jkл܄:$Gz>vGn,zzNkѕYח&R-^81}tYQ A;NF1uT.2!CfBA W&\mتm .vٙ''HUVfZOGmewCOY&ascFʼԺxvX3u!zDivjx{M}kֳKX4XY˦:kUU݌WDu?nh 39nj C>`e;6kwəY Iw@$4yT,y"kE,Ui}d.ܓk쭩̊4-|ZA3-=,i 5s\cl7;aΗ 'YO\_.E h4y25$YZy3.BMōXB*˩/bP'T),K$Մ;,J)PM&xrI42P"mMR{1rIL:^QVqYo$5fиN=q9y43sh o.9.WK?DsȻGjڡ7]`Y|Zf٪BzOJ/,}r!c9PrRHKԮX@a Fe df"RAٌ@b S6;e([j\Æ3ō˕ yU-"X5iLPVX3?kk?:2By;LguT:YszuqhA,IR 12pW{ x,fxO*RFom Jf(fT㚢~ 5b 8nݞЭdTe;ͮX:%7Ǖ[cbtrW<rfx4*L4Bw2VGEg\R-5u̘Qs Ǿl;Z+$q[ %SϚLU/XJ_R/]nB[E@Bpʲ)lutǁPUohj^7XXӄYle9 AK(r}ܟvcDR ?)5k"mKo05pL}$_"R:qg!jQL.~A]+} PKWTz(0j̼ .(ۺ\xN#ъh9c^~>Ӡs5{؛\RgKSm׬9"%󚗨R]Qn0-&u\"\qȈ׮l!W*#7V303u 3g:-z 6Ï-˩e` 6aVG<L&&NhArsӛ]{P.Mrڱ7{E(U5PXs7E kka3ll,1МV l 8F\Ζ&V (ʺKJ%%R+NWOp Q 2'( 7<-`[Ϫ| \:nD4ۨPWܐvt1sȋ޲)~d%R֞W4 (D fXIne<{&׋rk&v htB-5C[<=91֫Yt?[[\zJM/t$#.\T͕kzSHPTDl@U_tkefψ0Gus#)lIgkL)E Z2yYLŨ`J{W}h{:Ā eݯn,XyMPW Lo,,B;sf@%;5}} 4ǽ)37z>;PPN'-VҴ$^f&1I 0XE8H"hg*b;yY-K· ۫\LPƴq]e"KYrqK&HeƢ1Qoy6$6{ IHQdͭY78^E7p @"gڼQz0 eznL E2C7~!+.YD.ϏBg6fHCe,cOhnX^xwZRy773UL$S^,G=-k*h-Vݩ|ҴCK7inW/#iGl@z07NS9l~eL~jN;B&DXj|&mii_NK*D l .vcYz" m F0ʎ Z]w}050a8$;|wc@,*'|jL@99Qvq8Dhlg3̃'zvX3Nص%wXWlLg;{rYgn|@9m_5wR$3̭:ދMJ`Gޣ㄀m 5.b߰6k(^ɷ Lد,JѷV *QɀFc_ w/>0Df~Y~gۜ35BOyvt7A>kc'Ƭ(:>zIG!+ FmD|TO8tL2NG[nh܋tX{~:TvrK!b d|{yݦS#p1K<ڊqߍLf];&0ɞB2jx {+,o3 'RZOs5.woggxp`}3!Z":gڤ2gaUwgt_?9?zHZGz Y.?=AaU?6]#C]4j x_,V9yy Kik1!)Vz^]3}b\ >Sl+ǨKok8h$f;bgel־G/Q@ؗ7ؗH*L;EDTɴP*THfn U^]ؾQӜfŀmR] U_ek>^'î\is{7, h]tw IS~)QayCzB$E_$q 4k>5U|Jʞ̲vj,@̆!_'M#W}b#~yNDE {| z㈟ (XH向=|d]3LSDٯ WDC2,.rPF O`ޖ?\#ۀl=(UQm_2#lU9_Bt |iit ōi ZJs }zz1[X [XۗLLՆRE L03̔yBEV[[j!j7r㼦Ќ^a,[  09Xe$E2(7|oc䩕 6[%H]MtC Hw&=:Rؚ "wĦ`ց= /ߏVT?{q0A!ߣοoRYξv;yXx-e, _M4۵89}U-6u3rϛXi+oHXAOgrulDc-:o,C(Lx{.ڍ=ȋBZx6i43eE9?XlI)B?dUeWԦaMtQe (lװtDl{2?hAI_(WCv نJJgv.JxOv YZD$tIY &,.݋/֭|iyU̻sb~!"s amm ݈v[H` Ί]5`%KZaU *HI+=X5e4ƱB[]{{>3dl}bƒh. ,ˏ #R<\y- rZyƅ/UE 7wP6Ԇ t2ŠP3TUI+=d0n7q0# BSk2\ja/2j0ʹ*Ӡ!L%|u_? /9{d kn#w_yl"X&;>)xoO&&MHjmr-~[:>h T낓M Oϛ9.D(:2 EB%r,أ| \& yC:H`3- L+ a?j>c;_%ʾk2bXy^Hf[¸!fVE A:DXL7nޘ2!MF1L{'~!>oI]Jxgjg.豨xT;J|@@|vZiW Up.L< yRIc}O$"BXaB7й%LNK{*Q=FD)1&Irꮟ%q΍~ҩ⹐{Fm;PHe=MG A|Z^ITv8^Y-=slEzN@h(,!3 U䜷v'ҐRQ_ 2w{N匓,l(E$3i۽`Qhbc&SHcxך-&ɚ~f~>D /3%x~7GI:,p *ILF{cCp&Al+޼qGP^!Π)/C[7a4>;̲CCJȖ\r]Y)21S88>wrA;8)}1U+-DPrYA%\%f4̿6q," p- yLW{|2?BjE ĮIwv"+<7r.Ꮤ4 N,?-eutD1Q.^L1.\lm 6}]@̈tݭI0af@#Cm\^F·)~]{. 5Xw\%m |S4% UgMztwŃקY.߉wKsz*͢/} _ @w%' \~^,a,BY).L3[D?Ҫ^VK[:H'7޾j^y2鵢akMo@8GLU}Czr/fyNͳ{ 6Ff'2R߾䚲EY `4J#s+c/d5B>WluN;ލe0`{ǗBvo M,iqd&VV|g(QӁ;,ifE!KJ+sUNo&VYȷCDjU@GLDDԸڊP2T͋?}B>E$ LY,H+c &VlNFw) )To<8[oηcXe.eUEP6Mᯯ5, r=0i.˰.Bg4|`~c-%S{Slr8 OMė@L ~^^~NίP]Syjڑ=P ʘ05/xF}7˧R] eIVf^mHy߯$p?-ϔL 6! \ddfG2<{[̪못@:nnZZفڠJG RK*oB^%YziI0:3*Z=DtH3RY_v͇aV<-=p{[xԟ$)Hb@YB1I[1C,Z'̣/_ +Ε{]{{搛н@>ך=;]fﵾ-ۢ߿w0f?xa iQԕï&łkUl,(֦vSĮW8yl\P)fJAs|e;D-|S^ @Ԣ^L:k=``>sC\.$<+QwWnԃ~=s;trx0{}im2C0D(iL<;˹@S:s`zs2tŷ5 XCGW.K uǪ$_=\'X> 7=A̡Kc(gν*co̒}Yn(k8dTH_$WytyR]%jH~V؜UarɸKgbG IAZﶟpEkYV'N7)^(Ys`!Ig7CbZ"K.4;ќan=xgNKX@1 z{aAJw0dz&n|].[R򈝤}Kr %&[D u4ruyZš N&QǙ6>H8 b5yȁ`'c 44ٽ>S"pe怜dcuzHC_(pЈ~!% CwW6Zdraʣ(<= aGp9T'W&Ϡ0=xͽ0m0"I)ڵ2 eSOql _<'4ueDQ}a(޸a\䧋/LM|Q33kP+$(7LWFo8)77xZ̭$Hsϋ {1w]\w^=)w6`pB$U?[1ICjC1.xNUcX2v|^ Zsٸ-`x*ڴ=IVrTɿ^xn*.lcCꢡ\5Q٢?R M9T+75y _ɨ9tuZskyAL1G{tǏv]@g9̓i .=TUT6eV˰N3K¿2}RR]&@sOYGSzT!FŶ ʻß8[άrd$JI4OX^]B'#S5 P@wЏū F<, o/1gi̮> f+?e|"x-KcgqlO8`=}jO@ϧ'47ׄe@)S8ftpdnȀJ` RĚ%lZw5ez͍g%t}>޲C!ߎ'azix C^Cg\Lsu+ *|7Y bO^MKtԁY<17:}2gܧ|쭵lPUUE؊4b}H M:3LE?+',TF?@Sz!/8uת+y1xa& n7?a뮌q/D8 Ͷ){ 56Jꦅqq8)Yy^""$An;lyO3l}+mŅ=+yMy̑~hMMiiٱq/kǁVt<7ҽD[*ì.&W,%я I|7 j5J;5G L l{.P40Kа>BR"؆62*D'z肁fG:LN*ˎG}a 9ov^1H3!=9CA27sIXkG3"CYs&yx]#kKuP-+q}>kan]pᄺ3oZ1N[?GTk_Zbl#yJҴFdHɖUJYt=5bY:jb+oμ hb %rE_ZcZkkj*~':xbU^sk+ƯF`HʄuÈptjCf i,v M=B'd?EO Ž$ [lc(PW^f>z~{&?k+;>%%'H[@GiQc=IڙF٩ݢ^uddNt .aE4CB 񷍇]d#6gH.s;ɘ#ӗ'`x7LpzI'(8P9j=3ʗamgaH3WDfPZx- [NɡPLk_6ZLɥ?O +~Gy2s(MW]#"l sUwڮ|Z1V t<-稞̽QRz_?([b  k ",)Mb Quʝ`Bؾ#H?;-Y ȍaEYo먹j2KZNT뼖 K[nj>,QZbϗ^KYc!ͷI N>PN)hf EP^CVnJm`~ }hEZ^ߚ̻hGR2=: H%V/hu|_^\\?Q#fwsp[BNV(liXN@m/mߐCAT}Ty-kpBp IY&YѼq{X{5˄lI{}|{E$B{εulP@;mГ\jEa#O?:=fA |<*+&.§I.=:&߀|9oJs^|SeavP^/ET/c"==%*Mq>S}VxjE`76${[F1J޹3=~3* {@34fSKC,vZӍj`ڂiki9^(2jϹjf9xfҤc[:A(BMzJE1' U3*7HDh J+>Ho賈q4t#}nx]ߨLY=@)*c_WvwNEv UQn$Ѵ&#TIOGlwxz7o+͉47R(]1U8i|+[[>؊{VdttCG`;Inj8F`lk"PUkI/'DV1zOՁg 0 }.$8vAnk<<{\N\β+b2Ҥܑ{ oԘԔBh9 {i.prQZH9CjOI, ևȬ ~zyP!UFʘ|ډy⭯Զ?1\CYGҦaۢbڵ1/Q$8SwՀSι*_m5\gG真^HQ." rVN?\CrwwhOT& No\wsMXаWy:IeeټE:BGK<|[\*F_StAHE>A!eV߿eE ENUMH+GH{ X*Jw[ PJ#eTB(bjΨf[1x`r ۤdi[ qA{߼=~b`uB L] _C@.+>>Ε42%^9MsRFX|"f5ts>קmFbAN7LѭWkUq3✼wfOP)8:tӠRKE2jYG( w+7O ?HMO m m2g6ΒXa6[8ZY9x ke0S`wڗ*5 GŪ-zD& cp!bc[ur7Ĺ##pZn>Z_3+B,B''F*$"< /ࡩi BEɦtu2Lv}AQYceRފDRgN?R%EQnu)jy=.!n2GjvDTqζcE,dR;C@m8,27ǟZLKe@Њ`AͼfI臌7*#!(}1o8]6o! N d E`Lѹoۨrs2Sęes!lB\$Dy Cf &8ClS_VL6ndH1Qw>dES aژzՑ TСR TҺ$;Ck!i>Wf?`bzMOv-`+" 9WzIe# m_`cK!zpH*SRKߓ"Zئ-ǎs P@_|љSSK 2Yh[+Qـsл i ^|Y S@Lz a*; ?]AHb(pՔE$ $Ĥ&鴨j!Li3RjtI:0\ Tv{_9#kcS2'F~-9*2sӢ Hlme|Fv* Ogq50 M3$Kߧ~[~>-GOZ MdD:|+!̨%[n].?5Χ&/DVN% xm:J'oʀ?#O$382ڜ_xfuihp]5r*CqUQ76bp(@Go$E-gSpiX*'Vyc42RsV-=][N06{h ZNA=E0!źåoҕ/+?6olS=kF|GN@}|]/)qb׫AdƾݶP?|-bkF>kl@/qA?~'Cf+RIJz"/2Ļ8/wU Fz05#~22O}撛>:!S#l| !; A3&_f\M`35-rT 诰gp ³{Gϛ՜34*"⢪,P&٘d觕/?Θ/И JeiKwo!ǻ~}"6H8r3J?Ib|;OQN>TKnt4x]${ ?/bGfyN' c8+{8iJoH<˾ˌAp|z V­hPyi i'[7Q! :yx?tȩ+Q:soAhR-fզְݪfc}lŸZEQMQA V12 @Qjy #%_' ըM5/ S`vJ:@zl}`V%}q'sSUt_3J6ߙ}SC$d\'al%}s񂻫m L;]Y!bOJ̎܋%l0VMO\mH\;)Ts07 qyLX܃Xd'I O\aVjsX\Pyr~[leJK9p7|_.j!y>QPWdrh9v^[^+=3nCI~Fn qDo|&dUsY%V7%A&DO&߀)lZVS !@/(8A1 왒ssC0n4>eO^L6#Y6RYA(Ldb~[ݎ"OQ1mԡwPRJoa< Wa4[as7'ػs`^r` aQ}8;cHM5=ڸ,r!q?@nJo"-VmhijisÏ?lHmC/md7 ;vWY]Bl? :|i# N,Is0L/4\=+vR֎D}6 ćxfCϧATd҅`0ykv1vrvMC$╔IJqzovf&^y T^mH|A?ƾCpvZܚ"eܣݥE+EfE߾"~k?Ic}SHi!'[`CYH=H^ c \,*1L4Q*Sl"CB|=wD>?[b_/wBLG14 K6hc@}C)>rO.ۧ,޸c›rPN[vwOր,ܷʍ8zea`2}kźem7p:/uߏm=;x,ҋ _ 3kã 1+ X { ,)w,Q xRGͥ$?>ob}M\)%e a f\té~~(y $?b;T՟[ÿ9(3̹*6扟4aX~a[CapDž$=43(}ܝFQ˿ohvo7[>=󽄃4gtWfJ؇Sk}; OAe%+M uB`&Cff)S$-󁌑r`!{dյ%m>̂H!B6VTk$דy#8׊X]ͯ-KeBt{ET:C+s&hC?C){ks!%)vkD:1 HG$+ٝ3\~KsHjgg^trvA|210dCMPC+l=_d|>_#g9f,eEbf;NvK&[#ΗeU* \[qV M.]3m0idB`>ߥ1q^=@e'b&Iui+G90IKHݣM!Z~nzzd}_fFOW={gr%2mbٲ_` [N+Y-" [*a-v& ]dlFUJ7ׇǼ.,1paRn~E\})l%n?|}9u3w^t0 %$Xzl[(wyr%ʲ6+TZܾER/9n+Oք$Oa^FnNgYƎRy ] BkL^p= =pl/P|)ǃeeժ:ŝn, asYab0o?D7 _.||bq,/QsitoFhxK<0%vL'L{2 ì~|+*> C)וRAQ \-~`15.Iovys3*1\Nw1iˍ MHO^}:!zH\w]"Bh|?dɿf}mb~ I:dRMaLyC8_N8)Mlh+ 놚^Ūi' UcZVw/,Rwvn:lT&ރǯ+18*XD* '/F~PE_y6l]qLUSCZrDLi~JBhK"#,P_E珋oiNMh4jy0F ~GL=s"߳B4-W3Y}}c vlS)YM(|AoNtW\ʋ'#,u4H7'+qMw/ :Xh2}-&m6zxU;K)_`o|UNbN|'bn^LA1oU(~]X$C۹~))KA~Ra? Kv=NB=3Mbi ۟@io+{52E,mbn aEI`뱴d BOr;Tΐ/3Hm;<|(N>IKz j0CxHNPSqR[wdi٥L/|(eӴ1CO*ƞ*,iCtse\E]uSC[b: Z'F!.*"ӆhStߔIF~4*0+=PP?eЋY  DrN⍲ăG>~}D!Cظ:XX,V /0zujUx.Kfa>R j5A8%=`6:|o(cb ITc0~~v&bEr5Z'˗i2W]HuREɖhsȿO|9[`#ʿ#j~:mNpE+hAMOe!m܉1[<] fpsL6 7_uw&N2bY`3n<)'#_dF̚kΔQCyͼ9kM+,#/|RybŲݣ ^|rpE~N$ܣިL(- Jygj_Q3GCZoak8e{X53D_K,gPm! \ J#m U4aA/xSjĪ7~0mR3f# >5Oqe!u{yrwwc^n.tsK4Iw# `ڍv2~NI]m k/Xkp{CB4'dW@VV\p#U'@(+-?ֵ1QYC_?Ƽc*<ӽ"\-3mO/=TK~ >K$r$OU7lx7zo>ݩRV!=m@68 C؝/RNN s IchJ7P?C˲~zNYэsӜrۆ3,H38j Qޗ#(/=o| Ҍ)m5}I({a_肐e`k9WTVבd^[P֊A!IڋfAoV aқW1&]=83ո?^ BIb<&턣%yBYHJe+pnZ\NWKN>`wI'J2{|NbjIŖ/ u8mDGN?ҸJ DZV_[P:, Cv **xO:QE@Nze`LL|C#e= je׿³^F\ O* ^G5{Z .4]_?y{u+ls6 1CG y P0?_?B>^}-ۦCF !CrX'Q2(uvuT߼`G$;Iꁲtwn]R22z…/Lk4dANK|%*4qlMlf*3Dž$߽)+LD$?~gn\% S? mݯ9F}wzhK7GiNA8ʿWVAi]uL@. )C8[ f.a$@U=jپa:6,ߥ4JXnS)DvLQ#$frz߆.Ը[OŠn%]_[k3Tn4#Ht~g㴟;a!m2@M hƭl K & d)Iq0ԓ=\(DҸ:A+/aiكE~ݦYFܚu~ ; ܃%-SjH6M|֑VZe*0M˹|hu*Lhz1}Hg减Sl<ܛ?2 {eOѫ@o n8h_JNͼMÂ,e}\gSw3jX!5n'LJ`#*yM={'0=ܓseW_~*>k&etkki>q7RLepJ+y<XXk~6_ӂRՇrd3ɁBoTE0ᾤ cG9᣽j'f+,v=\fo0@Z0CΝcfŸ9%T_ ȧ,gecu]XY CY1|PXܬo?/HrP/JyoHk=Xr3}s$'ߒէ󄾘PD(+B)q6X-Rgx4Ij>@SB]U~h# P;l~8g6$S22mNj2sl1n&|2AzWAJ g ~Ǜoۍ,Nޚ2^% %L2~@Aj6 p+KOax!I)LD|hpe{ eΛkdNxni(Fbwm.@⯫ yuO2VO~9[ ZI##ka敯8llnl.wE1Q|It N۲IGg[Pݺ%N.idr*}}OyI @1% Y[m|OhfN\ 0w,nn|v6Kf6K@2Wt#;X#U ;J4ƾ`{֗w_&#p[ D&m;zT/!x$xHT6DQGR5mB*=9,OzcKWCжe 6+"]sKg,z*~m:P4 4%66 nky#)ێBIkbڃ~eDݖ^̡newWb*./dW=Js$Y/;]SRllhn+h!m t!Q YFU_}dᝏD_0/P>k&.3Ki6ˏ@u}5yR\ TnlseAH?b{(߮?@Nu Jܲ]<;S=i/C3o )6mDD( 蜰Xg25 (7=w,fP*1c@Yʃ&$_'@ ӆ|Pɔ+6zWz\T}wٿ#=OcBUB[Y .B8^]Yy,xy. z/eC"Fb}! &<,kfChRbl_S_bŭf 9l@D@a^c^<>UH L|W v=XY,"b_KU^]015Jve]W.?d}S^CsdɏX'ב[g/dHNSDc0[#$+3J93Yd sd@'j]Kݼit>=Z_$1jնu^ oxj~b8T5lg6.poQ8y{%&R'Q/d߭IeM}YFxt 'b$st \ҊICպu1ichMhTޜ-@|9L6IDVҗ:+ :uSA?Cj;4|-Oۭ&SGݷ8}mp0BI#v&(uwt*gK ѓ%A#@fӛf1;SB/wwK#@k6I3j>_;u2q? !I/`d@H"!C*B 8FK$|T4G~4q`1||=n$,[z)DzJ 4{y "dHVmBػC^78zj~gQھƑш'O (H8|  _I P_!l+6[[YXJKHda0 u;O'[ϟ?P ?^.ypIM6. 6P`K/u`IoT]Xj9})DycQ`[ڮw_ 3fqˉoR`8uU9m+.TAT9<"%d5 yZmXվæA\VA[t(u93{qC@Dƣ׏Y|w6;7Dx;i^'!)EmU6-}KȯM+kvߑT&*.ūÖzպ9X[д+$8B:n & O̔MĆ$.!6cׇL&b\Zا{*kfHL!̘v,nXaTCU;8x$1\m;Q~&sXSnng?sf3Ai0Wfpv1,bﰟo8LPN:T@20c[BFVq{$A |5#BC ub>pnCL K4áu䰐`\' zAf\p73ڐ==I&2W0(sЎ6B2h]5#|c%{XEN{ný:!$?b>Ֆ']sŠŕXtUj#` oM mf#~~*w43 7q2Y9H^Iǃ'@0EV'4B eC&AH13htޢPJ!te^fPDr4DU7yu u](*l LjT eژaf/ML>9_Q5{YtX|6OG'4әhv$V h@?g= i@W㘶sZʔ`՟XB1;?#fphmH=(/cp!7i SCÍ H!֜M]5Dd#&)Aԋ-B,rR]RG#F`\m$/EmUm+\x)&d=ޭ矌"%7IM&fa K%/,(1T8_`DzܿsD11鮥/H BiR)?1U5gȎ2`ou"٬E9Lz.DH#dFS _A:$s!uW`j~Ut`!un>&yoϪ࢟hEnf ᲝƐM{ʵ}ekK_ K y~rjzi Sj]zW(W֥ YV1k E28+ {!:sJj,vheˬFʴf1]HF=c= ܾW7;›'N5.l(RS ;42bV ;Zkf'hD3+}ц@$4R]9MF>IK[(#ĸh%h9UDLyx 7'D>I=A./٦=PMa5c.(E8ܤ\Ud^uBL/z8~W{xbp_jw 2nM y#Hl"BNg3(#g%=Wa6o̲2)uqDC꒥MF ߑOfC%"QI#Of*侲/&6O|?1 3x(<lw4%lCX]0 qj#ULI.rvEb+_^?,Hx W8-G(+Y[ 'Xp眙U $+ѬXK2uy3 ;8|Pba -A0l3~V \2dvʝOOz16ӶuaOMõK_.I%a )Ou"G%=A :!\_¯IVè_s=0,ԹAr #LmZobYZGctwl-WSDX7w E~_ɴhlM||-i1,50n\ᣱ({@v@;?nBm)ie?Ti> u4z:XԺ==PC%_U cA/X-e@M'Pm#g^)Y}sلcQv,DE_:ݾF@B9GP?;Ɩݕ)(2f=03Wy`GNw{bmf!>nwCVdso˃"z p||˂8q6g ]g+k%@R[-2_PR$,0'[~tKp Yz)<(`N=D?Y?G=kx͡b"mwc"zAASxB}}0̚1|5Hr@עajTHnv{KФTX s83Ru>^p(O򰤆ffƊcVў,9g#F:~fse#W{6S>ec4g*y\AGmoA΍erO!DlnI’I0r"[.(bCa&UI[m ozq-x#QLɩ(F,\H¦_eΑy|QH3\;LHlMf켗Ld~۫ 8)PʲAVJx - Ɖpu}D嬍^Q(O>\=g_p=vY.@HHI;˙7/Z!uxv8h3FI{k84$c$ޏJԆjS+L I ד2u_"0ΫG=rL5?yJIqA ~}.*$hW~夦4}WI@b71<0 n h1HcŌ&{v.HE{;wŇ?my eF&.4@¶- nBkY[gsLpu*#KL\it9#c2 ذ@;&7V9JN5kXB2L7n;ĵ$_A}dUh{@Q #*6O 2.DI㛼Qg#pIv^ۤL#/{UgxXvqan)L) @g^E fa::2n`誉Xì`vv _[538]i~HVB;S~9Cuk#yjwM'z W:/`c#q[ :`y*I\H*ENbzQj,?!o\\"۪K"']6= |<+[i:B x>zc.4|hL>_ZW76Mc>J^eGpޢw,X%H7TEI@1koC7[%8*upi"Ex;:9F|*+%&?fOmrDdɶ8{z`r$ħ pd+ iұy_!K|q)_WV#/6"*غ[]uf}z<1:@ؿijD^j%ry/@A!A5]t$&i*~TOt :nF&ZrRkWrfݧ)J@My ׼dVDhOl fwh.98W6F1EUFX^z)xԉӏNبz=yLk*oI׆R/V?ekcRFe\܌j$2fJ4ޭ񣐞;%\W!R__qmZO XQ:wM?6z=&FIg ͹6&a(Mq9ϓתtgy!Y}'7r*Io|^f\} v3k0ܮeuπq@~ *F; WMb 1Eoԏ9*MZ|G"d3|7ܧ?咝GRVo]̧}LDb#y[/M1juHW `Zxz.žRU}['v$Ud u blRkCC !?e%{,X5kt8?k!ԟr3 5ݢ'( HW 4H5 &{ZzyYN;җ>Ji_aHVXW7E_SǺQWU(t% }4|ԪRp.z mgx)݆iQ3u|]%[+22 =l0 TabՍ"c1m/f1DZ:b{iP>N&#g3pKVA Lwox&|xa?#]D~A\_{<r0 g m)ЊL VS ]ӈ,;vM%W=HZH~B?]#/7~|6=}8jYT7vv~/N_/ܓAbu:N܃SA51 +c+ՐUU3kC_QդGgl$<+fܰo*EؖokӰn-ޙbUb9=5FT6z[7jwT_;r^r8=S9j PY_Pu0Бe8fu +QO,EdBI\lWܿ!sgJH-uܛB?^ht4KW!HZEmo¯E* jʾS QI oɎl_vpKxf=փJ5 \:^qz.}}͝3$*;Zw>MrBPURH~B azFO@@&%sCRA\6/$sIx=jp NVq K=xVqbp|[&!?p& A *ȩR'{a3\u걈#I=.\m\zXVm6*w$UiWIe}!LTkiR+ P<]j:WIFd}pp~Ru_z0D:Z޴֨WMP橙 \*q^q炙e$ty:{ʂRxFV~|-֦Wkk}Ƽqdž֨Ѻq״Mz?tA*Y…VŐԶ_zy,գkӂbA\٥ 7]r~HfRAٜo﯀3159ә(`#>X$njwR:nnDZ9"}=Cz,E#k0>1×5#EE.͹hgW}/vi/ȂR ^ӷ Ku G:j #g-켚4k Y e]*u!NYVgNYu֕2%Ħ38q%NZνZ\V{(R{)滍nQVI-l<,Iϟ+֚AW~;O\hLb4{PF[u&uBM'JK7+mo01g^01?" DڶY~#pY?Yahn"E5z#GwX}A)L@=4z=d +6!Zx`ֈƿTӤ{ܹ~P~{yw`um'-g_$|󭸏93{?"pk3ñ-Rakѡ7sCuҬ>ꪟffhp(2 IC<#8)xKr' ?NKP(offSYC l-|4[ `"V3̟!^ 0.(Oレn]Y(Y|df/D"EdW=5Nl|uPJrKÒ=D~'ƬJtD'N-9&2/J0. = UB/x0") M$¨迧zd`v׷κndGp+$U=+qsKeҬ#Ҩ2$g@:/sųL.]4 +}$诱,abĕ{" J_؇?+4ZJ ʖ 2C0_AٳX]ػ_cKtܥ?bv2i'y g<!w 2c :9^i]W)a=tNdQDǤ%LAmc1&3dRـTy N Qlɜ)?;ynL(8UNz<Զ /Ժ6 ¿cќĵЉq>#POĎh& ϰtG6jSG[2d,^wè1Yv|Ѥ T*eYwM68~v'C|T1;_7W.%3r+_B˶CHz_iȧ @g !p1#.RbU!H>mcE,mxPkxeQ·DwdTD=}3_>%zDW"Ӟ}]MXY3b>û9%@0C%ǯVXTM2`7JMNȱ2u,Z9o n,;”+_OՉqJF&SG)ǵ, ~?`E7 ./vȕ7  ?VNZq/3{NTV貛? \A#eRc*=N!?PXȄd7zaz֠f>_A$nDH.k`xJsL  a%Q`┧v-*)I>MEO4_C#7~j KHxq~tj8}tp6ac~cmd ^'+# 1 ' 9IO$o%_g\g}|mu@>`AT@.I }˛$PZ~o n=pڥ-遆U Sg`2 $~(?U9P$7AL/UWޏE<$CzVCz= 㱽l#PUk-xǃy'1X8熉hH3PY %ܠs 3}O<x+^+zWFTX>rC:̗*z.R$ynYT#:XGmGDzZu)@yLaG^%ڈnPimh#&vypTGV7`Gj6ԝaWi%f *{% N]prڶ8K#(5jqu]x;dgFMY ͽC2o]=G^ԫKɣ7^ 4=(ĭ22qi'XEMo*~ |o+zq0Sv&o5N8lάJ0%x;:"(VJg{) peVMR)UFH )fo΍`h|-L;|xŤ 4ז pp},|td 95z _?ԇऩ[MxÓ=hG KJ X#x0lAk{ Y: ;q2Q'Pl0o%GH@ցj{2V.'yM" _Ïfy#dDOY0&ОnؐGX76m;Jj3 !O1};pd"X;oT'}`>Odn=$[+Eϼ1aK@)/ ݄/PR{oQkvUH>ؤ6^<\by˃Ul,RJo>ޢ0e1cZGVɯ^{=G?G۸( :FHիmO>S``{E sǹ{x,?7j.'[?jZ* Y1'wu. ٽ@Z_ND߼m˺aF>YşL]n-@QboxֺUhC_Ss15 *bG` Bc9!#rcp!N(qU*x>.qa LWUݠ<XT?(Z^.%Q"sCa_SgV~: BT :"˫~B3#^}sodmj1D6CRso3Z3mZ,DR6n+FSu__i"'_bLCvq F3,-HYF9uxZLI^5H^TEJP^2~q<;Eak 0s׹7H6+3ѷbBJ*'`/Dy/VjoI:Cy~/u"8GֲI BfD R4n`-7;pZVtjgh Ĺ:DlF{]H\jFv}|Nh\T{?Gt.hu0BF/['p@ԝȍO*NJ;jp: #u%4E))ld bR{j疐a\ :_D#QxѿUp*YuEub-wq"Fǘ:|\Zz53%rm& ~_OҒCUI>"ȇFSqs}W$s!FS2V)5'X0uHg mLQ˵+b֜S[HKg]~v_<͗?gJp/fVo\A!'>ٗ|ϣa#h6}b T^6x fS?Сo%}+f}ZQ,c^ҞJvqVa={ i:j 1gW/HclGP_wRkY A &0hMHB?ȫӭc>D2s>r >*kj*NٕogVY}bN"*J -Mhu-}WƶqB(CYg( &3`ڟXt̫WSIϢ>u1۽=a;}J:F:XV1[߫*@ן6v\2cgZ_<\gP_&dOpt6]|=wz @FNNXq % @u0l65PU]nA~/ e萅rUس %9̎@ D87hGU|S+;=E <#p]!3ըqgKP,'W:rUA_IZ@T[+'뉃4̔k|C*g\s^~ ѤͪV`òD69d]3ڍLQquRlM3wRUHnOKN+6RjgyxGAI K%̼Ϭ׷ők=8 ۑiΏgɃcqB{U/O1d&J?ۨ!Eqy΀!. X1 &$e0׷zc1״r!FӘ} }^N[DԳ"6&\nBLFhCNlM֣<"> 9}~p2L|;AD? {?Ês 7u_T-:ϗh9??jEVyȓĔ 'Va:yݪ8Õ(K6f6 " .6BJ;7Qsr~*AwU`@ִ@;1oj2IҌB3CO2 [~V`,Ǟnsbb{ڎN׀\yaކæ"?vuG f׉lϯ䪓aS2.Akp"Լ,v;R+i$ d@$H0*O^Ÿ>%YD!$LVimR)Ϳ߲ ] >+3H K P0TvFNUl*Xφ׌Y>pNa3 ]rTy~V%_VQ1]fІJџO>LE,| h[§Ů_ެ+>|6{#Dt*EӁ';-tUbTCMH <fCF9A=~( 3ߢ`Fj**@dX۩&5 PCHH?] 6fױN?^ѹ/Iǁt3yxX@zkJ^;7۸jf֠6ûX(a}VamM+O [lGϒXe3GQjٖ t ŭSEzD=>_`ݢ4׵[*hLidr$A5 R@.uTL' a}c/dk78%n7fPi)7IPflEz4@;nNf\F>h+je[tP)G=1CFLlš#|UYC#dǒK|\ԟz"{YgZ/=pp!VɨWc M)l)WF@ Q(%;f2Dń⥔FS e'~܃ɾ4)Z[y`(c@)vu'[e?:dUƹeہ.B|U|C]\hK(*rXt7DX3R?Bf^/Mq|*]VT*мxaGYO@hkUhK[x^{q]ugIbbpo:!: CnkFj@@ PY)5[zx!E$G|? Wp6*;B(ŀGGCm9F8"!)\uM=4 ""' ˖ʢKs8u38coK=B?>'={0E\0C: :@ JKET#:݇xi=э8r24S0'˾(Sߵ-qw_7\bkL!'렦8,XU/\h[Ku VP"3ewuU`nk*?Ps&S;5mIx@juCQVkRRKƼ('l<|.GC~LJӷ^5VsyǺ渷ẝ?o?}q5&UpRyʰ2NFx!$d0ق`>[l2**b~6LSS+T M>ot1ƚc<+mv_jAﷴ 4/p*ʓpe硘z0E9(\m%j%eh{TtWC\9,_[eXCcTi i?6PkAR[|?ۥh9oǖ7+{ _J7z3@g qB~vw_ 3Oה'0:q&y68AE }P8~šo"X/1{q *cGi(T9˒ mv[eExڷӒ B)/E䆌Ͷl? Ѕ ,vlY &>Aĵ0ӑ F+-ܙNoފM>wZ7/Y+#g|~֤P_47M97KmLCQD @n1|3^e̟|y(Nw{cP{%Iqwwҁ?߽>.)A yD^{潢dCDjGnfWzm>3.h kC(V*DI*]e1g[K2?xux#o;/rS{ =n7 E?m)qLiFH! '+gAزƀp+ʃy0(TW]rȸ:,ywf5p?yVӗc fPKW=zBylXBQ~03qy&01+eemz?4t^?$}z- /Dg?P7 ;ԡ@!.ˤg\ # {'ES]0]ɼG.C<ҤL~H~q|CAHY׋z߭%;kޔئy/d-XtDcGxȠڜw/-Ugz23u>_3ú0JM )P%dE1BV@2冀2;ލ9٣y?IϫXr|C ` Փl"KInhBq0}Q_ PZORxR'f#p>aO)x s5 3vXLI3d!춋׆'\{S؆Ǫ&+ \5m+Im[-Y$8Tr`+füLi&,KqA, q6ȇk6;o~  u~wblU:x5%&*f G@^dͱS9sa-R[72oI_RCGi0%:䰀8(~V'JsJOZ fӶҺ=N/Pi+ǁ܁@)M*= Ƹ܄A$. Ct'شr6b mY9, T4l)' ,@NG=X ʓeo /SpϐrDXSCUi2*W'E=j0MxM8}džסy?K0p;SHQKJ^88&.h=IMhDZoSe )J;1ZQy;2Vi*ڳ1v}s%z hq@0F =n02R|ǕV[b== WlFWpLѿ%'2lC23zGMZ om{e+ \1/(ֵiHe7ZsrZ9!aο!ًzנKr_p\J@E],0v2kLt(&CuU|njQr0 zBBsm`?%Y ꡁ55k3Ӝ?: ת ozaҲHw^КJ4򊦆.p#ErW\fDǝ}R-/n!VqRMT{E>[:i\l˜,ŜZ6*/"埣 <"t㾒!ݽT?-;r#<4hhbx #\ p샯 y_Jc{N_K]Ƃk]T>茭̄_0WDdA;ÕVJ % ܉;^|*! 26E"`藴;w~(z{a8a܈b#+zR4`rMt~u/p!Kk{Giފ0 .^P{?=k`C^9ffAJ ~U8A[cw:1ne&VƼCw[XW#Y~6ݔ aP'G>1> aݽ8|&QPJ\{rZ:g /\s"~{>*x: 6>)5W^oZ0,6_7 gRw/QX,IZó |R9 Iq ~ޫ=#QF=^x1*hjOk&~6؊mMVc$"G%k)fۈ^qZM*uJ%}B303 ]ErnBDyy(ЈO䅎$y a/ pZOt4Sdw{;gb3R*'um4Giw1O 5aАܸ׺ !_VÔ=i=\֛l3kW2 *xf1B$hX'gZLZrG7$`溊,ӝ(+7|5FȞ H%!q 32Oqrr^ ][51C3vm[Wq#lͺ,#Jg .K,r?}CM!H5 )_ѠLِ16=֢MYtbV Tt x=9 4aDV}Oeyi7,He6+цZE K5,dDFЅD[q9F|\(0v9(#ͧ 5 ڦcjO=>}IN%Ab w9#56 mH>90kVNOb'DO(k@ =ج/A`4qH^AQ\tK,}s6oyV!'%_Y7ahtD>h9WͿl$GG"G)hhvGTYZވcS5#a5>5:Ưi+2,eu5+ď(BoYo'\˅Uۙ[ @.eЋc13UO(d*ZŊ{Ti*㧆A~yJpfEp:)+(3TNg}N76 ۸Pёrw ~7c 1:d I)͊Uh0:8k% OU4jqyp$Fz 3QS/%wk#@o9&._of>%15d[J9Kx%1j0 QG3\'rߓNgR1C{DA s#^5TWZgn^פPn-{PkЩ> _5z2t2[Ӏ2BSʙH>\eΈSGG1͔kC ʁf|]gP\ ^yDѦy=;3{6~geOd,:B/[ pP1n@\!TC/>LjnxnTi(7Aƪ)PőF ]BJ''nķ%ȱ[^Md6YGS|;ߡ>|xڭAW^1>X*ç.z֡7`{9 qF֢%{'csv0ƴD\)s~%?CCaÜ:G5D i{%, 㩶mR_# HGG*yo6;1.iDDRZnf+MzQzi!q! EE΄a!# -mlpŌQϙ!V/Ẅ́7ʎ|ſ#:Z7ϟꮗ/TeS 7Jq-p~C Y"V 0RJo}sNǬޔ=L-qeL#3vݒ.!+Gq,l^2?$"~O#gЏ{Eg58(|p?M"Aʃ^^(PQ\zJC@FN^.f*"E^_ϟVтZ#uXYɟ!I !{(< eDpK6kJͿ1 -Ňx64S I$Ap}v2'6.,'E] ?..yOpusnwwȠ;[Ej'zDʩ6'5ud/pi6ųFdP"b9hhH(Q} k mw ׵g*/w L/ڣm0-Zy\-9ޱ;(89S&IrUtV1 $cz ]`PM;ѫڙ.?͖Q{Ei;+ma"!h@"PM_[]|fZ{DM֠rB'2E,*욕WΫN]*ldyL:'~Gϑr=n'L ŏFK*#dųNeDP^V;-:% nF~E͈vJy*H!T+`/=,&x?(TJ߳%`|O\o 6w6O/tZs͂JIPM-E { g=[L KxTqb\2˖gIƀ~VLN }wGVY6FE+2#f@9y>w#b4L&c7Qǩ{S9%~3ڍt8E~8ߘqv,\Ƀq{ࣼ\h ;[a-yZ*bc4Y- 3 L`˹sQj'-WQ{3_?R\?X+9ؐq$;%=x8H 2M@. 7ʳ?Fζ[ɾH'Q+alJR,B8qL!Ca9X{U< stPf4['ӊ'G&4?%IΈ at[ \Ve|oi5MVT&wa}):i¯T}q4RD#Z[J@-5Aw a C3CT߯!Hy|1!\>_{N:˺PQpZmѠ;"+YIr9תȓR,c)hs\PT;/UI(GN!v֣aMufR{[ƮW!^P-DY ala20>u7f vRJ. oV  $,/Է6&r˧$_иIkܨyZG`ՐٵtbhO9OEIE2m)LHXD9ԻczVc Tȭ<Ȧ2afq~zAmۏMh~вSyd+Ho1ic^bg QQvӭ=FRQv<^ev+B[%׷f16ۤ+{"3|ƱY ( <NN0&~l:oeb44v2?M$D.~H18$}ubwFcjJY3c|mzW<0oNuu L2տ#Hs d]7絀~ռîPf k0>>bI9 BZfA* #^6?Im_-H %O JoFf w'F*s}EEmHF<ߨ&Lpeƅo'eK^ *0|0n,^RĩpOd廽3EÓ,ex*Pj;EMȥE,JCcCڎ!s~&WXCp7B& |z%맛Q09ӌݑPս7gk" "փ|1HaDezЋ'C⽻ޗ`& ݾwZ5HbP!5W5%*j]"uq27'd@y6N|5ifD* Z֔q:zOKTU;4XWZؒeyǙbo@ D ?)9w,nE)S[^ @ MY1B_ZI3P脘-ML/LW*~R&&ms`/5 ,TkbA!,ʜ $O/e{ -"h ,ioW^j}F%QS7B3@.-g XxJp YhM֯w**A6b fXX.ܪb{#7cZ\Lk(`QIV<w)Z9*:4Py2muHSb(fi(w0mt[M<ʰ57zN Sis Ěa.i u_ Ȳ%L |q*IY2F5UB/_^-]>D~|f95ҥM9R5 Zޖ!ޑs?L- Xzi$f sξ«K@][hxumG/"(n~pcEN8d:. `CQeļFS-`LNjIV&9K9CE+kg.U* '?~RגW/ʷ1#J@ rT5ツU)oJkfx!'xσ94r+e`~Bb$]5.-#ukq@!Cz\,<ٲ1mr,Ek&Xj*SXί\#An/'~bq|oRDy6C#ܺ]? %R f3d>D !FyLʹZej]栢Vb˕ . lg @=7IX¬EPR2w2Ix%dvZk"jaƄRK7I _&Yv>o{Q/?8]NŒp\gOjڶ.o|-e3#|i1'Sվwq H6bu!FNҾ96Baٻm)c|v@&WBڒ HM" Sbo]]([j Lz6k)o湱5:WP kѬ]Rm,%ܗ8tEPY/[JhgЄi"Ħb ]Mv=n>d,o1'G ݪty 4eh6(Ʌu #{QV@5A[FN%Z+ `:awhfUߩfǓo,nBXup6,? I0N1bZMGf[+.n]ZrEB~{v ;0ZW.M_*5tW暖(!;cE_NEB赫3J”1 ca.Z̦GPcb:" ~_ʤѿdyQ( p]mU]˹C0k1NB]Ra+|عPbX1EdM]ij»- 5Tz*6iu>>~XV=XVtΘR.Jn)&bܚ/j9N d+9Ͻd%=[tS6j`ԗkU^4b]!4;8`멑Ry- ! 4)0xkJ݇eV/J'4׺GAǦ(#NPqBB/ >+lVy&ۏAOR5Yɉil{ɰO|С@|e,BF_Ss>;z3kJy AgphQJ/VS >D3T`nu,* `PJ4lH~E#Cm# FK_)$P4VRb׉w(ųV/xI*eJz(X(u5>SM~d@;T2-M+ݍ|j֝-წ CqVw%LwW$T[*g:ݜ$Įgm3E)b"dhNS7g?4XaUI+]#[Gsq+>3,阵C Th5؆ۉ97)e ýyNBh+9أ~LJ0:F~ǨgV]/u}>erlWlL> XAk}Li{ ?Afu%azUY^  c<`|fx*XA;x{[ОS :0)j+~" "i-YYAFU JȷUcɾFN"n#/Uc]KEz ^gP|c= 5OQ6.ۀ<1Tte܍R+x.|@+7= 7iLL@F>tID*qQ#d!C;n9.ݠ& !TJ$]=Rf3ĥc~sA/OZj^}%&Rk3V+P|ςA2K?>»UM3IltVR)d23i`6|^yMˬ#L}У_鄭4Rt%U)?\AHjR̔_Wf,sş Xg*=`d[Z92x5H.6ZB";h4q6oH {#A* ,<`rl8d‘H$hڋJ)~֪ 8lPVNwnx( _`*z% ~)SQڴvTۚ?X]zOV02PG`2R0t3e:꺺>pAϴQ Ƴ7_h|:BLb4nvBAF,Μ 2* $@K?&tձx6኿S|-TwL rϾVSCVP6Vr:xl!RHd kK;RkfQ7]YDSX"ߺ'N8nw%_{Fvjo5-e\7߻h"Fcp UF0HIA@7 Qz( .{%'O05?10Q;4@TZV?687*y%zp P`u/;صA xgƂ^] 23NFM~a }ҥTJ%Yſ)!ȗ.؆ 5ZxϥqxUJA}ړ}LF Nw LjKft?ሼ/Y18zSϣKN6`~YD}bӨij$Dp*avI@T`|cu͐Bqev[_eVF i7z^\IC}-,Xe>a>lX)靠A)i[;z7|3UZA;˃F |_>+} TqZ `c;9d.=ys4$CΩFͧPW^  yOE2kgV>L\"I6c%8b1 aəlNDN_ ҕ4]ݨvdj3*ߙz)#{PR9;rw..蝸a7y cK&?zvXxA~5~Z I_; ( aRQ3Ӽ⡙$p?(~?0Def;﯑oψ=Ո|]:BlCIsjg{䃒veI:\Gc8}\;\:rSp޿9 mWp|!\vN~;H.i^ݰYooڀ?Dp6I"nIy'ӣعx+ݼTu*z o_ͺ$}xq绳SڗS~  7 j{^+2wZe=Z Zēgɳ#* Z3qJ5*O>9O$]0D]$ؠN%D䎙/(r* 'ԁ_wRjPAy,":x%$ }pNYUz,> "bt72mB"|W'tY~Ĝw**T'h)7^9it2&UF Mڰ"a'O Cÿ3I,3kZ3!H|W|!eQ)0Q;[/U;߳=L+KZ9 <;9D7R_fz">kauyHo]eƣ~vO,9nlSNylIrᩏn/PD&K9u_NP".4{B5/~PT"%I݁g/ }!L`H]A~ofq0`6lW-;~~DX[^3q_ zS\yV\T&e A*nÖ'+%]AN,0 P SĶpl쫼K!@:+y=C~U { W/ٱv:XK/ &Ѽ}낶[IzǠ7؎I#"{- zZQ!7 $9#0C6QW 1]48/x9uKkj`ԯKSlYռo%̷ _wv8V[5_%/{0NUͻ M7XFB]Ll6"Z+1ZH,D k[Nԏ@c],ƍSNQڢȰl8)>m_b#`1@NNhia5͘}k7oQ"讹@+"S/UG6`$ RHQ٦LȽ?X%.s@z|.iRd}MgcO'sR#rM?x/|r*sfڤ-gFz/k+'ei|fOfsدgq硂uLv xü4HZ{?s9m%e1ۑ@?fّ rA腩+4ǒ7&G5@cvFֶg^k;dtaqlc_pN+@yO;>nD}ynk9K=Hzoub }A5F`z4F>!VpW0}yCZocLP[4L]ǝW-IXmoPD ?*?Rmӈ|(}V;=t݆^M햻܌)I"RI0’`=,J!ן'~ BGPAy΂,*ɭwt kׂy 19%숥&OSЖnrAiuA~ rSn*z0o1c N3p  Ior `NWY:*↏f!?yU)1E%uÍgy#55CS>[Tթ0En7p5(|lB5ggQoړRN*r yUa,JաM >t3h@Z>VXPmWk!U}wU&Nov0cB`JO}T8[B׈S{ƆՔQ{4&WIcxuomheaY0?/ Yoڴ^yc m=Sw SPγLǣV=;k^7  J5,46BpMGHaA"l~UQ*oF-mB#$oxs*|Lb);;i,Rq&d>Op+vUޅYb\%?uT;3 4` DMδT3Ë9cR6䱘6iǁ ^*!?Peu0Th}kX O HeW=%0<6v/3x&wڮnϓu)Zo.R)PT:E;vcGw9펢(|YH7؎cÍZBx>]iI}7ߩ-(; C&.01SS T1K+zxvX#wLE,mA!}3tx wQoq:n= Lt"Nה JhU$Ag8z>8Q)=ZƯ >+-C;ΰHc=V-&nNݺ1{s= w{EP:D ŊMIJG VXwAG^d߉ɭ">\a|}lns5BcaNeO7XM$$`wyB>xq|)[5''짾R5uC1+i ΩC^/ ;Hr:u+>|u QT7`(.-@:oa*sh%T^G Z6F/u3tz x[u%1G|3D8r}C2++YX'_3CP=ESc(Q\9*fH_e8l\ú'$ǿR+erNzI/FTLBN}{zz6Mef!`7#LhMc, p Z!I{}<5V0ERO̠H$pq[K޹#2~*^^<"648enj' ^G)(f&f#[7Ÿ%rֶ;ĉx nkT@1D'ɀ!jˋɽ.APR1#EyX"OxTuKB9y< )gmMv2^:ap s9 GL$P?3E.r5ż+*4(}o@a}P74(*qC!IAc/=CPw#Uj_wocz(]>}C4ךNTE O_-DlZ|0b-)8sJ16 _7q2q'٘i>Rx[%&x~lMI K1vٻKn\$A\>'o>w;=N%z,z=z w(X?S/Q},3WP![b&JjV?BgЈ) Lrm U:l14Z%kGfU,.YV0АCcB1U2LSJn _@!<ok>D;pZk, fг _'aJ. 2 pX hK9,OpO]yR2Z/Μ#{H@A|7 $A\IV]oxhwt/xkc8Ȋ8&Ø;CΎEQ4BIU^us]e0͸_zٕ|@} `^Ll ;%Ƀ[= }$ڎו5r|{L^VaUg}1MBvUI{U]&n|?uz2)'z=@E {SI#EJʤ78wa?Tà:9|W?UG}!*%U_M@o@}3e ;?hNv^fLsVڌDڋ'LOixR$S}i9O-/"xy-vuS;?]D:(uX}g8 \gX—`^SaYSӂ4}rR=zs?H$|+h``Istf<[_{-NÈ Kg|;mGv=edlbb\wo4[z(+Vٱ#ܑ-I"~n&r..O0%?\-yQ7]&#jKd)=7mu'S`),J)]ByI㋎;F2ka[?Kf":Lxg)/11GCɮ6͇g2/.tW.eC݋$1ǝ+1-X?T N𴦎"ZP)u&Չ=>@}ݤIL7BEaOce4+& [bޙ+}\2G1oAa,^Fq=_3>7O]ztPzsOEa'+]ڷqz~ݣeQUqJ7L9iU=D]D}c՗Ǡɔ=>oer^XT4e5McMk5?NVv{DQ[ X^A /]5dqKv!uǘ t PpT?i9⸴V, M̥z{P0Ԅ{ӷw[mugU6Y;:NIApeƺuieыNru \t<3$& #eܯc?OZZ n8yj~iܻʬ𥏏)ZRtҌ^}<{z{)гfsyf?2>'*~j@w~,a7yQ= cd^?)fb*yT2k1x(Eˆ _/6ͯ_'~ާ;7&o :+VxTOq0ۨp/Ld,wpvP ab$NY.P#k,Y)_RPPUlIǘyk^}M؄a[*+Z@c#&7 az0ǜls~O@cCte+,OUƌfg "wBfoWޔbt]\M "ɲfe; :p?X\)px*yc1jL⇧B7dAQGaGAy >g)$n=/?% 3{2 ,UV3zYqms16vPo+ZnCbOHggCUE_j@,,y?'4ܡdR.F$:00 7<9!S~$r[K^s+ר/96,& #=b㔿cqM~FA Զ%RtJn-]Wh[ZZoK3W|7Q.Ҷ#DTK7;O 3Jڶ):@=TjS*xdvkrE;n8?-5ɈR!M}42r(;Yڛ|DX̯k5X<=iFNy+"d{/om6jBۓ>qzw St ?Ty"Q^=i^#v_\JӏVo֌-) “J;7 B`t(RGdUw;4D?~Xhve7ʲs}XtEmV"[v7GݸVh /GskkY:> YRϡL *s9m܎|rpNzޔ6 IČeHdMv'4Tz5\+%4slwWk 7?Y췐`y 1ZR4BIP%i+%d7N,4z}@h.S[=w%YnJ0TR;IJ`!}mmF.;<[x/4.6V;]-FCrp0_KGTߘCBapB 11ga& h|cgQBc,b?N]rOS-a݊fp tT<ѳI6,+%PY x]z#OR #1OШ`m9dq2Tgl3~pa&G{Ծ~?i%;3m^@>2{7g>S |׋IwkP;!#g X _i~dKZ uBZZDR_biNЇ 7\*k?5҂hoBNZY2}|2 iJp?o bRPoX-!~KZ6=lNw?`T,e%<2}Țo#! hJ‡R aM2 }G SB9'|Wl&)ꖦoAc(Ta̦Eqiþ pqڻ96CK+]N>x ;8V?G MO5Ewb&Z2RIMjm12|fK5!- <a~J̛cϯG]PvaXƳb^%Φw :a#3qSk&@\=&$V!a^&mNQ-y7$w5yD>8e2!B wI8@@}"?DnY9DdnGWV MI*(# hJfʲ?0zK9wȟ2L_,&~#:&}/(-ϗuOLʨ0X!>^ ^AрbxFS4ud|e…pݽWw[- GZ5Ѡ}L>e88.Y )2[4y zs^`|n>F|;${P/ZeY QKh*Izgwj_p/E)^ۥ¢Ûu)" ~R#Ǭ 0N,7C7|O *N⑰sHCd_IAO\ aCAiueCA*^9uOE9mIRa>Cՙf#!j\^_{*k[ر\J~r`1bP,]YlcP6hsH̱ITh8x{wMGPOIqkY88XBVBK3ILܺk 8//aSst[K&$}t:SqӀjpW=C!=Cb'R2xLG(,zTG"'Yl!8lHqJOcolOB6B;UL.?ޫQdM?f&*͚Y;pJL;T^{.)/D*5 $!}$nK8˪A߯5dr$ )Jpc  zX"'¢ncWa aU;8 }tT 7}Cv&"cuR&+!ٴ{tZ\{&aǾ_nUR)+zte٪b慏,wI y5cl1 ?evI6,q^ t۬AK3ټC={wp%,:}N[uF;/> wF= 1!pCH._!5MɊ{x};# R޺E+~,=ȃVw*Tma\uX]\h[*]m0- r$ȿ8ېb5]@V+ ]hOFd*H=J}u#[ o$ǝ rc'Kqj t-]U{9. cwO{o}n)s(&#!؊oQ:X y?)t8s= *:fxa 9bXy8 ud\09٥-WHy})N% zs-2YA^>͡aLP8rK*'uZtc(ܺ]O+fF4hn*\@ՙ/9ncPLk=7Bѓ@ͩ\q wRXDe>@j2[(FjFWn"tl08m Pxng4ۀ:VwDvmw\H/lX5\dy \5ȑc(+<̝H gRlpD֞˪o)H坯u8; 2q`p2㘻u~8@\WmFT|mtA$p7NJ^jgiT&>UwFU0`lYvt vĝ8_8J֨QS.e˸i+xe)*?$2gy7c[d7ֱEigmxkS@W>&HQyh8❟qLI;vUjUᗦxa~6!L qHF+a=Tn"RJ:=lc+Y𳘴SyHPkIg^v=,| oޑ$Sr+lKyvb\ΦRT.d?0v|ݔ$z~&Z%> 8~1k0児J*/< M_~\}O⸻ʮA> @x"*n sծg1!uԺJ;&hHx 52Ϸg` HnKDL$)-T.n#$C8g 316|ק5(ծֲ<XӎU, +b6*B}.(*cĭ gfrcY/k L9piOBjj&ÿ+mC5 T=[-O`Llf,_ZGczT2csk@Y]!:Y鱂nJG~'lx,^"z+~(唙=(UԋC}^Es -:}bAi7;2 !zi^NXWw} sN+]0=(i?Q?K,@`V9O*һp]Ex|4Xq9pp_:-eE{d~55SфwqĒѽ מ97G6D`:2YV Bl6`TX;|>}NSJAJ̟Tuk1@9 KGENGvYG;yBaZݽZE뽚ͫmRa-2U&ϾA k4g]+~1A=1ۻGEE`U1jg/uYqc!Г̫cB&@mw^\:<յߓ.Kiot.$݅ fë ,}lFN ~Ӈ{\v(F)]^:gO(vj6f{ A0Cn u0ekj].Аr3 ~m x}›J=X4ȃ7J5" JФYVwA/9_(Xy^RR:&c5J m:kkpx96< Wv֞֞jc>펚OE*CPJƁj]7BKV4mx԰F_z}b蜟J 4h5\ ǘU:Uw!:}4W_ RD3y^D뇰vq 1ݯ^gL`f!:T="6EۧJ(w,߹c4ꊊU~.U7FJI팤«vIFf^Ŝ.,A8E[~ڱ+$&@ /Fʪk5\bnG(;dg3e-){208)/۩,LSJx^j}  SUËB7JX~%{h2j_U!w`\FqKa;] D&dm"4!%uMu[OəS#6ѦL꽇Ԩ#eG_iT<]ֵׅ 75ZDҡS]FՋ-pΣJN:^Ngba"ޜTWj u"֠o1zNPNgYq+R+/1 ^2 0a LXnr#y(Ąqh))yM(>:ԞXFE9]2v,kÖ ;h, J>D`˰4=U`*Exv|OT毬"qF+7C "`)!4\ҸҪV/ɸ( 4_FQ#)yL ~}-v.ZHz(̋4-ѩ$%3mCKׅ~._ײ1%/hwp&47Nσ#Lԝ~`pļ~iٟN})#/;~![MQ{v?Jc@'Amw1c~$ Ӕ7]\ca}/_X17ќG?|_'&"7GO:UQ`)$ P+!-(+DhHD[Aϯeׅ ~U47o+A~~M47~$_m?M Ͽ&[B~U4#N_knI#24jW]j\U~G ~٢\lJoG/~x Ou?O3ކ3Ca7?Я38?o~GV+ ' 2~Mm(u_8a7?# C~¾a~~㍿ceW4H:R_U~%s} Sk@m ;O< gL}]aW?pӾ8!8\ o!DaWCpr5}}5!8m5(jNOՐjoo)X"ME?R_K^GZ ڿ7b<ٮC(XAȒ864M -d-@>ח_0X ߡ0W#s?JedFTAU,IڿzW">2?Cߩo=H|X\|)(@ː?|_~b^ﻫ m~` ` F@Q"OJ EʼbO쇏t 4@FX}sA`O$, oqP~poB`ӻcDBw_y; ~B{{:H2Iil':`1Yg4/c%lA'$_9 Fy If~pAAbAX}d~%b+2C,;<Ma"k))wuMt@oa0/n1 cGwވ$goG0'"q>bh&!,KbG/>0]" I|߿B0O,΢H- t] pP 0` ,C"J$BObc Qcp}"flP }d>aB3?`po4FGy'X!G %EpB }$NB Çػs,Ϙ ӧ,QhfJʿ@s_ͯWwz䟀,Fì$?G;@`K_B;GQkog(B}20Z ?}O%P ?1(ҩȓa0$E>atl˟X?)z|;& D{nW*pxbt%6!?QJP_\kJߤ߼hG 1$N~8j$I 424 u͟_X+ѿ D鷝zF.~;n./3_Z4AϮi" 2/ "!ˢfKԿ6~;s?Ư$dgx #$M1{7Vm:+ca@~X`5(卋ot#@f A4@yj拫qyɳ,A|I 64Kd8RoOQC>!qᓠ &'?_E@?V\Vc0M#ffgRFXm;@/׶)_w{τf;_,'~狢mi=`pMޠ4?}#tMI ?{z4OIB?LnJ %c3@&l,e.}'ҾGSJlu 8ξ֡z9NYǝ@~oEΖk6rȝNm U _l'؜ls+ŋs5=' (r@Z@H<ܚb\c)7'PPA`u[|W2w%tG9".鴟8:Uz}rF, EUT$8!)ŭ<\0!L;l 7bƋ68XetHPnGI5 OqqBk=ep^:>d.TBȨNG:#⮸֍M0].iGW}Ml3gUas.WWs{=@7>nl&V\7|>ir^& ,kg+H8?X^& d꺳Pk¦Sh%InHMnл/\c,@Uxen]y)u=7NJ[IIjI2+y)<1D3AazkQM8Bzg 쀐Mc}n!sX>XRӥ,iCgeUR'zlRPJ+ b 󪈃JY!)ϸa0RO(U=b/w~MN$ϗMyUq3;ֵHpp!!棐[ι5VVdNu?i1{պkV8aQ4] g]upB9B{OE `CyͲKvvy*T)_xb.Xv~_T((k:%vhԑN7mi>t=㉭ݳ)紲ȴ >0D|}}AT_rkd2+i:Ks,\+/LF)>Zy ǹߍ|-[ p̂yئ-CUv4zb-m&=lX}opzs76uV.惶O{gZ&ֵcĎؾܛ14]q+u%$pʣ*2 N-zIТ܊fwyba`$mg.6|tZzƘVhBN{QǼ ? Y'3{&>5Nlwf XZ4r`[@_[djǫ<59֣ -!`<6r ZJ+2MNw/JJtF_㺅8ժFn=e]ُ^vJW5'H5SzrLtoP<+w, xЊtDV{Kas-cE1!H a9dH0Zdzu\KSXM<y0Y+=IaJsS ý>;U+ʘJqg ta4 hzs@iy=uT7Sj]mtSr$>]ʦꨚpYS_v0yArB_S Ktt4t> D|c:%!ů#wa ,Nʕ$i#"pk|U2S&<)"} @> pCV0nqhmb@%H|^3f@>@q/qPiv D11)1-IF|SʷYp7^v^Pf=nqas艃dmFv08O? Az< )goaIXB?[sd$T.z91o/y`6a8 #R ,裝GcZ##O5{h6 ųLL&aSg}@^2-2wVꙕظf+X~ZdF>Hu4I!ċ8@gr#}  X74m|uƺp6,ٽi yXWt5=^K:.y |'sxhp"9-03 ?9q -[p3; 'Av ]DGBz;0зYtc6ZeЗ3D楖8 o&0Xl]12LT~=ج{ D9@G4yo\/+1F)o6'0KJbRah!fq 9pԩi{ퟤy+{m /r!e*>ux=$1~P`#e΄4h9v;|,eՒV=S/X[גlK3=j&UV}?bwth=hYxPYK"Rt`jmXb7/Iz*X/ eALXbFX:r5 b>481s8un6(n{S'7jܴ+c7(c b3¤wޣm)Lhz@2YGfo$?Wm>ŪI>d%3=?$I,GP>zo(G(۳MX R75gnGl.*4CZB0ZΒptS@cTb]IBd)Z􊺽 051`R<Ɇc,9p(\n/XF6S)'^s^L?;7!WxkpL7;k/`y@7zƈ;I gPs+|PN :/Aud. ?OtY^LCW7A?0%Enf2;-V0Zv,4waNTNڎ;T{#֋E\sy~>pbY.AfS jN;wDt>r?F^$9q?Al=ie=+%,w/M}]wU:)kB.LNݻ~ "aM=(4Ayeߨ6g{RI[zt~,0 &T.XDKfXD죄%E7M\ݹ d$xhӞcla {s&;iVCUKv7#~61hO!VBEGɼ !ձ ?d8?02j(Vlw𤘝6 5cvݳ =_5Si溘"`|(O`D] "P a:' ͹0NȀ jq<pfZHvdE:z6>yx .{D8 5c.b sD-~qjHONΉweŸX寳JgQmU;2rZ—(7{/Ϣ6L6h yt`+<^iz5H֋AyG'y8x d򐑃-,D gHۺ93<v'4"Ee Oʱu-I/[[:_ehACd[u=2៦kAd/vܒk5_ /.ΰѻ{%:D!θ&CbR\+QڲU0r3!̖ٖ#WN0;‹ tu+2&mEdS;,BLNZ2364lf:Yb*c9<@2n< 91jF4!.ވЊ.3C}DQ® ~=EЛx6y^+_B7|0%wmE>o# &\.~8ݠl!́,,]鯶[>Nw_8X[-HC79Xt:-,&9V;KirB]-_;iy=;qBwi2+{NFӊk Emhةoz-q>`z΍,ߕuzT,sSݒj<x,]})]rr&@u_0曉0sSWwτDh+Vdw3{0"ڋŌ|~EC BoDzW3^e.Ci`lxYQ05Ob4@Xᨪa .)}RYdbVN}rO '< KTISitS+7r8g"P㜂L*wz:ݳON.\q whZ/0!69v۳(_jmSs|4*gnScAݐ<^zf,)soDH8vt sGWnӫuDS,( 3gJL70?ihwXΧJO|jT'I,eF7衁ڤ#ъM YstފQz $CI%%gq_w̙}֒i+iϑ QOCp30Q YvsVtSbh(;Tfd-v9S 3a,̙/9Gj[z4"w nU'@!#.ڟrv54TO;kމ76螠ًOJhNթh4P~ih[K,Ah83L_˵ \[4!,5y=+L7ǔ+}s&Ct,˟50 5>sd4q>$"\b(\PGJ3U%R@ `WN@ns&c u!·7KM=%^#1He1=K0J|wjap'D գdQCY1.\اfIJҸP P-X)Vhp:^POϫ ^mUm켄g$V`^ѫ}:5) O2 w*pV=ų;P! RKw }i8-\!*(ߔo^x L4XQ<}}5T_'Э^|ĵ\m!1SC.nXG+vY.R>zjPrHA5~DVƏz{tm-Vq$wM4U$S=9 `׺NwqvK3PMC-SM &\\*5!rfqD;d+( LJ(yן >ƿٺV2V߼46q_+aIAIϯNd~HN2Aem2cqwBE(`874lw]JC)aٟ3n+Hzu}MTx5(3>GRW/]B_ 7Y?|,DU > ڭ!&c`_?'́Rli^mo1_,EsC{s+/졫Zr؈ؾ_oSs ({ل yRX1UwQ՛iꩧn~>Hw.YHS4 GVQ=26Ò1UPjs/x#~=JQl M[~Z'l0zgc(S.k"N $HX]?<MKSiE`{7OeΊl߼I3S 1 ?B&_w~a颍Z_HW*s|tQIgV'd26>ZqՙepL0iEhE_KA9֋ZCasLd1|%N3:a@ii⯎]o5dk6fD F0bKVSDe+iQdg5B06(Ocfuԃ@Vb:* *)Y=H4"YT i^syX.{O(b(cV3 vsJRhyA#}Aꕒ=hD+5xϖhsQc\O7YgGr38pͧ\p7ioAX.1+Qɋ̕cu*.GsM g5J?evQ-yg:m.RGaA5"3|*,=zK"z~ItEJqDY'.G(k24[rW3M>3 0kd+cf|H+W} (JP{qīKum4,Sh,,:>&^@sTo ~XD^vo~2禋?-E~s~~<>bSE'0Н1ÏW*f f i>?z^]ah/r־\R 0>(ڜEpN=OP-Hˤ(Zʼ#<&˂^M=]¶J51J#6-#qywQGǢ\caU4D$SEC98f~髿Jzz?b˦^J(~q.GJD)A¸~cfZm0`yiեOb#>òtWn 4IA87Q Q`)|>d\-1mdynC펅g>$ƻp6JA>g!9bf9F򍬭CY,H'­2x^8Uן߱ A fڗɘ~k0fqòeDxrSp2o!h Zu{R_ԇ~ŕe3H| RF?QG! *t_יWѮ|8n7"-[Љ֧@%pZ&|\ "w kvT΄1W ) hXuآ*YSd1UZQlY6ykPg:Asl q +-c(@Я~ZF-п{6Y\b:"6{~,R FyBQܠR& xĞru ÷MZGYgEXX$!䀛 U ״P..aQn61Gr;bɼcNkfNB dxl*7n'j#^z/+WkTwY be pRisi'ҫtuh{L„|=~wrgraQL*F3hǕ$@O@yc7ۚmU%{G ӳWEΓ½?eMulEj'|z̬*@5x`Pnij^2%u? <#fCLrU&OêMr>WH@7$T :w KW|v`; 2Š]\ Vea zdI0]byo \ɵA21>SW>@IuHx: o=V_xc|˳%$(ɟbpq^iGHmpR҈G-ܕY}oGI^``[8@f+WcB$֌ͽZP.w#덼WEp}!5?́-- I>"tGJ ^kߎwIh{! tF 3scH6rRȇcb!Z쀗/z*pmwa;k1>5u—RН=jժU>LKX-Kr>ًwMƊ#G{b s]܄dl ?P۱eڥIεqgͲ~wgN .i~^3ɱ,C_|,?fG|0Q@0x49o'n-@l!AX不( :VhcG)z p3i7 &IgjfNeW,`}rdfHJT#WuVYSKu*711GgX|1eԓ ih* 6DALarh,14Vip! -v<{ח86t~<"]#ᓿQ${]jafFV-]m{18Eh$0bMөqt%#Ov[K}iSF+X"FW;%Z i퓇?ؗCX}^s [L]TGr,c>09jE(4&Jzô>˼m֠vb2C ׬vC{!Rm:7:4`gX]]?!e45!`r%&cZZMDf_2x3sQ'=}N3Ǜ3Ytei]C)O7I|Cv]8@ >XliuDWje9|bz$AfcqyY݈wGL D~c I64I*|-d~⪺#]VFOk:hcR[[{{=T;\r.m"#R4Gp|u? $'jlyA'JEXTdPivJ7귙Ct+$uQ.Z_h^62lcx7Ŝ~ uhA&( {i݅Wdg"V-=mi9/B߲z޵a`DtBVDO6͢\$Gl_GJH[Z_]&Ԛ͈Oϛ *9:>%٪: j*MAأB|.9N SS>ĭ̒a-MO+ Iq?*xPt q]2܍ pvpLN(e531)fNC;ޢawppaX)OИ|F1̈{'<- Է,.EcpWs-Ϫ3X4Y:~oh]()U|nrªg_-4淟ҡ]3>F+Q&,5Q޽@:]>lP齠GpfRO& 5&Wb_6dzDz̤" i`S:΋ ;R!o!9BcA%;ԶL#Ȑ7Q<`HgPuf7uzR2ҥDs>S`ԋpk#YE<+)}%9aѷGE:,x4?"8r Ɩ->m&o'!ŲVW%7y'P޷CT;!Z|xroqľ 涍 IJ۠0852x20`U_aa3c AUL%^Qq$WFz1=򏶞1'HyBNO@3g(%9_L`}V΃ؔ-];^Rok1 Qal: iBKr1Mi5lD P b]{#/蒲f4 u %^?}U9Yb$;7+G.WFOv+5˪XSǷ?c2g(00Dǹo$5(e۟zZPc]B cdK8 DŽgN 3u竛ʖ9\;.Og"@7Z/(,Մc3\wQUiɛ|}j=l/F; s&ȣOub(0UquO.N\O]ܼ{HI-QL.Ŀb-5/pޕA eL_ҁ EIR8%J/ЀGjBU|4vJ;!|`  C%p6u;e֣n 9&5J?"GWtw~cèw*?إmiOt1ֽ0h P5W̎O&=Zcz| VE>?M/8}+M^Ա® tBsS&z /dէw/S>Z J&B{UádRAYٻS)ɍUL˩1_y]*%ET{~/<OsBF #Ò]ׯ'^,ϠNk,/NC 󷠸'@sOo#qP}׺(cQg{LL ۃK17 N!/OudHL(or4}Q5_SGۇz:SҶ!3Π hNۋҲmX,V|6&'/޲%ȯ%\rmwO^Pu?kIZ&Gu+minqbὉĊz";wt&3Kӊ)wEtuRhHQo:|S֎1] Rj݀((yuhtM{2'e^!#̿h VP[H(L"1KtTI1AeDĶWfi˜elKh .>|tlΆB#$=h^cRQ,>Cau. 9B5fx9lR uV71 畮Wu ')/wۍ5? ׬}ڮ7 g0h+x2,=, J=`/۴/Rgoqd&zc- ᩇGxΆ'J&C" Ef bsW?NWj׮KsJȟ` 'yXz{Q"AX􅯜y5fjybR+y ʳdoFM=q"栒O(V€2$[,,#_+#;ИteYAy%3ApRN|]BTh_/]tc3gqEroHO` $2i|Wz-iߤ|?e0LIQR+k,%bz$V^c\f9rq dHQ)tsb摛4HޏZ=;]n*Z>۱i#Q:7LѠ`]Ϗ~U9ZđJZ`QDʼnF~jSAdvoW+C{+)=U&as`IJr.TIo(!qi^[#c l&?"\%^(QdsڳC|&OT=2bugl$ ~Ȁoa;W[VNaE[htM8$(eND ^_> [`D:i~/^ LvEǺ cU&OneGʌg%{4ÛJ⁨RqWw14p 0P %oFߪA?ft2*reR2s՗HmٲSg\$CĄd,7UB\Q(#_1 [Լ-0x2JP㿟/y2+~_2{ &r^fHVn=kNL\)3P-EM\ zPkY* n?>?J ȝbB[I5mh~hW" NZŵ\;mBATKȁ?ŬO:V j{L9F8*%˗ *3U`bZT.2V=nɝh,; F9cQ~2Y=IU-ib۳T+ &PiE58{_}MU֮lW^Y(?H{謁J*إU<<9}SW/uKŦL' [sK6M[΀5gЛ'AWľ;.;]7r- qFYt_ԧ0opY䊓7E #ͭ`Eos -C>xa@#JǦ-nzv5 ;'+bC;IoF'cܭ"8+d[IEhR3gqzo i,3CSVh4ٜ?rʱCv&mQTBFzhٜ]n}Kcu a ;LiAoq-yDg,'ܢ,hnx]H>pn4d!L2,Uo:뢧l:&pbVHw?aS!}Yoj_Wci)wJ@AWtpsbpR[Y<:;v?q|vDȤ@5STVl drzG eC2^tѐ:!c!KI`v[ZfxO5mFL#UfK47T)Z14I`;&P #7(&}iyovQ2)XH1=9CIk0o)XoGr2Gs.xS~KW!v3V7]^" ɳ9lF9N[?U@*GTk_[Rl#W\:D.31Wo~ɑV<>&Z] [p7]oF&NTy날Nٿ7(ng: oy&M{E?]z2:x z3".PMA`̪:aQ<:8'@s ĀpZK$n^Uyl'KB2PI61iTkr/U?=$`NfyR.}x/B}(잤z&. ݦ_tTՅMv.$4CFI6*Ʈ?nE[r9.+ϴWxPpadr4->r @?>pn!Xf^ix/Fv\aӥqcGyxa07:G`>T1x Kz(V+pOYHAAЃ|x-))^:$Mj]R:W+4أ1]~+;as%2 ^6fe8J92cyR.RY Vw/ <=2*ioe`HY%Ű~,/EdWdu2yoŷ1 yrh?FG]9DRd3M$J;1 ,>-~8 03Z6FޘfV4q)F,rG2W |?N>YjdC%{iÂN3L^~"w"?pNoѸfu}IBuY6d\&nlu^+?~jYAhh/_ +E/ -}nSᝤȃ]VwdO [mDq\{kB_:mIW!'x$|hLwbn1G Ρ_ZUi`Ul''!~j[ЗzT"`H=>Xu1>Dw휯He$7k_'yE]0a#f?:dVIAdTVL\DM/#8߂|'b;00*#V2(w6Ox$ȢW YK؍e"q.X r`߷awɈ^-vsY{'IiC|+#iՙ M; M:+ْQ(e&7+A^=qm#4 /]2g،"S \K3lLZtGyPk?wpo%PacnRQLqpFQ@V@5(LáTXPq|5It0-/;/˦Εd\p MS?szT0|h`F˦ETۜ$!,!K;5O6+eoZ+Q4$A5p~qhsno}QK(Lh-:¯ZH̨c润! (UwX;qRw48>Ԯo2i}xllzxE.?Fp{:L;U W0rgs"c ͔ofqGQh1;W7%Ers핵 YUH2+zMb9Df`3+a e,'Hagrz#+2r級.YXt;_Q9V(B^Ra ԩʿS4ι*_ZJ}9QhY-" XrvN?\QM4-b:EJcG+:״JDLqu<]1QV֙-j)Z#( P7DqC 0 Տ)%U'w2C8W0j'݄oYQJ i :AB4wk AxZDL+LWᅤɪO$?@h9_QxږRn97 AjbMB L] _q! G +>>ε4EKdasڶ8.DBu >קmFbsʩO6-P5luؐjh qN{k ([`z 1(I)=&xyOQS Wn" 1TH& 8'KL6_sg6ϊY`6m n^J>qմHy\:)`Td ]wW5x  FRZ#8ַsmK8Zz$7=͎dF|0Y^6;h IUz HA\ {4 QQي;P5%d1^Z#rL{5&tr>l~`S0HX6DB5*_V7AtJ俞Z#(⢻x`Q,$DV.|tpP ŬlP6w -KaǖMtR/WYzh}BB@%eqiB|)l h tiirQ}G88|.EwxIE `9|KiHk<غ ~w-Rxjabh'lr9,W$pu1DH9Sa6jma)hQ2yɁ+ORj88:யpbA%jR8B=poJONݭ'6׌7XKs_(CxjXrs}̚P>d.zմ#VC3-*2B6؋)T fk}%9 i <\H(*aVY^2I$ђd.A459=Z@pk Ⱦz*"2< ]UԶF6%"Eɶ`\nC&q`Rމk7zo/[Β9a nKG omه)jy# ns{@MvDTqwjF#YGޫpd6JtXGj3E!UB'm4ϒ7Ƈ‘_6Qʓ@ >'^AH^()ZM. Nfʤ8˦\xFX˿.#y$G|!H+DvL]#>3&St8s"&-}̠E%;VJːsGg_Tk@xAҡKCLcs*DE^Ï=ߛ95VOi퉯P[H:]gdo/S\vx*>N DHkiok'>ö-G_Z_P 1t"ؿE3o߲ qAtr+pY;I@o6Jy16%5})38$LN`jϞ/g{t7SvCzÚn8\_5!qs1ijF9ysso";MԗF2ZZ:Z ݦh$ J?-Bf၎S^:sO"*I:46ol[?7y&Yf|FA@5}r ]i )r70.o}{]|-bk$]=ӿQx l]ĞDBMii 4ΐHR.zAx:Xb?+'ϥnu'1PWnf< .ȣȕtg!3  YP&魰tHP|L-$qc0[ˡ\bp!m c?NVb 5{P95#PVfwL\!X%}K1=]R误@-ा-gj$ɚ<F;]H/T55.L0">~J-a$ꜭO@u NAsunEhJi nH>NTSOB^Au]؁jB%'jUP q-f_Ƥi[wr3sڟg,AJaEF6r.|[ QVonݰ̞aBK`u['I7 ΄ ^P&uK '07)C@A& bv*& z`V$ Ϲ.qQZ~?!ad{\'Q+~-{Ewûo L?z ?|_Uޱ7BI~E{ݓ{Dߪk `:A+ETecTc Ex¢ß)_Iz*׬7$TD,!׼Eryٷ>.Jr.l\Z̋9pيKІޯ$ Akhh.bl\79D>E] X?ݹ5*8=s[GK[/Ɍ:FR>^| w0XR S N%-hmZ rrkUOΥ qaEP?ҁ8~Sbϔܟ[c^}U9Au)b Hk;UTuFJŴKM6fA21Zy*ZƜRֈVAce~j&oz!VԞ%%Hdž{ "S\)3;nΝSPqUX{># #fY.zWvԖu{(w}:YX>/$uy]{_(~8]g)wK(bwaY>P=2 OC&JzEΟWY7iqG*%g^"c Ti*A?gOp/6`3)6l_Q_A^Tr0ιjVNi5W4G%qpGB3 V4o. IjTԼ4UY!>u勵,^-47/4odֆ{SWh$KLE=UIYJk %\.k9J j[ކlc?uv}ᄟ;"?"r޼_fʣW 6hc@s#%)>Nߧ<لc۳v_2 z!u+2m7YzoyQp0mG7K~ǔSu X4%Aq?վS5@,72/p)0:"2&ıo  }qpDY@+= 2Ěv6Lzn?{eVVȶViE#sv$>'#=,\U34c);a^}9[P2#ɞrac'( s XyJwR*3m >ӹ50/;wY\ܪl"aDMv<Fhʜ.9i 4m~Z(RuQ"͋J!82FĜ-vU PnjbM뾪W.JZل#R.͒346.8Pw[:9O0&9`mdQ݅HZgTZ$ , K7c_~xwP pE_Cm3{ q݆6PQT" wx`@yDv:Nt="-W)sGVY{6n࡝{ *s'ݳ%/Mo^gQ$\X|v垘K9'e,DV .74 slPH-~d'5KCȴ]DUbCƛ_rE\i/;8YOkESV֥suv13Οw\4 w(HڋBh@}%eBlC2Q9{iyMZlNpry1!;45&4[yLŗ˻h>1{XĊU/e ba;Ny`QʝxPDBq^[W~Bx[y9߼S\Fa&o(iB9ߕ5 ޼u$СΡPO+|sa'14"=$?<&OA1unN|v8b2L|314<^qP"$9tuN{m[2 v"ϱEwG[˝sBpΒ2p"Qі ,p;o]M.^}Y9<f(YX*6DrI"8!$:ޘI4icӴVA—r}hZVNw \=]NrPʼn^(~CUf? ("t o9!^CF^(zFik;8 `F͍r`3(A-*We}[SL1njޔv~ŝB֜>MP{d;uzcʟ{d=4#e-J2Q\v"?auBRLrM(% G6k#6Iײ7W@vԝOlXմ/NWMzגP. i@ϭDڦxeM^Tɡ i4߄_񂊷)SBwP"$JvZFqUj4B;Sk,Ɋn̎rCM]5F%g |ț0jm !w?W9>Rgܯ}Qx':=Djm bj՝:O?&?MT==j ^*ʧ)W:8hnON⸭g~5.^~3 ȲmVj6_l2~xu'X}S< }H.\M.N3r~? ڷ.U?X3/$C۹~*a{"Bf!%M{'eP3EˋM۟@iѮBS zl.Q6E\Da9|6Y$ 3Q\@In.X"ep:gICW'/~-UҬ|ӓÇVeWOssM. }ra2nWg홶-yRvuA}*8W,B6^wU=5{f2OMb$BZ>H&^0IИ*8VaݛoM?Ӊ򧿎x, z\ӵ)tё7U[VU#0U?)Cڄ&\8,VA`FC%xSlj\a 2:C۸rPŪ!-T,]HPbT7Q\euqGFѦ,+3Q%sPS`apbt b ۗנA.nybȥI 1 XF|]ϯ'ϴj1em4uZ[$K\aH#ckwL ,ς|@Kr,ku:G]"; P<AɗX@u&\հW5̓KzfՕOP]Z(6yh@8mT M@ i{E/hTJj'*qZ 9[.nHo`=>d +V0~NE0o ס޸1nO.N+*֣)Or΂uwf ?$DZϟVg9lC&,Ղ.<rq^c]CP1 杼\.roZë!R 0x{}U7]b%Pc)x2Ѷ ?qн.U]2JA3Q_-PF2_ԟ0i  ޒ@jSKQKR͆mi;|mDS4 ήP0+gpĢxD^>2Dy4"~_{1A2ܧ&oi_,P/1U|V4Y zxÈpuo!C~~Pe~$nQo=~qb4Kf w_ć+_tx( IAHUL+z2g-= Bf44Qȱ<#Mh!#RT ǃoWI> MH6aim+_5JKt #?~30d[U)'; m S?jU\@Bֿ³$[u=֒pQzⶫ7I'o>zy}ڍ]/eA F3Lb0 ؎kڕ.#d(aZcAPh ayiEKzPiO^q}[ jv1NҜ~\;~ni/pU0˘f;5*D'T};|v=keСcls`3T3)l^e"bi Yt:pb^ Wf| T-=rS <腥Z >#;2ϙ m4״{skb_'ԑAed~![dj">OkAf[׋7} #1*XknDd9>dNY2ЏfOnh!uI؊Es ,A|[~cR*E| l-8Bӎ7%'O<0?|>L.z?=G|/K1b|whz݋uBrI׊'4R<0mC|(yV*,MiK9gBx5եc::rHEd;;u -~^o~"QޱkJ PxHl},deI{@ C翠E΃p`=31E5dn8}/SϊW}2o}@e9K>aM6넳ӹ Gtg 5P۹ ~˦#Y5zOD#镲Duh/cTndv%׈tq2 խQ0x}g4 !Z0 qb>ˇwpaUȳO5ɷF7b!@wߖp 9OBM΢P~t8YSʦܙ VDMq}hNxf \FեjfIMBJsAZŞ)0EE.q/@9zRτ~]vBtin&q\6BͰkzfG0^N%UٰL;L:o!, =G`AE@uN 齃pQ"pO!drW ^ud~P'L_[{_p9頹>_p=+k+LKJt.Z[mR|v<%`n#rx' nL"p14p^ZX<*WLt'ҼG,z (.l4yξo q̖vׂ&403`eRX"Aj3 )o9;-$Ԁ4FF:p&?]hV9f¯_Y?dC G:x%7ǂ#CNqdFZ0ܨHߩ $nyJ6lZӂ%:@ia~ !JivBbH-7)D$r^L8NWƷ ʿF~O% ɐPR%w_N?*`pWit] +z}ka5^w>sY=c(fJ?AOmH)g϶&IΫpz}M׹ܧ˹S] <RA6PȿDj|R΢˂k+^_7S3DkPNyMd{A􌿜zD s7 Z'`8og5 q6EZM :s@ȧZ!JPM;xV ׄLyC$"RQ$3nD)m ߨ ?~SBo[^;n v"7#>jMm&&Ӱ@ȬPkXf!?sYQ6/{8zCDʥ}T2%S@;sAvXt2?rV;W"Kԗ̘30oDhFCԩdx7R9`dHFS* ш %j-yTD!F~~ Yl1c0R>n<߄j4RVA9ʩf?>Zcwd = lBzO]uJ8z~ig4N'OH8 Fzx&pjj(_|_M^*1)dQeqL,*&Ϫ$=Po٣a9<&`nE^PZKo؂pYY@S%/Հbs4\sRqkU/ˬ LL -deQJ88 G x$?LmtxfBkpH}kOV7$h 7,aSY?,09 ??RfO 4 )[̅(hӟ e~!˅=N\_u"8C Db;;@=ZeZWYr7zh$4e cf=KJ c}ˏ Vi:U5fo-qRTkjOc|"JBGrȊ-9T[е<RL} }lý׮3Nqd_# wDPŒ⬍Ț:>:g"CqSRs`PMeN=xŕӊ5um5 m} &w:&,ׄ@CGIgofkF>VwE3o]'#|7ZumB_E|9,ŋ}O&v5y)N$U>%@AbWS쫼 yFwcBgkI,%_PGܩO%:0I#vv"xǠ+mvN(0\h]6 `e=62 jfcDVbמK͚`R OW}KO>ɖ {~h) h,zscFAL9_f&\/"J/SW÷^aMmYOfjîM5- ^\ [vL'Z?O/$axU$u9V[ƨd#]YȈ$U?rJ(j]/v),ߍg,Dt_E񶛑:)|}pWUł5uŁs#q+HrZPeDƉRD^%:1c._2GP4I{W"Ns<1W UyLb ד89-^ F :3D9Cx Rߺui0HeFŬA8E~͈Cč;.$J7KD<lwWbÐ(t @Nw{bv!n]{*Yߖ,Eb{sՈv $Jp6kf [g(k%PR4;Ҵ؃|HN)d/ɞ0gFbh@AXLΜt=s#ޕqLe@ {nYpn~` A׌luS sߦ0Rw;+v!0}"轖@wVXH12=e+qQt{lLgrxo ?t0̫wC5C+̨j[{K$X4D{DW_ \z^S_W߁3+I/3ez*&N_q cue]qEpu  C=RWEד!_~v,h#@~ N4ikNx0[lGG:{:I#d0e-TY7(YD}UA5kk待bT!M1E yak@CM? SBjwGv[$&]K"dw>Q C7<.b%ع5@'!"K⏿rdB^H" "YG6W&; %D?o3P6?qY@ أH~!DlniI0r";/(Ca&SI;ol {q-xd#gqN1ə*F,\Jfɜ#6#ex2N}Qb'&wmS0gbbz\l.Rmj^Y+3o nWx_9_] \/"usF1.gc͊BE߹{7㗗U4h_c0aR.2= C(efw_]bN^ꓰTjA?v-@a#՝ɞLa;툺$P 5-|gaM៌5Y⺘15`ȥPhokk7B v1mIHp:XSȻ:c1K^U/n $T Os8&# [ T crS`3YZ/ _ƮѬ CHbT5gJ,ܺXM)?Mux6B?' N{ZѥUAޫ:k㲋snoK}`}ULȇ3 }ٍ)îw{3|m17|xH"ZJ9䀲˹C_˷&|lw꨹zU6f0¸}크 &_>v#POe:9-{u4+)`GܐgE-"blV44v 1hC\s_J%DM'bޥ'H*7Ʀi,H)o[K >f) (}Jp@3b$=Be.MoT'Gވ"2e$f@t@l 7 +ЩfNM%N#+\)]JN|.ƌXKQB ~t=ؑNPcJl}5sE>c|:?< +xuݷ/Kyh"Y?>KNn7bZTp~e085T_yiutcҋ EcV8[eƖWyWZ)><@ĽvL2|2[!lxThPΡ~NJt0W&9ş}oޢ]2Ю<9\ixV>l554<፯o.:6䶺te 1Egܕ2퍭{^YI}S7;2 #IXv w>FL$D8EWRJ +?h͙6Q7*bziM1"ﷵhUQw5ί'ִӊLhap0 Zx[:hOmm-U;IzBϐ^%>UZ[CަJ|m#k\:=>4r%lwƢ+'b?:^R30J).͋]8749dmu0kP5)[_ BAb2:P@3[ct0s%f4.'iEyc_n!fҋ0NBoa1Hz͇Fiӎ<>LTGPw۠BVjd+'upg#9Su׸)OD~nNx&`ɷ&R%QLQm=^ \Gnl\h:S|"o: S^[%auSRɱjd4>]>o__CDVKlw8yh}"W73ǺQWU(u% }wܶ|ԪRp.z mR^C n#X,u pT犀 CA#Lq,]r!`t %ֿdOnj ݣM/ 7 N+VQ97<`s`̟"? )~HW= 9iF߮4"nCJ&Ӓ~Ǘb4%KbPI5f}. 1{e7ަg}P0=}G$EFE{ڶ(XκNgb=( 8t}a6&sI(YC]\X=\1+}:r j H<$T7y':[2 97,›=D,j " w~* Ȟ *i;.;(.\;/F~Uj PU_tE(:pwLȁ24dEU1WI"2$.1+ߐ3|-A$K N:]M~723_BxqNp2қoE* ʾ3 UI '/a#WY8 H%:Qm%JF \9^qz!.}}_F}3$*?^w>KDLb¨C-L+樆8ԹjPm^ITiف)z"J4C K=xVqvbx|W& ih& A oɩR'u9b3\uA≤m/=Q ,7;媵+Vȴ>Qnj~W44 a_i (^`.zQBZ_9WIFdpp~Uzrh~PI3|FYVNꆂu6 , tNYt1_TBq/NT|E]T)>I#%JyW jͨ'`|`=&2yWjk5sՀIVa:'ۺAi?`.s5ȜZhcp"1r $΅gh+M3 mƳL,)T(Na#M1(YQ8b3o]^vscP$ךTl&h~ 1eeXz+|̗H\Yfl(>mAk\TaL79CsJ :tɳr ՝(k 1g {J9[kYdhTDŽH+4ֺŵրFό{垚P-ϥ)Pw.YFI^HWg,D>72ؘ^E-|u nh0llA_գ>Q{E MCo/5[1$Nj8(gz ̬걶}d47[/;p`]6T\>r!ܵKIr+_t!fNdJ]S\g{&BN\g£"ƒ'xIGs8?i =x6虜uΎc -OD{FD)Gbtaa}bktG$.\sk'DmX>F@RvN|zAԕbMX; R`HqsF0cmoaմD[4b(R g3mGUcgk&Tp(>3M6Mq' _)vN³*Zlue 8Ȕaɫ\x)a !6/"9KzEO3X^?ҙwTPGt C+2 !G ӮrP56xxosKbn>H%|nV]n12tH2,0G.=Xmͯ$35e.[;ž2{-a^H1m,Z~GdvdA@:ᔳx#52ǒ+gźT*Ȟa8ze8^le)޴[ Dt>* Hxrx/ ׳@BBAt]Nt_YAtɩhΛ洽J}@#J@ގb^Ɨy{JAE_- ~4)bCTu|VߍueL==i> G\ }?c0'b×.^\V{@zr=@@[eS2K?B` -BI{b~+9$y-@ Ujdh.#/aPӉ,XQԶ7y{/KkaL_ĒH6+9heR.粒}_#" "->\t&o@V/vN˶:Ih| #HyaS2MG|Hlx3;7{˯tKw)i,CÁ E7߉ZIs3> 6s8{`".?:[V*:{3.?6ߤ?!8Ih(x1OhfJ{ԍ+U[$]+RHS,~H~K)P6_S87ev 3{Pu>wjIZb%^f7SRtTve<1$c~4;SUTxugubܱy+i$WƽMޣNU\e{'Y&to| [}#8-($$[[7&rHݶᮏ #\jp}k$n6,cxQy!8 ,a}` 3,-1FK~Uqdgh?ϲ@$}`;M%> =zaʈ|[hŬf?%"R*` ]PĀ"}=ݺzuPq64XTȯfTkd=% xH(OʾO[_+mҡ 7LpP7 yYVqY?gQ7fyX~ PkK?z|g+rѵ;b\&!xl|',u ?=XB|;(g#u;•+P.He K7~=bBw8Dfomʖd/ *-\o{09-/ܑyŠ)4p*R?׋eoboI9i<^|&nY"ke>|XjDV Vl7_B6?W0#xk^@}o*wOز%'dACYS~v "|3b5%xEyo~/;zp"쥸o&:!̭`zp6v#aBiA?(ȔepZofMO4Nքo_ 侻1ϋTDm{jo!܉hAZ{8_ >SK{4QAgXkcAΣ'aԘo90xi B|쾓Q0:wAIF_Ze]*MQ|D|w9XfXLJvDJlsܡPO˹ +oL?Vgt<'dfqN&T-9QIc3CQk5T%7JcU_$QP%YoqlR{@%E_ k\DyPbB/@}aZ͎\{-̭{ ocv:x11ݛp:*trMWٯLJ)x{nC~ nii@ bӃ ^IݘyA3;4NvǕXD ĩ[ ;rURO>MEO4@#3Gn |BTH*}]7rT-0V uj8}r%pQ?ߚcm9 WV" 1 'Kۊ9M[O$Ulg\>?v: 'p0U(PH2H~}xvjA M1eٍ '--oL4R9Cu[$mO4@Zϊbdd}~)! ѳ՛7QxR?D<1j-yǃ}_' X:hH3sDnP9Q9C}>'K@rK/~WƷTZrC:̇*{.J$ynYT#>X'mO@ -,]QR1[ݙ5Ɗwɏx)J*8:%U {d%9$A_VMLxاD1kc4ml}AqzsVGA2scFO4% 'xxKj vԛaWeM -k$NEG?h2qVc!ZN(5iqM ]x?΍\wj?m|sElBXK6kRyղ'#.$Qe_jjvStto_7)_G}^]K_"G(TV*g{) _/m jb_ |0q >rl.SqnCc!UnEvWQL@s?@^'0,D'щSkݨ)7??ef [ O?F>,)%SN8=dm|W4XX: ;Y'qMAq%Dj+mɨS(|>7\Q$Ar HI]MEc"ĊUmSs7( ;vdsJNYeDV@n` bOÓ;XaЋWh3)/q8ش1qƈ*7Itk $\ Yax(( D87_ߪ&J/*_&Y,^^~H2Ũ쥄o1sηM12WFD^|cX pxBE*POAޡEiTDD_{^kخd]aTU0e;2ꚞݴ*휖av)-̆Ml:偯VsTPZang@:ls+WB$'*Y:$- ;v5 7 }P9ؿ\Uc=曐 t|:I)sx$0Rˏ=v$b dR_z_h0ԽO3kYo~c`C+O /}j0'Bg!:^q¨x$)jZVvЋe;āichN4F/- ޏ ,8t{[َ.of : R`GlB6xFzk~ȷծTJ燄Ҝɭg~fVwTe |U~$'sXk=d~z&i}\kfyK['VN0n偮&7Bj 3j{g%|CѼo9UߨBwйY_͋J.?v!w>13V-D3=swͣW`)cgPݬou9M!I͞c/oKA5})C}uQDc;9%kF3wVj,\IJ؉REJPQ1 yˇ(,߯@|(F&|L}ЮujO2e/_c *&<jI:z/1xQu,^_uõnC֤z t[J0m-Mʑ7Y/qFtvͰqlBSphOv _5wIt>G-n ˞G+UAJgE~; @rbz:̼LVY\-~n=Ȝ9} d q5B.|5 KHLq?^.."h2 5_DبƳK6p _cGEER8~|M6E=TA5c;胿d"U7fE %ta{8x bo(T_F01vG$nxs/ j}+ h]z͂%تx|4'-5ӓ,"vxj) Bygd]P `M`U3,$#e}?LJ[Gv+6ܘG6+Y ʺ&pr~{`dYl̓8፾j@SDLb ȿO^ lʄF-УlHzǨf_[N=7[#Ò;LfŎR<`TU.Ņi^.Yf{^VJ E2>)1̐], #B='6}| ýk<\6`ˋ+X6?B͂_߮o)gJ- i-ocb\[)8~4s)9ڪ$6&/'e /cW*t ܑ-yTUG7E.F~XTb\ F,b M-v,+z_.Y鿃jXF~kMO_ѹT MJ>G̋ ݇{PjFPIhjq6BE1=iosZKe9ЫʹRtGCR_(JYoUYcC~Sqs?kYIzKp!s:L69 -"'Z1uOvdX5v `!: 7ȼR"f])9hw߶{~_?ҹgJq/fכNoB8QSoCS%@!'+җɋ !_Ik_I_y'fs{СO|O\݄ܔ8Ge˙Z~K~(={ i:uj^')zIǣ3ū('㛯Z@4HY4ӟ0df}Х$!vzg*Xf·(SAڹ>]ڣ][/Ov&i-$~I5u\MSYqQ?/.II#{$eF&0˼i`n8t VMy1pyJb tuR6;[FmoSK>'WYW)YDLׯ\ IݒX?hK|T0퀡@}ܡ644y"D&-gdJ@uƟ_}SJ ߪPL(FtSx3ɐSI& < QB#eȅ>޳3+tm9M4tjip^gnVnq:JفOI}5MLg7S(L/?Eg~R p v6^6z%9eqӣP)ߦ-$ѝ8ǶcD2J+>ƵMJ*B78Оa+:3tl*0\4iY,fĔ_',^7GP[Y5 lXж~s,KĒZoƒ}'T~Mrm9di/Jym#-(-kӷDڥ@'Lc3^rex-@|}qw>!o݇}MH\Vg/D7n /$t"*[,SiHP|0x?(4C:"\6!(f&3$PiA5P$ɡGH3P[C/:ONGd$pOA_l>7S[} B 0qaXيGΕljn G݃edbAB=3i,_tTLa}=GR"qù"`ԫ;b zA7',+D>^4ѓ D0[0uD%aw.HlNޯҎ*Βӟڠ?נ3V%\/X"r ļJW|hn_M{;.HUVY1ʶ#AUɣiP597Ԛ&ﳔ}=%/7(6-UI٣R~Af7aKDwSl| Rԓqkmo&R*e/fGHo)Bl[uoe|sݶgG۶.n..7;J:'_Bj.h0Vʒb$Ԓ EeǤ:QTzDXKXR(}X/eVƠr%Z>ggA'  a x~%MCޓ67栌[*sC$R QѸ9<'zVX광)O%|p`%~/r+4'n5ؠ'shɋܗT z7]u/TLk$+3Kzaꕽt]0 Ň^ cٶ_$_ZtvT|4^Џ6;Ma\IY0W槊aɓ2.^py"伍MrROKCe.1r!΋_AC#?9 ~kNr$ c0Epsqe1^:1.@|gv}#1'CP~b+ss,U J*EΡR׌zHIڱv~A Nw+gm +.YA?2g}x~hলJQLUƦ@s'Л6#+29uĂTIjV|(!G|H{@=]!V$0vp?n/]s`1-ٕ6^&Rg8J$攠QW7[Ha bWr3GVAV~ FGut#~u~} /sk&%o'&g%P1LQfdE|df̓N4 :=WWV-M#2)rj36H"o%*(z艎9T`bR X/^ֳә2BKE"Gɼ w*S}@b,F;t,WBXT@ a#fDAƤJ %'~fߝ|iՖA eG:7S^iJ[ے׉:?jtd疘Tj)6UudcLE$2K`ќXtePˁ8_$}*cG[1O@/W-K;o&Z~u>ʏ7 oɖrjK#EʉE''JrjH oy^)XO$9eAX[/sN$ of(0ڝ:Tr ˪%Bb-epUKP|_׀aRTbt-6BZbЎr|},t'%(LS?2GjF!c?fj!qI9 ˣG]ZT%l% 7$L6ulf5 @JyC&By'7Rg)L>m]#`+~z+NTI >?zw)h= FHlj8k/U]qW{yE%+v26|30ZpKH]M6O^?ixOyn"hP3Y@U+.eCv19bso"-*v4.@8SC,]8E䃁 Bx9u\S 1tvOMׄբM=%', 4bncHbjZ+16rw[2X,o1|-ٛ(:\b`>Hek5ng*IcO!$kby#q֧oFq,Ƃg>.l!*Q}Cq1ü* % D`_3H+S/0h2^×H85L.6I &F?I}`kn^4P+d5܉vkܲzj7W"GdIAŞ&'ח/E7C*\uDCQDuCG>ɟXN@0=q$yaC(* UUhyt/8 (yU@ĖoYca#_*sB|jN݋qO&AԬJ=f?c ¸[mj e>\|ds;A.ǯ,*a{L k b`r  b<#%I] k.n]a=R##]y"bx.{mkŸaߘD8y 0z*$sϒ2݄rA(lܥG}ƎoxX{Aʾ g':ybgPfC:[Jhpna&9MdW ѰZ +aA_sKc|Ԥ8|mѐN  ɒq|ٰ5L*VTN1OU\%k}2鳶L;WV:{GACT6\W/ہM .&ngyIfJ홴+|l%'+ė3QOB귤d{̌a:By[xn^ x*D8e)pWb VTVqGz@ (؅7s4=^Μ״_Wxӏ3Ć8Lgu8#9;UXۅ8eU)ʀ#u)[/#t|Pk%ߴ@`~VP䔟TQRncdpAK`m X[baڭ=>*X8ӚkܤKD0u0 PKfak@U[Y *F|;LIX;Da^z$Ő y]`p ^7OXNF|xOL\4:=LɹvZ-y&H]fډOzX+I5+$y_s# ߷f:aVϿ n.N/Ah,  ́P0f],dEOR~foB FR礹ί hJe=0USLp|Y3&sbchMXpƭJE0<$UGaEK|SR}ѣ,_JY9ub_96Z8v!ztz[Q_%B!(ZF3+B]8”ETCϏ,U]dNQ9x\*~#PiL{](K<^AЃ#H"ji0G0g<8]ЁDto%,`Ti[ :-d8g0@_0X")?Z}7!ě'^]o e HG' {Tws3Mg#~UѵF1!X؃]+T **@3;;0~FZOӍUBSQ) ˺P;~Y~B:_rKcUM+2Eⶹ_~ȯmrLJ;dž7IGȑ/[zNF3 |uXtoצa<% $o^Kl˔s\:(q0|ucO0 iӒJ0)3J$j?\~ :1 >4g#u'G: A|(D S!_5 hx^S4ۥx{?A>[DU]R)TuI[;Kς&P.ZEUE3ػ}:m 2;U  y *M* qT#YsF'0E;Ƌ:³f'VF<̣)yiI5WZ_ki,:h[Dӝ C߾DI b=dq* %?;_y/<h3{0C?6riXa+5}X\W!)'䫗ôC`* ؐ:_XD$&XPȲ8sUd/0b_S͝&P=~~z5@]xo$ayt;E/[l-Fڷ(=]|[$3} ҐwZ7 s{j9M r)1o}eXpjo$">֜/"&;Ni!QZ/lu٦`Eq5;L >{#$P/6D/qGfcYį~Lor ׷ɶۺ*?თF5i3_Ֆ}0mҷeI<~ ?mC }tV* Z<$]BƘj2$fz&Wd NFz9 4`DmfLX^Jt "#JZň:f.A"Rt+FB= }-WiBQkn6<.ZH;1n+>QWHCesHew,,B9ˁLۢ f{S>ɩf v7 +kO)<=Xʢ-oq{¨<YPfe6w:l 8{-πRh}ޘͻ,$EGN6=d'VΎꯩJsūrtiq-y4-|k_ǯO_*NHQ=84t=*}`iJFe.| Tq騌ţ!G'-C xq4rb4 ":c/IF pO'G;TysJ*9(% 1YQsQP 5[4<Ts(:]`w)K#5ђc} f\<sI v~%*BG(D+'P~GM~ /8屩Iև%v눉Ͷ k35֍Ȯ_rn"ӮbJ&"n:Aॠ^\Om1|8%b'1?,lUu+&!?nP܊CP17 paIkX*DL[eJFU=CRή E" ln_II!ͼe6uC,oׂ]ѲĨx\\YYO-fְb]$X0q췶x)afDm.h] GQgő(\E0cV}ҟw~"jOh'f3ӎ{ѬGl^e]Z?*N>&7ndJx4࿾d'CT4Y?,^*F4#mFתjOw !s($?Jx(I7Ơf/x:$XW ' ( zµE.LxDt%gHr0J:8=t zђAkۘ_%Nv {k+%C: pU 6N9XH`z)z} uT '̮ZK#,9\VʜŔd`}0-Ksmp6TR%g9d~RӆD0Gg)W֘K [񥣩]GTҨ؟|l':L/_/GC"ܺb(dAmuҙm )AY3Mr [!O;dPI(oFM8{zb{O$@ԍ7/ax1Vd]YH/Y"2OVe|^ T6-BxmʷzFii s4;C) o}tK*A,xnG8 o/bVjTuTg!q?ǵ{ʻWv.|R|OAd87"L,ӛHRvtگIqJɓ͓tf\FIJe\-bR-=0!RL X1L 1$~Ǿ0 hV8}pv}.iVo9Ú mB޼=efEk`@EOY{Jo1b.U@\cxͬ6D0egMJs b;`2 +؝XLyŪ&]& ż7W#' wgQ1_qAb~3#d0%wofB <47t8vAOo~~9Xd G)8VDAr)#ȮaJi#+zw=ʻ~! [@ۆC.͜1 Ĩ$#N+[浠Uڝ~auՆp |׳i.?.%Gbm&? 0UQCˍ!Jc}WUz+!"c?*˗PV&Is54pvaV6^l HO=F.e 3ʼ,udNngGg-6V,fr;z>HpIY9  o;tE21Ð9sglvW Mk,_g.3LdOJ~~iZٸ^Ӹ <(o ߵ2A?!4]>dWuA_1L8HԦXDMd_nS<+M1ʂ.H=F\g6m38n{?: BxC8_4/ᘪcb/D|,a.frVdE0^c CuS7["~/N>qZGMeG!0L &ʠ ?I `5>e.cFCSW5xBzU MXؑqHD}qloN} ĬB^3!V||3vqu+k .u!} pAo@Ɗ ctй(jN}$ZK |8&:x>6w?6U %vC]`zHM8-bR `مIC~+T*ݝ7ÚZoMS3Kjcd0#yj܀"Yp׋$, G7T݂zH>Uw繽eW9q@RAzgh^ ΍ʼnW1&7V, 7O$b6T9ִU1ڕ{ق{20w;"sTMH!<ōVJ͋҈k֜ķŞ؁'//TpӑFX>'A~Fķq~Fqynz}GT(OA;a4Q#-UIocU|'.rǣ$pPOYr1xj5Yr0ؔQ#doKC16zvmӶu5`K#<@2oRXuy+e𦃽+b?/^E?M_^C5 (ؙ,y&bL X/e(ft7{3$8gJQ!}|S?^O?R%ןO~qMcOѫ>4Fʗ#5Y3EZrKLͫ|9;![kaXP7v耴`x+ӆ5%O6zkF+gHh)荾C#1j +?&Thȼ@|б(PeC9zcawO76/z4x.YPGN`\`T9^dÌ[p;b&VzJƏ|- C*Y:W)L _ҍ r)h6& a;2ȃ#%`jzq'L iPtJ4J˕Y0^ K|4Zw1NҤ{3eI_>6IWrݲ-a%oxn%,6c5JqC K`G90澨`/F*)7O>5?*ݼy~հV⥦U\T ^ >nwGa[R_Wu[z:Xp-4&( Z$nz8e'̏OJ3;TOFjHȸOMpQֈˊD[>*ź_n48d*X/.Ŧ~]9{ӥWQ>+tdrwU"|Iorm$ 8.!dEps ~$=bDrmZP*X{G:?KSm?{2 z R-'7PHWgo& )>s!_DXlēd*y3]X.Gndp^ֺRuy'@b6(HK"qpar7\ ҕBY)#Ǐd,g]g@-PAR<yusKbfymA@XTpe(noXsNf-VIk988E 3ܳQfZZ 4K2PI{uwQVgHvlKaym;VQI|bYϏe~#|e 'Swq H5V3C$sX [d&ߵI F/] 7 aDkcG 8w$"3Ӡ1ۛbc]6]4+-}>虹l. ߿}kn[# \amUKj̹"->Z6'o8q(L0|M䲛XU BΣƂPF ޛYZ ^%F1.5Z'!}y{W}'-G-Q2C*]@$-KtET=Q`&`8Vkk_C#՞6oЖϤjPhɆVqY`=df۵w$ 4G,+ߠ5/9A{z\M4;"R=x'ucx``WG~ A K>.ͅ"!۞&'zuM}y8tR\"w&d5ϲT ͏!+r8@]HPf\O QkҀfVqն92MRMPap‬?΋e}YqRB[mz{b?Ê"C^zfC z.5 %|OTF*8}} N~ 5aFne3W)*IZY藅f'ˉN&b}P= əJ.Jn)bZlrɝc5S)(Orͻt!=Wvʹo>j`2kU^4bY h:8#MqZAC _ﳴbT n+ <rJ Y;sXW+|B127o T<D{aӉz Uu}YK#˖|X7hv`d')ůHxb1`@ꚛ QUyy1u%<7k'8>\4`+,I3C2=0{}<7S^;猯_ $5;R4d4óUT#p,c_ b \~0hVP-s~ "W-puVd %Ш|KH0:GMHpti8?;3`$+56-{:b|&]"yLӆ\狑R,',U@譔ZS&ls&:?I FIib2ֳ9C3L -g>vUwAʎkq:2l#k'eZ/Ow9CЯzh@믯+hHעPԀΔn]_>RFZd#_Ns'=N 9ԗn+J?X4H[K Y:ٖ}ҬPP~n"d2l±i^b?2[en~ afrJFj> Uٱ ExpM}ef j"֏\,tpiC zu::pH;(*鄰k'SKWwPR;@(ΘڛOЃ^N΍xe$*MiDAi||v?XBgT~6O84SR)r) dRWwDҹ ΓH5Bl'쐲 m,,: ү,9:HZCbuuA]SvƢϼ!u`-ذY #UĦAҬʋqowMLʏ?!Y'CˆR8^=r̿| \ a=+8{N4 uu x(?E-Bu?)!IKO4QT/wu7 &A1KRwOZk]ȍ>z@p Xaݟ2Sdjfܣz }mTum'WRU?Tǐ՟*1QTK@Gi?]A/:TSk`чHl \:X\5}$$ɔRwŝfrx'SOTm&ڿ_Ks3J {P"C]"P\T*3(TAf 6ʟ/떬D/%q=8Sy,xATǧ-Q_V/+*d5*4z;?Lh?X~UϷz:h_q>H?ّ*A* 9,tAwAܤKY/4~w!l1Q|[]vSBAX%OTH":-L\7~73|͒t\ r>}. cmum3|,j#ђi6a -~cb\_(IA׸/UXY^}Aabο9nK_}7cl.Q SI RlDIC/z<5ᐸ`() ˇy .VO+n~)(kI[8y$ C9i׬:4׽+4["WGUI`~`8 -AYCDPz- 3 7yh;9)TL >-Jnn:E%hޜ,c"nkWbZ>FJ$HN0RF .Ϩ~g/LY18 @zmu$=O{IϽpY(w."u.U]D$w]A !=<8rI)s[JDS?A#@afz^+swZdg=Z [_9gɓ` *)0IJ X1*O>gd6}H揻a0a& HaI63{_"P4ρqS.$IAsԋ@ "YDtNKN󓆻?*X{= fW|qgQg1K_ɬKq] cE `s߿t2e}įh*{dxhyr34IP^U~ hԁ˔JtĿ[9"Lvߴ"f[k'{C-PbʱeQI0ٸuətܢ`S,AbenfVW"3>++yb!8q6瘝ձ[IϜ I1<5XeN<ߝIXd4$f'Cz6  ))w: m>{y蓼aBKD2.D kEp9d~=_g۷am~qd%8*3Q h usLyRpecMrQc/ᖫMGvc^tҷȦvf<C3ĦmBvO+!@:x##K~  W6NNXKE/ & Ay=cҫ~َߤ)}򩈛`mQ0-C>Ԍ ݑ1]B4<x뜈{{w%M4h`i^gcVh8b7Aޥr6W/~Skj7_{ȸeSW=K+1YDb|,0}ph,XJhc#,Ϥ2:R:R`],[ʍ[N!fbYYa^qmRaU1m !_aWr1"=4 j9׮ϿĮ?V~ TrW*0ypRDUQ<|߁߇كYMvr KPWOAสǡǿ/sR#pޭ wXڟ [)=lbGIx@yh%Yya|,O#v|c&74^0 hi;*6XH\M?gA 4%R79*W5@srG{ƽM06NZ]4/83؎:~G׀DfvDGaUǞY C =jrKa)Gh4@{ |:kC[a91V'F1AYр x: I:lt/؏"PGTV*M#U9k\nWeo} ]^-햻)9>egg_/J[Nad:s\6#ӥ3'6Vee#"(ˡ`3V{CvG ?:3)}|CEw ݳCz?4s~SvIJzOtSdRj_C}\Tò}aA\u۬2t|WHc~( )C2k|.o**Y%M+<(մV+ڼ@ubzН5dRtFD6)~1PR2Csj|Lb%7i,QIe:C'8'3'b*|ɤuwVah& 妢‰^(to0!߃"OI:q QʬI!az9KFO_ryo@*#xZ1+䬊qzA#V} y?P`お}䪰'|>_뫍8N)%Sj:#ґz\;ve`%#}:c}W]^S" v3G6PvږCcƇCi(Iկ'x~e#wD'eۏEv/wԇYmq:= Õ , "Ζ @z4. /g8z:9Qo{J^E1|BO?Wrc8":X*w4uS5 D/P}= e)g "Ҫ{rIHGֈta~p^d/S+N{뛇^c [e~97.J-&z<`wOi zeEB1-xyohn2JOws_QN4uC1+m] o)n[^/˶L یG,vx5i8n>`+aDW6 !EU09 AD,'@Jɞ6A3 3 z Jde7nb=Ƀ'o>U)x5W,u,_=CX ?Il3m*q\6*jJcP8s>.ˏSc̹k4=H. yw˰9ȖKhޓ@5t^.:vQ`%6 3TLэn2$pȬdž:r/%0\"Pw<xR>2T ?ٜ.x(}Eryۭ0䐝-WjInߠ\t~59/ gǿ2AMs(jGt}UCa I( Jao$P_墂o}@r77&rw3 1Xנc\{3F! d]s-אQ鋧U͉%̒iS;"@zSr%Tv<@h$P0^:lIyv_p*eCazj$?2Ӛ-[DdBZW֏G-;k/;•GJ۞|@x!<^>Wiqh#b[W=NF1kO™rP?!x@[[΃>"++,IbLK >{wɟ{x'2? FǣݤѸ'PMGsb@| V5kwٵAOZ&!ُGِnês#c.J _U~}KK? oA0k?GoyAPD"Y 7Z0ogc{ziܢ ~tFx\W3,u=>^SIi,h*Vu 06ˤFىZh| ;Ỳ)X'ܞH-~k""IF {Km@܍QɈZRgYI+/P_'ÿ}nϘ:8: <6ws#kͣ&3OCj5lPt5R^s ,n:KgJ*ĝ=|VY* u*cR@3^\:^ Bdo>}6 fa Sh ']+}@̂Gc۳hY ̰ pAnjf޳r,7*hpV^,v=+gbaG[6zn58m9JTAۓԪӞTڇ]w3Ja :^uꤧYfX,nqP?dzY֗afqɛ<|V Z.3Ug8Ԣͪ3:jZeU=;|\Pll9tobnjG*EE? cqqU pڙ0Tb^>̦z RnT\Sf'뼞6&j+QP3gtC'U4[R/v쏊Wf,Sj8 #Ce6sΡwlA; 8>Cj.Z^2QE.L:WZw-66v˥7k.^wCG&~V߸RѱQ uCߓKeg"۳=*eV͌;6yM-C_[+*ev)5=1:.ȏKKb֧'Y~ێ1 it)WQ愳/@ԢުJ1P•b{3+tJm;ջ=7|]  pB5Yb>SihCk;:F} > ey#0r0|Y|lGt;UT0Pjѥޙ͆`WhnֲWpc?e\YO(Zeg7jc.Ϭ7N67i2vר =ٵeˌr|I]~SC3iC3% `.gNzi猚g.|Z]69A͑[d:FFcK6)lpucϽZas1>,=uJ(P n1cdڮgJbNN 3]vYmd5ke}"϶PQ(ɧj-~o-+X:kRu%v<(+rC=:jAʺ-A+ uI]vdKRy.fFP}"Wi%+OJaéF,E03Wh[5=t wNL7#6;"\ѠW}2'zVZOR-NGRG^nfMpGXdD}K3Y{^(YZZǰWˍ,t9*v]ޢ173 >;F&'@Z5VnI4JZSe=qf6c[dZ Lw(#f˦Ͻ4`UΓGhFѪ~ҳ|Q۳R*XEWVPMsٯQ}tXΣ @ݗ(v~- Nz'ӦOx.5"CVkA.RgR-.ڀF YmCk3_\K'~'wnZT4WUgX-ܭU]'u0Xm "xQZo:$ȗ/a4O3U纗>5*-&?bƵؘ}]:}i9ΰZmvn?;Dv|8:9NW@}PނI˰φQeDz+ h Fah8ՇUlEY:ai 4Nc'il; ϕ*/>_ݨtǨ#&ݳz. *K|ZusBBٗ#g"iYb]*nH/٪6ZdWU)~[Ҧzc+gfh٬Dw;=L/n&܍b8=7 e{=)U檆v9bg{mHQ /C~FD2Av8ck*s3\f tmw4aOo"+n}J=XXn-fzǧ}x39el]weBÞ'1er̃%;nU/n'B67ַp=4ƶ Ay۬Yʆj瑵fؽҮQ]֭:g3+~04iCuЋƱjJtAJӣ0'tHX9ʫsgLј=اsjϺݻm WXOehJ?;1 (#WL[Y`VdXUc+:ai{ $'n0Dpsaf_`ǭxEi+q;arNnw(ZmUmL5/ӛIsQYʢle6Bl:ة R$W/GRo7=t3;k0,u&-(x"ZhMWseomsոi,?Vyydts+[2fys3TXPșa,[.2nai~5꥜%;w.nZ{_Km1>xv&+6Zɛ&MǕJ@N.`q2~kilDE㋲_M'հQkS;pBRYlJlZ 3rfLȡ2t2^3 iGaK[{.LZjFnbՕjSCXҞHtdsg++̟*)2ɖz^uy:!uJ)Wy-Ǖ*ىk3]<ƚz6p*]viuN'Ѳya{p?'25jSxLմUطwnTVfqa|FRbU{e6q̻5XGd\)(ʾO׋= >/MGv|*me.G"hZ͝`/IW!h--Nfll9;ؘGI= r9>)Z 865}89;N-4,n::7gALR3`RuW}?19s_YzS66ֺޮzϷm4Vqtvш2 ;HNɅѳ6![-g*MwoZb: 9G`["[LJ%wX,s] ~QIg]tYV 7jWf.6||6+LlU<tF5۝^/sj㠵Brϡˍ8ph׋a;i^DDFg{^㱬wKT\[_xYaJU&~yXmAѺDzzަ3[NlۛZ` .O]OƁ([iYcKAgV +Hjn֌kfDnOV |e]C-x+EE, 39 |Xk.(bۘ.׎zLn6Bv6Al4˵xaxitA7ȶ9#irYj|Nլ]VKS4tZv3wEJi%WggVMW.ۅ'ur\vhǩQ{c5^dADƊ7̇b3ms6J6''[7Ls1A0)UkYRNShiߠZ56Rٰrs[-ܡhC49Nۧκ>/Uɼb#VmV)@`18h9;[k64"攊 (KF|ҖY:,۔vkcVc2xJY5 Ln $KFIjqw b8Ssq0~Ml(Kxq̪tсZ22K*Uơ.QFPI)cVh5kH1qXԍn2\-2*V8/%cz˾3zl,/UhT"1mZJQploj [rqZp˅g+Ce}-Gh&- CkQ7楇} Kٖ܍ܶK Ex6^GeV-,ef!ݜ|V12KoV\խ<\gXx<8ul~mU\P>I|fl;JybmF?l6V Kٽ/Gſ"?]_/8;si7I*D G<\B)_ٽ^/W{wX[ۂmdG`9ܿ{kUܿ }BL;0S7M}o*~”<3ͭny:a/; 엎RP7o/u>1kAoY8G:&y~'U~ BؿkPWܥZaRU)~XF*U8梒wJI~oo7%ާ)̊~ڦ_͹cY^Ծ5C?~{#c%\1 R;B=*ɘY&Úϊ(/;c Bz(:_>_|n-5KD?- WMZ#o(+Oj{1 ~ԝ"S jN%o'uxʞNzF/o)N&$ATsBm!&ob? (ON9`?VQP+Oak>'7t?7'*gN';O(qPˏ%S#Ͻ UB2F*j? TJQ#es/j#g|?Z{委3Pk>G}OM? T(T{}Nc?Z@yff)o|WmfZo'\D+8oڏ 2`exqk {Sc7o۶ly}Qk#XN @ㄿCPZcڿQ 4em} W:Ɉ ln_|m{= a%BӉ$2(w,YN 껢p0q;;g2%7E28C0ɻ5I| @GUA߉7&@Q$7ETMл&5ҏ jў͝=Wכaa"- 5<mf})O8x5qa_\oa3NC5/\OєAQuEk?' ^؋Og޴GǸ0?⪪ʿ4Mbӟ8YgqT8@}!'9!)4")(qvqF ;&*+zb ̹7xJ&$4MwLTU(B"M%P01R(%J2SiE 1MѠ'X\zS}** 1o3fIwD=*#Jo2ewzW!t` @% .2+-%7EК"!4*ooH4C4NB*RtbOSFهY*/cOD@ C@ '~'AǤ7ͮBPD.Uo?>_g`x8=zC\BO|#1tqnбe9S,ˠaι0x>}޿Z}O܇kd2 `ȫ HR}U%74 T9 0|O/d$gT7O>j8K}. rb ui*bv\S`Bh -p@$hn$ @D"hg 3*p L@a\R;e" Mh3!(pHQ!Ɉ\sL}H;!smd$Pp峇}YL=dJu)}CrQC(2Їrߏ3;AagΞ;?N̻ͥ 53ϟ+|u;3+j/}2^/σ_ @!7C0OK0j6?~9fN[3anw}FA~)gY/f97o{qEO>l板>r\̷{4%s>~){2prw3ιGH|Cŵ ܳ{o˘0tÇEds,n =Y:x0~x%V>[Īݑ$'AşY~m4trg_ʺ&bżx6{Hi7\0o' qAչ^RHVI !~.knKeSmA -ݘ N1dREcX?țwvh|Aڸٻ?_+0ò~{CaPyG;rsW(𿒇6i9﶐_4k8* f}%TsM~ٷ*yBxJpkWf6u<4foӐ\-?9!4zҧ~PyL5z??+qedB[ 3 _p~R~ Rd,f*0U' X2AS *EO$ J3&V U0F0pBL(rMT %s`pMX&X1)&Q%DBQb *V*H*b-Mid@NRh $ES -) 4t|MA I(i ŷ7bizQ-Gl2(PD_^|2Μ?bys~U:v}3I@2we}z,.oͧ|@ A`E&rSf2`h$RWv`~E"Be%-]ڸ.&[mʘwr Hp"D؂z%>r'a^"U9Q]J TI^2`*U!1+ b«PcXEM ]"pzqgab (4x Sd'YM -FԒtwB1p'LrTt|*&C\L0RMtOk'%o)`&cĞ%/qy'l`T!Kşe2w߀}J$$' @DlP1'bA,&3}MEkNN[RVyRS%i剀r(([ךV,Љ,@yj@$(a%c~(f+ I5,$ʚ"rT% 7ҬA)Pd[+$IN*$%I=?ԤhMlO4 e%͆J5\)<Ƙd)8tPX_j@þibɻJI*N>wJ!QI)Xȫ 2M=vLk.'e \IW0b]=O4̠D&4?N)~'FśKҧ׳ʾPtB lN 2ց)2dEu:X s=Cp qؘ*Ru /HLM@uF=DHPoHF  3@PR H(&&0'Mg8~=x\rH KcI2]L$$S1&1jD{ TDr$7E rdC  LS(*`:E$'RBt=`̪F0ZX<7| ?^oCܦ;ȢdEl& sfnk~׍_! b!pc?mmf2)w›XMu뿅kSk[OԨ8o"ÈK0w69DXJoo7=-gXJkg7nJ'-YDt[Zrn,Bv[MJUwEjJzK>d=OW[_ US^`@Z ^*2!K"gW8 S "DݓD!"s)]CP,.z[{מB|PL(dklT$Aљ[k5dTIf2.&-% UtH  X1) ӕ8ICL s!fuaIX4.`.([1B!D 0_ ̈9Ir{(e?>]TS?]ս/prCvnNoK%_{ˮK8k@n5K}'?BvSCE,H

    >Bgz!dɂu=ײz7L!2Sw2+^Jq*~AoM4}LaB tm@<#sv7kfI)aIjO6> #ZyXY"Ɉɋ ?IJ^~g3+|_\/DXU_)`On{YBi(M{n ^bczT#=%iv۵Ou>bS! fvHs+nBMP+Ue"YO[DIԭv=O<8Y?(t *{b.a rL5w@&EMWHu["6^b߳p:CJ+?=CvPg|_i5$A 3.v1ͷ#bM4 ŢNEwOSt7 %NryC``@19+A2ЧcaQ C_$Srdd#"=n7=Ք8Bvk[S4B7BZkFF|FErnʡT,/quS\8STM`Sd7"t4Zj?89IrN;}rBV0mIF)VoCN!OuN0IC9AszJW>N(xs!jM18<`^8i:HjY3PWzɠ_ nsL1h u,2IbH̀fwS1L|X'^@?z+"k3"gb*P#X(OoB*7DE! QXJ{ND9IAD厦?k> #,U552c" 4 d+8JhR' Fx2OXK1 1j2>n@<ē4o8 t&qL8B5*TM@OC7x Ƌb`&j:шC7&?"$4Q0LM~,cՁTX} z(k|wp;*"@\IxSTnw^< kr(NF\ @(p ]F.?AvL3 b-M`˜$wDCyJ 2xrJI4J.˂`ޘ_A?EkP}FA&f! ʳi\8dLY)<57A8bBvuxEIE%AEՒJ!ê8b%HmTI 6!V^XWX@ )nFݲE%ъl dP,%/"z2B OS -ld7K͈̝ ,Ķo=]'Z\P=Һ0P2_w$~&v! DU y=rTIȄ]8I&r}TlLtOFJD "OكZZH,'LT h䚉~&Xi!NwL$RR,TCKDtBF-nzoflS0BSP p& ,\Q,RD<^ DO$ɹTɡ|KFCx@k!W]782 1H{5 S|eX ƥ&JJsGD~dBI'QqF?E(HI'$;)rgSPv%q{d&L*v:n ]DEH)+Q ;vW*$ 2ᯂ %2,cUQpW2Y,{B侰/n*TKqݥX1Xyb#ʽnIpK"!'/ r^q^a W}D b Sq{5[r?7<ȋG[w^פ SyRX@/ȟ&SUv͎x"U6i qc >o了-٧z&B1:(ld72  ;}Hp y{t1I}WëǞ D(d⬔>ׯ#޽b R{.~[|TP孵&}ic֘s' @jOnʤPxW8F|P&{nWE>n *x޷7<=M<Ԙ/0 t&{J`]G\!b?Byڏ`#i@*yߌq.gu/Bt^7,p\>Epx !{\b+a~w$^f=Q~)G_)x"N?Q\\Vg'v^\9*Wx-Q[iK1%=JPh;\8A Y!e$)hv$)"(~( y>S{${6Vzl\ɔDjz@hv"Cy Nh9Q 4ZaM?4ES1cx,Loq 4[AS"hd*%g'E̅3"$Z 0wCu~)U}/_:ãqԨD#!@[S쎮Ds˷%0e6RRFKqS2\oUGd4оJ 2W AV?Ų_Dsiy毞 3(KC#I$$ ciV2#N?J{H1W `j>􄕼ydNE|^Bٌ{!_} t)gK:[άV A>̎56G#/gbvECa< Rޘ$^ מ\\jb_^|K7uqqQ  =N54F,7=g xW̧&}qY\p+}hZ*\=Ch1jh)Ħ9%s2Ri5p(˙0IۢŷEh`E{A) m5mH'-ly]h6V-[3Eolo2y<,|ϡ΃/>XNC ' ,U(=QRug"~jL"q!MqyZMS;(5-/w6nZQ#* )n;q ExRb}(>Id;F2|HŢ+ӺvUO [|Kz@-]Yjm/?d,vUj)>-ewX+Dm1 tEyؤfx);$T@`yt :߻ZX}r}t93)*sxX,牄N[X~6Wd>y\?NKs7ۤ7T'[q+O D8vDm>}Pq+fuG8Ō0ꎳJ*DvGIGde[+C/uK#mZ&|"wVx){JWm ;+-w!Yc§!WȤzDɤD򴳥%d}kЧä6\ɤaL[(76NQJ}fldYMM 4r%hق@7 OZgs`̺7 ~ EjkdQPѹGýopsفE%)]z0tS֎]&.TȬwKT ?{K/M6]Չ*2a3$31zɉN!LJLx5'GjVXCI 0FE .(a%eQ=À{zzeuCV—z>@#Jl碜j>NPW6>wX8JQP{5+@p<<ɩ T,'Q?xYMzA42w4KB4ޛ@ ǁ{p~ HQ-Lh|&:@g}'z>՜aH5(Iww&oYd*53 Z a xZ3O2Yߟ(i/ Kzh:bb"ыV` Y~KbDK&Ә Z$b`S !xh $zL "Ee8/M( h i ,STatqOm1DK&'[M4KE\ VtÃЉE3V _7uIm>4\b.7.Kv! pc\.!WheTVpQl5 q:a0d&Ӣ=XyP<{`MN;tlI^6 86ƶuCwNR$`1ao+ Z!,p/r˦CIZzZ?$c77uo18b@ IZk(n%@/]}u攳Tx,!L9N2 ; L~ -EXB ]Fw: ,(>Gfg\Y,H4KcMyoE#*uLkhphVXހ#Tp Ш1ðI!#Eo2D$ƖoLFU^v $URѤC@Ѽ"=U&3PV_ZWDD?*"aO`*\8v6yZKdTMo[z|z[[-_#=ψT2y怹<5y]pzN&4Q~g=H^z>Ϧc43]N yw>0'D a8Ԡu>~y+fPCq[zFD̜7#f` qG+z,3MCnyȷޤŗ/`f׸ 63LH<}( HY~_;,^#g# 2B_`x v1=m~-OrrF^ߗ䃶22 5?ÅniN1G^xѝӜIFjkhMS OYnZgx9]7Cv7 ,g@fz#za[)m :=axJG@v,.!1BpED3_ODd]|Cxqc3ysͩ#}0̡ v- ',9~ӊDH#Ho?(gRq4 iцn-؇ VIQL3iMˌ &XEՑ-l~6}6zE4WR$Ck ,Wr;pYLF'6-'x콗.D[{DL #D*\95CLRhP,C])~]|.Yp38ݷkE4qL4 =-9sRb@Gt̄5I `sT.DXFA Uk %kOw,YN1 _{ k{ZK>vΛԃ>32#lsKBy)%Ys2#qզ;|@#@9H=ّZA4/1QN=&X|_'a+2Ұ ~?Ε>UشuCi[h>H ;#%!eEɷyp"q⢢pM&Rx  Szq~׹bƣ:S~Aـ}8UGzK"2/xe;=X^t P׋r  #{R #@޹j83(: j뒜]9w`2 !IyD"?ĭ[g\DZ]Uv,'ΥM-;M;By}VvxjZE,ȖwXGbۓwDl׏!"E1/IڙhcB0ɧbOCCա=!&J]&Z:Iwai5wkw`?TJ]@;c +J̋S-|w'IF~9Lo|$mr>:$q7) D~9QC]ÈWFNAߘi'¸'pHZ:)o>qDD0Ɍ紇E 8W^0~9*o`?OQ9ΓG42о/<ў쿛\MQgz5,m>. M@yh@Ȕ21t~Xx Qڽ9^z:+{]hQ%?U 񤄘;]ND{8JS/7)F*#O ޙrAM7 u_$6S xo2|}l퇿Nr=9p'N. B~r Ja..g'xq&c/+'m`OI/9H 6^LY@= ?!5Zl-xL EdA&O5?hdTW,]S#zӽ\%fz0CG9\2B[!;5d$㴐2I#N$0AD#NÖj >Vh*W4)䭁Jl @ CFU"hxx~9F(Fxq{_zʅ+0Ny)HFXGD|'xq9%OS~gRO]sWiy F,1cKTmZZXgUzߦZW1Uc&C%$0,NҢ&#C bƁ=d K>5:tt3yO{ORzyc-y@Kw>O\| !phC>:SϧӲRJj !$"iF#E Yg7ᐔ#OBUϜ IhL4`9YwUT'iIbOQB@H=Ҍ3*Y::%|@f)gcnGR[uB3L-^)|kMnzQGF5&݈ٟH-XxX9^l$-@eJ;>vQCTx{W~mx':R _,>*XsUMlm鑰F1B5#v=rS4O0Vٚ'ޙ&t P,.K@Vڠ"eRRNlt~a`MCқ_`6ɄujgܫWj7ƞycx'u[U9o[cxpJ@t740 ˾O ms/vJ-ΒTBc6V.@836yuR'ihY;1-lvZV>}U07-!' )}'.٭<:?~U'8"gsdAj eLJ9 QG$#=͙xzG1 W&6$rGb`è^w2:9FRJ D4@:pt:Iy*Xhi x'I- ӹDZHHs.8NFɒ?NPosN ~·A12h[\q Pz<qgN V<~0(az.㮓/r3hH5>,%,Y7t~xrE` Fg+u|:i`gΖb/<6tLh'cҡk dGl `mܮ[6>tiabqRiΒ'Mhd6^NF&sY}hfu+K_9Fڻ]p?zfvfGl@Yq?+GH=c?n|^`ecsMgPx}LK$5f T[HmF !15M#cr'n8D`w7N7ދZ(=d{\e)n\*A6e*R-hc,hFի:g65w!]Ʃmƫ85kəVzpl~ ?qV o4B䀎b9ǘ;W/Mdd;_QZ洯>Ӣ0*:m&]nD0SU"7"-:eť*&R!Qy{CFÔnm&[دEP4*.*TBJc$mEUq kAv  t%MdH(47,Fd!|c3pJECc^ƅ"$@+,0"()rPq@vNB=N\i[q"z|VUv$-@'Ap n E CBJ[IsP(" VyX/)wM4HCa:g0^SIEDPS:Y^i-p/0O;-`N9%YEYV_םwԃㇸh,օ@}lW{pS[v;#3aA%MF j^i=}PGDrt:17l>|X[Sli+h>ȴv̴߰#RqH;)|ج_'ߊ>2~ww`'ݰ+G QDVVzOi 5B-/{R9mDOL+tF/т(՘?.a$3hb)*P`p?׭,52D4:@':#[eLZk<c9ᑺP#yw[ xa& 7C26-supG2U«ADGnfL%BSFs0?]|'6Ѩh x)W6߅9Πw@o[(FCbRPZQ4ԙ/{ YřU|j2xb$; >h[3X@UWq%gq+Yy_1<J PE[. PRX~I]u]""mqܯ8K=il\)\{mM!~Iղ8y쥬-tEG m1H񝙦# V<*#~2j|UFP>*#Px#kdg0bhƴ[9,.s}qp۽1t13%p2#{ BcdwhRfy~ iʈoa Be%ej6(;ƠxsQۓ8뿬3zTH:#L=<o{6̘q@sZ#Hkcc8]`茳AqM@U xz|كWeE)6g hH$O-driI4"`} j*Y0%0Du:jsbN{.?4BtLNsd]ex2r Y'Mr1NGu9-3IFhZ,h5,"Z:snF.@-0%Rº>QL P)\KDAvaCD:/ӎ0O+_'~Ni—tzW"A{Zb H'pɉ,:72.'ǐL,LnZ^ N"&Y/{sb;/;W6!sjuk5 _-!ڿEJ$=(<,3 V_#ml }BɃm52u($x}xB4k$I8}kkONK(h2V< gD!5q>9i`|UV1 g }Fx܇$ČN!Jc 9kvh|塜F: ,D9K #ȣtgY[;Cv#!^9p`;;=2U /Tֆ$ş%8/Ŝfka1m|%8VuΨ7D1~gf$㑯@ffS"6u%%;MY\0חi_ ?M}jAs8_x:p<ö2Fu ߾8,]Fh@U T1¸XRObR 5STD߉K c\F=Zc_JbIxՓ(Ө#ߜ?A\u)?D%OU^~'uq˫ t֏ $hQTD$4'y02W-QqZR9`X3'xΌO`5xu; "%tLw)Y_a=CTtXj*es"|N魉~N@'ݕ ]O@q5^3J~y;FG:CJN)\yB! u{c0p@1BALw;_:bu:{Vtyv=&^&<}r檗Ɂ> 2UBZ*>"sZ[NK>8"(10Y?1>a}dRcPbuV=9 +ݓrSn.bdfZ#I$Xl&+z0C 3P֦ͫ m_ݓœ#eqorX"n8?-HjjY ;N\g]?7M~^6F|6CIcZ0F-j+Jh.udk=-9rgrڋ+cC MZ ދs~v-0g@z;Fx&QӒ 43E69%t{B x,loRN9}O'CΦj aLZyѠƯ86rMBQr+jL5-`$EDE ^7l69V:0D rBy <@b+g䠫h ʓNv=tLI|- GGʤ).it鯚))8D|z9T^RԸDR#UtHj3FR2%Pi\@5FF0n E^L}֑45>[mH P5fƔ7Ӻ?h?ʚמ1ŃaOIe-+l\*lq[ZhhlLB٤ ܌348=/?q+et _IX@=V`ߴHо9h0G3Poz`A Q'SX, Ps>'@MƦ ::žoHb=\&5+S@Lh?8AIAž;M.a.~0p-zyEt0+XZoH%0-(ɔb<f\;1lm@)wĜ%#BYlfyv0dO@|nǖA HvTJFD~"&EXSF kO"vj<_Pr hGAdv~=vsSN8p>O" Z}lq(K$j>:~I jc1̬LNlD:%G.K8)1GFx{6yVY*5|0>4.jeM %i78NR~{d %ѹW#wSn=rW'tӐ~aWI:v|,6SEKlYBLN- m5-t'keۀ=fR5]^WiC YG$w ]n#u#t$,5{\ ,}?2BȐUZebZ+7En+oumNLrD.HuI6EoJ ðgy|0nM򶕐!p8Y|YZ$q#pOx\PB&\ěen*6O=nBSfivXuOFefmܲ+~@L;JYсD/b_)˲Jr֟HhhNA: sEh܎VHQ^C݌i'&^籠+/N-2EU <)SMm> }%F^/Ҭ iI4;;BzT_-/A3m1 :bdK 5onՂU<=}Km:d IVk^&DzUA^C^MґM Y,ݜ!mVHS9Jzsɇ3s?aA [0BFF?X+am]~.GQ}9F;.VoZovM鮟_^5Qcd}p?9| {[1#iAƯ쾖DWݟ!Kaٹqh] w4%\#?<%c] 6?HydI)`ȑ?cl eI:-8%.OA0MM`V]J$VK9VR^nEp[R5BZwU0!BV $tb}k)fۓbݖ~-HHu,6Z}iF1&(<5AoG,b:cY!ǜւ/+EEAi-@R|H_ CN*.Wo:,E"l+hW9lpˇUZDJ'R{W߯g藛:t8 1 ơ&S ndI `okP?y _ Xv ;9u}Pv__{ϔ񄙻aR#ΜLzzcoDX+4p2b;4xy:b@JHM%(lFYӑv5 #ss6rX^>;] =:^ǪSx%+m'VtcC }>>YӅ?8(j-/H{&EtAʣXx{c,;hZjZv`YuҒ>ˊ%{%ї|&Ew#q7,7o]lN;>;(kYmeYϤ\Y "|I(AH}w"<EZ8QSVZ#|"sI{]? ZZw6bQbTԖe\koe?W,jKg, rKۿe:HFSʾy#-f޾W模W]sҊHɫ{>)=g1 u6{_[f(r[('6uk }.4*Qmͦ;7Μh1Zi@wr3M2@Ιq[ $\5W:2`TgfwWIzRFBlyѲM_ep4W,n>įE!}S-2= z!~^(b6 X])t÷wR" /_4{c_IxǩjƅƙO2M uҍϓD~f#;Aq)f>ZgIݙaOPI35ME]VCC.9 a^n`*9^G%\pxo,*{spMh9%>9J1YI 2V"!vE] rs= ms]Ge(GZqD"ḻ":Ict\677YGXNii5%FF](W;Jvm+x~E0lf ˿ &J>mPެ" !܍7Q¢R/HoTAPh 9"|DZ_IN?VXL/QLPnT&]G'2:&>;CIҒEҭA{v>omrOY ?h}R~(bؤcɞ/*%[oKt%nd\]QlHaF'WJkm. U/e{&q't=wwpc?1YQ\5񄈹h`U]%p蒂` ا~pE22Wn+7Om`#wЌ/ > *cJ# ,Үi fs7-JM'/^6q/;f d;I'rSs&~aMA&He,:f%ćϽdjcYB,NLyy3lIj;/~qeyW/+Cs Φ-^6{.˾(p6 Ow*lkv}<|z3X\?çpNuH>2L2>ų˧ħxzr {;bS>g<>|OP˧շ`kad[O)Ϥ;/L8$^ xx']qX*?H 3/w%Tq(կ/L)߯h߫Za)vb/)x[F68O_?'uE]:u l:9= ˵G ٚ_M'Lg8xpxBWQP~bui͚`PsCX/N;/nDoĕInyjcTpya,Zށ9 tm # =EjUEׁ@Ӕz坲]=4~⇊ 0tMyTa݊dA>0q^'oAY r<&'誁|:VJb9K*T1[ 6$oGC)j JMP}1љ";_6W(cl#b'W̱eGG0RP&3]k$GK\ tQڪyL{mǠQM))bx3,1qmǰ<ӻЀ!yk-$(!TˋxZɕ%"$r7GJ_?گ$`l{p,jA qԠN=~OAytc-_r?Њ+B7qj2b/ue%mbi %7NKWid_4=<6+D$7Xv˴Mq֙*dΝJά"{}͞x&*1/G, E6wòdHАe) Zyi;5v*HF!Ľ&ZV_AAoϬތ%ceWon8;y|YA>[p)8$;A/Jbq0*2z~K:LSKWՔAB;=@:*MH4D7xT~3v>7f%f{#3BHaP>Sov3 |pOTK Nabi3Ɣ8X8c4t6tK8CqЂZTrT׸ODvrqg{;Q*@6ҩI;Btlܤ0\'65I R|.B%WpF ư+9 1(k9D=v0TqUJNRzPp>'|<J8IڤUf!\8 u@Tn| OدQf9/bh:<. Ia B v&jrDCC'KKDH$hMZJ]Wqj詆 جBjKC)m8PT# TxLKhs#ݼ wMM K9@GX ' Zl^y%N% hhq>>H ٬=4HTYr2"bbuD{l FQ:ƦK@ 2b @%B% uՃAm.sV 7\ޗ]Q+[=@37.)6Qp3[C7tѮWM$8V'ŚiQ0XSZk1'Qhg#shE<(9ek#7j+m_`LP=xĆ#r#g# K't\E"vt"ʜш68r4ŗTZ} C'I)4x;.u[w̖|wc]=At_Eʂ Ee @ÿZbj'~R&EN哒e 0$%pVr>rEFvsb>L1t%I4& }ݸצ9mc3&r~n#l0n:EL!UFn IV2rnlUH2I(QT19WbrKr,KVMEΖT9d0QM@4lL LxPN2)Z8IkRa,1m\vXP[tLD` 4fMB/iJ[Kxې KIWL=3ͅW Jœ& l>%8T7$NK$M@ZugMM壛$c> e&;AnMƫRt&N? qVI5NIr'j @]E1#K*GK-%3UERRɪzS |Q!IsUEڥ䢲J奸M/bq#9 Ytr/5`+v2.taw$U''U"I:.UQ0QQhp !\*j{WhQS-[B \U UN=SP괪*a<+3! ʈ=8X~bT#eUR pIzg陵m>k=5QhEQ<,g-J,3{_\*OQ _aua |"(5YF^=N=N& {ӟ Aa)+g :T ֚8Væev-Kvӊ[ ??LKF s#v,QP aa҆^kz$;hiX% JV!Q ?aE+( ڬe&jTMs #Ljw:YyS bBqxk25-w{gz>xɃ|Дyh>,r2z\M}'J]s=%.¾Uu2ֲ4a]Y&K=ͧ byk8A V*KcVMSA|2PٯaSRQOl#dgfZKl%X{+2C漇[ jfH ;e5EEzpߑ}j*8ݰoew}C,pd;Cj1;i$:6ݱF=o_r)qsàrS^:jOFT[$EKnRRzKFccPm+gck\awx5Hs]P\Rchུ|<÷|\rcIPӳ.jʟyȠ\2m/Jv˪/sI?'C o>2R$"Nndl^31؜-/w?5'@avL~Nd!tq?L͆_&P۹v:ar&< ޿p!k:Cyv|6+'ĺX(]UIw^8;LpC̘&̙=UiőVJ HB=(ne#8?GOz7Mj{ !ٹG!)MdhCuºN̸/ӄco2|8ȣ nl: B9SQxyLݎ|I:hvذ?@.]w *3΅;;`]@hqU4Bi:ڪO_I-ր;dO@;h#>:t? }X\d6b w̴~D7oZvhmԩD$+_z>0Is>\*p] /_F`-|lv_7.-vʍ99*7ȩ$vu@;\p5SlA >AvHڎ WmZ4Va.FF/?|i.bj dVd!`7FhvgQGw0ǿٲvDv|fX z;NC:(#!I~`&hu-x092͗ov_x ~P\ \q {$3|Iᶏ_vԿ?I=b1+i7DoPŘޒ~z+"m@r˞I?ZlvZj@so9Q8Q vYnW!6C6^ss{da{ǻt Jt.4Zqf΢xpv;%ª3@Z5πzZU[L!x&d'"k̢R]疅^ yqcP9>KN3;U~U-+E6 Y q :# ؊ [[ de&8*ysw Va`@aJ-rȝJ{-:;vun y8*&a"{eWI( ͤ»rޅ JXx7e au. ^)jg-XR~P(«˩;?>/bP5s(, xPfE!7 RC?Ġ+3< MއAAϿTR` _y?c zK(K }Qk#vHEpU5*hICۊ>~I7zZоLl8{"PHߎd*}JSVFGфÛ.`l ,!]p]ӯnx/,\03=pr=mTA(sE@k&~9 XJN"jЛxm 0Z]^7S}YaȧO$4۩1F\KmlT"Ѵ"p?R,Y48xd1"btܥmC0dId5^puC~l]`ea%kji8 T |Ѿ5knv³<z9J6 vWH¤bV4Vv}Z [wU\j`F;~{nmt.XL荒'VnOhصb@-ˤLa -(?KbX~%ѥHK;n^"\c"JIӿ~doJZ h6n^ Y82b- E=wMs3 .EV6mm Hw+dyqe΄-߉F+ru)CqCM+7w,'PrRCm_~:${>}=];ʗ!U>2Lv&w=Br6\MwŸ:}OX &xr:c"^\&'#;h=KؤN6} 躷o`{GO@_*P@F5|87GGaECy\Gm#%)7׊Q-1~zFv{H^q/k VX0.P^##ԇ^ݦ{pt9dd])}["Hp&i(8mjCbӍ"'O|PKwhjqߠM͔hՒ)٩p ݩM^Q׵tߵOdFf1w)m;oA"֐ޡ(o(CT=%+Hc3w}rRҥDR"Zw,js:E,s׏5Tt! ETcaG]į^7d5c,_a!.EQxh9)$y%kjdHqFsXRHJAb&SIa8!/OJTܞ¸&{JÜt s T>фL J,Vk g b;pc]l!fcܤCd]&m< l\85ʫj(-13` Ak7Ā" ɸ`Gv| p2_ww?{)F biPAR)€v @9%i6"8H3,X,.EX1\ p\̜c-! pzw;LC %4R~1RŁ{ h"R꼬BzWO.A b3{g)`ԣ{0oI~`зb$%mNdu%!LۖIÅiQЙY7*A%1l`'6?~.@]I%3fCR5 ;dQˣWגhsvϨ 'Sep()T^^1H9Af}nqicO t.S,8>y#i`p"o)hk]wMxر~ u>c, -@6w؀@&hw)R<Sc_ٌ$q5mB@iVoHa)WzeG&Idlru$`iց 1Qv] "w&Μ̿ޠ!mfcLc=:Ӽ]+!`): Ս OX(g8-/ ɳD*(PcdJb&{UV28! %f^WэבV鳲Zdl;dRwIqZUpMsv{E*MstMut8:OhrPhmis2DX{ a.^b5RULcz,3vC\sݬOÜW}Ț~i]'O(\뱂J>=Q so5DI,WF,L zR0>5D>4?O^SPs5 |DdՖϗ[{|k*cڏyOdҫP;jg<,NiR;/ۘ)a=3S:kEp0+_h `'Thj'cX"^)EjQ=E>Z5OGdj=dꖬ{wOϼφAK..PO"Ol 485L۳J( !R$-UPH('*a'a*z 8f176 $+ 8XTsE*$5"j؅eO;t};``e(>*F[Q.*ZYNpQyX10\\68>TV}&]Q !D]TVb $m@RME UD 3O#FH`'> 5D-9+{Ec58*tOAn_LY@*C@u <D,aE7jÊo5b p{sZN%(.9<?e>xed\~i0S /Cgi'qfeܲ="?fb}->6N qS9gRh]2r!"lMI/S6 #M8\4 m~ޟ+}<&?3 W̪bcp QSYH5ר`3bn m Ӱ81478tel yf P$j*t telԆ܇sk3@ PP-2~QzRkwZ@aף\ q -7ʅyF9QvpcC]yѠEjr߮i%j5؂QiSKzMz ]kce1Q=aRyVwA"Ur=)JV<>v:' (9„Gف|أT+P3` P҃PlO0@G(~-3(Eb̚-LiMmR/y̿ @/GjrQ3`(5ӆ)'cȫ &FsӔn!iB/|:QӰ@5tW^\F] Áx+t1I lja?FR_):d'`dױɫ`yTڎJOH#ipŶRv@oG!z}s! ŸߦvJP%&B,:[ڌɊp ͈ܰ@*x3l‹VͳA]}@ 2%DGh{xY] ׽}Cۜ$n!݇WRN.>lO)1En_mK\9oGQ ѡEu19ҺGSXQPg.䧉)LQj0ǩQͷI]uͰ47T^'dxh G1^bZT=.,&dVDR` Negב wtAݵutup_ jḒM{ɍGrޮDSYG/͉Їpvtq(U Y2*<#viZ)`X2Δ҈ݻXAO*6 kzB#RP';Ҹ#$~IJZ@!3) ӿ5FF^ Wʵ;؎r{*iIFӞ J4Λ(Q'O={-s6Ӓ~7jm B"=/c (Jrَg va'8P)\?P%πlb(O~Lj(~o7ʑPn|@9l(D/`VNS? <Oسi= Ԃn} :3L tSǓg;AraKOx)߳s`?pN ig ΛARAQ,u>M@rf8tID_== EdjA[!7~ݜq\e0TאW/ u@xU@ԐGs4BM:mQ4o׆i @+Q3 Ӈ #VSРWK9BoJxh"P4jċehz1p'C& I~OGw],mԨk&)vM :G⨁^[@m]NVU#4ۙlЭnd"BDg"ceKuV4 3z63s Ք&wHdJuà l5<# ;hNփ{?j>_DG>8`EA(E z3kPmps2"[MQoPn K EgÏ"0oHKoPa/E rp„;Uaԧ~@lUᣭSbc U.>nheAU#"шȕvG ZunIW^.} 9vx#`2$}(b W8D@t|@v%h*< {It02(b Z$r#UI?rh"(T#k=TȐfvߴCK#n77Bcǩj<rfkk-ܜu8 HQ9I )Z8=4[*} FK:7R'}:7@,ny@*)PGh!@}h^])Wx?XO"JXT`Sih5%j>&>t44y(aR= CS fCQ5<6~` Z{ r&£y&KBXAu T \'.Fjd6'"aH2<^A~- @lNd&`۪ںrsRJxgBZ7yMi]ΠRI,)WBg#5 (2Q zBBNKe5~ }ㆈpU\Ge$[dW M; M3jK羱\o:sZJb2δ fO$PNs@n (#m 6<̜}kٔx_`)H @"gV M E-H_TUl;kt}Kss]"> ]Z/Q?6M?+YDFkv8rғD{ m$42RD δdv.,押Ci`yPyA@\$j}͉5qysmb-.6}]뢄w{ԦNќӑE_a2+~2ƪ챀֩#ɤ*7qZNO-oDFsH( ߲ءVgM2;UHgs·:QU(8ëն(Dݳ5j"/o?ߕ 9oN)ZNR-?(Ȉʕ>re' '#J9.*EfO˾=MG@Dpfr\(3鄲&:M@AE: y}:#<]ѭ[rX>+"gAt١!1P>{Tb$lst5=t GOAdsMock^ʌω8.&TX+ZQG2F oNKRRMQ®Uq޸iUYZgRͧ,ϸ9;:\G4pR=Ne^q+)Eq'Bwrn@v=9 dLnqT* ʣqY'doVMLKBCɊ{A=U2kd?=o zėܿ^ Oo (rT^7 ˧ew4PN 5SoW9⸹Xpag;8`8Dit޽j>Ja ߜk 5 Cf# Hpyrr<(9x1qs Fpz3bL+2viQjz$q<0DV ?gr3p2#xj2q+Qxo'[tc+a9YYRoD""l kiglU·3%dvʃqHl:G漍EVdS0&q&6!䰎;I:gTĶ"$ V/&t;#ȾeGaFYrK̹yhPN_Lei@9 \2U)4H#:\КǥKUF4,nK07@#8"H3=ngquѻ>u$5gሂ_9~#L#~t#,*6fF/ΰKLʊ^: !^ޝh AL_(sKfF|j%+UWO(X9W)LVu$dZ yzi%q[M&Al1^CjZIL %&`_u`Xc(: dfL QQVA>C&WD{ CΆfٖ0Ojy- 30LkCF탆ةՎfV|!k(F #DJAv«V}>{hĶ(V/KGڜU(VX!S[(Y,fZ-}SP 9=RQ 5̅Z3a* 1 %+ l,#k ?Ypg(_FI\zu F6xGnwWfW"vT=aM0̡v`jY5+:'l Jl)+܌^S>es 7v @Fv@33Ɨ)xv;4_<݌$^@")wh;teh!nxv3g-7!0o⠞R-+l7 D|&3N@.ﭰ~Rny}jGHuԚc]e2ׄo*W]5WitA9^Z $C`T#>6NCs֧ukZRV>_CϿ비A XP.Q7w;R*a }TugJi4dP-KQG+erڦtJ M}1@srH 0`)uyrm # ]1dQXpJфo5j#W6A^DٛCsfzJj.hO m#:^ÊE dݹXF!6A {LOFvkl. im+Er=ԽڐVصDpnܹ QX}Xfvg&ёpDPLZ=޵|E*{asSrsUaaE>^\ukgnE] `\zjK`s"„֞[.QxgYjg3.yN>q@DxtlMGZwtR7רι Nu/;}IU#1&DP^e5hZV4ìMHsӷܷ#qXm8"jv7[m Ki= wB7eD ?r15.t7&׽kf䁬E` lH=vdmۄE. Zdވ iP!N"\FD{,h^E ÎJؖ-/IIzb{Jg;3FIC&`#D@u{2I&Hmxb,dž7 ~:/3sadՈ׉ak< )n<;4VcR:P5_aM,L >sƔ7QH!NJZ2һ)̆El:CTa H v1[dNDy90@4ra6;W@9}(v)#2J%#Bbc: GC %[JSDU8xȥZbtA dS0Y sOR1y?p %;ԗ\.T 4C^P0mhw9YVtT-᫾avs޾g#,݂%S8yc4r b]5 QXQiwKk= rW~t=ۣBR=#=$/՘<)U9vdՅLԈ`p]L/ Ķ FЊ l۲M]s'<>]@cެV29"럥<40_Y+Ioz{pP᷇+i2&{(^8Y)w]*4E, )\y܏ۈk.!m\Jfڬ(&"BS#Auk(yqy{ 8.QiU$_] W=a!R< d9Bɀ"ڍM$PЋ7sL #QBl(+enoO|T{y U)~t4eg.Z9#@ n{ɽGɽP{(۔QScbϴ#e%`/ёzݬK00]`~`)wg"WaNztJ&d)=''+%GdRxЋYaA29(IWu1|.0`qmO78'$R`T NYGV6=J%lJ,J++ _\*5<*bi^bkfsa0% 7Rъԕpz 8NW413N/[=6ũGl󹍓WС 9!z 5ݔ"F~r`;Y!7:/6mWülE7씎܁?L$jn*3fD."g }^gS6/Co!.Z* ;5pH\;`xѤcG-- U_b1zkaRa'\?fW"}cd2g2m^(ʀL⫲W_G ڕ6GPW/"guNL6]1Y+w?Þqq?Ctq З %հ~< 5wW^^<TsӾ1Z2![m##O!eb Wq_^ZXdAGgbۺB!,7yICҧ|@sﴔGzT!G =q 2 q6)@Ps.ޙx22k1T6J9:WAHiAj[.-ԘX7{ @3BT+qL%M~]'!%/qޥ.Nd4?RFwwniwk@['ikvN[z96eXvK'g#=&m TY.jTm,z?1sϰt0/-n/g0P4}eV@anT'vB)W4jPɯI@J.0wi*SZm\}wp%_QJ TێЅSdAy8iÌu-S>"X3׬DWn* ˦%R͇$D#[c6[B>\wdV.d$*ot~O 1UcG4D5PVG0{#ZcWZ׸ο[цM]5rx\\ÕhG'r&H8s%!xu@L2bg6ǕqZ( .":ge ?>Q$m j\ϷڸjhӪr #nˑ  >R b5ҋM @C/ [Y2x(g['W1Tmq7:ZKy7#%!( 5.iU#y#-WmKwT\{',M)$0T ?޻{MbW23r3G }AljԪ/0(~>jLGRRCT!YhVbnzn ] z,E*U^WITӌ+ DpvѠ>?ENDTd*g*u ww aÄ05RmNQR{u!KE\,.o2F-i9tlTSTWU[^e(U삈]F%k59UX-mwo.rqLlm?YAn 8Yb-zgW4Jf| ˙ȄD2;-=7>&ǾQH8SFތ% k8ՕD~KݿW+]mƺF5ߎ wCJn:\mela)UaΊvS̛)@\j"rqrp>M5q'o;||G8Jh6 5f'J=@Fd5Z,z1IE Oj܉$f{dҚfLTw:ş%$X\$'5n*1DZ*܂l~ Q@*-?M $Ao\=|II IgӖ84) SU\L97O7kԜB@#ƪ7=E>17ὣ}<-[mi#K@9}GOvGO:$8 9湈'HҝoJ(G[#÷A*mn"+3)S8:V Wم6M7B"lnMV;z2%Aֻ{S ͨN4zl]jMP.P8+\vl=$|5|(j3zӰYB2\1g'=:[O d1XRj|{擞âC!®ſW˄':z-[Qei!:ZP!\W&,5tj!J3eDstMцBTF6>*1(+!R@s[YhV^ ?Z|k=-:⽆%@Ȝz` X4ˤT Rý-2m%xuٮ^ a82,|u_;py}pu zP;~3ʚCX kдGo6 [~ P$(Fr3F#r1\o3T)DGJjB4iz<lv8_AIP=5?4_S@ytm*H ,a:meǀ^Et טTaޏVQCryup0C;XuQPP ǀ'.kEI4v"R 8DOB(ՏnjK>: '7sw8 ض#&)?=x},z:~ ʘAnT{3Pj5rSN^1 vGfqGBLVl݃ ,Xnu=UzԶp },-T/ 1!b"tu( >H1XKoca7A .NYDϤe(ے*ef)z]l נJF!=$h"o“QZ7]<>E|](6 jڒ=5BG 폨t#L5(z=8Ri!¶!I1-J8|Y 5bAD#w&0>2>G02q %|,kgXBg1f"=˔ Ij=˻ˌj˜ ^*[rF[n:# Poy񢛜(sIK@"l?Bsͥ$h$! K+%G` dNӂglbjoF.i6v4&%=v$5d,&s$-P9S)ULM3ǫ*J: `<%C ;:sԻ_nJX#6ifCH)3,^8'>yx '\1vSi5ф/͑a9J*b4WEVU#Ȃq"{0EO82<͐_@lUh} W[n%JX9W5慸X_ ځbKIa )dq}x /E uq*̌ZVGcTAVT5 ;&< xU^bX4%1)䕍.b =I] !5vϮĵoEqk~l"rd9*K`ĵBEs]8H6VmI)9  MuHF?C d).DjBSȅ8jr TٲPkk}t>q(śueځi[;ru\P:ښ餒 `r݆@pwb&Uaɢջ(j!tD)EF Zg=;jvUD6@d!ڜI o%Ds8"vk#L9\*e, S*f!hv. vh(0 zrt8PC"Mxr䛊݇ Q3ȇqEa!ʥ50ɑg_.y tzCu!z=;;n93&ᢘUY0 ;=|gC/5Lw~3!nO2zJ5351Xd8Sg=tׇ8SXLÕLr~x3)t7PZ-#IPp1t(SeJ_(SG-xm"ܧ\Y3 8W^!aCsG)G)^@RT(>wkEO)^@d&ƑgG"9T䐯@R[`yMo. &3*u=|隡ZɸxP%L/EtK|YCnauh)ڐ z=#^.\jWY 9,X}F5 ],3B4kfrY$*EM3Z :E 6dmY`iV0z"m-qt_R4p?RF!ASƍg==_ncgVªO{(0oOqHmiL?Ljs ;kE( qM'ksİ~Ut;lkc_ܶɃNs+KE+BbW}A *R|Fjf[R;Y{D2v/S<#w]!\.JoQjƴ* /i5U _n5ʇ2/9N' _^tY!o7 +f9CSP*ߧ2 #sQKs("G@#G9xV̝vd e͟ҁ`ro X/.G6ciꗜ soBQ8'Ky`>]1|ZQP~%(V7FkʘD(LyoyT.rf|GZFG9`3Q@&V@ Ym fgۇoz.~ç?9?ρՇ ՗E~?~u/ӏ_~o_$iGc?orO ӏ߿M_| s?}Ͽ_]O?=wO~ӏǷ?o~?i>w4q̟~rM+Ͽ  C7~jYЯ²ͯ:2'/'0|ӗ_=gBo?~gwH¯O߾|v0͏hМwGH ʬ'[[&}TZ+By^#iʰмJP<V;sF>C<®cAsM 2fK?GqoLc9Jἡչu OgVs2kGQZIVLcF!h1zo9ےZߨ{4~B92bV1  EL# #oߨA)ֱovǷ TfG6G+!mO?5$o\W֑[9; ̷_>DLp6yrPاf49j,"qasX }goԣտ {$e@['z r1 !.쾡ŹdQD#"s)oj4GQ@7T; z3u}HS!\jHuvg RM}hޠGXcr5"A#Y(#q{\Mu}QȢZx "ԥ}H2\=[pJɄ9vHF#@}rw*Y > `#";R|D^I$Ϗ@7CQ }֗vHXЕ`dA˄suց9:ӑk@K[+Br ͠?RBs&QTwQ7p:8bQs2Z&. dtyeb3z=eozw ?>@- șK<;"(vV9hH+g|\XPpH{#+E9-clXü!zH e':DMP$혵lF~d$`{82̈pnd:^_B\dh0޽_l:돮Qb47߼<~Yy}g>tп/ofW?~,bPww4=9Vyr}|ԩ1^ uTh̛m*!%~[Vڙku_>((ɠe1*g?叹(g׵,h1%]9<=qx={nP!}}_߽__`| /zp#QhUU &Y4=|}ѿ0Q\Ne>le0|fm\x2oe]yy?1> OQ>.mmyy7+gA]c>y Owm>^cƝ,>+AW͔5)7IHWpUٟqҿݪ^UZΟS~Qw>(A}*Ƙ%8BʦOeU;oǓ 2g٧+y]ni ohHaVpyU-f1Y.lR)afK]RլoiVnmPnWM͇ ƫo~.;I ):du4A\?Lɟ)ciQ/h z? T2zo!Zkֹ^Zg>0)i܊SJmaPVRBWߞ:J=BUY6F'4'=ҋW??MبHa)F)Eu<B.iۉp!JqRր{Nw?|ڀҀn5?kBYeƏﻖ6jC{gp{{5iMFg$smtoqO~_[|߻mo-S!ڹ(*q#OXXjv˕ mxwHer'!XH+_[#/֖ rwkkBbvFD.Quf\|e.lŻga^^~GzwD}s l=O_?6[kmyU~(G <_El諷Yn8+'ҶC2O=>hcPJRCԡflev( Ucd3V :-^_ܲx \>I~NꤢRWJ!&1u 17X],@GUDSë'"rg:ޙ^ɧ:_<'pW`>:Щ%_VW@ؑӣa왇niT{;5;=fV?tࣣ?EuBPo k$Z&)s&AnbibZB?mV=k$DȪVAE(ȑ>NkPA߻EN_D9>"?m}Lh~]¶`9͹rs+gW4bv zqq l1 t>s-*0A+@HXM B^*Y[kjĪ?{?2棩hǯ8AC -?(}+/g{^珜yVBz9I:1:Uʟؓvܠi%ڟXY&=)uZ)''|R:?׉/aeN}\ Ds3g ͩ/7H`=kќ8ƹĹV@4's'Or'gm {rqq'n b7BůbGB}5;꫁ؑP_ C@<^V|5W r}5W0z}5j FȯUT·/ y{L y:JB/3Hu#45PP{ ޵i.ѸP Mt\t0/~XaCn$[dS60A =T:ZoOvIqL|oN&WOXTIn. ]jfEn/ ~&mVf mp~\RŌǧS*uE1{L%/~U5ʘlB-Dgl|8ƒ۔9NwH6:*]ܕOA]j#AS@|˵=:uka;_KPW/Zx.okYE=mkEr~G+fa$ 5heCsJ ,Ё쇌`^-F̄€T3JZSfbAagQbWBσ CR!;=X"Q}v$yQ3zf DU *+aJAe iiz8&*GA0dzAg&t.mYY[8)  }M*Zȩ+[6KOj1=/a֮K`,ZK]Gǭf +^hSWxN0uu+a\4ĿBEڹ6%"%VD\ aZGm`.ʮcX .8Ctxа]!1J@)`Y𑨹oxaZ|!z8|+@31 a~ԅ0'jV"w\Ӝ]]99EzٲZ7I`V >"yV)1yC40v"1B@t2,t0B*oͪ{oDyS|E'P&=ԥ,cK};X8~8Mi]y Kٲt /%[N^K#0冿@G.{ނ [.c ajcϊtvujQاFwi2 Oɒmctnmuo↢* أ#EJP@/;eY" gzOѿEdVV(+Xͩp:D=fkbRF 06ƌ11*NjQ#y*LLG|B ò@:JӰ̠DZf%Eq}/wW%q,;myaZz8q* *ºamj3G!п{pTyig2"ew;~ۿٹnsy@zb97V?Lw9)q.g"{}- Ǔ[N֢SpJCUKh 7b\EYVo@TzmVL}NooQwGZ)i VZӄ H1 TN&Zkɘy #*رt1e*f%sRle"r6EK&gZXh 5,Τ2UI+$* }nο2Sڪԁ!^SDYH٦P᤮ոXh*3b+,̋8m( 0 PHXgQaYӪFCJWF) 獷VRwWE P (H b*3J+0X5џVԭM2:hT48bMV&5ˋ%u-j!-<3P7t2Җs$W@s4q酥*QQo՜ZU &*j?3u@ iz?Z'曡Φw$+1Z1awM [nGɳ"Vꪍt,ITܫ֐|u; w Q~~Wj+z+/4?s6jG ^$bkUHac I)4A8j sYp-ȩSCHmвWm }_FP$$ଉė3(ȝ`JS(y0D}\$^PA$܍gIK(bzhqCLEbL aXwk$%ݥ r$&wM-a*|žkeRRFM:R q7Cԃs*`M-9VSa"NFܪ)\$9y㖉5Y5}egzAdW+jZw.fD|m< 4zG'hOb%Xpx4˧ß+ U4>_VŬ~J>'h(slRee޿]Mg%5w]qL/?N崊n'x2je[ñNvW o?]4|[N+%x4^4y'崜|(/޼h&ّ;ubL|n&qxn1goY6|2=r,-'3eZ,YK9CBwCA9l…6ʚ-Q5̝@tx&z ˾JxKJ9.] ]?P>̯!$>*< |Ž̾|kHR,~ *2sy 0SRjMm쥊zTIK]CaN%N &G&bTiErStgmDool/>w/M#.e6}Q09 ^_$b4C_l_5N$auhºUBl2#Q$`Ktҳ 4YaTKgTicT^X[4 )|:9/Rd(4MG+Dq Qԋҕx0đ02Lڤӗ0xH; 0gM:ObaЂi"kiO U@˜Ɋ¬yJ{E'nGp *X>tE6@3ܜ;σ„!=ҫ%nJlk9T%-;et"8ň\ÃJszP & &?1tJA2HpI]ĀZ'鯣7mͫ-SHЄHV$5K:As^!j("$y3)sg>Bk*e5'?[+:!?6AĴI4^40=8e!x&:"98L 7otGQ25RT Iӧ2A0ļ]Rl3=3G9 $(ό[IW9TH>,uHe6[ )P,YX!1PӚzÛ"@Kv%}{' ! J6`a]D&|N{lv$+GĴe q)k엢m'K)TҲisZVGw_kTc o]OXWofzX|QϕYOZ~ݟb(mȾJ!5SJLcE`rԆ1 Un-^cJ؈0C"4`>5LKi fa׌ :[G2q26rBW0,ͭ8k _juZ^B !ɗd vӡ{ [[utPCw _433$r/QR Cg+=7%p5wWe%y o օT-L c1nbD}Ͷ%W03 mcn_":\_:ٌ:hdLbRX {4aۊ0;hd:ܙj$_ HvsbLM#y@7ktrHjrTiZ)}Z]pR'G6khڈ ook=h1J 5k䆁+yBC7}flvwd0n$z3-M0-X3lWKT^`FV-z5CӻrMƃV&AaNWˆvLRrWA &w߯.~|3A7+:R5vrQ}!=]w㫳sۛS}'x?=o ;+?yMYW/~Ooskw}zՇ;,Çk'c^?^p엳]qOwxA7)#~_>=^D+Hi~vOgW@q_zqzx[x1za2P]{q]=~~_UG&+]!o i1ۘ^oޏϺ>ʕtj~9ܸLksqڬ1ʹ\A´zlo^ԍK_1gV7 9X(vmn17WF>na>8nT?է?iO37ؔw*z~)jw?J6vn3m.)o\PFwŨV5=>jڬm{ٟpϸUM^qL8 Lz!Vh]\&٠&n"V@Z-`{p:onlvq|4.k__,oߊcyM)awuۋV=woznnn=~NͺCUfL)T畚9Yoj]Ʃj FeVɻY*UvMJjYmu_2IR(ըgIk+Si;q>窶 13Lh1g*1Nn'+R@9i5F3U&:.bB2V\Un +36Zj=JiH[+K 'ϕVKx.lhrL1moCy ?o1p篝xsMg^;y߯uiG^l=f#?}|x:EZ-_p/WrcC[y3YN&2 h_SJc9B(8uH$AGcnCH;ْtT/ BFb \=vQ($RۄĚ>۪dOVNeekcAlmxD.M2.xTbrL֬Jc;/d8@u/٢>>?/HcLKfSF?=K1d e! +@DfhNCNU>Aeʷ9δ tp }uRf6J/4g5ė%HPLLof_ۏl׸:.i68vko&@~Yd4J XFnO3EG.5A?ك;cg4!| :ǵo/5~&9l(|:6 l@]w_PK5/=Ma}g9k:jx42+X`k۟g;/ʜ:ut!];o\CSN}jMԣ?R4TGi,Ćht@MC]zbE+sH6ܸOrONuZYCos{.?Lc2}6ر>1۫?  dVie?o4B}Ţd4 Ҩzs` TD<]lI(E2-ɐ熓|B -We|!m1-&i]+rliN$goq'cӨ9OMGn`FCmVjset9׸` oaȑoNKNuoP]Wj?֋⨥.:Xzh.DE+{-?lc ,B;k"kO(3{<դìQCQq,t<°:1^(ƬI)& C2`Ȁâj#''7@$v1?ʣMԭ'Yy W-ju &j6ok/F酝yHkTþ'l(zγ p.$1F:e]BoWZ^rNTa6O__Ǭ3YKY;,Q uĢݴkWa!~fh Znv&[epdd3+owBaɸޏ{%}d:m[:g(DJ<+9b.S(>)6lЍoׇ"L w섐nz* L[Ƌokz2"E:4cIL*GwrgdJVmg#A\|ba9pXN^&9Ev$)#O ]\N!-2S{eS֔+ZΈ30~n,KL&w̎#-6MO]L;LiY$F|p,w98PLmsC2nmYe$=i,8ҏg[N VsQsb:_Fnt'R&jBYr/lxBm5Ӵo9m5q5u &y1c#.H_jnQLqq.1s-я_3|ft~ݟ_jJEh_ mѥQJ|RI(Q6jS̵_h4ZS̖ KRxCiи]6*(7y`RBu}k#?^=!T֮-g6:$ ;|Z:Ia.XI oܩ%.80TL+x ȤIrW[ۗ4VtkLRi|y)1~x&̤a&{_f(RhRNxǮ@o&4{Фh3&P^4itRMn|.Фx<;俁&nAF4lhR/iA$Фiɔ 4)w{xMb|*X\A&Td(GФ-(QM SI ~JoZ/W,l44e97ԡ|M[Ӕw~cmo&>gpzYikiv=:I4sVY?osˌŷZK7ESؾERxrt v~~v[%6:jCU 9UMuώDU2+|ELf'7QRʖMi}17Ge!K~ؽKO3|]mj}Gh5ζ2ؖ LdmqaL(t̤C¸ݱl=' oɌNLIvf#X L*~ft*t6$IJ7];LQx8Jy<>\㥻S6ae:ns6rXw%fSLJ;͞lDs95:nnZc㞋 B=BfA 欘5ʛc&cN#MT!پ]lm #TJ9/{^MnGG7HG:uX娬I+Gc.Ja(&N< ux?,uW6 .& TP0Br-oCy>҄#M'/߾9U.!;&!0 p؞}83z=n `by\CW Z񊥚1A<JFO0 ¼Ôuzªŧ\]1F~YO䍘o /^e˜d3x#xqxdw_vK (b`4!1]0"QO}}sh:jw?hTl'F}Hΐ $=uf|6vfaϡZ:^j^!G';cj9|V/ˉTV0۩Wg~-`I#' Ahz0{Q2}e:&6|^cϋnK>v:#ˈ)@{%V$UC')jtB15-4v3p]􇇤'mZiVp؈X2hT*ҍq 򍷦 x]A nӰU֚&dLEUGF={bZ㸚P'tr&d{tZ)i!GԳ|r rDPH;n8; 6'VqZ@+M|Jbtݙ<~*c⿍MY7nǺ)XKlcFxMʪ͍CS‘!1H<& ӜJٵo6 Em2$ao7_f/$&haA1j- +&ED Tb@ >G+A6N;K!Z? i4uJ_)&vDհM>p127|s&As ؞VvM̸l7˜XPmWZ|N{j m{`B'ο;#dzmh)d~?X .MN[G?33J@Θh,Wn1vyHv!D36u{xmIv)\$3arB dityr&Q/ALM>lir+e9_y^8r-RV8s(U LsM{WA&T yB 0SVluazOK Iݨzɐ%1tr10" >݋t̐fAq<ŝn-vsLZ#+.O2Ga~yY9ezATz DЇA$Dd*C 9kH׶qPx 8!$LbeD&'W&Uq$dȀ&((0CƘ E.ڢV [`ޓ5_6%ɂт͝鞞~7^gc_?L#%F nkc)e6=Ѱ@0Nc%g9E/v]'~)[UaOy8"}+H$D%4l}V).PMsb&eRЬsK vgK3kacB9΁+O/h&ʘ*{H"(3N1]hַikc(^xOxj2U2,m0Q$B ]Xc  俨^s `) wAaQ#T |KH|f/sfxyqo(1Z{4fZ:-<6NZmֳ1\_ fKvjS٨,E{ǎKTMSpv=]v2&w |z3{ruSRe4l~{:T^I)l3:&@D&^8e׆arc h}c oEUB[;26.h;~\5Jq~ -Z?{h'lw1pH!=O'GMBT\O`>GU/ dcd|Jڝ^\@6ߒON0 'w1-!]fxu)rm=y-!cJ(bm8z\1fqm72i(eGaq rzKG""-[nDzu KJt M][Ub-&A`T:(HL 6kk[a&p>:CA1*7-Scs-^[Mu{3Sܲv.]olq, ]#R->_}VY.M 3zl?o{M\VstkQmLJm@.bjsuʶĈQOz̎OYСgðiIO|blNgE+{ܖ~] K=tH7 $_rLCKC|t1^`KO)-۾ǎ)SN)g|@'^fՕʉ~ra/K-kjG[)Lݑbo/U^}K_J/'RIjSRj©DCVܞgOOAЋ$_Zhzc6Y}Sq {{!H{m`Dj엉-o-tvˍy=|_tю+mE/(,.T|c/R wz#=32g=O*Ivgl\LJ}_,&xg`19Jrjt]-tE;藎LA q ~3NW j i]")l}fLNtڎ~~v[%6:6|*o& 2E߉ >N=0jVlwg>lK?/ _E"zx_{6YR2əU{MTUϒ1׽=oؾO?s<YjU|gȏw>^]Fo۷ʿzuWb`G,o98rħuzO+w].Ϯ٧W/ 3EH[0u??~r描W7?o]Vok9?@ҽyCJzO˽:6_:;tb_^{Tco0x15^u!g|8lŕWCPRZ>\uH3\1f2cli`qùly(悮, 9Ԋ?]=rP/؋7\߷8{{[x.P4=t/ǧzs/^wﯛwOzoWI:^=^9ۏ˧xxejm)x\n-\m5o?}/.bn1B~|-pZ~}[&'>68@AVJ2>cZkN^.0CLr wg* CE':6+5ڛ(ݣLz5>P|e,.3 Pĥ `*C`XIP0LauRܡ2$hq*mb&-(iz6Kp1,pc 3D]Z%zXy;K4˅'qccbШu-pa =4grVzM[> ӏ)FҍoMY}Xԟ+5h X\kCT*ɐJ?۫yZrч-c.*HvguFQƢKcI1Ǒ[O$& 髨Vx!)O}0598%0ZUwO`S*[yiBkغ+%p:Agù^D#8+BۍncaqU%?E(̎^\W_QnB;]^|uVXuKVnW`WHa#!#R`F3o]Z;%o;q5Nkf[NugO`;%z@3G+c*(,`\ʶ\}*nx{+T-!Ώ 0A)謹oڪjh ??G|?(Dg HO$ D2U\’N&/'tё% ٲ]è5,`[c K*8@ RarNcaBm$l`#qpU <( 5Nlm.dT]Zֻb|] ]&a5@n<W߰b};Chۑ_n{cä7x?<MgWn<1\}t^ˀ E8Ga xгlfnx>+V,/描'(H-'4mDs/@qWĺƝzƽGnAFtѪ[qQֻ@ tjDT?{~7'<. bJ+gfXbW4ֱ6cl@l%N :a l62n 7m85+VmFn L &Gb]gn^ξFMa:K zb YgAivXB z#FZ,)l<%d6_-'#tU8MWVw*T+I\!>1~1X]A`낰is&sҭAN\nnaK5"řQ I"- H8>~h͝!b #ZҐx`H$lIpP, Y!K,`B߯H4]8y)/P@-#m,z4C6?RvW ߲WWhHHH%t; OG RIdCZ676TkHj}jh1%$gƓC3j-=Fyb{uu`1G{Wֹp̺4;Q7"8uC愝`G( <3*Pw rP[zD%z969ٻS3-ě8VgؐBKNdꠇ[uEALBM-DY^!0M*^]c\o`"oW݃x^uPHO1 p g*X8E.^a po筚'y;on|\]ʗ+-6d}q󨔶*}VBlPwy\h Qiې.& I"A%`.j>Lsȇf1i'HHb䉰 EY3!*_KoTAdc6%ʈLfʈDBBfJߕ:+t6c&*fP4@&n0V(46`P׈m)2ViCkzN[Fy+rb FP&"_$J/H t90^6ykhtvL%Mk"7 % ▕Tq˨<([! jr@<^W)yLˉw_ Wfa<ܜgQ$hϮ{F!φ=;D0v:6JړXq6;u4ԩ_^4eWikB ueڞ.H+3 c:&XHDBeǞ PyJOt(tGEمTP3lHjtΆx - =خT-sp_ۊ&C؛ʻ6^|Ŀ1&gOsp#7B/ >Sfꏄ\;Ѻ2*v[L i#ۥ"ۅ+_jh(jS. h+􎀲( !n:I.r2AȲsk29 AC1Ǵ&).P;Syi}njP,Ql"L' ޥ-IxVlAH"3lY,c !Eozw&măML3oA6LA[g[w Kmb/K=u/@JZ QYh4W?z࿚N$ENi-ɐ$'A7|G'Ixd*U Wafhp"<4IJV;KLV(ᦘnx,K),%J9B"3]qy*B؂A8f.S=}o``KZ'PcCBa_vCSyi4_)')׾bO· PY}s ,ZT~Y/~vS=;#秠? U-<4>݉(Re̴Żd{dxy&)sP Ma6wݏ&- -i8!}d'9ɽ,;R$*<$Hdzع )9X4Ǥyn@붾|0YҶ]ͨJ)L؃TұiUBZA14|`>*ڐgeUl)' | i˧9+Jd!Y-<6}!:֟*O 1}04dW$C"Һz_X߽:-K;sБhR|V'-5pti%CkeFoi#R.S;q"{DIY`=h0ePR,~$+[PhEVψq8L2\Px -A)rM?wV?*1ȗE_v`팑8wUYn! ko"d)rVz#mt:...ׇL4,7[ͱ ќ`&{jW*SUڊ7zYf K/~j/ Oxg5hrCc[)1}j$g '\=-r357xwR컴φ{~ϧ&w,i7u1nMQ|G ;;ж ]RӃ.K+lZA{WE}Y›!uOZsZ奍^J&2PI1hɷ1el$tYb0d:֢ e!D+8b/ -1oo3wąEs0oՇ6c@~ hHk/ASQN2DsY`u BdlM wүLИ ,)&QIT ?b7IT0],p NS2|n)T6Whp@Mp="LsS*fX3.Md(UMTh1nN?Hwa6tj$3wST3x|0#(RI{} 2oOb$+^|Kxi #JPbd>y▀Z-0ԈPo-M 3;`2(|' Wp[Փ*!Jg#~D8[°w̵ g 1˓}mfpĴS\]E6q>жSJS=$h2-n!ZZI_Ub,ztZC.cYTl㱄+IhQm!|i Xfθ>8hO <+A^&z S!۴YI^A/.gL B "7$t2rlr$B,5U_g܂.vym.[+Dxm T&b!7/+eHGJV >oaOPcC`R\O} 4XŃ%j*Uՠt&: sj]"8U~=2 &&RD$-eƎҤU5K4OPU7!'2O(:,,#o C _ھjhl1FP0c\V `F;L+7Wp H05]' ^7 L!kT+>j 0+qMv`q#Ǜsyf, ob6e_okొ2{+EiQL5^ie&i"_kJu)܍ ~'p+7aw. [Cp.4W)DEifIYfZ5|ӟ~`ʟocsigenserver-5.0.1/local/var/www/ocsigenstuff/scalable/text-x-python.svgz000066400000000000000000000257261417255654100270570ustar00rootroot00000000000000}mGw bKփ,0[>(6[l%DV"{Nl*2##_-Gכ7zތo?WhLoWooU5i=n7ϋѿM?~n>Rfv5_͕7][_2Vy~Nm[l9_)seLv?>=jRWy^/K n>L6OO'՟f&7ۛkۛ|07WMnw׋LPA\t&֔k\:JzYl_՗~|iiQk~_ޅ|ܖ&l_0Zor^Z_=,~6W/_? vn!MKc=~0ޗLrГ` ?7 kY!=!ͧ뿬7 ,R <ٮu]v3Nfu9/jZ_vƿhZl^7# !:2Docz3y]-7C=U^OߝӬ̓fQΝnvnzlhVnm6?6_ 46ԍW/3=]~~ݴFxq='hn>ԅ_l?m뿓noR~xs7ݮ_FuN>aSީ;}ow?Iamt+ ]QR?qAݩR:w=;:]hڬm{or e)j511ԻFaB5HJsքXu2qle$~{&DZ2p:sOf55_8@{j==^c \Qe'XNƌ09E86X8NV)84F'ej&ѱx 8)3 deBK\G;q4 H[GO.52lk18hV&-&[3 =QJu@jL ڜ{ =t_+@DŽ} Ӄ|l::IQV 0R]*ꃉ4xAi0:kŠgF+=;9@$a8LQhfWUy<4B9\TlPkZ?QCj\IPT -)g%QY|u㌦goFB0]hte"R!anWҶU^(PN# 8\QaCǦ( )ތ(CcUp1&iRXFJ4u9 Ծ24c;EKZL#ί;GsލrԢ=*c5{5 N6YىU1rxeq3 ,mmDa34BvJ2ʆ&ni[4:L7^`:?a.YoQ Epg%4Az^db< L3~]ș;Y&gݡU.ģ!#٧*h^b0g6@T5oHJ$xkT#ZCbdz<^TѤ\sq 0};=C /As,D5h.K|jol o1.\ϣ9 s2 ]6o4lK徯FbI^4wM6ߴluOq/ 47.p)>(OޛIB3akң(W$}~oEތsЀtԗRtZ$syߞowN[\3ۈű=ݡ/1\@ؤ mZ`-yʙz;9^r$e?|:CJ"z$ʤGg3)SɣA H,a  8?I[Ϗ4q v2mFatg1at~p4pp^(nHcqPYpHBEuߪs~f {/ ߯cLDf=sd*)0J 0J}5j0Zi(k opt'31En:>;I^A11:YO{[3Jp" )IVr1u=WISzi|ݷLkV~άlM&i֍`PҬ KQJA_JyxJʾ)S $kv=0p$da8 Ջ3^BG"zK?^FNoVe7]B+vE,zͯ"hoۛ7'-V}*sO5+,_nydXm5y4oww*S7͑xz~e=Fj&دt9 54[ionՇtysw/ů$ R[w^}=W.}.?27~x+k WŇ=?k}FI:pY,thh4{8rDLzuwkf4eY_{㎺v/-]2|rolc_.?JgWg46W~ \}c 9_̗耣X>=ܭn5~ޚwmv7@*KFK)]v.Ω{ТUAEBPY1 M4$Y ;-롅GFqВ+iuly2*ȷcSLGVZҚqwlnC`^ i iP3*;їh Y@[ɝG?vfS&GMEz._Ci#DPN:RH2 4˼?dc xq K>%_h@ imJ,;AdK [$y_S(0nKdc`@Yp%s+(B5*lt:Ð cGQ@GD#)_%nDseãRI+'JtB[}HZ"$3" n5CS)R.1p R5Q0\hgL2=S)2& fMH[ң_Goxeٷ,Ik;q@ ۉM%oRH.k/CJ*p@N1&!eK zRȈMeÐSͩҒ-qr:,UrŹ6KAeo-+tĥX<S~cDaeGPtF^Z0(K`9M),ª("54_=bCdgщ4jZ " ^K'֋+5ؚ$,7.Z_PsTf74QF;yᵕoǨ[?&Ƣе712Er1s;g" Ƥd­28Gْ)0a#$diV2Îl3-b%%Bc;OjYXNx%ALl2 siq.Rx=U2ħy~ a/K431fUsY׵/ޔ d<__[ĞY_B0&10@P s CLJs /cɥltd1![7|a^2:S14"*N.ibCm$#CݕpO9DɄ.S A! 'C{gu4` y f8+1d9 .7 ѽ"GOSRcM$ sw˞PF#$ ٸ 'S6Vc]S& WʻAP sָQ]dzY D< {%$$$;lr!ց!IP6oakL dX/.#ݐB\mH %ylX m9t,w6^oكbbtdx5I21p?r3k$߼]hZ(|rPJPoԅK0}Fp8~A=4EЃ GPF:\VBJM\Ҩh 9 +v<ć^Kޗ#H.H(>\IUSAz>C(ِpp= )V)In1dJێ3mVgl-. %'@F} T#9ʚ&ifg]>M~ύN`7iUǡtQ7&{ہ4왴=&o=ZR.(A >/4 ]Q_O(r)OΓZ;U^uWC$+Uͭ8YQ7bm:KJh:AQ\-wtwxб5q`ީ>k` :2_O)!sQNO<蠳|ڷ֏h- "G KvS'N*>2*G4o.~Ҟ#ʊiXa=2pi :9@vD)S#|b[;ԥ=vk }Tr&~>8гDoz|;۩S認ߎv햞?!0]PPԏN?ц"H@(FRGek΍(  aã*eJBNQ 0h{) MmdbGhXZ8H1bʐ"hwe21MA|uPV>絯Y 3r#T wbt.fK#2G*45Mb., SgЬѠW5MPمJ$*p]tU!6$KjI]ʲZcma֋s)Tewdd8Ud?3p\5iD`  )h)j(kf}4K颉1XHO9Rhh:ž VA"˥TG }NխF~,Fy%0bmQRb9hnb)@6G̎/Asף1 `0T,8 SNDP[?mc}eY\F]`E}w,1۫SD+fQ06'Eǚ(%X(. d^"pPvڧQ]4h|;ᵺlU.gUcF*Z+/D$7b.Zzb6vqozEzcgb^ Voz7==wP4VůݻRq鲔2]/^g mv)οl Zrzf>[!]_#Ϋ#6,|]աMfLn[,]{\~֫fw RT^+>uoA$|\nwWXF>w:N`kV7X\S,.M?ץ7,|soӯ׋ҿ_s{AQ~t6tezowc|U UebVf5:/_Dqeo] ØH3'U._|EvbSSkgnʙܕP.GJdh'9ɛؘGܟ܋9!:b ԄN&7AZ}҈n{r:j<)YQ+ۮ` .isJnGaeP]ftD Z[`}D~P}];f)z/SaYF=U]NLRTy|&D㯟P"R9p3Q ^h @YH _*9YUOU!Q5y)-jECAU3%Am9A2:1Z.]-2\^1 1v+:334 Jb>dIiJ&vHG΂?-e:Qt J΀^:Ҝ}uqzJ|=\T=tSgN)n3v mg;"cW]˾lh5M m Bq&]bIՃ./%nN7M"=~HFB:% &+oL^Xt$mS\@+ZTCOP2>L[9zb<>V, m HI)ݓ7kVlUQ>=BSwo9UD,L% z4i|cs.*"01;~%]PqDlZQ8 =lo~-PB _ێEQ|ffI"5[@6lSجzjWb<۽u;!"CИQ$8cpk.C#+͙QZcGc3i\/Ryo.pO&/-VZ@H~ ֒=pc;Րx [Մo޹Bѓ+pw:1;у5;.vaxL!js]3oˡJhqJTkevn-Ccڹo|X5 t(Ix'wW/ Dׁ×1_>>}? p64==y!qMȤp{X|IXk$p.mdF&fJ'ٍxeEi#[nWd$LOȞɞ"j:J"9M qI;+VSe I3brkЍ F]^YdzJEZb( \KAFo(:Y38 p J[rnI}MG P UK,ȠL]Kd>JTR4x>,cI:R1>Eu \Ǻur!>(Rrbj5<:M֟6WCIkRYhHQ#9SY."ɌJ;o+K o1)hC`M&#{ tBIKZrܣrڨSsNO< LF6KOz3R9PM.ˎfM u;R0$јWQ?Jv2p2:.wAdt6~K8ցDD~Q, ^3 ӸA$ i+=xB9c @C ` ^k?5`cW01=p<ar̀Caf2 h1d]lؖaAudW(Cޑ`1q@xF X4ϸ_p#IbxQ)39ecRaB}WHuEaw򔧣LIAa$D"qO43 Oꕰɦd962.r>XjkI,)' F]= TG@lMVy"inŧ\+V i YЀfq?،F0禍P3ǁPm /jֲqxg,:&g~WK[ey %|[C nք:[Fm /BinY-_M\,5e˻n>Nc°2ӃilGjy5Hp?0{[`t7r`5__PGsrsMNDp$'q0֓JŨiC>"'smxg ocsigenserver-5.0.1/local/var/www/ocsigenstuff/scalable/text-x-tex.svgz000066400000000000000000000151661417255654100263330ustar00rootroot00000000000000\is#Ǒ_KĢuԌk)pqA3zՍnv&AW]/_fVnէvtΪv9[]͗7?l˫bl?-WgQvmmfӻͼ+lVwU]77n .7Wg]B*^E{.sl>Olu{ZnrQ6gJ%s>Wܘ5r;}b9 5_Waxr2v<:5 ~=kѲm{Yj{5qd9m7wY9˥#$yo>nՇ3也NTcMu;~RuI=j5 ?mۇmP_/_;_oZՍ*]]j狶xqu۞͗Xz]E{~;mwtX=s?pA7)CW5) ǐBj)J7A[ݵAvuN%cφQfhKzZRhͷ:bS=$=DoL6O:r{hjnfkYicsVg O m.gO}z^{F׋vn-w'$i)us97D^szRo?NDZDM{!?DGyDaM0څAR J}2zTZ:}ωN_s7mֶ{?*Q Y7 ޜ5ugWV{8e3ڏ"%P{KjSΌ>߬}{8w+Hf_']}yz8|Mws4G}|`*_asm/7]}X]Nbn š[_'{7Vv/o0vfv>2YP3ݡ_=x+ N{H5̸܍˻]OrI.3:(w/$rU2DFy2Щf^J&&3G&|p_cmʼnQ1Dz7&X65>u::}b0g{~ R~nWt@߾_xYV f{,}n~ %ⵘ|]^U~ nmrvF?s}:ow2fٯ[FoF|o<bzU~jUtuwj;>nq@c;/` ?wZ#"%tfk-3?6 2~*W$$Ye $KUƛ%ĨC"B3bΙ BA9y+!Lq*@R s [{M&dIf腗=&AU6:rҐ`?8/z@'z:GJck Et q4?ɹ- sʆQ[Jǡ$`fpyH3'^CՋpQz^9:8HаiH"ANASWx=`DcgGEw.VXpVaQ&'HR!\[BiIW]qSV7=3Qރ&5($Gc Do!XB Sh*& %;6d:H \NXtgpGmaTtB@.&?>)ɷҜzq4/…$ tN+'5 >ɜ{z=AYlbt17/ðY?y .,Pa:s0@n+SJ@ާ7fiK0k6Б E 2'Z)$  3(hGɳEh=9'ZxWc'y5-v%2DUku@h,Kcj= fM%,19 $P¸د׷O1,aLw`G!#8H=4R/0H vZO ,3/װ{c(JPㆈKYpy+pU~`y0ˀ֡B{ PBI;kqXy=BN9J"2ea1+JBw YeBI8qzG(^gbm::3u5 h\sߗ1v\v՗b.\_vtq^O2勧= 'N4 4D=^h7/ gȸMy/F>O\2•~f'BoP#?3֔TS8/h? =&=#P = / Ip핑Df~c֠@?X$,X,og 3oGV ] i˚a(ubCSѩweI^5j|V0{'j8lw Vۍk H/)"EEeȴehCHr!r9z ݤ\N׍q1h9}[xRP;P@zOMF*@d=6̓xRL)bĕ3ac93Ypfqy0It=bK@a+,#kkc3"fjd"bBKDx-*؀5.2Iia,̓H + %^\>=Łqa7͚Q;ے)r2CYnLJ8us7"|yNJ֡dwl%C%KAQJ  mpEdѨ*_vzGt&L[`] exy#+xxh;쀯r@xRYq 9$Hd1ɮ䥅I y"aa~&$;1r9& 8C40zdqD`sq Vď_m$3*-bBMg[k)Ӕ(6vLʑ|d4Wq\Sӫ`1`! |䎮e5?׷>}MaX^){x]Qw;k^[Ry=ozu.+y~>VzYW˫MmNd\sJ(W}czU !l[Z3`n -ۼTrR_ͺ?O.חfZ-||SnǓzuޖ?M/ *槜p{; J\iȄJIUzkr1ߝ/>+tknu=ϭ`^I齪7Mb.:uaqSNru=/09ޛM| nƳ^v/oNV ~@Պ53 y/[&5OԲyo֋۶n(A}-^\]j,蔭֟gu]NW|`<+t6Bn Rjoe[X{ꫝ~J:vTJpe-ԭV>ۤ?o0܍g}gƟW$waYCXac3qXM5ݪ^?_{W7n>R`Hg R5Dkc:f;|,kgF]9%rBJvT Ui}rsRSGKۣgT { ۢSCRV-3_ջDa@5hGu҂h6Y[|ud0F9 6}"`&#$]nFo4p6d6ÆMoE!mxiˬp?Iw՛ϱze9[~>9oSQv(P~SHFAUV\1)`Z-dQGoUFhUQJoT"j,K֌4("()Y`(B%F-Q GAJ QIgIcQ I^d(^#PIɲ\E*Q642=Јrl0BJ XAWFlPׅz|UжVؗ-;ŏ厤 2a]}aʿ# L?1H7ig/5d-{5κ^nQtX\٣B~UGc/j:n9ȫM ?Nja{ C<X u-SKcu҅uQQҪ掮a+i4=OT!ƇV{d  :WZ{Dt8=qBգ&Tm,|ga_L;h.jvPoO'mn nvQNAGЁP:*MW@Fc "FAxGR \"*P!>-P((DH9O&Z::%2Z(Qk"]͕A;^Wij?Ǡ_8&<N)cn<чS_xλ~[Sn6>aonؿХS8͝=ݽ]Cr<_i3Pt:|d+t ^> o1'yƠ-CL ~DNA{:y/gfie#7= At&@ꗿxK*{FA ZaRjKKP~}}K.8P^W <#!Ohܙo:G8[LjW |ɿ=֌ԗ6?ތv|]'M9g3y~#5z{sflu\ ?_}_.>;S],nR,4*<ȕ${RFGYwyen^[.Ya6\cWnL)[}X|^]w*{|V~i:-7y5!{ԸJG zj>-gكOo֗6M Fѭ^.nsY ZZ;6z:6~6YjiG['=]T' ;[1Eq=7^M}҅l>76s#8uў6vҒy~(%cy^#JXoҐ d/*Λ|h'6w_z=[ܖ4oW?oM!*/+ " 6_73h̓^emewrr3K]Ogg'#it?>v4Z#3˷-ҷ0!T~~gE!I>ےM]wcnpS8mNfC.zg|voƶ55SB0)a L+fb"G6@.LB쥋7YYTKcT! s:2A6Jic;E/>4tdɩfR.O"b-p ,"PD& s^lIR ? -qL.gE^\6GNdq}a $%Sh0HL䎙5IӉ@A=Q^aTJAysZ0 sMP0t#c1M:UYS?>8dÃ%+{<-$`pa]Њ:sAi߉#y"YB3"%rĜx !dv\ؑ?UEbz iē@xhv(tA@5U„1$,,|q `:P.da) sZ9kyCE[qԇPϏ`{ B :4SȑY(  t<?J ,ZX*4V%:M.˂`R`^ 1#}g@Zg/7@iKFz)GaNA%k7d\' FN6D0&`˷I?14 mtH -#LŴNʼnsõHq}tD)Z$ұ4`O!A +BX;蘱'IegDDBPZI"<IĶ2Yr 1KڦUA>[ ۖScn[L7S4}M´eۻ>C0'A 1D<6v7ă&|99sL ȝlV@w~>yO0ʎ?i84M3s`O`Q=@M(2ퟱ\k׫Gs$׾zTnxiex{ƶjQJ!y활뵤ג^K|-p-r{2]KP[y$=D7{H@j|ng~/ܚ}ln?ݼMX oಞ,li%2 V6d̍\Nls^~~R.zb)$e~j}~I֙˻DrCFfܘ錭5ĘvΝ`li<#Ǔ_9O&w7wy91 `4c#G*ƤCe#ugZ$AHC Vxp. 1%Z"ΈI=1*t0)T2)D3;#l\ʃ`%batgT/^%vmZJ{Y:%Ld ɦlak'p #3b_f;< i,^%^ϔ+֊ T^ψCuFc$9q;Ѱd\kb đt+34%0op3dBLG 5PBb6]iM |`iStXj܀ }҉HHd:MApVfti tنpAا<VLyE[u: )]z]^i%m9 G57 Η;\g7=/2ŤɮqOHyf.jcDL{F1B8jH bkgҵ D n,|݆`A d/O19A ]%AI&V#M b??K eՒ*"B tzɷ 5%Diَ:dc2Sp^JŎ%A!y,֐1Ǘ6}RvV@YnJZFۭ*zWk;;W}Sto/_\P):AaOw~?vRޮե{lfО`k>S,.lͮV^Z8W7>Ct=ǭ+^߳!Rt}ҽz^t^W/ݫKy^_OfPazơ~8Tȴ8W/v[VgG 5W~pz_=ܯߙcv8-?ocsigenserver-5.0.1/local/var/www/ocsigenstuff/sound.png000066400000000000000000000016661417255654100234610ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME %2]u6IDAT8˭Mh\U{_f2L;)UkA+$Kt'fQlARRZtUЂ q؍.ąP*&!?qaZҟeBy{\71xp/sP(3< xwi Ƙa{QCiR v&"Z_tM硵NV߅zGqm2]/t᡽ycZ)Ta/;JJTk =9n]7pzHr JI"!ʭ z O}FmpENuyN<>YǥY̧w[׉R*yKpgϢ8p ~Wch`S$IB$ۀEs͢0G.nEZl ܳAH9!hED&b^nREƖ( ]*$;J#{r`jݷ000 SSS5`v}XkZ++\},|H?//7$#LOLHq"q5Ɲ?w.(DJ'ϡrKL/,ՠZ""$qBi2>>n.m =3_`_rPIbc>Ql4 N%Zk'c=:2 ٦ŵ&y H!Ӫ -F7n>sssSwүlMAHReN*kchNqVIENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/source_c.png000066400000000000000000000020221417255654100241160ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME .-=IDAT8˭ked&&nb"E* BY1me.59]d(O"cZ777(֯H",FѯxoˆEahrG93}zX_=OTa2iNe&x4R<Xl v@,V#Jq5v<* CCCt:xu7# *Z <Fi˓Ǚկ|c "!v?CFaS$'b-1`,]1L S?G|]ANNucR4 ֳpŽS~N1h܂"B,3Ţ]᪪qrxWAmi+0E( KoQ8|۾'EҰ8yʏ^@E)E$$K/gK7oXk7o/~.XoXӍfSr]!±cp] gx1[6EX:QDkst|轨Ѝn-c-$Az'jsJW lJB*" C8}Dal8].K]?/hQ1$acczT*OKKwϟ/_e^E ?0e !Zk>@JIeXkG9kyR+i1={2Z4M{c 45q.s$KPu]Rgahh8vH&"Km= xcA!$Ƙ]ϕ%fceǁ~.\6#"CϥQ)By_"mmd!ѣ=8lP>wޥ\~RbƣQXb1Q" CrY)^s%RJ3MUǫk!5 QI؈%MSrRdH}BXq$Ipp .BR 8BIIf :ZgdA݌؅:0w \*jgP\.>yyG^,hjmݻ]z ycccaÔejI1$Ic}'g>^TwvH>FGGIz2ZhpwfFߘγֲF.#jK {{Q:׮^%L|cjjZkZ[VkmZ8nfV*vnv޹sQdu+>>xŠ4MOcedl67GG}v͛/3MaM;== \{8}Q}p|Kˀ7 8IENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/source_pl.png000066400000000000000000000021311417255654100243100ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME )0gaIDAT8˭KlTU9jL;EjZBR!m0`$!D1`kܸ2lFta4AF6.jb@(}Ѣ-mLsE@im_rsι|Fi>i4oL!m0K4mSSWG@1gS ZsRZ,Bu~(1|:Bb1,u]lFJI8Wp$BY,F(B` @HI(y)P YJECaZW/ݷ151D x)g/@ 0,@ k[ѧe|2_$i}Wgf$c#:?7 Îe|x[ėDX,D`W0++b]y _}Áq{6RopW\qW".taT([j)*i,6M󒾼wy\&_8 3 sh6VU"敪Z˫XtZiJϽ"PĠvo;2 YUZ0YF\Ղm~\mLMw@`Ceߥm^Ͷ{Al;~=Tݚ j]+R h}+N)L[EJJ!J6xVhMpܜsQIߌwŔ` vI9W >WtTڈw o3s$(azl(f?c`On#(kQ$*Ce T kkPӟ:' H&!wl照fH6@} 1ظHQ)Dx~4t DN5>a u<S !qp[cHH"n&LIͭx5$qdW z)g lx Q| ԁ|C_; : Dǝ.EDrv{M~.pmC+G0q`?<-Ƶ_v[BBkME.~9ui`rCp!F 8`̐9@Et9;6vzS$:= mAl]+ .OLgN[6!D`dʿ¼_!$@ ƙ3-+Wd,JDU1Tm7gZI>aYAb4T… ε/f^m9ʲwsaz'ZqxfvIENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/style.css000066400000000000000000000000001417255654100234520ustar00rootroot00000000000000ocsigenserver-5.0.1/local/var/www/ocsigenstuff/tar.png000066400000000000000000000017771417255654100231220ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME  :oIDAT8˝k\U?)3,61"բUjX.mR[ ׺qJpQMv@1҄4I g&3y=縘I&\}y=P'@[wt޼&MduޛZ:k2Sf*r  Acdz3#bfp `xCF~_0 h[0lNeb,G*Yl,,,dd2dHH{7Tc}6ٌqLeSN'N{[ j=AT"_#㬬yS9HO!ϯ~_"8~;~v˛ĉ'LݙƻC1~=0XI'pk2xUD8qjUPz]>l#EqΓ$!.A|rIQս͉J5Fii`*sR=hꦣVs("Pۡ" sBecco0P_ahKxzWVCÐDQd;{l9jk*P#,J;[ %bu?E0Sξ!"™8!}<8!0 31ZK I‹RcJ"ѹOί6V5~=[ONР3FTf0b1h䙁_}s`[9LJNM27 . vhG4Un*=L$. q=(sq*N#HĜsVVmuef+Wƣ(z]PhroɶT{IENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/tex.png000066400000000000000000000020221417255654100231140ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME 9!IDAT8˝UMHcW^^ .D*L1;7Y uׁ.t1q-hl] fV fA\8'YLKGjIm޻ua|^w1~{eY>]nKC'/3sf(-- '/++J$`@cy 0ߏ!`+!.B)ʭpyys@jRK4%߷>xb@ͼM[A6pBk.j/򐚆ai (Ȳ WMǶmҒF&./PSS R-"0 v}15>hr?`JfN>yf#a ŐB)u`MWt8ŏGsU),?RǬǍFt B!sֻソ+ 0-r(qa}r {8qgg'mGQ?l|M_dItuǘ\=]x8Mo_:kɁkkkE:t]#мv 8Lo]uxwXM<9gQP߻xJ ,[U4/G2ebfL|u1k,v\V@*Nh9=_-me aRq\Q"\|6lE@4bh MJed?cH|b=qLF;Ca&)ñLB!zO DjVO)U?+6etE#t_¶'dt@|ҥ=y֭úvpI!$+Ô _NuQ@1 3!HcכVZFc*Jp=OwR^ZD¤qv.\c۶H%ooBOWdLϾ=D<GWyXE,ÙgQO:=|Ŋa8kF[ǶI8Mk[[ʦ{BՍc;H]wljZ4FS*Lh4ZZZ~fP2Ly n~]7#&9IENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/txt.png000066400000000000000000000017561417255654100231500ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME 3 ڷnIDAT8˭K#gǿ3IM`hcAFœ'7xARIq.}ϣ\B o}ѹLƊw*VT@ӍJP8 ˲ !iVPSQ044tⱱ1$I_J)Kr!DVu(&IǶo: Hu7tBb1$ D"r9yaii AܷhWE&IuVxǓa<;;c*ǂa0Jyzz続kDX.yU.qfMaՅ\YYA4E"WOv w~l6 u{PqX$p}}|-('''J*^mB0Nscc<::&I !nuOoޘivX pxxZaT*躎d2 p]R LWS~H^j )%B!\\\X,"CQX_wvY[MI68T=;>pmm2{Ƕ:EUqyy\X ߿|9 ǜWM0 .//yzbM>,뻆RK~ #bW(83IENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/unknown.png000066400000000000000000000015641417255654100240250ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs cytIME )FjIDAT8˭jGgfeI諩 In}SH|р B_!R\|!_0ŮJ.bYfW;szbGNK,38t} X{8u h kI)EQPh4 (!TQUڝΊQ<9*f8簕 LDZ1baeF#>yBc l6(b7Wj F#ScDls3h4{TpInAjJ~嵈 -vvv^ ]}#"5,ωD"!l NfET,Yda2g(!Ps<} k)96IB`psßWW}{Ky"hݯxKUC̜;{ݻ/^|R2ٵ<(P MS7Yrζz!{l2!2<'s蝟+50'i&ϓ߼9~TZj*F"ωG49v>UNhoJ1NL&$9_=oΎ۠4c=99~PbQWRXzpIENDB`ocsigenserver-5.0.1/local/var/www/ocsigenstuff/video.png000066400000000000000000000023041417255654100234250ustar00rootroot00000000000000PNG  IHDRĴl;sRGB pHYs cytIME@bKGDDIDATxڥkL[elj>\X (-Җ:F[JKK[`D 7;af@2,lc5.qfLL&$Pe} .N]˦o{swy[f;pu53M!'+΄K?a<3E%a4wuqCt6}f`uww 6 MM-; 'OcJgg TB1?@X,.ĝ>4F贶cMr EbqFM J^+(r5b$4ˡTjP&M 0X!7 SÁ#0۬b.h!:T?A707#pfX@CnF1>@o/A;C%P LU\E{{~%l1-PD2?!)4X&SCb)褵ڵ Pk <C"P9 r$E`摑sf19PDm +R hm뛡V)P,lZTUU}G2a4-2T,.޹PTC$A~HH` 6LfogL$yH2νޫ;%|iTW#=]7XwС`~g >j5ѣ0ڑ.Rdca~w.IDDKшdq38^{hj_5Ͽ^8]8Z݈ xxhpDD4A&7x6I)S&q9"i`%ŸUl0GTTlhpL>TT8QPPMNR*Ut:q;86R8)"%$QP`   o6BaIENDB`ocsigenserver-5.0.1/ocsigenserver.opam000066400000000000000000000035551417255654100201510ustar00rootroot00000000000000opam-version: "2.0" name: "ocsigenserver" version: "5.0.1" maintainer: "dev@ocsigen.org" synopsis: "A full-featured and extensible Web server" description: "Ocsigen Server implements most features of the HTTP protocol, and has a very powerful extension mechanism that makes it very easy to plug your own OCaml modules for generating pages. Many extensions are already implemented, like a reverse proxy, content compression, access control, authentication, etc." authors: "dev@ocsigen.org" homepage: "http://ocsigen.org/ocsigenserver/" bug-reports: "https://github.com/ocsigen/ocsigenserver/issues/" license: "LGPL-2.1-only WITH OCaml-LGPL-linking-exception" dev-repo: "git+https://github.com/ocsigen/ocsigenserver.git" build: [ [ "sh" "configure" "--prefix" "%{prefix}%" "--ocsigen-user" "%{user}%" "--ocsigen-group" "%{group}%" "--commandpipe" "%{lib}%/ocsigenserver/var/run/ocsigenserver_command" "--logdir" "%{lib}%/ocsigenserver/var/log/ocsigenserver" "--mandir" "%{man}%/man1" "--docdir" "%{lib}%/ocsigenserver/share/doc/ocsigenserver" "--commandpipe" "%{lib}%/ocsigenserver/var/run/ocsigenserver_command" "--staticpagesdir" "%{lib}%/ocsigenserver/var/www" "--datadir" "%{lib}%/ocsigenserver/var/lib/ocsigenserver" "--temproot" "" "--sysconfdir" "%{lib}%/ocsigenserver/etc/ocsigenserver" ] [make "-C" "src" "confs"] ["dune" "build" "-p" name "-j" jobs] ] install:[make "install.files"] depends: [ "ocaml" {>= "4.08.1"} "dune" {>= "2.7"} "ocamlfind" "base-unix" "base-threads" "react" "ssl" {>= "0.5.8"} "lwt" {>= "3.0.0"} "lwt_ssl" "lwt_react" "lwt_log" "pcre" "cryptokit" "ipaddr" {>= "2.1"} "cohttp-lwt-unix" {< "5.0.0"} "conduit-lwt-unix" {>= "2.0.0"} "hmap" "xml-light" "camlzip" ] conflicts: [ "camlzip" {< "1.04"} "pgocaml" {< "2.2"} ] ocsigenserver-5.0.1/src/000077500000000000000000000000001417255654100151745ustar00rootroot00000000000000ocsigenserver-5.0.1/src/Makefile000066400000000000000000000045111417255654100166350ustar00rootroot00000000000000include ../Makefile.config all: confs dune build @all ### CONF #### confs: ../ocsigenserver.conf.sample ../local/etc/ocsigenserver.conf ${MAKE} -C baselib confs ../ocsigenserver.conf.sample: files/ocsigenserver.conf.in ../Makefile.config Makefile cat $< \ | sed s%_LOGDIR_%$(LOGDIR)%g \ | sed s%_DATADIR_%$(DATADIR)%g \ | sed s%_OCSIGENUSER_%$(OCSIGENUSER)%g \ | sed s%_OCSIGENGROUP_%"$(OCSIGENGROUP)"%g \ | sed s%_COMMANDPIPE_%$(COMMANDPIPE)%g \ | sed s%_MIMEFILE_%$(CONFIGDIR)/mime.types%g \ | sed s%_METADIR_%$(LIBDIR)%g \ | sed s%_LIBDIR_%$(LIBDIR)%g \ | sed s%_EXTDIR_%$(LIBDIR)/ocsigenserver/extensions%g \ | sed s%_CONFIGDIR_%$(CONFIGDIR)%g \ | sed s%_STATICPAGESDIR_%$(STATICPAGESDIR)%g \ | sed s%_EXTPACKAGENAME_%ocsigenserver.ext%g \ > $@ ../local/etc/ocsigenserver.conf: files/ocsigenserver.conf.in ../Makefile.config Makefile mkdir -p ../local/etc ../local/var/log ../local/var/run cat $< \ | sed s%80\%8080\%g \ | sed s%_LOGDIR_%$(SRC)/local/var/log%g \ | sed s%_DATADIR_%$(SRC)/local/var/lib%g \ | sed s%\_OCSIGENUSER_\%%g \ | sed s%\_OCSIGENGROUP_\%%g \ | sed s%_COMMANDPIPE_%$(SRC)/local/var/run/ocsigenserver_command%g \ | sed s%_MIMEFILE_%$(SRC)/src/files/mime.types%g \ | sed s%_METADIR_%${LIBDIR}\"/\>\\\ --\>%\%g \ | sed s%\<\!--\ \\ --\>%\%g \ > $@ ### clean: clean.local ${MAKE} -C baselib clean dune clean clean.local: -rm -f ../ocsigenserver.conf.sample -rm -f ../ocsigenserver.conf.opt.sample -rm -f ../ocsigenserver.conf.local -rm -f ../ocsigenserver.conf.opt.local distclean: clean.local ${MAKE} -C baselib distclean ${MAKE} -C http distclean ${MAKE} -C server distclean ${MAKE} -C extensions distclean -rm -f *~ \#* .\#* -cd files; rm -f *~ \#* .\#* -rm -fr ../local/var/log/*.log -rm -fr ../local/var/lib/ocsidb -rm -fr ../local/etc/ocsigenserver.conf -rm -fr ../local/etc/ocsigenserver.conf.opt ocsigenserver-5.0.1/src/baselib/000077500000000000000000000000001417255654100165755ustar00rootroot00000000000000ocsigenserver-5.0.1/src/baselib/Makefile000066400000000000000000000021501417255654100202330ustar00rootroot00000000000000include ../../Makefile.config .PHONY: default default: build .PHONY: build build: confs dune build .PHONY: confs confs: ocsigen_config_static.ml ## Ocsigen_config ## VERSION := $(shell head -n 1 ../../VERSION) ocsigen_config_static.ml: ocsigen_config_static.ml.in ../../Makefile.config ../../Makefile.options ../../VERSION cat ocsigen_config_static.ml.in \ | sed s%_VERSION_%${VERSION}% \ | sed s%_WARNING_%"Warning: this file has been generated from ocsigen_config_static.ml.in - DO NOT MODIFY MANUALLY!"% \ | sed s%_LOGDIR_%$(LOGDIR)% \ | sed s%_DATADIR_%$(DATADIR)%g \ | sed s%_BINDIR_%$(BINDIR)%g \ | sed s%_EXTDIR_%$(LIBDIR)/ocsigenserver/extensions%g \ | sed s%_STATICPAGESDIR_%$(STATICPAGESDIR)% \ | sed s%_UP_%$(UPLOADDIR)%g \ | sed s%_OCSIGENUSER_%$(OCSIGENUSER)%g \ | sed s%_OCSIGENGROUP_%"$(OCSIGENGROUP)"%g \ | sed s%_COMMANDPIPE_%$(COMMANDPIPE)%g \ | sed s%_CONFIGDIR_%$(CONFIGDIR)% \ | sed s%_ISNATIVE_%$(NATIVECODE_RUNTIME_DETECT)%g \ | sed "s%_DEPS_%$(INITPACKAGE)%g" \ > ocsigen_config_static.ml ## Clean up clean: -rm -f ocsigen_config_static.ml distclean: clean -rm -f *~ \#* .\#* ocsigenserver-5.0.1/src/baselib/commandline/000077500000000000000000000000001417255654100210635ustar00rootroot00000000000000ocsigenserver-5.0.1/src/baselib/commandline/ocsigen_getcommandline.mli000066400000000000000000000002111417255654100262550ustar00rootroot00000000000000(** Contains the command line that will be parsed by the server when Ocsigen_commandline is linked *) val commandline : string array ocsigenserver-5.0.1/src/baselib/dune000066400000000000000000000011621417255654100174530ustar00rootroot00000000000000(library (name ocsigen_lib_base) (public_name ocsigenserver.baselib.base) (flags (:standard -no-keep-locs)) (modules ocsigen_lib_base) (libraries lwt)) (library (name baselib) (public_name ocsigenserver.baselib) (wrapped false) (flags (:standard -no-keep-locs)) (modules dynlink_wrapper ocsigen_cache ocsigen_config_static ocsigen_lib ocsigen_loader ocsigen_stream) (libraries str findlib lwt_log lwt.unix cryptokit pcre ocsigen_lib_base (select dynlink_wrapper.ml from (dynlink -> dynlink_wrapper.natdynlink.ml) (_ -> dynlink_wrapper.nonatdynlink.ml)))) ocsigenserver-5.0.1/src/baselib/dynlink_wrapper.natdynlink.ml000066400000000000000000000020631417255654100245120ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * File dynlink_wrapper.ml * Copyright (C) 2008 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) open Dynlink exception Error = Dynlink.Error let loadfile = loadfile let error_message = error_message let allow_unsafe_modules = allow_unsafe_modules let prohibit = prohibit let is_native = is_native ocsigenserver-5.0.1/src/baselib/dynlink_wrapper.nonatdynlink.ml000066400000000000000000000021501417255654100250440ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * File dynlink_wrapper.ml * Copyright (C) 2008 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) exception Error of string let message = "ocsigen compiled without native dynlink support" let loadfile _ = failwith message let error_message _ = failwith message let init _ = () let allow_unsafe_modules _ = () let prohibit _ = () let is_native = false ocsigenserver-5.0.1/src/baselib/nocommandline/000077500000000000000000000000001417255654100214205ustar00rootroot00000000000000ocsigenserver-5.0.1/src/baselib/nocommandline/ocsigen_getcommandline.mli000066400000000000000000000002111417255654100266120ustar00rootroot00000000000000(** Contains the command line that will be parsed by the server when Ocsigen_commandline is linked *) val commandline : string array ocsigenserver-5.0.1/src/baselib/ocsigen_cache.ml000066400000000000000000000400111417255654100216750ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2009 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** Cache. @author Vincent Balat @author Raphaël Proust (adding timers) *) let (>>=) = Lwt.bind module Dlist : sig type 'a t type 'a node val create : ?timer:float -> int -> 'a t val add : 'a -> 'a t -> 'a option val newest : 'a t -> 'a node option val oldest : 'a t -> 'a node option (** Removes an element from its list. If the element is not in a list, it does nothing. If it is in a list, it calls the finaliser, then removes the element. If the finaliser fails with an exception, the element is removed and the exception is raised again. *) val remove : 'a node -> unit (** Removes the element from its list without finalising, then adds it as newest. *) val up : 'a node -> unit val size : 'a t -> int val maxsize : 'a t -> int (** returns the timer of the Dlist *) val get_timer : 'a t -> float option val value : 'a node -> 'a val list_of : 'a node -> 'a t option (** remove the n oldest values ; returns the list of removed values *) val remove_n_oldest : 'a t -> int -> 'a list (** fold over the elements from the cache starting from the newest to the oldest *) val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b (** fold over the elements from the cache starting from the oldest to the newest *) val fold_back : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b (** lwt version of fold *) val lwt_fold : ('b -> 'a -> 'b Lwt.t) -> 'b -> 'a t -> 'b Lwt.t (** lwt version of fold_back *) val lwt_fold_back : ('b -> 'a -> 'b Lwt.t) -> 'b -> 'a t -> 'b Lwt.t (** Move a node from one dlist to another one, without finalizing. If one value is removed from the destination list (because its maximum size is reached), it is returned (after finalisation). *) val move : 'a node -> 'a t -> 'a option (** change the maximum size ; returns the list of removed values, if any. *) val set_maxsize : 'a t -> int -> 'a list (** record a function to be called automatically on a piece of data just before it disappears from the list (either by explicit removal or because the maximum size is exceeded) *) val add_finaliser_before : ('a node -> unit) -> 'a t -> unit (** replace all finalizers by a new one. Be very careful while using this. *) val set_finaliser_before : ('a node -> unit) -> 'a t -> unit (** returns the finalizers. *) val get_finaliser_before : 'a t -> ('a node -> unit) (** record a function to be called automatically on a piece of data just after it disappears from the list (either by explicit removal or because the maximum size is exceeded) *) val add_finaliser_after : ('a node -> unit) -> 'a t -> unit (** replace all finalizers by a new one. Be very careful while using this. *) val set_finaliser_after : ('a node -> unit) -> 'a t -> unit (** returns the finalizers. *) val get_finaliser_after : 'a t -> ('a node -> unit) end = struct type 'a node = { mutable value : 'a; mutable succ : 'a node option; (* the node added just after *) mutable prev : 'a node option; (* the node added just before *) mutable mylist : 'a t option; (* the list to which it belongs *) mutable collection : float option; (* the timestamp for removal *) } (* Doubly-linked list with maximum size. The field [oldest] is the first element that must be removed if the list becomes too long. *) and 'a t = {mutable newest : 'a node option (* None = empty *); mutable oldest : 'a node option; mutable size : int; mutable maxsize : int; mutable finaliser_before : 'a node -> unit; mutable finaliser_after : 'a node -> unit; (* *) time_bound : time_bound option; } and time_bound = { (* *) timer : float; mutable collector : unit Lwt.t option; } (* Checks (by BY): let compute_length c = let rec aux i = function | Some {prev=p} -> aux (i + 1) p | None -> i in aux 0 c.newest let correct_node n = (match n.succ with | None -> true | Some n' -> n'.prev == Some n) && (match n.prev with | None -> true | Some n' -> n'.succ == Some n) (* Check that a list is correct. To be completed 1. by adding a check on nodes, 2. by verifying that newest can be reached from oldest and respectively *) let correct_list l = (l.size <= l.maxsize) && (compute_length l = l.size) && (match l.oldest with | None -> true | Some n -> n.prev = None) && (match l.newest with | None -> true | Some n -> n.succ = None) *) let create ?timer size = {newest = None; oldest = None; size = 0; maxsize = size; finaliser_before = (fun _ -> ()); finaliser_after = (fun _ -> ()); time_bound = (match timer with | None -> None | Some t -> Some {timer = t; collector = None;} ); } (* Remove an element from its list - don't finalise *) let remove' node l = (* assertion (node.mylist = Some l' with l' == l); *) let oldest = match l.oldest with | Some n when node == n -> node.succ | _ -> l.oldest in let newest = match l.newest with | Some n when node == n -> node.prev | _ -> l.newest in (match node.succ with | None -> () | Some s -> s.prev <- node.prev); (match node.prev with | None -> () | Some s -> s.succ <- node.succ); l.oldest <- oldest; l.newest <- newest; node.mylist <- None; l.size <- l.size - 1 (* Remove an element from its list - and finalise *) let remove node = match node.mylist with | None -> () | Some l as a -> (try l.finaliser_before node; assert (node.mylist == a); remove' node l with e -> remove' node l; raise e); l.finaliser_after node (* These next functions are for the collecting thread *) (* computing the timestamp for a node *) let collect_timer = function | {time_bound = Some {timer = t; _}; _ } -> Some (t +. (Unix.gettimeofday ())) | {time_bound = None; _} -> None (* do collect. We first check if the node is still in the list and then if * its collection hasn't been rescheduled ! *) let collect dl n = match n.mylist with | Some l when l == dl -> begin match n.collection with | None -> assert false | Some c -> if c < Unix.gettimeofday () then remove n else () end | None | Some _ -> () let sleep_until = function (*/!\ COOPERATES*) | None -> assert false (* collection is set to None and collector to Some *) | Some t -> let duration = t -. Unix.gettimeofday () in if duration <= 0. then Lwt.return () else Lwt_unix.sleep duration (* a function to set the collector. *) let rec update_collector r = match r.time_bound with | None (* Not time bounded dlist *) | Some {collector = Some _; _} -> () (* Already collecting *) | Some ({collector = None; _} as t) -> match r.oldest with | None -> () (* Empty dlist *) | Some n -> t.collector <- Some (sleep_until n.collection >>= fun () -> collect r n; t.collector <- None; update_collector r; Lwt.return () ) (* Add a node that do not belong to any list to a list. The fields [succ] and [prev] are overridden. If the list is too long, the function returns the oldest value. The node added becomes the element [list] of the list *) (* do not finalise *) (* not exported *) let add_node node r = assert (node.mylist = None); node.mylist <- Some r; let res = match r.newest with | None -> node.succ <- None; node.prev <- None; r.newest <- Some node; r.oldest <- r.newest; r.size <- 1; None | Some rl -> node.succ <- None; node.prev <- r.newest; rl.succ <- Some node; r.newest <- Some node; r.size <- r.size + 1; if r.size > r.maxsize then r.oldest else None in node.collection <- collect_timer r; update_collector r; res let add x l = let create_one a = { value = a; succ = None; prev = None; mylist = None; collection = None; } in (* create_one not exported *) match add_node (create_one x) l with | None -> None | Some v -> remove v; Some v.value let newest a = a.newest let oldest a = a.oldest let size c = c.size let maxsize c = c.maxsize let get_timer c = match c.time_bound with | None -> None | Some tb -> Some tb.timer let value n = n.value let list_of n = n.mylist let up node = match node.mylist with | None -> () | Some l -> match l.newest with | Some n when node == n -> () | _ -> remove' node l; ignore (add_node node l) (* assertion: = None *) (* we must not change the physical address => use add_node *) let rec remove_n_oldest l n = (* remove the n oldest values (or less if the list is not long enough) ; returns the list of removed values *) if n <= 0 then [] else match l.oldest with | None -> [] | Some node -> let v = node.value in remove node; (* and finalise! *) v::remove_n_oldest l (n-1) (* Move a node from one dlist to another one, without finalizing *) let move node l = (match node.mylist with | None -> () | Some l -> remove' node l); match add_node node l with | None -> None | Some v -> remove v; Some v.value (* fold over the elements from the newest to the oldest *) let lwt_fold f accu {newest; _} = match newest with | None -> Lwt.return accu | Some newest -> let rec fold accu node = f accu node.value >>= fun accu -> match node.prev with | None -> Lwt.return accu | Some new_node when new_node == newest -> Lwt.return accu | Some new_node -> fold accu new_node in fold accu newest (* fold over the elements from the oldest to the newest *) let lwt_fold_back f accu {oldest; _} = match oldest with | None -> Lwt.return accu | Some oldest -> let rec fold accu node = f accu node.value >>= fun accu -> match node.succ with | None -> Lwt.return accu | Some new_node when new_node == oldest -> Lwt.return accu | Some new_node -> fold accu new_node in fold accu oldest (* fold over the elements from the newest to the oldest *) let fold f accu {newest; _} = match newest with | None -> accu | Some newest -> let rec fold accu node = let accu = f accu node.value in match node.prev with | None -> accu | Some new_node when new_node == newest -> accu | Some new_node -> fold accu new_node in fold accu newest (* fold over the elements from the oldest to the newest *) let fold_back f accu {oldest; _} = match oldest with | None -> accu | Some oldest -> let rec fold accu node = let accu = f accu node.value in match node.succ with | None -> accu | Some new_node when new_node == oldest -> accu | Some new_node -> fold accu new_node in fold accu oldest let set_maxsize l m = let size = l.size in if m >= size then (l.maxsize <- m; []) else if m <= 0 then failwith "Dlist.set_maxsize" else let ll = remove_n_oldest l (size - m) in l.maxsize <- m; ll let set_finaliser_before f l = l.finaliser_before <- f let get_finaliser_before l = l.finaliser_before let add_finaliser_before f l = let oldf = l.finaliser_before in l.finaliser_before <- (fun n -> oldf n; f n) let set_finaliser_after f l = l.finaliser_after <- f let get_finaliser_after l = l.finaliser_after let add_finaliser_after f l = let oldf = l.finaliser_after in l.finaliser_after <- (fun n -> oldf n; f n) end module Weak = Weak.Make(struct type t = unit -> unit let hash = Hashtbl.hash let equal = (==) end) let clear_all = Weak.create 17 module Make = functor (A: sig type key type value end) -> struct module H = Hashtbl.Make( struct type t = A.key let equal a a' = a = a' let hash = Hashtbl.hash end) type t = { mutable pointers : A.key Dlist.t; mutable table : (A.value * A.key Dlist.node) H.t; finder : A.key -> A.value Lwt.t; clear: unit -> unit (* This function clears the cache. It is put inside the cache structure so that it is garbage-collected only when the cache is no longer referenced, as the functions themselves are put inside a weak hash table *) } let mk ?timer size = let (l, t) as a = (Dlist.create ?timer size, H.create size) in Dlist.set_finaliser_after (fun n -> H.remove t (Dlist.value n)) l; a let rec create f ?timer size = let rec cache = let (l, t) = mk ?timer size in {pointers = l; table = t; finder = f; clear = f_clear; } and f_clear = (fun () -> clear cache) in Weak.add clear_all f_clear; cache and clear cache = let size = Dlist.maxsize cache.pointers in let timer = Dlist.get_timer cache.pointers in let (l, t) = mk ?timer size in cache.pointers <- l; cache.table <- t (* not exported *) let poke cache node = assert (match Dlist.list_of node with | None -> false | Some l -> cache.pointers == l); Dlist.up node let find_in_cache cache k = let (v, node) = H.find cache.table k in poke cache node; v let remove cache k = try let (_v, node) = H.find cache.table k in assert (match Dlist.list_of node with | None -> false | Some l -> cache.pointers == l); Dlist.remove node with Not_found -> () (* Add in a cache, under the hypothesis that the value is not already in the cache *) let add_no_remove cache k v = ignore (Dlist.add k cache.pointers); match Dlist.newest cache.pointers with | None -> assert false | Some n -> H.add cache.table k (v, n) let add cache k v = remove cache k; add_no_remove cache k v let size c = Dlist.size c.pointers let find cache k = (try Lwt.return (find_in_cache cache k) with Not_found -> cache.finder k >>= fun r -> (try (* it may have been added during cache.finder *) ignore (find_in_cache cache k) with Not_found -> add_no_remove cache k r); Lwt.return r) class cache f ?timer size_c = let c = create f ?timer size_c in object method clear () = clear c method find = find c method add = add c method size = size c method find_in_cache = find_in_cache c method remove = remove c end end let clear_all_caches () = Weak.iter (fun f -> f ()) clear_all ocsigenserver-5.0.1/src/baselib/ocsigen_cache.mli000066400000000000000000000137321417255654100220600ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2009 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** Cache. Association tables (from any kind of database) that keep the most recently used values in memory. It is also possible to set a maximum lifetime for data in the cache. It is based on a structure of doubly linked lists with maximum size, that keeps only the mostly recently used values first, if you call the [up] function each time you use a value. (Insertion, remove and "up" in time 1). This structure is exported, so that it can be used in other cases. Not (preemptive) thread safe. @author Vincent Balat @author Raphaël Proust (adding timers) *) module Make : functor (A : sig type key type value end) -> sig (** [new cache finder ?timer size] creates a cache object where [finder] is the function responsible for retrieving non-cached data, [timer] (if any) is the life span of cached values (in seconds) (values in the cache are removed after their time is up) and [size] is the upper bound to the number of simultaneoulsy cached elements. Whenever a value is found (using [find] method), it's lifespan is set to [timer] (or not if the cache is not time bounded). If the value was already cached, it's lifespan is reset to [timer]. Using [timer] allow one to create a cache bounded both in space and time. It is to be noted that real lifespan of values is always slightly greater than [timer]. *) class cache : (A.key -> A.value Lwt.t) -> ?timer:float -> int -> object (** Find the cached value associated to the key, or binds this value in the cache using the function [finder] passed as argument to [create], and returns this value *) method find : A.key -> A.value Lwt.t (** Find the cached value associated to the key. Raises [Not_found] if the key is not present in the cache *) method find_in_cache : A.key -> A.value method remove : A.key -> unit method add : A.key -> A.value -> unit method clear : unit -> unit method size : int end end (** Clear the contents of all the existing caches *) val clear_all_caches : unit -> unit (** Doubly-linked lists with maximum number of entries, and (possibly) limited lifespan for entries. *) module Dlist : sig type 'a t type 'a node (** Create a dlist. It takes the maximum length of the list as parameter. The optional [?timer] parameter sets a maximum lifetime for elements (in seconds). *) val create : ?timer:float -> int -> 'a t (** Adds an element to the list, and possibly returns the element that has been removed if the maximum size was exceeded. *) val add : 'a -> 'a t -> 'a option (** Removes an element from its list. If it is not in a list, it does nothing. If it is in a list, it calls the finaliser, then removes the element. If the finaliser fails with an exception, the element is removed and the exception is raised again. *) val remove : 'a node -> unit (** Removes the element from its list without finalising, then adds it as newest. *) val up : 'a node -> unit val newest : 'a t -> 'a node option val oldest : 'a t -> 'a node option val size : 'a t -> int val maxsize : 'a t -> int val value : 'a node -> 'a (** returns the timer of the Dlist *) val get_timer : 'a t -> float option (** The list to which the node belongs *) val list_of : 'a node -> 'a t option (** remove the n oldest values (or less if the list is not long enough) ; returns the list of removed values *) val remove_n_oldest : 'a t -> int -> 'a list (** fold over the elements from the cache starting from the newest to the oldest *) val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b (** fold over the elements from the cache starting from the oldest to the newest *) val fold_back : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b (** lwt version of fold *) val lwt_fold : ('b -> 'a -> 'b Lwt.t) -> 'b -> 'a t -> 'b Lwt.t (** lwt version of fold_back *) val lwt_fold_back : ('b -> 'a -> 'b Lwt.t) -> 'b -> 'a t -> 'b Lwt.t (** Move a node from one dlist to another one, without finalizing. If one value is removed from the destination list (because its maximum size is reached), it is returned (after finalisation). *) val move : 'a node -> 'a t -> 'a option (** change the maximum size ; returns the list of removed values, if any. *) val set_maxsize : 'a t -> int -> 'a list (** set a function to be called automatically on a piece of data just before it disappears from the list (either by explicit removal or because the maximum size is exceeded) *) val set_finaliser_before : ('a node -> unit) -> 'a t -> unit val get_finaliser_before : 'a t -> ('a node -> unit) val add_finaliser_before : ('a node -> unit) -> 'a t -> unit (** set a function to be called automatically on a piece of data just after it disappears from the list (either by explicit removal or because the maximum size is exceeded) *) val set_finaliser_after : ('a node -> unit) -> 'a t -> unit val get_finaliser_after : 'a t -> ('a node -> unit) val add_finaliser_after : ('a node -> unit) -> 'a t -> unit end ocsigenserver-5.0.1/src/baselib/ocsigen_config_static.ml.in000066400000000000000000000027321417255654100240630ustar00rootroot00000000000000(* Warning! ocsigen_config_static.ml is generated automatically from ocsigen_config_static.ml.in! Do not modify it manually *) (* Ocsigen * Copyright (C) 2005 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) let version_number = "_VERSION_" let config_file = ref "_CONFIGDIR_/ocsigenserver.conf" let is_native = Sys.backend_type = Sys.Native let logdir = ref (Some "_LOGDIR_") let default_user = ref "_OCSIGENUSER_" let default_group = ref "_OCSIGENGROUP_" let mimefile = ref "_CONFIGDIR_/mime.types" let datadir = ref "_DATADIR_" let bindir = ref "_BINDIR_" let extdir = ref "_EXTDIR_" let command_pipe = ref "_COMMANDPIPE_" let builtin_packages = List.fold_left (fun a s -> Ocsigen_lib.String.Set.add s a) Ocsigen_lib.String.Set.empty [_DEPS_] ocsigenserver-5.0.1/src/baselib/ocsigen_config_static.mli000066400000000000000000000005331417255654100236240ustar00rootroot00000000000000val version_number : string val config_file : string ref val is_native : bool val logdir : string option ref val default_user : string ref val default_group : string ref val mimefile : string ref val datadir : string ref val bindir : string ref val extdir : string ref val command_pipe : string ref val builtin_packages : Ocsigen_lib.String.Set.t ocsigenserver-5.0.1/src/baselib/ocsigen_lib.ml000066400000000000000000000376221417255654100214160ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2005 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) include Ocsigen_lib_base module String = String_base (*****************************************************************************) module Ip_address = struct exception No_such_host let get_inet_addr ?(v6=false) host = let rec aux = function | [] -> Lwt.fail No_such_host | {Unix.ai_addr=Unix.ADDR_INET (inet_addr, _); _}::_ -> Lwt.return inet_addr | _::l -> aux l in let options = [if v6 then Lwt_unix.AI_FAMILY Lwt_unix.PF_INET6 else Lwt_unix.AI_FAMILY Lwt_unix.PF_INET] in Lwt.bind (Lwt_unix.getaddrinfo host "" options) aux let of_sockaddr = function | Unix.ADDR_INET (ip, _port) -> ip | _ -> raise (Ocsigen_Internal_Error "ip of unix socket") end (*****************************************************************************) module Filename = struct include Filename let basename f = let n = String.length f in let i = try String.rindex f '\\' + 1 with Not_found -> 0 in let j = try String.rindex f '/' + 1 with Not_found -> 0 in let k = max i j in if k < n then String.sub f k (n-k) else "none" let extension_no_directory filename = try let pos = String.rindex filename '.' in String.sub filename (pos+1) ((String.length filename) - pos - 1) with Not_found -> raise Not_found let extension filename = try let pos = String.rindex filename '.' and slash = try String.rindex filename '/' with Not_found -> -1 in if pos > slash then String.sub filename (pos+1) ((String.length filename) - pos - 1) else (* Dot before a directory separator *) raise Not_found with Not_found -> (* No dot in filename *) raise Not_found end (*****************************************************************************) let make_cryptographic_safe_string = let rng = Cryptokit.Random.device_rng "/dev/urandom" in fun () -> let random_part = let random_number = Cryptokit.Random.string rng 20 in let to_b64 = Cryptokit.Base64.encode_compact () in Cryptokit.transform_string to_b64 random_number and sequential_part = (*VVV Use base 64 also here *) Printf.sprintf "%Lx" (Int64.bits_of_float (Unix.gettimeofday ())) in random_part ^ sequential_part (* The string is produced from the concatenation of two components: a 160-bit random sequence obtained from /dev/urandom, and a 64-bit sequential component derived from the system clock. The former is supposed to prevent session spoofing. The assumption is that given the high cryptographic quality of /dev/urandom, it is impossible for an attacker to deduce the sequence of random numbers produced. As for the latter component, it exists to prevent a theoretical (though infinitesimally unlikely) session ID collision if the server were to be restarted. *) module Netstring_pcre = struct let regexp s = Pcre.regexp ~flags:[`MULTILINE] s let templ_re = Pcre.regexp "(?:\\\\\\d)|[\\$\\\\]" ;; let tr_templ s = (* Convert \n to $n etc. *) (* Unfortunately we cannot just replace \ by $. *) let rec tr l = match l with Pcre.Delim "$" :: l' -> "$$" :: tr l' | Pcre.Delim "\\" :: Pcre.Delim "$" :: l' -> "$$" :: tr l' | Pcre.Delim "\\" :: Pcre.Delim s :: l' -> s :: tr l' | Pcre.Delim "\\" :: Pcre.Text s :: l' -> s :: tr l' | [ Pcre.Delim "\\" ] -> failwith "trailing backslash" | Pcre.Delim d :: l' -> assert(d.[0] = '\\'); let n = Char.code d.[1] - Char.code '0' in if n = 0 then "$&" :: tr l' else ("$" ^ string_of_int n ^ "$!") :: tr l' | Pcre.Text t :: l' -> t :: tr l' | Pcre.Group(_,_) :: _ -> assert false | Pcre.NoGroup :: _ -> assert false | [] -> [] in let l = Pcre.full_split ~rex:templ_re ~max:(-1) s in String.concat "" (tr l) let matched_group result n _ = if n < 0 || n >= Pcre.num_of_subs result then raise Not_found; ignore (Pcre.get_substring_ofs result n); Pcre.get_substring result n let matched_string result _ = ignore (Pcre.get_substring_ofs result 0); Pcre.get_substring result 0 let global_replace pat templ s = Pcre.replace ~rex:pat ~itempl:(Pcre.subst (tr_templ templ)) s let global_substitute pat subst s = Pcre.substitute_substrings ~rex:pat ~subst:(fun r -> subst r s) s let search_forward pat s pos = let result = Pcre.exec ~rex:pat ~pos s in fst (Pcre.get_substring_ofs result 0), result let string_after s n = String.sub s n (String.length s - n) let bounded_split expr text num = let start = try let start_substrs = Pcre.exec ~rex:expr ~flags:[`ANCHORED] text in (* or Not_found *) let (_,match_end) = Pcre.get_substring_ofs start_substrs 0 in match_end with Not_found -> 0 in let rec split start n = if start >= String.length text then [] else if n = 1 then [string_after text start] else try let next_substrs = Pcre.exec ~rex:expr ~pos:start text in (* or Not_found *) let pos, match_end = Pcre.get_substring_ofs next_substrs 0 in String.sub text start (pos-start) :: split match_end (n-1) with Not_found -> [string_after text start] in split start num let split sep s = bounded_split sep s 0 let string_match pat s pos = try let result = Pcre.exec ~rex:pat ~flags:[`ANCHORED] ~pos s in Some result with Not_found -> None end module Url = struct include Url_base (* Taken from Neturl version 1.1.2 *) let problem_re1 = Netstring_pcre.regexp "[ <>\"{}|\\\\^\\[\\]`]" let fixup_url_string1 = Netstring_pcre.global_substitute problem_re1 (fun m s -> Printf.sprintf "%%%02x" (Char.code s.[fst (Pcre.get_substring_ofs m 0)])) (* I add this fixup to handle %uxxxx sent by browsers. Translated to %xx%xx *) let problem_re2 = Netstring_pcre.regexp "\\%u(..)(..)" let fixup_url_string s = fixup_url_string1 (Netstring_pcre.global_substitute problem_re2 (fun m s -> String.concat "" ["%"; Netstring_pcre.matched_group m 1 s; "%"; Netstring_pcre.matched_group m 2 s] ) s) (*VVV This is in Netencoding but we have a problem with ~ (not encoded by browsers). Here is a patch that does not encode '~': *) module MyUrl = struct let percent_encode = let lengths = let l = Array.make 256 3 in String.iter (fun c -> l.(Char.code c) <- 1) (* Unreserved Characters (section 2.3 of RFC 3986) *) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~"; l in fun s -> let l = String.length s in let l' = ref 0 in for i = 0 to l - 1 do l' := !l' + lengths.(Char.code s.[i]) done; if l = !l' then s else let s' = Bytes.create !l' in let j = ref 0 in let hex = "0123456789ABCDEF" in for i = 0 to l - 1 do let c = s.[i] in let n = Char.code s.[i] in let d = lengths.(n) in if d = 1 then Bytes.set s' !j c else begin Bytes.set s' !j '%'; Bytes.set s' (!j + 1) hex.[n lsr 4]; Bytes.set s' (!j + 2) hex.[n land 0xf] end; j := !j + d done; Bytes.unsafe_to_string s' let encode_plus = let lengths = let l = Array.make 256 3 in String.iter (fun c -> l.(Char.code c) <- 1) (* Unchanged characters + space (HTML spec) *) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.* "; l in fun s -> let l = String.length s in let l' = ref 0 in for i = 0 to l - 1 do l' := !l' + lengths.(Char.code s.[i]) done; let s' = Bytes.create !l' in let j = ref 0 in let hex = "0123456789ABCDEF" in for i = 0 to l - 1 do let c = s.[i] in let n = Char.code s.[i] in let d = lengths.(n) in if d = 1 then Bytes.set s' !j (if c = ' ' then '+' else c) else begin Bytes.set s' !j '%'; Bytes.set s' (!j + 1) hex.[n lsr 4]; Bytes.set s' (!j + 2) hex.[n land 0xf] end; j := !j + d done; Bytes.unsafe_to_string s' let encode ?(plus = true) s = if plus then encode_plus s else percent_encode s end let url_decoding_re = Netstring_pcre.regexp "\\+\\|%..\\|%.\\|%";; let of_hex1 c = match c with | ('0'..'9') -> Char.code c - Char.code '0' | ('A'..'F') -> Char.code c - Char.code 'A' + 10 | ('a'..'f') -> Char.code c - Char.code 'a' + 10 | _ -> raise Not_found let encode = MyUrl.encode let decode ?(plus = true) s = let pos = 0 and len = None in let s_l = String.length s in let s1 = if pos = 0 && len=None then s else let len = match len with Some n -> n | None -> s_l in String.sub s pos len in let l = String.length s1 in Netstring_pcre.global_substitute url_decoding_re (fun r _ -> match Netstring_pcre.matched_string r s1 with | "+" -> if plus then " " else "+" | _ -> let i = fst (Pcre.get_substring_ofs r 0) in (* Assertion: s1.[i] = '%' *) if i+2 >= l then failwith "decode"; let c1 = s1.[i+1] in let c2 = s1.[i+2] in begin try let k1 = of_hex1 c1 in let k2 = of_hex1 c2 in String.make 1 (Char.chr((k1 lsl 4) lor k2)) with Not_found -> failwith "decode" end ) s1 let make_encoded_parameters params = String.concat "&" (List.map (fun (name, value) -> encode name ^ "=" ^ encode value) params) let string_of_url_path ~encode l = if encode then fixup_url_string (String.concat "/" (List.map (*Netencoding.Url.encode*) (MyUrl.encode ~plus:false) l)) (* ' ' are not encoded to '+' in paths *) else String.concat "/" l (* BYXXX : check illicit characters *) let url_split_re = Str.regexp "[&=]";; (* taken from Ocamlnet 4.1.2 *) let dest_url_encoded_parameters parstr = let rec parse_after_amp tl = match tl with | Str.Text name :: Str.Delim "=" :: Str.Text value :: tl' -> (decode name, decode value) :: parse_next tl' | Str.Text name :: Str.Delim "=" :: Str.Delim "&" :: tl' -> (decode name, "") :: parse_after_amp tl' | Str.Text name :: Str.Delim "=" :: [] -> [decode name, ""] | _ -> failwith "dest_url_encoded_parameters" and parse_next tl = match tl with | [] -> [] | Str.Delim "&" :: tl' -> parse_after_amp tl' | _ -> failwith "dest_url_encoded_parameters" in let toklist = Str.full_split url_split_re parstr in match toklist with | [] -> [] | _ -> parse_after_amp toklist let parse = (* We do not accept http://login:pwd@host:port (should we?). *) let url_re = Netstring_pcre.regexp "^([Hh][Tt][Tt][Pp][Ss]?)://([0-9a-zA-Z.-]+|\\[[0-9A-Fa-f:.]+\\])(:([0-9]+))?/([^\\?]*)(\\?(.*))?$" in let short_url_re = Netstring_pcre.regexp "^/([^\\?]*)(\\?(.*))?$" in (* let url_relax_re = Netstring_pcre.regexp "^[Hh][Tt][Tt][Pp][Ss]?://[^/]+" in *) fun url -> let match_re = Netstring_pcre.string_match url_re url 0 in let (https, host, port, pathstring, query) = match match_re with | None -> (match Netstring_pcre.string_match short_url_re url 0 with | None -> raise Ocsigen_Bad_Request | Some m -> let path = fixup_url_string (Netstring_pcre.matched_group m 1 url) in let query = try Some (fixup_url_string (Netstring_pcre.matched_group m 3 url)) with Not_found -> None in (None, None, None, path, query)) | Some m -> let path = fixup_url_string (Netstring_pcre.matched_group m 5 url) in let query = try Some (fixup_url_string (Netstring_pcre.matched_group m 7 url)) with Not_found -> None in let https = try (match Netstring_pcre.matched_group m 1 url with | "http" -> Some false | "https" -> Some true | _ -> None) with Not_found -> None in let host = try Some (Netstring_pcre.matched_group m 2 url) with Not_found -> None in let port = try Some (int_of_string (Netstring_pcre.matched_group m 4 url)) with Not_found -> None in (https, host, port, path, query) in (* Note that the fragment (string after #) is not sent by browsers *) (*20110707 ' ' is encoded to '+' in queries, but not in paths. Warning: if we write the URL manually, we must encode ' ' to '+' manually (not done by the browser). --Vincent *) let get_params = lazy begin let params_string = match query with None -> "" | Some s -> s in try dest_url_encoded_parameters params_string with Failure _ -> raise Ocsigen_Bad_Request end in let path = List.map (decode ~plus:false) (split_path pathstring) in let path = remove_dotdot path (* and remove "//" *) (* here we remove .. from paths, as it is dangerous. But in some very particular cases, we may want them? I prefer forbid that. *) in let uri_string = match query with | None -> pathstring | Some s -> String.concat "?" [pathstring; s] in (https, host, port, uri_string, path, query, get_params) let prefix_and_path_of_t url = let (https, host, port, _, path, _, _) = parse url in let https_str = match https with | None -> "" | Some x -> if x then "https://" else "http://" in let host_str = match host with | None -> "" | Some x -> x in let port_str = match port with | None -> "" | Some x -> string_of_int x in (https_str ^ host_str ^ ":" ^ port_str, path) end module Date = struct let name_of_day = function | 0 -> "Sun" | 1 -> "Mon" | 2 -> "Tue" | 3 -> "Wed" | 4 -> "Thu" | 5 -> "Fri" | 6 -> "Sat" | _ -> failwith "name_of_day" let name_of_month = function | 0 -> "Jan" | 1 -> "Feb" | 2 -> "Mar" | 3 -> "Apr" | 4 -> "May" | 5 -> "Jun" | 6 -> "Jul" | 7 -> "Aug" | 8 -> "Sep" | 9 -> "Oct" | 10 -> "Nov" | 11 -> "Dec" | _ -> failwith "name_of_month" let to_string d = let { Unix.tm_wday ; tm_mday ; tm_mon ; tm_year ; tm_hour ; tm_min ; tm_sec ; _ } = Unix.gmtime d in Printf.sprintf "%s, %02d %s %d %02d:%02d:%02d GMT" (name_of_day tm_wday) tm_mday (name_of_month tm_mon) (tm_year + 1900) tm_hour tm_min tm_sec end ocsigenserver-5.0.1/src/baselib/ocsigen_lib.mli000066400000000000000000000074361417255654100215670ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2005 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** This module contains some auxiliaries for the Ocsigenserver. In contrast to {!Ocsigen_lib_base}, the function may also refer to libraries other than the standard library. *) include module type of Ocsigen_lib_base with type poly = Ocsigen_lib_base.poly and type yesnomaybe = Ocsigen_lib_base.yesnomaybe and type ('a, 'b) leftright = ('a, 'b) Ocsigen_lib_base.leftright and type 'a Clist.t = 'a Ocsigen_lib_base.Clist.t and type 'a Clist.node = 'a Ocsigen_lib_base.Clist.node (** Generate an unique and cryptographically safe random string. It is impossible to guess for other people and will never return twice the same value (with very good probabilities). *) val make_cryptographic_safe_string : unit -> string module String : module type of String_base module Ip_address : sig exception No_such_host val get_inet_addr : ?v6:bool -> string -> Unix.inet_addr Lwt.t val of_sockaddr : Unix.sockaddr -> Unix.inet_addr end module Filename : sig include module type of Filename (* val basename : string -> string *) (* val extension : string -> string *) val extension_no_directory : string -> string end module Url : sig include module type of Url_base with type t = Url_base.t val fixup_url_string : t -> t val encode : ?plus:bool -> string -> string val decode : ?plus:bool -> string -> string val make_encoded_parameters : (string * string) list -> string val string_of_url_path : encode:bool -> path -> uri (** [parse url] returns a tuple containing information about [url] {ul {- If url contains scheme 'https'} {- host of url (ex: http://www.ocsigen.org/ -> www.ocsigen.org)} {- port of url} {- path as [string] without first '/'} {- path as [string list]} {- GET query of url} {- lazy value to decode GET query } } *) val parse : t -> bool option * string option * int option * string * string list * string option * (string * string) list Lazy.t (** [prefix_and_path_of_t url] splits [url] in a couple [(prefix, path)] where [prefix] is ["http(s)://host:port"] and [path] is the path as [string list] Example: [prefix_and_path_of_t "http://ocsigen.org:80/tuto/manual"] returns [("http://ocsigen.org:80", ["tuto", "manual"])]. *) val prefix_and_path_of_t : string -> string * string list end (**/**) (* This exists to facilitate transition away from Ocamlnet. Do not use for new code! *) module Netstring_pcre : sig val regexp : string -> Pcre.regexp val matched_group : Pcre.substrings -> int -> string -> string val matched_string : Pcre.substrings -> string -> string val global_replace : Pcre.regexp -> string -> string -> string val search_forward: Pcre.regexp -> string -> int -> int * Pcre.substrings val split : Pcre.regexp -> string -> string list val string_match : Pcre.regexp -> string -> int -> Pcre.substrings option end module Date : sig (** Converts Unix GMT date to string *) val to_string : float -> string end ocsigenserver-5.0.1/src/baselib/ocsigen_lib_base.ml000066400000000000000000000304151417255654100224010ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2005-2008 Vincent Balat, Stéphane Glondu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) exception Ocsigen_Internal_Error of string exception Input_is_too_large exception Ocsigen_Bad_Request exception Ocsigen_Request_too_long external id : 'a -> 'a = "%identity" let (>>=) = Lwt.bind let (>|=) = Lwt.(>|=) let (!!) = Lazy.force let (|>) x f = f x let (@@) f x = f x let comp f g x = f (g x) let curry f x y = f (x, y) let uncurry f (x, y) = f x y type poly external to_poly : 'a -> poly = "%identity" external from_poly : poly -> 'a = "%identity" module Tuple3 = struct let fst (a, _, _) = a let snd (_, a, _) = a let thd (_, _, a) = a end type yesnomaybe = Yes | No | Maybe type ('a, 'b) leftright = Left of 'a | Right of 'b let advert = "Page generated by OCaml with Ocsigen. See http://ocsigen.org/ and http://caml.inria.fr/ for information" (*****************************************************************************) module Option = struct type 'a t = 'a option let map f = function | Some x -> Some (f x) | None -> None let get f = function | Some x -> x | None -> f () let get' a = function | Some x -> x | None -> a let iter f = function | Some x -> f x | None -> () let return x = Some x let bind opt k = match opt with | Some x -> k x | None -> None let to_list = function | None -> [] | Some v -> [v] module Lwt = struct let map f = function | Some x -> f x >>= fun v -> Lwt.return (Some v) | None -> Lwt.return None let get f = function | Some x -> Lwt.return x | None -> f () let get' a = function | Some x -> Lwt.return x | None -> a let iter f = function | Some x -> f x | None -> Lwt.return () let bind opt k = match opt with | Some x -> k x | None -> Lwt.return None end end module List = struct include List let map_filter f l = let rec aux acc = function | [] -> acc | t::q -> match f t with | None -> aux acc q | Some r -> aux (r::acc) q in List.rev (aux [] l) let rec remove_first_if_any a = function | [] -> [] | b::l when a = b -> l | b::l -> b::(remove_first_if_any a l) let rec remove_first_if_any_q a = function | [] -> [] | b::l when a == b -> l | b::l -> b::(remove_first_if_any_q a l) let rec remove_first a = function | [] -> raise Not_found | b::l when a = b -> l | b::l -> b::(remove_first a l) let rec remove_first_q a = function | [] -> raise Not_found | b::l when a == b -> l | b::l -> b::(remove_first_q a l) let rec remove_all a = function | [] -> [] | b::l when a = b -> remove_all a l | b::l -> b::(remove_all a l) let rec remove_all_q a = function | [] -> [] | b::l when a == b -> remove_all_q a l | b::l -> b::(remove_all_q a l) let rec remove_all_assoc a = function | [] -> [] | (b, _)::l when a = b -> remove_all_assoc a l | b::l -> b::(remove_all_assoc a l) let rec remove_all_assoc_q a = function | [] -> [] | (b,_)::l when a == b -> remove_all_assoc_q a l | b::l -> b::(remove_all_assoc_q a l) let rec last = function | [] -> raise Not_found | [b] -> b | _::l -> last l let rec assoc_remove a = function | [] -> raise Not_found | (b, c)::l when a = b -> c, l | b::l -> let v, ll = assoc_remove a l in (v, b::ll) let rec is_prefix l1 l2 = match (l1, l2) with | [], _ -> true | a::ll1, b::ll2 when a=b -> is_prefix ll1 ll2 | _ -> false let rec chop n xs = if n <= 0 then xs else match xs with | [] -> [] | _x :: xs -> chop (n-1) xs let rec split_at n xs = if n <= 0 then [], xs else match xs with | [] -> [], [] | x::xs -> let l,r = split_at (n-1) xs in x::l, r end (*****************************************************************************) (* circular lists *) module Clist : sig type 'a t type 'a node val make : 'a -> 'a node val create : unit -> 'a t val insert : 'a t -> 'a node -> unit val remove : 'a node -> unit val value : 'a node -> 'a val in_list : 'a node -> bool val is_empty : 'a t -> bool val iter : ('a -> unit) -> 'a t -> unit val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a end = struct type 'a node = { content : 'a option; mutable prev : 'a node; mutable next : 'a node } type 'a t = 'a node let make' c = let rec x = { content = c; prev = x; next = x } in x let make c = make' (Some c) let create () = make' None let insert p x = let n = p.next in p.next <- x; x.prev <- p; x.next <- n; n.prev <- x let remove x = let p = x.prev in let n = x.next in p.next <- n; n.prev <- p; x.next <- x; x.prev <- x let in_list x = x.next != x let is_empty set = set.next == set let value c = match c.content with | None -> failwith "Clist.value" | Some c -> c let rec iter f (node : 'a t) = match node.next.content with | Some c -> f c; iter f node.next | None -> () let rec fold_left f a (node : 'a t) = match node.next.content with | Some c -> fold_left f (f a c) node.next | None -> a end (*****************************************************************************) module Int = struct module Table = Map.Make(struct type t = int let compare = compare end) end (*****************************************************************************) module String_base = struct include String (* Returns a copy of the string from beg to endd, removing spaces at the beginning and at the end *) let remove_spaces s beg endd = let rec find_not_space s i step = if (i > endd) || (beg > i) then i else if s.[i] = ' ' then find_not_space s (i+step) step else i in let first = find_not_space s beg 1 in let last = find_not_space s endd (-1) in if last >= first then String.sub s first (1+ last - first) else "" (* Cut a string to the next separator *) let basic_sep char s = try let seppos = String.index s char in ((String.sub s 0 seppos), (String.sub s (seppos+1) ((String.length s) - seppos - 1))) with Invalid_argument _ -> raise Not_found (* Cut a string to the next separator, removing spaces. Raises Not_found if the separator cannot be found. *) let sep char s = let len = String.length s in let seppos = String.index s char in ((remove_spaces s 0 (seppos-1)), (remove_spaces s (seppos+1) (len-1))) (* splits a string, for ex "azert, sdfmlskdf, dfdsfs" *) let split ?(multisep=false) char s = let longueur = String.length s in let rec aux deb = if deb >= longueur then [] else try let firstsep = String.index_from s deb char in if multisep && firstsep = deb then aux (deb + 1) else (remove_spaces s deb (firstsep-1)):: (aux (firstsep+1)) with Not_found -> [remove_spaces s deb (longueur-1)] in aux 0 let may_append s1 ~sep = function | "" -> s1 | s2 -> s1^sep^s2 let may_concat s1 ~sep s2 = match s1, s2 with | _, "" -> s1 | "", _ -> s2 | _ -> String.concat sep [s1;s2] (* returns the index of the first difference between s1 and s2, starting from n and ending at last. returns (last + 1) if no difference is found. *) let rec first_diff s1 s2 n last = try if s1.[n] = s2.[n] then if n = last then last+1 else first_diff s1 s2 (n+1) last else n with Invalid_argument _ -> n module Table = Map.Make(String) module Set = Set.Make(String) module Map = Map.Make(String) end (*****************************************************************************) module Url_base = struct type t = string type uri = string type path = string list let make_absolute_url ~https ~host ~port uri = (if https then "https://" else "http://" )^ host^ (if (port = 80 && not https) || (https && port = 443) then "" else ":"^string_of_int port)^ uri let remove_dotdot = (* removes "../" *) let rec aux = function | [] -> [] | [""] as l -> l (* | ""::l -> aux l *) (* we do not remove "//" any more, because of optional suffixes in Eliom *) | ".."::l -> aux l | a::l -> a::(aux l) in function | [] -> [] | ""::l -> ""::(aux l) | l -> aux l let remove_end_slash s = try if s.[(String.length s) - 1] = '/' then String.sub s 0 ((String.length s) - 1) else s with Invalid_argument _ -> s let remove_internal_slash u = let rec aux = function | [] -> [] | [a] -> [a] | ""::l -> aux l | a::l -> a::(aux l) in match u with | [] -> [] | a::l -> a::(aux l) let change_empty_list = function | [] -> [""] (* It is not possible to register an empty URL *) | l -> l let rec add_end_slash_if_missing = function | [] -> [""] | [""] as a -> a | a::l -> a::(add_end_slash_if_missing l) let rec remove_slash_at_end = function | [] | [""] -> [] | a::l -> a::(remove_slash_at_end l) let remove_slash_at_beginning = function | [] -> [] | [""] -> [""] | ""::l -> l | l -> l let rec is_prefix_skip_end_slash l1 l2 = match (l1, l2) with | [""], _ | [], _ -> true | a::ll1, b::ll2 when a=b -> is_prefix_skip_end_slash ll1 ll2 | _ -> false let split_fragment s = try let pos = String.index s '#' in String.sub s 0 pos, Some (String.sub s (pos+1) (String.length s - 1 - pos)) with Not_found -> s, None let join_path = function [""] -> "/" | l -> String.concat "/" l (* Taken from Ocamlnet 4.1.2 *) let split_path s = let l = String.length s in let rec collect_words k = let k' = try String.index_from s k '/' with Not_found -> l in let word = String.sub s k (k'-k) in if k' >= l then [word] else word :: collect_words (k'+1) in match collect_words 0 with | [ "" ] -> [] | [ "";"" ] -> [ "" ] | other -> other (* Taken from Ocamlnet 4.1.2 *) let norm_path l = let rec remove_slash_slash l first = match l with | [ "" ] -> [ "" ] | [ ""; "" ] when first -> [ "" ] | "" :: l' when not first -> remove_slash_slash l' false | x :: l' -> x :: remove_slash_slash l' false | [] -> [] in let rec remove_dot l first = match l with | ([ "." ] | ["."; ""]) -> if first then [] else [ "" ] | "." :: x :: l' -> remove_dot (x :: l') false | x :: l' -> x :: remove_dot l' false | [] -> [] in let rec remove_dot_dot_once l first = match l with x :: ".." :: [] when x <> "" && x <> ".." && not first -> [ "" ] | x :: ".." :: l' when x <> "" && x <> ".." -> l' | x :: l' -> x :: remove_dot_dot_once l' false | [] -> raise Not_found in let rec remove_dot_dot l = try let l' = remove_dot_dot_once l true in remove_dot_dot l' with Not_found -> l in let l' = remove_dot_dot (remove_dot (remove_slash_slash l true) true) in match l' with [".."] -> [".."; ""] | ["";""] -> [ "" ] | _ -> l' end (*****************************************************************************) let debug = prerr_endline ocsigenserver-5.0.1/src/baselib/ocsigen_lib_base.mli000066400000000000000000000142071417255654100225530ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2005 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** This module just contains only extensions of the standard library and very basic Ocsigen values and exceptions. Cf. {!Ocsigen_lib} for functionality which depends on specific external libraries. *) exception Ocsigen_Internal_Error of string exception Input_is_too_large exception Ocsigen_Bad_Request exception Ocsigen_Request_too_long val (>>=) : 'a Lwt.t -> ('a -> 'b Lwt.t) -> 'b Lwt.t val (>|=) : 'a Lwt.t -> ('a -> 'b) -> 'b Lwt.t val (!!) : 'a Lazy.t -> 'a val (|>) : 'a -> ('a -> 'b) -> 'b val (@@) : ('a -> 'b) -> 'a -> 'b external id : 'a -> 'a = "%identity" val comp : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b val curry : ('a * 'b -> 'c) -> 'a -> 'b -> 'c val uncurry : ('a -> 'b -> 'c) -> ('a * 'b) -> 'c module Tuple3 : sig val fst : 'a * 'b * 'c -> 'a val snd : 'a * 'b * 'c -> 'b val thd : 'a * 'b * 'c -> 'c end type poly val to_poly: 'a -> poly val from_poly: poly -> 'a type yesnomaybe = Yes | No | Maybe type ('a, 'b) leftright = Left of 'a | Right of 'b val advert: string (** Module Option to compute type ['a option] *) module Option : sig type 'a t = 'a option val map : ('a -> 'b) -> 'a t -> 'b t val get : (unit -> 'a) -> 'a t -> 'a val get' : 'a -> 'a t -> 'a val iter : ('a -> unit) -> 'a t -> unit val return : 'a -> 'a t val bind : 'a t -> ('a -> 'b t) -> 'b t val to_list : 'a t -> 'a list module Lwt : sig val map : ('a -> 'b Lwt.t) -> 'a t -> 'b t Lwt.t val get : (unit -> 'a Lwt.t) -> 'a t -> 'a Lwt.t val get' : 'a Lwt.t -> 'a t -> 'a Lwt.t val iter : ('a -> unit Lwt.t) -> 'a t -> unit Lwt.t val bind : 'a t -> ('a -> 'b t Lwt.t) -> 'b t Lwt.t end end (** Improvement of module List *) module List : sig include module type of List val map_filter : ('a -> 'b option) -> 'a list -> 'b list val last : 'a list -> 'a val assoc_remove : 'a -> ('a * 'b) list -> 'b * ('a * 'b) list val remove_first_if_any : 'a -> 'a list -> 'a list val remove_first_if_any_q : 'a -> 'a list -> 'a list val remove_first : 'a -> 'a list -> 'a list val remove_first_q : 'a -> 'a list -> 'a list val remove_all : 'a -> 'a list -> 'a list val remove_all_q : 'a -> 'a list -> 'a list val remove_all_assoc : 'a -> ('a * 'b) list -> ('a * 'b) list val remove_all_assoc_q : 'a -> ('a * 'b) list -> ('a * 'b) list val is_prefix : 'a list -> 'a list -> bool val chop : int -> 'a list -> 'a list val split_at : int -> 'a list -> 'a list * 'a list end (** Circular lists *) module Clist : sig type 'a t type 'a node val make : 'a -> 'a node val create : unit -> 'a t val insert : 'a t -> 'a node -> unit val remove : 'a node -> unit val value : 'a node -> 'a val in_list : 'a node -> bool val is_empty : 'a t -> bool (** Infinite iteration on circular lists *) val iter : ('a -> unit) -> 'a t -> unit (** Infinite fold on circular lists (use with care!) *) val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a end module Int : sig module Table : Map.S with type key = int end (** Improvement of module String *) module String_base : sig include module type of String (** [remove_spaces s beg endd] returns a copy of the string from beg to endd, removing spaces at the beginning and at the end *) val remove_spaces : string -> int -> int -> string (** Cuts a string to the next separator *) val basic_sep : char -> string -> string * string (** Cuts a string to the next separator, removing spaces. Raises [Not_found] if the separator cannot be found. *) val sep : char -> string -> string * string (** Splits a string for words with separator, removing spaces. For ex "azert, sdfmlskdf, dfdsfs". *) val split : ?multisep:bool -> char -> string -> string list val may_append : string -> sep:string -> string -> string (* WAS add_to_string *) val may_concat : string -> sep:string -> string -> string (* WAS concat_strings *) (** [first_diff s1 s2 n last] returns the index of the first difference between s1 and s2, starting from n and ending at last. returns (last + 1) if no difference is found. *) val first_diff : string -> string -> int -> int -> int module Table : Map.S with type key = string module Set : Set.S with type elt = string module Map : Map.S with type key = string end module Url_base : sig type t = string type uri = string (** [make_absolute_url https host port path] generates a new absolute url *) val make_absolute_url : https:bool -> host:string -> port:int -> uri -> t type path = string list (** [remove_dotdot path] cleans the path of [..] *) val remove_dotdot : path -> path (** [remove_end_slash str] removes last [/] *) val remove_end_slash : string -> string (** [remove_internal_slash path] cleans the path of empty string *) val remove_internal_slash : path -> path val change_empty_list : path -> path val add_end_slash_if_missing : path -> path val remove_slash_at_end : path -> path val remove_slash_at_beginning : path -> path (** [is_prefix_skip_end_slash path1 path2] returns [true] if [path1] is the same as [path2] before a first slash *) val is_prefix_skip_end_slash : string list -> string list -> bool (** [split_fragment str] splits [str] at first '#' *) val split_fragment : string -> string * string option val join_path : path -> string (**/**) val split_path : string -> path val norm_path : path -> path end val debug : string -> unit ocsigenserver-5.0.1/src/baselib/ocsigen_loader.ml000066400000000000000000000156651417255654100221210ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * File ocsigen_loader.ml * Copyright (C) 2008 Stéphane Glondu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) open Ocsigen_lib exception Dynlink_error of string * exn exception Findlib_error of string * exn let section = Lwt_log.Section.make "ocsigen:dynlink" (************************************************************************) (* Translate .cmo/.cma extensions to .cmxs in native mode, and .cmxs to .cmo (.cma if the file exists) in bytecode mode. *) let translate = if Ocsigen_config_static.is_native then fun filename -> if Filename.check_suffix filename ".cmo" || Filename.check_suffix filename ".cma" then (Filename.chop_extension filename) ^ ".cmxs" else filename else fun filename -> if Filename.check_suffix filename ".cmxs" then let filename = Filename.chop_extension filename in let cma = filename ^ ".cma" in if Sys.file_exists cma then cma else filename ^ ".cmo" else filename (************************************************************************) (* Loading files *) let isloaded, addloaded = let set = ref String.Set.empty in ((fun s -> String.Set.mem s !set), (fun s -> set := String.Set.add s !set)) module M = Map.Make(String) let init_functions = ref M.empty let get_init_on_load, set_init_on_load = let init_on_load = ref false in ((fun () -> !init_on_load), (fun b -> init_on_load := b)) let loadfile pre post force file = let file = translate file in try if force then begin pre (); Lwt_log.ign_info_f ~section "Loading %s (will be reloaded every times)" file; begin try Dynlink_wrapper.loadfile file; post () with e -> post (); raise e end end else if not (isloaded file) then begin pre (); Lwt_log.ign_info_f ~section "Loading extension %s" file; begin try Dynlink_wrapper.loadfile file; post () with e -> post (); raise e end; addloaded file; end else Lwt_log.ign_info_f ~section "Extension %s already loaded" file with | e -> raise (Dynlink_error (file, e)) let id () = () let loadfiles pre post force modules = let rec aux = function | [] -> () | [m] -> loadfile pre post force m | m::q -> loadfile id id false m; aux q in aux modules let set_module_init_function name f = init_functions := M.add name f !init_functions; (* print_endline ("Added init_function for " ^ name); *) (* print_endline ("get_init_on_load: " ^ string_of_bool (get_init_on_load ())); *) if get_init_on_load () then f () let init_module pre post force name = let f = try M.find name !init_functions with Not_found as e -> raise (Dynlink_error ("named module " ^ name, e)) in try if force then begin pre (); Lwt_log.ign_info_f ~section "Initializing %s (will be initialized every time)" name; begin try f (); post () with e -> post (); raise e end end else if not (isloaded name) then begin pre (); Lwt_log.ign_info_f ~section "Initializing module %s " name; begin try f (); post () with e -> post (); raise e end; addloaded name; end else Lwt_log.ign_info_f ~section "Module %s already initialized." name with | e -> raise (Dynlink_error (name, e)) (************************************************************************) (* Manipulating Findlib's search path *) let () = Findlib.init () let ocsigen_search_path = ref [] let update_search_path () = match !ocsigen_search_path with | [] -> Findlib.init () | x -> Findlib.init ~env_ocamlpath:(String.concat ":" x) () let get_ocamlpath = Findlib.search_path let set_ocamlpath lp = ocsigen_search_path := lp; update_search_path () let add_ocamlpath p = ocsigen_search_path := p :: !ocsigen_search_path; update_search_path () (************************************************************************) (* Using Findlib to locate files *) let findfiles = let cmx = Pcre.regexp ~flags:[`MULTILINE; `CASELESS] "\\.cmx($| |a)" in fun package -> try let preds = [ (if Ocsigen_config_static.is_native then "native" else "byte"); "plugin"; "mt" ] in let deps = List.filter (fun a -> not @@ String.Set.mem a Ocsigen_config_static.builtin_packages) (Findlib.package_deep_ancestors preds [package]) in Lwt_log.ign_info_f ~section "Dependencies of %s: %s" package (String.concat ", " deps); let rec aux = function | [] -> [] | a::q -> let mods = try let raw = Findlib.package_property preds a "archive" in (* Replacing .cmx/.cmxa by .cmxs *) let raw = Ocsigen_lib.Netstring_pcre.global_replace cmx ".cmxs " raw in List.filter ((<>) "") (String.split ~multisep:true ' ' raw) with | Not_found -> [] in let base = Findlib.package_directory a in (List.map (Findlib.resolve_path ~base) mods) @ (aux q) in let res = aux deps in Lwt_log.ign_info_f ~section "Needed: %s" (String.concat ", " res); res with | e -> raise (Findlib_error (package, e)) (************************************************************************) (* Error formatting *) open Printf let () = Printexc.register_printer @@ function | Dynlink_wrapper.Error e -> Some (Dynlink_wrapper.error_message e) | Dynlink_error (s, e) -> Some (sprintf "Dynlink error while loading %s: %s" s (Printexc.to_string e)) | Findlib_error (s, Fl_package_base.No_such_package (s', msg)) -> let pkg = if s = s' then s else sprintf "%s [while trying to load %s]" s' s in let additional = if msg = "" then "" else sprintf " (%s)" msg in let msg = sprintf "Findlib package %s not found%s: maybe you forgot ?" pkg additional in Some msg | Findlib_error (s, e) -> Some (sprintf "Findlib error while handling %s: %s" s (Printexc.to_string e)) | _ -> None ocsigenserver-5.0.1/src/baselib/ocsigen_loader.mli000066400000000000000000000073621417255654100222650ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * File ocsigen_loader.mli * Copyright (C) 2008 Stéphane Glondu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** Module [Ocsigen_loader]: Dynamic loading for Ocsigen. *) (** Notes about Findlib usage: - Findlib is called with predicates "plugin", "mt". Moreover, the predicate "native" or "byte" is added, depending on whether Ocsigen is running in native or bytecode mode. - In native mode, .cmx/.cmxa extensions provided by META files are replaced by .cmxs. - The OCAMLPATH environment variable is ignored altogether. *) exception Dynlink_error of string * exn exception Findlib_error of string * exn val section : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) val translate : string -> string (** [translate filename] translate .cmo/.cma extensions to .cmxs in native mode, and .cmxs to .cmo (.cma if it exists) in bytecode mode. *) val set_init_on_load: bool -> unit (** If set to [true], the module initialization functions passed to [set_module_init_function] will be executed directly. Otherwise, they will have to be invoked using [init_module] at some later stage. *) val loadfile: (unit -> unit) -> (unit -> unit) -> bool -> string -> unit (** [loadfile pre post force file] (dynamically) loads [file]. If [force] is [false], remember [file] so that it isn't loaded twice. If the loading effectively occurs, [pre] (resp. [post]) is called before (resp. after) the loading. [post] will be called even if the loading fails. *) val loadfiles: (unit -> unit) -> (unit -> unit) -> bool -> string list -> unit (** [loadfiles pre post force file] loads all the [files], using [loadfile (fun () -> ()) (fun () -> ()) false] for all the files but the last one, and [loadfile pre post force] for the last one (if any). *) val set_module_init_function : string -> (unit -> unit) -> unit (** [set_module_init_function name f] registers the function [f], which will be used to initialize the module when [init_module name] is called. *) val init_module : (unit -> unit) -> (unit -> unit) -> bool -> string -> unit (** [init_module pre post force name] runs the init function for the module [name]. If [force] is [false], remember [name] so that the init function isn't executed twice. If the function is executed, [pre] (resp. [post]) is called before (resp. after) the loading. [post] will be called even if the loading fails. *) val get_ocamlpath: unit -> string list (** Returns the current Findlib library search path. *) val set_ocamlpath: string list -> unit (** Sets the current Findlib library search path. The OCaml standard library path and some site-specific paths are always implicitly added. *) val add_ocamlpath: string -> unit (** Adds a path to the Findlib library search path. *) val findfiles: string -> string list (** [findfiles pkg] returns the list of files needed to load Findlib package [pkg], including dependencies. The archive files of [pkg] will appear last in the returned result. *) ocsigenserver-5.0.1/src/baselib/ocsigen_stream.ml000066400000000000000000000176521417255654100221440ustar00rootroot00000000000000(* Ocsigen * ocsigen_stream.ml Copyright (C) 2005 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) open Ocsigen_lib exception Interrupted of exn exception Cancelled exception Already_read exception Finalized type 'a stream = 'a step Lwt.t Lazy.t and 'a step = | Finished of 'a stream option (* If there is another stream following (useful for substreams) *) | Cont of 'a * 'a stream (* Current buffer, what follows *) type outcome = [`Success | `Failure] type 'a t = { mutable stream : 'a stream; mutable in_use : bool; mutable finalizer : outcome -> unit Lwt.t } let net_buffer_size = ref 8192 let set_net_buffer_size i = net_buffer_size := i let empty follow = match follow with None -> Lwt.return (Finished None) | Some st -> Lwt.return (Finished (Some (Lazy.from_fun st))) let cont stri f = Lwt.return (Cont (stri, Lazy.from_fun f)) let make ?finalize:(g = fun _ -> Lwt.return ()) f = { stream = Lazy.from_fun f; in_use = false; finalizer = g } let next = Lazy.force let rec get_aux st = lazy (Lwt.try_bind (fun () -> Lazy.force st.stream) (fun e -> Lwt.return (match e with Cont (s, rem) -> st.stream <- rem; Cont (s, get_aux st) | _ -> e)) (fun e -> st.stream <- lazy (Lwt.fail e); Lwt.fail (Interrupted e))) let get st = if st.in_use then raise Already_read; st.in_use <- true; get_aux st (** read the stream until the end, without decoding *) let rec consume_aux st = next st >>= fun e -> match e with | Cont (_, f) -> consume_aux f | Finished (Some ss) -> consume_aux ss | Finished None -> Lwt.return () let cancel st = let st' = st.stream in st.stream <- lazy (Lwt.fail Cancelled); consume_aux st' let consume st = consume_aux st.stream let finalize st status = let f = st.finalizer in st.finalizer <- (fun _ -> Lwt.return ()); f status >>= fun () -> st.stream <- lazy (Lwt.fail Finalized); Lwt.return () let add_finalizer st g = let f = st.finalizer in st.finalizer <- fun status -> f status >>= fun () -> g status (****) (** String streams *) exception Stream_too_small exception Stream_error of string exception String_too_large let string_of_stream m s = let buff = Buffer.create (m/4) in let rec aux i s = next s >>= function | Finished _ -> Lwt.return buff | Cont (s, f) -> let i = i + String.length s in if i > m then Lwt.fail String_too_large else (Buffer.add_string buff s; aux i f) in aux 0 s >|= Buffer.contents let enlarge_stream = function | Finished _a -> Lwt.fail Stream_too_small | Cont (s, f) -> let long = String.length s in let max = !net_buffer_size in if long >= max then Lwt.fail Input_is_too_large else next f >>= fun e -> match e with | Finished _ -> Lwt.fail Stream_too_small | Cont (r, ff) -> let long2 = String.length r in let long3=long+long2 in let new_s = s^r in if long3 <= max then Lwt.return (Cont (new_s, ff)) else let long4 = long3 - max in cont (String.sub new_s 0 max) (fun () -> Lwt.return (Cont (String.sub new_s max long4, ff))) let rec stream_want s len = (* returns a stream with at least len bytes read if possible *) match s with | Finished _ -> Lwt.return s | Cont (stri, _f) -> if String.length stri >= len then Lwt.return s else Lwt.catch (fun () -> enlarge_stream s >>= fun r -> Lwt.return (`OK r)) (function | Stream_too_small -> Lwt.return `Too_small | e -> Lwt.fail e) >>= function | `OK r -> stream_want r len | `Too_small -> Lwt.return s let current_buffer = function | Finished _ -> raise Stream_too_small | Cont (s, _) -> s let rec skip s k = match s with | Finished _ -> raise Stream_too_small | Cont (s, f) -> let len = String.length s in let len64 = Int64.of_int len in if Int64.compare k len64 <= 0 then let k = Int64.to_int k in Lwt.return (Cont (String.sub s k (len - k), f)) else (enlarge_stream (Cont ("", f)) >>= (fun s -> skip s (Int64.sub k len64))) let substream delim s = let ldelim = String.length delim in if ldelim = 0 then Lwt.fail (Stream_error "Empty delimiter") else let rdelim = Pcre.(regexp (quote delim)) in let rec aux = function | Finished _ -> Lwt.fail Stream_too_small | Cont (s, f) as stre -> let len = String.length s in if len < ldelim then enlarge_stream stre >>= aux else try let p,_ = Ocsigen_lib.Netstring_pcre.search_forward rdelim s 0 in cont (String.sub s 0 p) (fun () -> empty (Some (fun () -> Lwt.return (Cont (String.sub s p (len - p), f))))) with Not_found -> let pos = (len + 1 - ldelim) in cont (String.sub s 0 pos) (fun () -> next f >>= function | Finished _ -> Lwt.fail Stream_too_small | Cont (s', f') -> aux (Cont (String.sub s pos (len - pos) ^ s', f')) ) in aux s (*****************************************************************************) (*VVV Is it the good place for this? *) let of_file filename = let fd = Lwt_unix.of_unix_file_descr (Unix.openfile filename [Unix.O_RDONLY;Unix.O_NONBLOCK] 0o666) in let ch = Lwt_io.(of_fd ~mode:input) fd in let buf = Bytes.create 1024 in let rec aux () = Lwt_io.read_into ch buf 0 1024 >>= fun n -> if n = 0 then empty None else (* Streams should be immutable, thus we always make a copy of the buffer *) cont (Bytes.sub_string buf 0 n) aux in make ~finalize:(fun _ -> Lwt_unix.close fd) aux let of_string s = make (fun () -> cont s (fun () -> empty None)) (** Convert a {!Lwt_stream.t} to an {!Ocsigen_stream.t}. *) let of_lwt_stream stream = let rec aux () = Lwt_stream.get stream >>= function | Some e -> cont e aux | None -> empty None in make aux (** Convert an {!Ocsigen_stream.t} into a {!Lwt_stream.t}. @param is_empty function to skip empty chunk. *) let to_lwt_stream ?(is_empty = (fun _ -> false)) o_stream = let stream = ref (get o_stream) in let rec wrap () = next !stream >>= function | Finished None -> o_stream.finalizer `Success >>= fun () -> Lwt.return None | Finished (Some next) -> stream := next; wrap () | Cont (value, next) -> stream := next; if is_empty value then wrap () else Lwt.return (Some value) in Lwt_stream.from wrap module StringStream = struct type out = string t type m = (string stream -> string step Lwt.t) Lazy.t let empty : m = lazy (fun c -> Lazy.force c) let concat (m: m) (f: m) : m = lazy (fun c -> Lazy.force m (lazy (Lazy.force f c))) let put (s : string) : m = lazy (fun c -> Lwt.return (Cont (s, c))) let make_stream (m: m) : string stream = lazy (Lazy.force m (lazy (Lwt.return (Finished None)))) let make (m: m) : out = make (fun () -> Lazy.force (make_stream m)) end ocsigenserver-5.0.1/src/baselib/ocsigen_stream.mli000066400000000000000000000111011417255654100222740ustar00rootroot00000000000000(* Ocsigen * ocsigen_stream.ml Copyright (C) 2005 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) exception Interrupted of exn exception Cancelled exception Already_read exception Finalized (** Streams are a means to read data block by block *) type 'a stream (** A stream may be composed by several substreams. Thus a stream is either something that contains the current buffer and a function to retrieve the following data, or a finished stream with possibly another stream following. *) type 'a step = private | Finished of 'a stream option | Cont of 'a * 'a stream type 'a t type outcome = [`Success | `Failure] (** creates a new stream *) val make : ?finalize:(outcome -> unit Lwt.t) -> (unit -> 'a step Lwt.t) -> 'a t (** call this function if you decide to start reading a stream. @raise Already_read if the stream has already been read. *) val get : 'a t -> 'a stream (** get the next step of a stream. Fails with [Interrupted e] if reading the thread failed with exception [e], and with [Cancelled] if the thread has been cancelled. *) val next : 'a stream -> 'a step Lwt.t (** creates an empty step. The parameter is the following substream, if any. *) val empty : (unit -> 'a step Lwt.t) option -> 'a step Lwt.t (** creates a non empty step. *) val cont : 'a -> (unit -> 'a step Lwt.t) -> 'a step Lwt.t (** Add a finalizer function. In the current version, finalizers must be called manually. *) val add_finalizer : 'a t -> (outcome -> unit Lwt.t) -> unit (** Finalize the stream. This function must be called explicitly after reading the stream, otherwise finalizers won't be called. *) val finalize : 'a t -> outcome -> unit Lwt.t (** Cancel the stream, i.e. read the stream until the end, without decoding. Further tries to read on the stream will fail with exception {!Ocsigen_stream.Cancelled} *) val cancel : 'a t -> unit Lwt.t (** Consume without cancelling. Read the stream until the end, without decoding. *) val consume : 'a t -> unit Lwt.t exception Stream_too_small (** possibly with the size of the stream *) exception Stream_error of string exception String_too_large (** Creates a string from a stream. The first argument is the upper limit of the string length *) val string_of_stream : int -> string stream -> string Lwt.t (** Read more data in the buffer *) val enlarge_stream : string step -> string step Lwt.t (** [stream_want s len] Returns a stream with at least len bytes in the buffer if possible *) val stream_want : string step -> int -> string step Lwt.t (** Returns the value of the current buffer *) val current_buffer : string step -> string (** Skips data. Raises [Stream_too_small (Some size)] if the stream is too small, where [size] is the size of the stream. *) val skip : string step -> int64 -> string step Lwt.t (** Cut the stream at the position given by a string delimiter *) val substream : string -> string step -> string step Lwt.t (** returns a stream reading from a file. Do not forget to finalize the stream to close the file. *) val of_file : string -> string t (** returns a stream containing a string. *) val of_string : string -> string t (** Convert a {!Lwt_stream.t} to an {!Ocsigen_stream.t}. *) val of_lwt_stream : 'a Lwt_stream.t -> 'a t (** Convert an {!Ocsigen_stream.t} into a {!Lwt_stream.t}. @param is_empty function to skip empty chunk. *) val to_lwt_stream : ?is_empty:('a -> bool) -> 'a t -> 'a Lwt_stream.t module StringStream : sig (** Interface for stream creation (for tyxml) *) type out = string t type m val make: m -> out (** Create an empty stream *) val empty: m (** Create a stream with one element *) val put: string -> m (** Concatenate two stream *) val concat: m -> m -> m end (**/**) (* Small hack that will allow us to move [Ocsigen_config] out of baselib. Not super-pretty. *) val set_net_buffer_size : int -> unit ocsigenserver-5.0.1/src/baselib/polytables/000077500000000000000000000000001417255654100207535ustar00rootroot00000000000000ocsigenserver-5.0.1/src/baselib/polytables/Makefile000066400000000000000000000002101417255654100224040ustar00rootroot00000000000000.PHONY: default default: build .PHONY: build build: dune build ## Clean up clean: dune clean distclean: clean -rm -f *~ \#* .\#* ocsigenserver-5.0.1/src/baselib/polytables/dune000066400000000000000000000001071417255654100216270ustar00rootroot00000000000000(library (name polytables) (public_name ocsigenserver.polytables)) ocsigenserver-5.0.1/src/baselib/polytables/polytables.ml000066400000000000000000000027271417255654100234730ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2009 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** @author Vincent Balat @author Jérôme Vouillon *) type 'a key = int * 'a option ref module T = Map.Make(struct type t = int let compare = compare end) type t = (unit -> unit) T.t ref let create () = ref T.empty let c = ref (-1) let make_key () = c := !c + 1; (!c, ref None) let set ~(table : t) ~key:((k, r) : 'a key) ~(value : 'a) = table := T.add k (fun () -> r := Some value) !table let get ~(table : t) ~key:((k, r) : 'a key) = (T.find k !table) (); match !r with | Some v -> r:= None; v | None -> failwith "Polytables.get" let remove ~(table : t) ~key:((k, _r) : 'a key) = table := T.remove k !table let clear ~(table : t) = table := T.empty ocsigenserver-5.0.1/src/baselib/polytables/polytables.mli000066400000000000000000000030711417255654100236350ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2009 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** Polymorphic tables (using Map) @author Vincent Balat @author Jérôme Vouillon *) (** Warning: this module is not thread safe! *) (** The type of key for a piece of data of type 'a *) type 'a key (** The type of tables *) type t (** creates a new table *) val create : unit -> t (** create a new key for each data you want to save *) val make_key : unit -> 'a key (** [set t k v] associates [v] to [k] in [t] *) val set : table:t -> key:'a key -> value:'a -> unit (** [get t k] returns the current binding of [k] in [t] or raises [Not_found] *) val get : table:t -> key:'a key -> 'a (** [remove t k] remove the current binding of [k] in [t] if it exists *) val remove : table:t -> key:'a key -> unit (** [clear t] remove all data from t *) val clear : table:t -> unit ocsigenserver-5.0.1/src/baselib/tests/000077500000000000000000000000001417255654100177375ustar00rootroot00000000000000ocsigenserver-5.0.1/src/baselib/tests/test_wrapping.ml000066400000000000000000000103021417255654100231530ustar00rootroot00000000000000(* ocamlfind ocamlopt -linkpkg -package react -g -I ../ ../wrapping.cmxa test_wrapping.ml -o test_wrapping *) let _ = Printexc.record_backtrace true (*** simple wrap test ***) type a = { a : float; a_wrap : a Ocsigen_wrap.wrapper; } let a_wrap () = Ocsigen_wrap.create_wrapper (fun t -> { a = t.a +. 1.; a_wrap = Ocsigen_wrap.empty_wrapper }) let a i = { a = i; a_wrap = a_wrap () } let va = a 3.14 let _,v = Ocsigen_wrap.wrap va let () = assert (v.a -. 4.14 < 0.0001) (*** deep wrap test ***) let va = [[[[[[1,[3.1,a 3.14]],a 35.1]]]]] let _,_ = Ocsigen_wrap.wrap va (*** multiple wrap test ***) type b = { b : string; ba : a; b' : string; b_wrap : b Ocsigen_wrap.wrapper; } let b_wrap () = Ocsigen_wrap.create_wrapper (fun t -> t.b, t.ba ) let b s f = { b = s; b' = s; b_wrap = b_wrap (); ba = a f } let tst_string = "test" let vb = b tst_string 3.14 let _,vb' = Ocsigen_wrap.wrap vb let _ = assert ( let (t,f) = Obj.magic (vb') in t == tst_string && ( f -. 4.14 < 0.0001 )) let _,vb'' = Ocsigen_wrap.wrap [2,[1.,[vb,4,ref 0],ref 42]] let () = match vb'' with | [2,[1.,[vb',4,{ contents = 0}],{ contents = 42}]] -> assert ( let (t,f) = Obj.magic (vb') in t == tst_string && ( f -. 4.14 < 0.0001 )) | _ -> assert false (*** create wrap during wrap test ***) let b'_wrap () = Ocsigen_wrap.create_wrapper (fun t -> t.b, a 1.2 ) let b' s f = { b = s; b' = s; b_wrap = b'_wrap (); ba = a f } let vb' = b' "test" 3.14 let _,vb'' = Ocsigen_wrap.wrap vb' let () = match (Obj.magic vb'') with | (x,y) -> assert (x == vb'.b); assert (y.a -. 4.14 < 0.0001 ) (*** big value copy ***) let ( -- ) x y = let rec aux y x acc = if x > y then acc else aux (y-1) x (y::acc) in aux y x [] (* type l = | A | L of l * int let ( -- ) x y = let rec aux y x acc = if x > y then acc else aux (y-1) x (L (acc,y)) in aux y x A let _ = Marshal.to_string (0--50000000) *) let v = (0--80000) (* it cannot grow much bigger than that, On systems with a small stack, it could die with stack overflow *) let _,v' = Ocsigen_wrap.wrap v let () = assert (v' = v) (*** simple wrap weak test ***) let d = Weak.create 1 let d_val = (Some (ref 0)) let _ = Weak.set d 0 d_val type d = { da : int; dw : int Weak.t; dm : d Ocsigen_wrap.wrapper; } let d_wrap () = Ocsigen_wrap.create_wrapper (fun {da;dw} -> Weak.get dw 0,da) let _,d' = Ocsigen_wrap.wrap (1,d,d_wrap ()) let () = assert (Obj.magic d' = (d_val,1)) (*** simple wrap react test ***) let r',push = React.E.create () let r = React.E.map (fun i -> i+1) r' let c a r w = (a,r,w) let c_wrap () = Ocsigen_wrap.create_wrapper (fun (a,r,w) -> a) let _,c' = Ocsigen_wrap.wrap (c 1 r (c_wrap ())) let () = assert (Obj.magic c' = 1) (*** Eliom_react like test ***) let r',push = React.E.create () let r = React.E.map (fun i -> i+1) r' type toto = { a : float; mtoto : toto Ocsigen_wrap.wrapper; } type t = { v1 : int; v2 : toto; v3 : int React.event; mt : t Ocsigen_wrap.wrapper; } let i = ref 0 let mtoto () = Ocsigen_wrap.create_wrapper (fun t -> incr i; string_of_float t.a, !i) let mt () = Ocsigen_wrap.create_wrapper (fun t -> incr i; t.v2) let toto i = { a = i; mtoto = mtoto () } let t i b = { v1 = i; v2 = b; v3 = r; mt = mt () } let vtoto = toto 3.14 let vt = t 42 vtoto let _,v' = Ocsigen_wrap.wrap vtoto let _,v' = Ocsigen_wrap.wrap vt (*** closure copy test ***) type t1 = { t1a : float; t1mark : t1 Ocsigen_wrap.wrapper; } type t2 = { t2t1 : t1; t2f : (int ref -> unit) option; t2mark : t2 Ocsigen_wrap.wrapper; } let r1 = ref 13 let r2 = ref 42 let r3 = ref 88 let t1mark () = Ocsigen_wrap.create_wrapper (fun t -> incr r1; { t1a = 3.14; t1mark = Ocsigen_wrap.empty_wrapper } ) let t2mark () = Ocsigen_wrap.create_wrapper (fun t -> (match t.t2f with | Some f -> f r2; | None -> assert false); { t with t2f = None; t2mark = Ocsigen_wrap.empty_wrapper } ) let t1 = { t1a = 1.1; t1mark = t1mark () } let t2 = { t2t1 = t1; t2f = Some (fun r -> incr r; incr r3); t2mark = t2mark () } let _,t2' = Ocsigen_wrap.wrap (Obj.repr t2) let _,t1' = Ocsigen_wrap.wrap (Obj.repr t1) let _ = assert (!r1 = 15); assert (!r2 = 43); assert (!r3 = 89) ocsigenserver-5.0.1/src/dune000066400000000000000000000004011417255654100160450ustar00rootroot00000000000000(executable (name ocsigenserver) (public_name ocsigenserver.opt) (link_flags (:standard -linkall)) (libraries dynlink ocsigenserver) (modes exe byte)) (install (files (ocsigenserver.bc as ocsigenserver)) (section bin) (package ocsigenserver)) ocsigenserver-5.0.1/src/extensions/000077500000000000000000000000001417255654100173735ustar00rootroot00000000000000ocsigenserver-5.0.1/src/extensions/Makefile000066400000000000000000000002651417255654100210360ustar00rootroot00000000000000include ../../Makefile.config .PHONY: default default: build .PHONY: build build:: dune build ## Clean up distclean: clean -rm -f *~ \#* .\#* ${MAKE} -C deflatemod distclean ocsigenserver-5.0.1/src/extensions/accesscontrol.ml000066400000000000000000000352611417255654100225760ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module accesscontrol.ml * Copyright (C) 2007 Vincent Balat, Stéphane Glondu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (* Filtering requests via the configuration file *) open Ocsigen_lib open Xml let section = Lwt_log.Section.make "ocsigen:ext:access-control" let rec parse_condition = function | Element ("ip", ["value", s], []) -> let prefix = try Ipaddr.Prefix.of_string_exn s with Ipaddr.Parse_error _ -> try let ip = Ipaddr.of_string_exn s in Ipaddr.Prefix.of_addr ip with _ -> Ocsigen_extensions.badconfig "Bad ip/netmask [%s] in condition" s in (fun ri -> let r = Ipaddr.Prefix.mem (Ocsigen_request.remote_ip_parsed ri) prefix in if r then Lwt_log.ign_info_f ~section "IP: %a matches %s" (fun () -> Ocsigen_request.remote_ip) ri s else Lwt_log.ign_info_f ~section "IP: %a does not match %s" (fun () -> Ocsigen_request.remote_ip) ri s; r) | Element ("ip" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("port", ["value", s], []) -> let port = try int_of_string s with Failure _ -> Ocsigen_extensions.badconfig "Bad port [%s] in condition" s in (fun ri -> let r = Ocsigen_request.port ri = port in if r then Lwt_log.ign_info_f ~section "PORT: %d accepted" port else Lwt_log.ign_info_f ~section "PORT: %a not accepted (%d expected)" (fun () ri -> string_of_int (Ocsigen_request.port ri)) ri port; r) | Element ("port" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("ssl", [], []) -> (fun ri -> let r = Ocsigen_request.ssl ri in if r then Lwt_log.ign_info ~section "SSL: accepted" else Lwt_log.ign_info ~section "SSL: not accepted"; r) | Element ("ssl" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("header", ["name", name; "regexp", reg], []) -> let regexp = try Netstring_pcre.regexp ("^" ^ reg ^ "$") with Failure _ -> Ocsigen_extensions.badconfig "Bad regular expression [%s] in

    condition" reg in (fun ri -> let r = List.exists (fun a -> let r = Netstring_pcre.string_match regexp a 0 <> None in if r then Lwt_log.ign_info_f "HEADER: header %s matches %S" name reg; r) (Ocsigen_request.header_multi ri (Ocsigen_header.Name.of_string name)) in if not r then Lwt_log.ign_info_f "HEADER: header %s does not match %S" name reg; r) | Element ("header" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("method", ["value", s], []) -> fun ri -> let m = Cohttp.Code.method_of_string s and m' = Ocsigen_request.meth ri in let s' = Cohttp.Code.string_of_method m' in let r = m = m' in if r then Lwt_log.ign_info_f ~section "METHOD: %s matches %s" s' s else Lwt_log.ign_info_f ~section "METHOD: %s does not match %s" s' s; r | Element ("method" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("protocol", ["value", s], []) -> fun ri -> let v = Cohttp.Code.version_of_string s and v' = Ocsigen_request.version ri in let s' = Cohttp.Code.string_of_version v' in let r = v = v' in if r then Lwt_log.ign_info_f ~section "PROTOCOL: %s matches %s" s' s else Lwt_log.ign_info_f ~section "PROTOCOL: %s does not match %s" s' s; r | Element ("protocol" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("path", ["regexp", s], []) -> let regexp = try Netstring_pcre.regexp ("^"^s^"$") with Failure _ -> Ocsigen_extensions.badconfig "Bad regular expression [%s] in condition" s in fun ri -> let sps = Ocsigen_request.sub_path_string ri in let r = Netstring_pcre.string_match regexp sps 0 <> None in if r then Lwt_log.ign_info_f ~section "PATH: \"%s\" matches %S" sps s else Lwt_log.ign_info_f ~section "PATH: \"%s\" does not match %S" sps s; r | Element ("path" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("and", [], sub) -> let sub = List.map parse_condition sub in (fun ri -> List.for_all (fun cond -> cond ri) sub) | Element ("and" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("or", [], sub) -> let sub = List.map parse_condition sub in (fun ri -> List.exists (fun cond -> cond ri) sub) | Element ("or" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("not", [], [sub]) -> let sub = parse_condition sub in (fun ri -> not (sub ri)) | Element ("not" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | _ -> Ocsigen_extensions.badconfig "Bad syntax for condition" (*****************************************************************************) (* Parsing filters *) let comma_space_regexp = Netstring_pcre.regexp "\ *,\ *" let parse_config parse_fun = function | Element ("if", [], sub) -> let (condition, sub) = match sub with | cond :: q -> parse_condition cond, q | _ -> Ocsigen_extensions.badconfig "Bad condition in " in let (ithen, sub) = match sub with | Element ("then", [], ithen) :: q -> parse_fun ithen, q | _ -> Ocsigen_extensions.badconfig "Bad branch in " in let (ielse, _sub) = match sub with | Element ("else", [], ielse)::([] as q) -> parse_fun ielse, q | [] -> (parse_fun [], []) | _ -> Ocsigen_extensions.badconfig "Bad branch in " in (function | Ocsigen_extensions.Req_found (ri, _) | Ocsigen_extensions.Req_not_found (_, ri) -> Lwt.return (if condition ri.Ocsigen_extensions.request_info then begin Lwt_log.ign_info ~section "COND: going into branch"; Ocsigen_extensions.Ext_sub_result ithen end else begin Lwt_log.ign_info ~section "COND: going into branch, if any"; Ocsigen_extensions.Ext_sub_result ielse end)) | Element ("if" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("notfound", [], []) -> (fun _rs -> Lwt_log.ign_info ~section "NOT_FOUND: taking in charge 404"; Lwt.return (Ocsigen_extensions.Ext_stop_all (Ocsigen_cookie_map.empty, `Not_found))) | Element ("notfound" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("nextsite", [], []) -> (function | Ocsigen_extensions.Req_found (_, r) -> Lwt.return (Ocsigen_extensions.Ext_found_stop (fun () -> Lwt.return r)) | Ocsigen_extensions.Req_not_found _ -> Lwt.return (Ocsigen_extensions.Ext_stop_site (Ocsigen_cookie_map.empty, `Not_found))) | Element ("nexthost", [], []) -> (function | Ocsigen_extensions.Req_found (_, r) -> Lwt.return (Ocsigen_extensions.Ext_found_stop (fun () -> Lwt.return r)) | Ocsigen_extensions.Req_not_found _ -> Lwt.return (Ocsigen_extensions.Ext_stop_host (Ocsigen_cookie_map.empty, `Not_found))) | Element ("nextsite" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("stop", [], []) -> (function | Ocsigen_extensions.Req_found (_, r) -> Lwt.return (Ocsigen_extensions.Ext_found_stop (fun () -> Lwt.return r)) | Ocsigen_extensions.Req_not_found _ -> Lwt.return (Ocsigen_extensions.Ext_stop_all (Ocsigen_cookie_map.empty, `Not_found))) | Element ("stop" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Xml.Element ("forbidden", [], []) -> (fun _rs -> Lwt_log.ign_info ~section "FORBIDDEN: taking in charge 403"; Lwt.return (Ocsigen_extensions.Ext_stop_all (Ocsigen_cookie_map.empty, `Forbidden))) | Element ("forbidden" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("iffound", [], sub) -> let ext = parse_fun sub in (function | Ocsigen_extensions.Req_found (_, _) -> Lwt.return (Ocsigen_extensions.Ext_sub_result ext) | Ocsigen_extensions.Req_not_found (err, _ri) -> Lwt.return (Ocsigen_extensions.Ext_next err)) | Element ("iffound" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("ifnotfound", [], sub) -> let ext = parse_fun sub in (function | Ocsigen_extensions.Req_found (_, r) -> Lwt.return (Ocsigen_extensions.Ext_found (fun () -> Lwt.return r)) | Ocsigen_extensions.Req_not_found _ -> Lwt.return (Ocsigen_extensions.Ext_sub_result ext)) | Element ("ifnotfound", [("code", s)], sub) -> let ext = parse_fun sub in let r = Netstring_pcre.regexp ("^"^s^"$") in (function | Ocsigen_extensions.Req_found (_, r) -> Lwt.return (Ocsigen_extensions.Ext_found (fun () -> Lwt.return r)) | Ocsigen_extensions.Req_not_found (err, _ri) -> if let err = string_of_int Cohttp.Code.(code_of_status (err :> status_code)) in Netstring_pcre.string_match r err 0 <> None then Lwt.return (Ocsigen_extensions.Ext_sub_result ext) else Lwt.return (Ocsigen_extensions.Ext_next err)) | Element ("ifnotfound" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Element ("allow-forward-for", param, _) -> let apply ({Ocsigen_extensions.request_info ;_} as request) code = Lwt_log.ign_info ~section "Allowed proxy"; let request = let header = Ocsigen_request.header request_info Ocsigen_header.Name.x_forwarded_for in match header with | Some header -> (match Ocsigen_lib.Netstring_pcre.split comma_space_regexp header with | original_ip :: proxies -> let last_proxy = List.last proxies in let proxy_ip = Ipaddr.of_string_exn last_proxy in let equal_ip = proxy_ip = Ocsigen_request.remote_ip_parsed request_info in let need_equal_ip = match param with | [] -> false | ["check-equal-ip", b] -> ( try bool_of_string b with Invalid_argument _ -> Ocsigen_extensions.badconfig "Bad syntax for argument of tag allow-forward-for") | _ -> Ocsigen_extensions.badconfig "Bad syntax for argument of tag allow-forward-for" in if equal_ip || not need_equal_ip then { request with Ocsigen_extensions.request_info = Ocsigen_request.update ~forward_ip:proxies ~remote_ip:original_ip request_info } else (* the announced ip of the proxy is not its real ip *) (Lwt_log.ign_warning_f ~section "X-Forwarded-For: host ip (%s) \ does not match the header (%s)" (Ocsigen_request.remote_ip request_info) header; request) | _ -> Lwt_log.ign_info_f ~section "Malformed X-Forwarded-For field: %s" header; request) | None -> request in Lwt.return (Ocsigen_extensions.Ext_continue_with ( request, Ocsigen_cookie_map.empty, code )) in (function | Ocsigen_extensions.Req_found (request, resp) -> apply request (Ocsigen_response.status resp) | Ocsigen_extensions.Req_not_found (code, request) -> apply request code) | Element ("allow-forward-proto", _, _) -> let apply ({ Ocsigen_extensions.request_info ; _ } as request) code = Lwt_log.ign_info ~section "Allowed proxy for ssl"; let request_info = let header = Ocsigen_request.header request_info Ocsigen_header.Name.x_forwarded_proto in match header with | Some header -> (match String.lowercase_ascii header with | "http" -> Ocsigen_request.update ~ssl:false request_info | "https" -> Ocsigen_request.update ~ssl:true request_info | _ -> Lwt_log.ign_info_f ~section "Malformed X-Forwarded-Proto field: %s" header; request_info) | None -> request_info in Lwt.return (Ocsigen_extensions.Ext_continue_with ( { request with Ocsigen_extensions.request_info }, Ocsigen_cookie_map.empty, code )) in (function | Ocsigen_extensions.Req_found (request, resp) -> apply request (Ocsigen_response.status resp) | Ocsigen_extensions.Req_not_found (code, request) -> apply request code) | Element (t, _, _) -> raise (Ocsigen_extensions.Bad_config_tag_for_extension t) | _ -> Ocsigen_extensions.badconfig "(accesscontrol extension) Bad data" (* Registration of the extension *) let () = Ocsigen_extensions.register ~name:"accesscontrol" ~fun_site:(fun _ _ _ _ _ -> parse_config) () ocsigenserver-5.0.1/src/extensions/accesscontrol.mli000066400000000000000000000020421417255654100227360ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module accesscontrol.ml * Copyright (C) 2007 Vincent Balat, Stéphane Glondu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (* val parse_condition : Xml.xml -> Ocsigen_extensions.request_info -> bool *) val section : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) ocsigenserver-5.0.1/src/extensions/authbasic.ml000066400000000000000000000106711417255654100216750ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module authbasic.ml * Copyright (C) 2008 Stéphane Glondu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) open Lwt.Infix let section = Lwt_log.Section.make "ocsigen:ext:access-control" type auth = string -> string -> bool Lwt.t exception Bad_config_tag_for_auth of string let register_basic_authentication_method, get_basic_authentication_method = let fun_auth = ref (fun _config -> raise (Bad_config_tag_for_auth "")) in (* register_basic_authentication_method *) (fun new_fun_auth -> let old_fun_auth = !fun_auth in fun_auth := (fun config -> try old_fun_auth config with Bad_config_tag_for_auth _c -> new_fun_auth config)), (* get_basic_authentication_method *) (fun config -> !fun_auth config) (* Basic authentication with a predefined login/password (example) *) let _ = let open Xml in register_basic_authentication_method @@ function | Element ("plain", ["login", login; "password", password], _) -> (fun l p -> Lwt.return (login = l && password = p)) | _ -> raise (Ocsigen_extensions.Bad_config_tag_for_extension "not for htpasswd") let gen ~realm ~auth rs = let reject () = let h = Cohttp.Header.init_with "WWW-Authenticate" (Printf.sprintf "Basic realm=\"%s\"" realm) in Lwt_log.ign_info ~section "AUTH: invalid credentials!"; Lwt.fail (Ocsigen_cohttp.Ext_http_error (`Unauthorized, None, Some h)) and invalid_header () = Lwt_log.ign_info ~section "AUTH: invalid Authorization header"; Lwt.fail (Ocsigen_cohttp.Ocsigen_http_error (Ocsigen_cookie_map.empty, `Bad_request)) in let validate ~err s = match Cohttp.Auth.credential_of_string s with | `Basic (user, pass) -> auth user pass >>= fun b -> if b then Lwt.return (Ocsigen_extensions.Ext_next err) else reject () | `Other _s -> invalid_header () in match rs with | Ocsigen_extensions.Req_not_found (err, ri) -> (match Ocsigen_request.header ri.Ocsigen_extensions.request_info Ocsigen_header.Name.authorization with | Some s -> validate ~err s | None -> reject ()) | Ocsigen_extensions.Req_found _ -> Lwt.return Ocsigen_extensions.Ext_do_nothing let parse_config element = let realm_ref = ref "" in let rest_ref = ref [] in Ocsigen_extensions.( Configuration.process_element ~in_tag:"host" ~other_elements:(fun t _ _ -> raise (Bad_config_tag_for_extension t)) ~elements:[ Configuration.element ~name:"authbasic" ~attributes:[ Configuration.attribute ~name:"realm" ~obligatory:true (fun s -> realm_ref := s) ] ~other_elements:(fun name attrs content -> rest_ref := Xml.Element (name, attrs, content) :: !rest_ref) ()] element ); let realm = !realm_ref in let auth = match !rest_ref with | [ x ] -> get_basic_authentication_method x | _ -> Ocsigen_extensions.badconfig "Bad syntax for tag authbasic" in gen ~realm ~auth (** Registration of the extension *) let () = Ocsigen_extensions.register ~name:"authbasic" ~fun_site:(fun _ _ _ _ _ _ -> parse_config) () let realm = Ocsigen_server.Site.Config.key () let auth = Ocsigen_server.Site.Config.key () let extension = Ocsigen_server.Site.create_extension (fun {Ocsigen_server.Site.Config.accessor} -> match accessor realm, accessor auth with | Some realm, Some auth -> gen ~realm ~auth | _, _ -> failwith "Authbasic realm and/or auth not set") ocsigenserver-5.0.1/src/extensions/authbasic.mli000066400000000000000000000061421417255654100220440ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module authbasic.mli * Copyright (C) 2008 Stéphane Glondu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) val section : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) (** Module [Authbasic]: Basic HTTP Authentication. *) type auth = string -> string -> bool Lwt.t (** This module implements Basic HTTP Authentication as described in {{:http://www.ietf.org/rfc/rfc2617.txt}RFC 2617}. It can be used to add an authentication layer to sites with no built-in authentication (e.g. static files). Beware, passwords are transmitted in cleartext with this scheme, so the medium should be secured somehow (by e.g. SSL). This module implements only the HTTP-related part of the protocol, and is meant to be extended with various authentication schemes. A very naive one (authentication with a single user/password, given in the configuration file) is provided. *) val register_basic_authentication_method : (Xml.xml -> auth) -> unit (** This function registers an authentication plugin: it adds a new parser to the list of available authentication schemes. This is only applied if you are running the server with an XML configuration file. Use the realm, auth variables otherwise. A parser takes as argument an XML tree (corresponding to the first son of an element in the configuration file) and returns an authentication function [f]. [f] will be called for each request with the supplied user and password and should return (cooperatively) a boolean telling whether access is granted or not. Exceptions are handled the same way as for extension parsers. The element must have a {i realm} attribute, giving some identifier to the resource which is protected (several resources on the same hostname can share the same realm). This gives a general customization scheme "for free" from the point of view of plugin developers and is totally transparent to the plugin. *) val realm : string Ocsigen_server.Site.Config.key val auth : auth Ocsigen_server.Site.Config.key val extension : Ocsigen_server.Site.extension (**/**) val get_basic_authentication_method : Xml.xml -> auth (** This function combines all the parsers registered with [register_basic_authentication_method]. It might be useful for other extensions. Not for the casual user. *) ocsigenserver-5.0.1/src/extensions/cors.ml000066400000000000000000000143761417255654100207060ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module accesscontrol.ml * Copyright (C) 2011 Pierre Chambart * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** Handle Cross-Origin Resource Sharing (CORS) headers *) let section = Lwt_log.Section.make "ocsigen:ext:cors" (*** MAIN FUNCTION ***) let default_frame () = Ocsigen_response.make (Cohttp.Response.make ~status:`OK ()) type config = { methods : Cohttp.Code.meth list option; (* None means: all method are accepted *) credentials : bool; max_age : int option; exposed_headers : string list } exception Refused let add_headers config r response = match Ocsigen_request.header r Ocsigen_header.Name.origin with | None -> Lwt.return Ocsigen_extensions.Ext_do_nothing | Some origin -> Lwt_log.ign_info_f ~section "request with origin: %s" origin; let l = [Ocsigen_header.Name.access_control_allow_origin, origin] in let l = if config.credentials then (Ocsigen_header.Name.access_control_allow_credentials, "true") :: l else l in let l = match Ocsigen_request.header r Ocsigen_header.Name.access_control_request_method with | Some request_method -> let methods = match config.methods with | None -> true | Some l -> try List.mem (Cohttp.Code.method_of_string request_method) l with _ -> false in if methods then (Ocsigen_header.Name.access_control_allow_methods, request_method) :: l else (Lwt_log.ign_info ~section "Method refused"; raise Refused) | None -> l in let l = match Ocsigen_request.header r Ocsigen_header.Name.access_control_request_headers with | Some request_headers -> (Ocsigen_header.Name.access_control_allow_headers, request_headers) :: l | None -> l in let l = match config.max_age with | Some max_age -> (Ocsigen_header.Name.access_control_max_age, string_of_int max_age) :: l | None -> l in let l = match config.exposed_headers with | [] -> l | exposed_headers -> (Ocsigen_header.Name.access_control_expose_headers, String.concat ", " exposed_headers) :: l in Lwt.return (Ocsigen_extensions.Ext_found (fun () -> Lwt.return @@ Ocsigen_response.replace_headers response l)) let main config = function | Ocsigen_extensions.Req_not_found (_, {Ocsigen_extensions.request_info ;_}) -> (match Ocsigen_request.meth request_info with | `OPTIONS -> (Lwt_log.ign_info ~section "OPTIONS request"; try add_headers config request_info (default_frame ()) with Refused -> (Lwt_log.ign_info ~section "Refused request"; Lwt.return Ocsigen_extensions.Ext_do_nothing)) | _ -> Lwt.return Ocsigen_extensions.Ext_do_nothing) | Ocsigen_extensions.Req_found ({Ocsigen_extensions.request_info; _}, response) -> Lwt_log.ign_info ~section "answered request"; add_headers config request_info response (* Register extension *) let comma_space_regexp = Ocsigen_lib.Netstring_pcre.regexp "[[:blank:]\n]*,[[:blank:]\n]*" let parse_config _ _ _parse_fun config_elem = let config = ref { methods = None; credentials = false; max_age = None; exposed_headers = [] } in Ocsigen_extensions.( Configuration.process_element ~in_tag:"host" ~other_elements:(fun t _ _ -> raise (Bad_config_tag_for_extension t)) ~elements:[ Configuration.element ~name:"cors" ~attributes:[ Configuration.attribute ~name:"credentials" (fun s -> let s = bool_of_string s in config := { !config with credentials = s }); Configuration.attribute ~name:"max_age" (fun s -> let s = Some (int_of_string s) in config := { !config with max_age = s }); Configuration.attribute ~name:"exposed_headers" (fun s -> let s = Ocsigen_lib.Netstring_pcre.split comma_space_regexp s in config := { !config with exposed_headers = s }); Configuration.attribute ~name:"methods" (fun s -> let s = Ocsigen_lib.Netstring_pcre.split comma_space_regexp s in let s = Some (List.map Cohttp.Code.method_of_string s) in config := { !config with methods = s }); ] ()] config_elem ); main !config let () = Ocsigen_extensions.register ~name:"CORS" ~fun_site:(fun _ _ _ -> parse_config) () let credentials = Ocsigen_server.Site.Config.key () let max_age = Ocsigen_server.Site.Config.key () let exposed_headers = Ocsigen_server.Site.Config.key () let methods = Ocsigen_server.Site.Config.key () let extension = Ocsigen_server.Site.create_extension (fun {Ocsigen_server.Site.Config.accessor} -> let methods = accessor methods and credentials = Ocsigen_lib.Option.get' false (accessor credentials) and max_age = accessor max_age and exposed_headers = Ocsigen_lib.Option.get' [] (accessor exposed_headers) in main {credentials ; methods ; max_age ; exposed_headers}) ocsigenserver-5.0.1/src/extensions/cors.mli000066400000000000000000000004321417255654100210430ustar00rootroot00000000000000val credentials : bool Ocsigen_server.Site.Config.key val max_age : int Ocsigen_server.Site.Config.key val exposed_headers : string list Ocsigen_server.Site.Config.key val methods : Cohttp.Code.meth list Ocsigen_server.Site.Config.key val extension : Ocsigen_server.Site.extension ocsigenserver-5.0.1/src/extensions/deflatemod.ml000066400000000000000000000322351417255654100220360ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module deflatemod.ml * Copyright (C) 2007 Gabriel Kerneis * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (* Compress output sent by the server *) open Lwt.Infix let section = Lwt_log.Section.make "ocsigen:ext:deflate" (* Content-type *) type filter = [ | `Type of string option * string option | `Extension of string ] let should_compress (t, t') url choice_list = let check = function | `Type (None, None) -> true | `Type (None, Some x') -> x' = t' | `Type (Some x, None) -> x = t | `Type (Some x, Some x') -> x = t && x' = t' | `Extension suff -> Filename.check_suffix url suff in match choice_list with | `Only l -> List.exists check l | `All_but l -> List.for_all (fun c -> not (check c)) l let compress_level = let preprocess i = if i >= 0 && i <= 9 then i else 6 in Ocsigen_config.Custom.key ~preprocess () let buffer_size = let preprocess s = if s > 0 then s else 8192 in Ocsigen_config.Custom.key ~preprocess () (* Minimal header, by X. Leroy *) let gzip_header_length = 10 let gzip_header = let gzip_header = Bytes.make gzip_header_length (Char.chr 0) in Bytes.set gzip_header 0 @@ Char.chr 0x1F; Bytes.set gzip_header 1 @@ Char.chr 0x8B; Bytes.set gzip_header 2 @@ Char.chr 8; Bytes.set gzip_header 9 @@ Char.chr 0xFF; Bytes.unsafe_to_string gzip_header (* inspired by an auxiliary function from camlzip, by Xavier Leroy *) type output_buffer = { stream: Zlib.stream; buf: bytes; mutable pos: int; mutable avail: int; mutable size : int32; mutable crc : int32; mutable add_trailer : bool } let write_int32 oz n = for i = 0 to 3 do Bytes.set oz.buf (oz.pos + i) (Char.chr (Int32.to_int (Int32.shift_right_logical n (8 * i)) land 0xff)) done; oz.pos <- oz.pos + 4; oz.avail <- oz.avail - 4; assert (oz.avail >= 0) (* puts in oz the content of buf, from pos to pos + len ; * f is the continuation of the current stream *) let rec output oz f buf pos len = assert (pos >= 0 && len >= 0 && pos + len <= String.length buf); if oz.avail = 0 then begin let cont () = output oz f buf pos len in Lwt_log.ign_info ~section "Flushing because output buffer is full"; flush oz cont end else if len = 0 then next_cont oz f else begin let (_, used_in, used_out) = try Zlib.deflate oz.stream (Bytes.unsafe_of_string buf) pos len oz.buf oz.pos oz.avail Zlib.Z_NO_FLUSH with Zlib.Error(s, s') -> raise (Ocsigen_stream.Stream_error("Error during compression: "^s^" "^s')) in oz.pos <- oz.pos + used_out; oz.avail <- oz.avail - used_out; oz.size <- Int32.add oz.size (Int32.of_int used_in); oz.crc <- Zlib.update_crc_string oz.crc buf pos used_in; output oz f buf (pos + used_in) (len - used_in) end (* Flush oz, ie. produces a new_stream with the content of oz, cleans it * and returns the continuation of the stream *) and flush oz cont = let len = oz.pos in if len = 0 then cont () else begin let buf_len = Bytes.length oz.buf in let s = if len = buf_len then Bytes.to_string oz.buf else Bytes.sub_string oz.buf 0 len in Lwt_log.ign_info ~section "Flushing!"; oz.pos <- 0 ; oz.avail <- buf_len; Ocsigen_stream.cont s cont end and next_cont oz stream = Ocsigen_stream.next (stream : string Ocsigen_stream.stream) >>= fun e -> match e with | Ocsigen_stream.Finished None -> Lwt_log.ign_info ~section "End of stream: big cleaning for zlib" ; (* loop until there is nothing left to compress and flush *) let rec finish () = (* buffer full *) if oz.avail = 0 then flush oz finish else ( (* no more input, deflates only what were left because output buffer * was full *) let (finished, _, used_out) = Zlib.deflate oz.stream oz.buf 0 0 oz.buf oz.pos oz.avail Zlib.Z_FINISH in oz.pos <- oz.pos + used_out; oz.avail <- oz.avail - used_out; if not finished then finish () else write_trailer ()) and write_trailer () = if oz.add_trailer && oz.avail < 8 then flush oz write_trailer else begin if oz.add_trailer then begin write_int32 oz oz.crc; write_int32 oz oz.size end; Lwt_log.ign_info ~section "Zlib.deflate finished, last flush"; flush oz (fun () -> Ocsigen_stream.empty None) end in finish () | Ocsigen_stream.Finished (Some s) -> next_cont oz s | Ocsigen_stream.Cont(s,f) -> output oz f s 0 (String.length s) (* deflate param : true = deflate ; false = gzip (no header in this case) *) let compress deflate stream : string Ocsigen_stream.t = let zstream = Zlib.deflate_init (Ocsigen_lib.Option.get' 6 (Ocsigen_config.Custom.find compress_level)) deflate in let finalize status = Ocsigen_stream.finalize stream status >>= fun _e -> (try Zlib.deflate_end zstream with (* ignore errors, deflate_end cleans everything anyway *) Zlib.Error _ -> ()); Lwt.return (Lwt_log.ign_info ~section "Zlib stream closed") in let oz = let buffer_size = Ocsigen_lib.Option.get' 8192 (Ocsigen_config.Custom.find buffer_size) in { stream = zstream ; buf = Bytes.create buffer_size ; pos = 0; avail = buffer_size ; size = 0l; crc = 0l; add_trailer = not deflate } in let new_stream () = next_cont oz (Ocsigen_stream.get stream) in Lwt_log.ign_info ~section "Zlib stream initialized" ; if deflate then Ocsigen_stream.make ~finalize new_stream else Ocsigen_stream.make ~finalize (fun () -> Ocsigen_stream.cont gzip_header new_stream) (* We implement Content-Encoding, not Transfer-Encoding *) type encoding = Deflate | Gzip | Id | Star | Not_acceptable let qvalue = function Some x -> x |None -> 1.0 let enc_compare e e' = match e,e' with |(Star,_),(_,_) -> -1 (* star should be at the very end *) |(_,_),(Star,_) -> 1 |(_,v),(_,v') when v 1 (* then, sort by qvalue *) |(_,v),(_,v') when v>v' -> -1 |(x,_),(x',_) when x=x' -> 0 |(Deflate,_),(_,_) -> 1 (* and subsort by encoding *) |(_,_),(Deflate,_) -> -1 |(Gzip,_),(_,_) -> 1 |(_,_),(Gzip,_) -> -1 |(Id,_),(_,_) -> 1 |(_,_),(Id,_) -> -1 |_ -> assert false let rec filtermap f = function |[] -> [] |t::q -> match f t with |Some s -> s::(filtermap f q) |None -> filtermap f q let convert = function |(Some "deflate",v) -> Some (Deflate, qvalue v) |(Some "gzip",v)|(Some "x-gzip",v) -> Some (Gzip, qvalue v) |(Some "identity",v) -> Some (Id, qvalue v) |(None,v) -> Some (Star, qvalue v) |_ -> None (* Follow http's RFC to select the transfer encoding *) let select_encoding accept_header = let h = List.sort enc_compare (filtermap convert accept_header) in let (exclude,accept) = let (e,a) = List.partition (fun x -> snd x = 0.) h in (List.map fst e, List.map fst a) in let rec aux = function |[] -> if ((List.mem Star exclude) || (List.mem Id exclude)) then Not_acceptable else Id |t::q -> if (List.mem t exclude) then aux q else t in aux accept (* deflate = true -> mode deflate deflate = false -> mode gzip *) let stream_filter contentencoding url deflate choice res = Lwt.return (Ocsigen_extensions.Ext_found (fun () -> try ( match Ocsigen_response.header res Ocsigen_header.Name.content_type with | None -> Lwt.return res | Some contenttype -> let contenttype = try String.sub contenttype 0 (String.index contenttype ';') with Not_found -> contenttype in match Ocsigen_header.Mime_type.parse contenttype with | None, _ | _, None -> Lwt.return res | Some a, Some b when should_compress (a, b) url choice -> let response, body = Ocsigen_response.to_cohttp res in let response = let headers = Cohttp.Response.headers response in let headers = let name = Ocsigen_header.Name.(to_string etag) in match Cohttp.Header.get headers name with | Some e -> Cohttp.Header.replace headers name ((if deflate then "Ddeflatemod" else "Gdeflatemod") ^ e) | None -> headers in let headers = Cohttp.Header.replace headers Ocsigen_header.Name.(to_string content_encoding) contentencoding in { response with Cohttp.Response.headers ; Cohttp.Response.encoding = Cohttp.Transfer.Chunked } and body = Cohttp_lwt.Body.to_stream body |> Ocsigen_stream.of_lwt_stream |> compress deflate |> Ocsigen_stream.to_lwt_stream |> Cohttp_lwt.Body.of_stream in Lwt.return (Ocsigen_response.update res ~body ~response) | _ -> Lwt.return res) with Not_found -> Lwt.return res)) let filter choice_list = function | Ocsigen_extensions.Req_not_found (code,_) -> Lwt.return (Ocsigen_extensions.Ext_next code) | Ocsigen_extensions.Req_found ({ Ocsigen_extensions.request_info = ri ; _ }, res) -> match Ocsigen_request.header_multi ri Ocsigen_header.Name.accept_encoding |> Ocsigen_header.Accept_encoding.parse |> select_encoding with | Deflate -> stream_filter "deflate" (Ocsigen_request.sub_path_string ri) true choice_list res | Gzip -> stream_filter "gzip" (Ocsigen_request.sub_path_string ri) false choice_list res | Id | Star -> Lwt.return (Ocsigen_extensions.Ext_found (fun () -> Lwt.return res)) | Not_acceptable -> Lwt.return (Ocsigen_extensions.Ext_stop_all (Ocsigen_response.cookies res, `Not_acceptable)) let rec parse_global_config = function | [] -> () | Xml.Element ("compress", ["level", i], []) :: ll -> let i = try int_of_string i with Failure _ -> raise (Ocsigen_extensions.Error_in_config_file "Compress level should be an integer between 0 and 9") in Ocsigen_config.Custom.set compress_level i; parse_global_config ll | Xml.Element ("buffer", ["size", s], []) :: ll -> let s = try int_of_string s with Failure _ -> raise (Ocsigen_extensions.Error_in_config_file "Buffer size should be a positive integer") in Ocsigen_config.Custom.set buffer_size s; parse_global_config ll | _ -> raise (Ocsigen_extensions.Error_in_config_file "Unexpected content inside deflatemod config") let parse_config config_elem = let mode = ref `Only in let pages = ref [] in Ocsigen_extensions.( Configuration.process_element ~in_tag:"host" ~other_elements:(fun t _ _ -> raise (Bad_config_tag_for_extension t)) ~elements:[ Configuration.element ~name:"deflate" ~attributes:[ Configuration.attribute ~name:"compress" ~obligatory:true (function | "only" -> mode := `Only | "allbut" -> mode := `All_but | _ -> badconfig "Attribute 'compress' should be 'allbut' or 'only'" ); ] ~elements:[ Configuration.element ~name:"type" ~pcdata:(fun s -> let (a, b) = Ocsigen_header.Mime_type.parse s in pages := `Type (a, b) :: !pages) (); Configuration.element ~name:"extension" ~pcdata:(fun s -> pages := `Extension s :: !pages) (); ] ()] config_elem ); match !pages with | [] -> Ocsigen_extensions.badconfig "Unexpected element inside contenttype \ (should be or )" | l -> filter (match !mode with `Only -> `Only l | `All_but -> `All_but l) let () = Ocsigen_extensions.register ~name:"deflatemod" ~fun_site:(fun _ _ _ _ _ _ -> parse_config) ~init_fun:parse_global_config () let mode = Ocsigen_server.Site.Config.key () let extension = Ocsigen_server.Site.create_extension (fun {Ocsigen_server.Site.Config.accessor} -> match accessor mode with | Some mode -> filter mode | None -> failwith "Deflatemod.mode not set") ocsigenserver-5.0.1/src/extensions/deflatemod.mli000066400000000000000000000006471417255654100222110ustar00rootroot00000000000000val section : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) val compress_level : int Ocsigen_config.Custom.key val buffer_size : int Ocsigen_config.Custom.key type filter = [ | `Type of string option * string option | `Extension of string ] val mode : [`All_but of filter list | `Only of filter list] Ocsigen_server.Site.Config.key val extension : Ocsigen_server.Site.extension ocsigenserver-5.0.1/src/extensions/dune000066400000000000000000000026051417255654100202540ustar00rootroot00000000000000(library (name accesscontrol) (public_name ocsigenserver.ext.accesscontrol) (modules accesscontrol) (libraries ocsigenserver)) (library (name authbasic) (public_name ocsigenserver.ext.authbasic) (modules authbasic) (libraries ocsigenserver)) (library (name cors) (public_name ocsigenserver.ext.cors) (modules cors) (libraries ocsigenserver)) (library (name deflatemod) (public_name ocsigenserver.ext.deflatemod) (modules deflatemod) (libraries camlzip ocsigenserver)) (library (name extendconfiguration) (public_name ocsigenserver.ext.extendconfiguration) (modules extendconfiguration) (libraries ocsigenserver)) (library (name outputfilter) (public_name ocsigenserver.ext.outputfilter) (modules outputfilter) (libraries ocsigenserver)) (library (name redirectmod) (public_name ocsigenserver.ext.redirectmod) (modules redirectmod) (libraries ocsigenserver)) (library (name revproxy) (public_name ocsigenserver.ext.revproxy) (modules revproxy) (libraries ocsigenserver)) (library (name rewritemod) (public_name ocsigenserver.ext.rewritemod) (modules rewritemod) (libraries ocsigenserver)) (library (name staticmod) (public_name ocsigenserver.ext.staticmod) (modules staticmod) (libraries ocsigenserver)) (library (name userconf) (public_name ocsigenserver.ext.userconf) (modules userconf) (libraries ocsigenserver)) ocsigenserver-5.0.1/src/extensions/extendconfiguration.ml000066400000000000000000000225031417255654100240060ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module extendconfiguration.ml * Copyright (C) 2008 Boris Yakobowski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) let name = "extendconfiguration" let bad_config s = raise (Ocsigen_extensions.Error_in_config_file s) let gen configfun = function | Ocsigen_extensions.Req_found _ -> Lwt.return Ocsigen_extensions.Ext_do_nothing | Ocsigen_extensions.Req_not_found (err, ({Ocsigen_extensions.request_config; _} as request)) -> Lwt_log.ign_info "Updating configuration"; let request = { request with Ocsigen_extensions.request_config = configfun request_config } in Lwt.return (Ocsigen_extensions.Ext_continue_with (request, Ocsigen_cookie_map.empty, err)) let gather_do_not_serve_files tag = let rec aux (regexps, files, extensions) = function | [] -> { Ocsigen_extensions.do_not_serve_regexps = regexps; do_not_serve_files = files; do_not_serve_extensions = extensions } | Xml.Element ("regexp", ["regexp", f], []) :: q -> aux (f :: regexps, files, extensions) q | Xml.Element ("file", ["file", f], []) :: q -> aux (regexps, f :: files, extensions) q | Xml.Element ("extension", ["ext", f], []) :: q -> aux (regexps, files, f :: extensions) q | _ :: _ -> bad_config ("invalid options in tag " ^ tag) in aux ([], [], []) exception Bad_regexp of string let check_regexp_list = let hashtbl = Hashtbl.create 17 in List.iter @@ fun r -> try Hashtbl.find hashtbl r with Not_found -> try ignore (Ocsigen_lib.Netstring_pcre.regexp r); Hashtbl.add hashtbl r () with _ -> raise (Bad_regexp r) let fun_site usermode _ _ _ _ _ = function | Xml.Element ("listdirs", ["value", "true"], []) -> gen @@ fun config -> { config with Ocsigen_extensions.list_directory_content = true } | Xml.Element ("listdirs", ["value", "false"], []) -> gen @@ fun config -> { config with Ocsigen_extensions.list_directory_content = false } | Xml.Element ("listdirs" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Xml.Element ("followsymlinks", ["value", follow_symlinks], []) -> let follow_symlinks = match follow_symlinks with | "never" -> `No | "always" -> (match usermode with | None -> `Always | Some _ -> raise (Ocsigen_extensions.Error_in_user_config_file "Cannot specify value 'always' for option \ 'followsymlinks' in userconf files")) | "ownermatch" -> `Owner_match | _ -> bad_config ("Wrong value \"" ^ follow_symlinks ^ "\" for option \"followsymlinks\"") in gen @@ fun config -> { config with Ocsigen_extensions.follow_symlinks } | Xml.Element ("followsymlinks" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Xml.Element ("charset", attrs, exts) -> let rec aux charset_assoc = function | [] -> charset_assoc | Xml.Element ("extension", ["ext", extension; "value", charset], []) :: q -> aux (Ocsigen_charset_mime.update_charset_ext charset_assoc extension charset) q | Xml.Element ("file", ["file", file; "value", charset], []) :: q -> aux (Ocsigen_charset_mime.update_charset_file charset_assoc file charset) q | Xml.Element ("regexp", ["regexp", regexp; "value", charset], []) :: q -> (try let r = Ocsigen_lib.Netstring_pcre.regexp regexp in aux (Ocsigen_charset_mime.update_charset_regexp charset_assoc r charset) q with _ -> bad_config "invalid regexp '%s' in ") | _ :: _ -> bad_config "invalid subtag in option charset" in gen (fun config -> let config = match attrs with | ["default", s] -> { config with Ocsigen_extensions.charset_assoc = Ocsigen_charset_mime.set_default_charset config.Ocsigen_extensions.charset_assoc s } | [] -> config | _ -> bad_config "Only attribute \"default\" is permitted \ for option \"charset\"" in { config with Ocsigen_extensions.charset_assoc = aux config.Ocsigen_extensions.charset_assoc exts }) | Xml.Element ("contenttype", attrs, exts) -> let rec aux mime_assoc = function | [] -> mime_assoc | Xml.Element ("extension", ["ext", extension; "value", mime], []) :: q -> aux (Ocsigen_charset_mime.update_mime_ext mime_assoc extension mime) q | Xml.Element ("file", ["file", file; "value", mime], []) :: q -> aux (Ocsigen_charset_mime.update_mime_file mime_assoc file mime) q | Xml.Element ("regexp", ["regexp", regexp; "value", mime], []) :: q -> (try let r = Ocsigen_lib.Netstring_pcre.regexp regexp in aux (Ocsigen_charset_mime.update_mime_regexp mime_assoc r mime) q with _ -> bad_config "invalid regexp '%s' in ") | _ :: _ -> bad_config "invalid subtag in option mime" in gen (fun config -> let config = match attrs with | ["default", s] -> { config with Ocsigen_extensions.mime_assoc = Ocsigen_charset_mime.set_default_mime config.Ocsigen_extensions.mime_assoc s } | [] -> config | _ -> bad_config "Only attribute \"default\" is permitted \ for option \"contenttype\"" in { config with Ocsigen_extensions.mime_assoc = aux config.Ocsigen_extensions.mime_assoc exts }) | Xml.Element ("defaultindex", [], l) -> let rec aux indexes = function | [] -> List.rev indexes | Xml.Element ("index", [], [Xml.PCData f]) :: q -> aux (f :: indexes) q | _ :: _ -> bad_config "subtags must be of the form \ ... \ in option defaultindex" in gen (fun config -> { config with Ocsigen_extensions.default_directory_index = aux [] l }) | Xml.Element ("defaultindex" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Xml.Element ("hidefile", [], l) -> let do_not_serve = gather_do_not_serve_files "hidefile" l in (try check_regexp_list do_not_serve.Ocsigen_extensions.do_not_serve_regexps; gen (fun config -> { config with Ocsigen_extensions.do_not_serve_404 = Ocsigen_extensions.join_do_not_serve do_not_serve config.Ocsigen_extensions.do_not_serve_404 }) with Bad_regexp r -> Ocsigen_extensions.badconfig "Invalid regexp %s in %s" r "hidefile") | Xml.Element ("hidefile" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Xml.Element ("forbidfile", [], l) -> let do_not_serve = gather_do_not_serve_files "forbidfile" l in (try check_regexp_list do_not_serve.Ocsigen_extensions.do_not_serve_regexps; gen (fun config -> { config with Ocsigen_extensions.do_not_serve_403 = Ocsigen_extensions.join_do_not_serve do_not_serve config.Ocsigen_extensions.do_not_serve_403 }) with Bad_regexp r -> Ocsigen_extensions.badconfig "Invalid regexp %s in %s" r "forbidfile") | Xml.Element ("forbidfile" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Xml.Element ("uploaddir", [], [Xml.PCData s]) -> gen @@ if s = "" then fun config -> { config with Ocsigen_extensions.uploaddir = None } else fun config -> { config with Ocsigen_extensions.uploaddir = Some s } | Xml.Element ("uploaddir" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Xml.Element ("maxuploadfilesize" as tag, [], [Xml.PCData s]) -> let s = try Ocsigen_parseconfig.parse_size_tag "uploaddir" s with Ocsigen_config.Config_file_error _ -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" tag in gen @@ fun config -> { config with Ocsigen_extensions.maxuploadfilesize = s } | Xml.Element ("maxuploadfilesize" as s, _, _) -> Ocsigen_extensions.badconfig "Bad syntax for tag %s" s | Xml.Element (t, _, _) -> raise (Ocsigen_extensions.Bad_config_tag_for_extension t) | _ -> raise (Ocsigen_extensions.Error_in_config_file "Unexpected data in config file") let () = Ocsigen_extensions.register ~name ~fun_site () ocsigenserver-5.0.1/src/extensions/outputfilter.ml000066400000000000000000000125611417255654100225000ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module outputfilter.ml * Copyright (C) 2008 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (* This module enables rewritting the server output *) type header_filter = [ | `Rewrite of (Ocsigen_header.Name.t * Pcre.regexp * string) | `Add of (Ocsigen_header.Name.t * string * bool option) ] let gen filter = function | Ocsigen_extensions.Req_not_found (code, _) -> Lwt.return (Ocsigen_extensions.Ext_next code) | Ocsigen_extensions.Req_found (_ri, res) -> Lwt.return @@ Ocsigen_extensions.Ext_found (fun () -> Lwt.return @@ match filter with | `Rewrite (header, regexp, dest) -> (try let l = List.map (Ocsigen_lib.Netstring_pcre.global_replace regexp dest) (Ocsigen_response.header_multi res header) and a = Ocsigen_response.remove_header res header in Ocsigen_response.add_header_multi a header l with Not_found -> res) | `Add (header, dest, replace) -> match replace with | None -> (match Ocsigen_response.header res header with | Some _ -> res | None -> Ocsigen_response.add_header res header dest) | Some false -> Ocsigen_response.add_header res header dest | Some true -> Ocsigen_response.replace_header res header dest) let gen_code code = function | Ocsigen_extensions.Req_not_found (code, _) -> Lwt.return (Ocsigen_extensions.Ext_next code) | Ocsigen_extensions.Req_found (_ri, res) -> Lwt.return @@ Ocsigen_extensions.Ext_found (fun () -> Lwt.return (Ocsigen_response.set_status res code)) let parse_config config_elem = let header = ref None in let regexp = ref None in let dest = ref None in let replace = ref None in let code = ref None in Ocsigen_extensions.( Configuration.process_element ~in_tag:"host" ~other_elements:(fun t _ _ -> raise (Bad_config_tag_for_extension t)) ~elements:[ Configuration.element ~name:"outputfilter" ~attributes:[ Configuration.attribute ~name:"header" (fun s -> header := Some s); Configuration.attribute ~name:"regexp" (fun s -> regexp := Some (Ocsigen_lib.Netstring_pcre.regexp s)); Configuration.attribute ~name:"dest" (fun s -> dest := Some s); Configuration.attribute ~name:"replace" (fun s -> try replace := Some (bool_of_string s) with | Invalid_argument _ -> badconfig "Wrong value for attribute \ replace of : \ %s. It should be true or false" s ); ] (); Configuration.element ~name:"sethttpcode" ~attributes:[ Configuration.attribute ~name:"code" (fun s -> try match Cohttp.Code.status_of_code (int_of_string s) with | #Cohttp.Code.status as status -> code := Some status | `Code _ -> failwith "Invalid code" with Failure _ -> badconfig "Invalid code attribute in " ); ] ()] config_elem ); match !code with | None -> begin match !header, !regexp, !dest, !replace with | (_, Some _, _, Some _) -> Ocsigen_extensions.badconfig "Wrong attributes for : attributes regexp and \ replace can't be set simultaneously" | (Some h, Some r, Some d, None) -> gen (`Rewrite (Ocsigen_header.Name.of_string h, r, d)) | (Some h, None, Some d, rep) -> gen (`Add (Ocsigen_header.Name.of_string h, d, rep)) | _ -> Ocsigen_extensions.badconfig "Wrong attributes for " end | Some code -> gen_code code let () = Ocsigen_extensions.register ~name:"outputfilter" ~fun_site:(fun _ _ _ _ _ _ -> parse_config) () let mode = Ocsigen_server.Site.Config.key () let extension = Ocsigen_server.Site.create_extension (fun {Ocsigen_server.Site.Config.accessor} -> match accessor mode with | Some (`Code c) -> gen_code c | Some (#header_filter as f) -> gen f | None -> failwith "Outputfilter.mode not set") ocsigenserver-5.0.1/src/extensions/outputfilter.mli000066400000000000000000000003671417255654100226520ustar00rootroot00000000000000val mode : [ `Rewrite of (Ocsigen_header.Name.t * Pcre.regexp * string) | `Add of (Ocsigen_header.Name.t * string * bool option) | `Code of Cohttp.Code.status ] Ocsigen_server.Site.Config.key val extension : Ocsigen_server.Site.extension ocsigenserver-5.0.1/src/extensions/redirectmod.ml000066400000000000000000000106131417255654100222270ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module redirectmod.ml * Copyright (C) 2007 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (* Define page redirections in the configuration file *) let section = Lwt_log.Section.make "ocsigen:ext:redirectmod" (* The table of redirections for each virtual server *) type redirection = { r_regexp : Pcre.regexp ; r_dest : string ; r_full : [`Yes | `No | `Maybe] ; r_temp : bool } let create_redirection ?(full = `Yes) ?(temporary = false) ~regexp r_dest = let r_regexp = Pcre.regexp ("^" ^ regexp ^ "$") in { r_regexp ; r_dest ; r_full = full ; r_temp = temporary } let attempt_redir { r_regexp ; r_dest ; r_full ; r_temp } _err ri () = Lwt_log.ign_info ~section "Is it a redirection?"; let redir = let find full = Ocsigen_extensions.find_redirection r_regexp full r_dest ri in match r_full with | `Yes -> find true | `No -> find false | `Maybe -> try find false with Ocsigen_extensions.Not_concerned -> find true in Lwt_log.ign_info_f ~section "YES! %s redirection to: %s" (if r_temp then "Temporary " else "Permanent ") redir; Lwt.return @@ Ocsigen_extensions.Ext_found (fun () -> Lwt.return @@ Ocsigen_response.make @@ let headers = Cohttp.Header.(init_with "Location" redir) and status = if r_temp then `Found else `Moved_permanently in Cohttp.Response.make ~status ~headers ()) (** The function that will generate the pages from the request *) let gen dir = function | Ocsigen_extensions.Req_found _ -> Lwt.return Ocsigen_extensions.Ext_do_nothing | Ocsigen_extensions.Req_not_found (err, {Ocsigen_extensions.request_info; _}) -> Lwt.catch (attempt_redir dir err request_info) @@ function | Ocsigen_extensions.Not_concerned -> Lwt.return (Ocsigen_extensions.Ext_next err) | e -> Lwt.fail e let parse_config config_elem = let regexp = ref None and dest = ref "" and mode = ref `Yes and temporary = ref false in Ocsigen_extensions.( Configuration.process_element ~in_tag:"host" ~other_elements:(fun t _ _ -> raise (Bad_config_tag_for_extension t)) ~elements:[ Configuration.element ~name:"redirect" ~attributes:[ Configuration.attribute ~name:"regexp" (fun s -> regexp := Some ("^" ^ s ^ "$"); mode := `Maybe); Configuration.attribute ~name:"fullurl" (fun s -> regexp := Some s; mode := `Yes); Configuration.attribute ~name:"suburl" (fun s -> regexp := Some s; mode := `No); Configuration.attribute ~name:"dest" ~obligatory:true (fun s -> dest := s); Configuration.attribute ~name:"temporary" (function "temporary" -> temporary := true | _ -> ()); ] ()] config_elem ); match !regexp with | None -> Ocsigen_extensions.badconfig "Missing attribute regexp for " | Some regexp -> gen (create_redirection ~full:!mode ~regexp ~temporary:!temporary !dest) let () = Ocsigen_extensions.register ~name:"redirectmod" ~fun_site:(fun _ _ _ _ _ _ -> parse_config) () let redirection = Ocsigen_server.Site.Config.key () let extension = Ocsigen_server.Site.create_extension (fun {Ocsigen_server.Site.Config.accessor} -> match accessor redirection with | Some redirection -> gen redirection | None -> failwith "Redirectmod.redirection not set") ocsigenserver-5.0.1/src/extensions/redirectmod.mli000066400000000000000000000005361417255654100224030ustar00rootroot00000000000000val section : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) type redirection val create_redirection : ?full : [ `Maybe | `No | `Yes ] -> ?temporary : bool -> regexp : string -> string -> redirection val redirection : redirection Ocsigen_server.Site.Config.key val extension : Ocsigen_server.Site.extension ocsigenserver-5.0.1/src/extensions/revproxy.ml000066400000000000000000000165261417255654100216350ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module revproxy.ml * Copyright (C) 2007 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** Reverse proxy for Ocsigen The reverse proxy is still experimental. *) open Lwt.Infix let section = Lwt_log.Section.make "ocsigen:ext:revproxy" exception Bad_answer_from_http_server (** The table of redirections for each virtual server *) type redir = { regexp : Pcre.regexp ; full_url : Ocsigen_lib.yesnomaybe ; dest : string ; pipeline : bool ; keephost : bool } (** Generate the pages from the request *) let gen dir = function | Ocsigen_extensions.Req_found _ -> Lwt.return Ocsigen_extensions.Ext_do_nothing | Ocsigen_extensions.Req_not_found (err, {Ocsigen_extensions.request_info; _}) -> Lwt.catch (* Is it a redirection? *) (fun () -> Lwt_log.ign_info ~section "Is it a redirection?"; let dest = let fi full = Ocsigen_extensions.find_redirection dir.regexp full dir.dest request_info in match dir.full_url with | Ocsigen_lib.Yes -> fi true | Ocsigen_lib.No -> fi false | Ocsigen_lib.Maybe -> try fi false with Ocsigen_extensions.Not_concerned -> fi true in let (https, host, port, path) = try (* FIXME: we do not seem to handle GET parameters. Why? *) match Ocsigen_lib.Url.parse dest with | (Some https, Some host, port, path, _, _, _) -> let port = match port with | None -> if https then 443 else 80 | Some p -> p in (https, host, port, path) | _ -> raise (Ocsigen_extensions.Error_in_config_file ("Revproxy : error in destination URL "^dest)) (*VVV catch only URL-related exceptions? *) with e -> raise (Ocsigen_extensions.Error_in_config_file ("Revproxy : error in destination URL "^dest^" - "^ Printexc.to_string e)) in Lwt_log.ign_info_f ~section "YES! Redirection to http%s://%s:%d/%s" (if https then "s" else "") host port path; Ocsigen_lib.Ip_address.get_inet_addr host >>= fun _inet_addr -> (* It is now safe to start processing next request. We are sure that the request won't be taken in disorder, so we return. *) let do_request () = let headers = let h = Cohttp.Request.headers (Ocsigen_request.to_cohttp request_info) in let h = Ocsigen_request.version request_info |> Cohttp.Code.string_of_version |> Cohttp.Header.replace h Ocsigen_header.Name.(to_string x_forwarded_proto) in let h = let forward = let address = Unix.string_of_inet_addr (Ocsigen_request.address request_info) in String.concat ", " (Ocsigen_request.remote_ip request_info :: Ocsigen_request.forward_ip request_info @ [address]) in Cohttp.Header.replace h Ocsigen_header.Name.(to_string x_forwarded_for) forward in Cohttp.Header.remove h Ocsigen_header.Name.(to_string host) and uri = let scheme = if Ocsigen_request.ssl request_info then "https" else "http" and host = match if dir.keephost then Ocsigen_request.host request_info else None with | Some host -> host | None -> host in Uri.make ~scheme ~host ~port ~path () and body = Ocsigen_request.body request_info and meth = Ocsigen_request.meth request_info in Cohttp_lwt_unix.Client.call ~headers ~body meth uri in Lwt.return @@ Ocsigen_extensions.Ext_found (fun () -> do_request () >|= Ocsigen_response.of_cohttp)) (function | Ocsigen_extensions.Not_concerned -> Lwt.return (Ocsigen_extensions.Ext_next err) | e -> Lwt.fail e) let parse_config config_elem = let regexp = ref None in let full_url = ref Ocsigen_lib.Yes in let dest = ref None in let pipeline = ref true in let keephost = ref false in Ocsigen_extensions.( Configuration.process_element ~in_tag:"host" ~other_elements:(fun t _ _ -> raise (Bad_config_tag_for_extension t)) ~elements:[ Configuration.element ~name:"revproxy" ~attributes:[ Configuration.attribute ~name:"regexp" (fun s -> regexp := Some s; full_url := Ocsigen_lib.Yes); Configuration.attribute ~name:"fullurl" (fun s -> regexp := Some s; full_url := Ocsigen_lib.Yes); Configuration.attribute ~name:"suburl" (fun s -> regexp := Some s; full_url := Ocsigen_lib.No); Configuration.attribute ~name:"dest" (fun s -> dest := Some s); Configuration.attribute ~name:"keephost" (function "keephost" -> keephost := true | _ -> ()); Configuration.attribute ~name:"nopipeline" (function "nopipeline" -> pipeline := false | _ -> ()); ] ()] config_elem ); match !regexp, !full_url, !dest, !pipeline, !keephost with | (None, _, _, _, _) -> Ocsigen_extensions.badconfig "Missing attribute 'regexp' for " | (_, _, None, _, _) -> Ocsigen_extensions.badconfig "Missing attribute 'dest' for " | (Some regexp, full_url, Some dest, pipeline, keephost) -> gen { regexp = Ocsigen_lib.Netstring_pcre.regexp ("^" ^ regexp ^ "$"); full_url; dest; pipeline; keephost; } let () = Ocsigen_extensions.register ~name:"revproxy" ~fun_site:(fun _ _ _ _ _ _ -> parse_config) ~respect_pipeline:true (* We ask ocsigen to respect pipeline order when sending to extensions! *) () ocsigenserver-5.0.1/src/extensions/rewritemod.ml000066400000000000000000000113511417255654100221070ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module rewritemod.ml * Copyright (C) 2008 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (* Rewrite URLs in the configuration file *) (* IMPORTANT WARNING It is really basic for now: - rewrites only subpaths (and doees not change get parameters) - changes only ri_sub_path and ri_sub_path_string not ri_full_path, nor ri_full_path_string, nor ri_url_string, nor ri_url This is probably NOT what we want... *) let section = Lwt_log.Section.make "ocsigen:ext:rewritemod" exception Not_concerned (* The table of rewrites for each virtual server *) type assockind = Regexp of Pcre.regexp * string * bool let find_rewrite (Regexp (regexp, dest, fullrewrite)) suburl = (match Ocsigen_lib.Netstring_pcre.string_match regexp suburl 0 with | None -> raise Not_concerned | Some _ -> (* Matching regexp found! *) Ocsigen_lib.Netstring_pcre.global_replace regexp dest suburl), fullrewrite (* The function that will generate the pages from the request *) let gen regexp continue = function | Ocsigen_extensions.Req_found _ -> Lwt.return Ocsigen_extensions.Ext_do_nothing | Ocsigen_extensions.Req_not_found (err, ri) -> let try_block () = Lwt_log.ign_info ~section "Is it a rewrite?"; let redir, full_rewrite = let ri = ri.Ocsigen_extensions.request_info in find_rewrite regexp (match Ocsigen_request.query ri with | None -> Ocsigen_request.sub_path_string ri | Some g -> Ocsigen_request.sub_path_string ri ^ "?" ^ g) in Lwt_log.ign_info_f ~section "YES! rewrite to: %s" redir; if continue then Lwt.return @@ Ocsigen_extensions.Ext_continue_with ({ ri with Ocsigen_extensions.request_info = Ocsigen_request.update ~full_rewrite ~uri:(Uri.of_string redir) ri.Ocsigen_extensions.request_info }, Ocsigen_cookie_map.empty, err) else Lwt.return @@ Ocsigen_extensions.Ext_retry_with ({ ri with Ocsigen_extensions.request_info = Ocsigen_request.update ~full_rewrite ~uri:(Uri.of_string redir) ri.Ocsigen_extensions.request_info }, Ocsigen_cookie_map.empty) and catch_block = function | Ocsigen_extensions.Not_concerned -> Lwt.return (Ocsigen_extensions.Ext_next err) | e -> Lwt.fail e in Lwt.catch try_block catch_block let parse_config element = let regexp = ref "" in let dest = ref None in let fullrewrite = ref false in let continue = ref false in Ocsigen_extensions.( Configuration.process_element ~in_tag:"host" ~other_elements:(fun t _ _ -> raise (Bad_config_tag_for_extension t)) ~elements:[ Configuration.element ~name:"rewrite" ~attributes:[ Configuration.attribute ~name:"regexp" ~obligatory:true (fun s -> regexp := s); Configuration.attribute ~name:"url" (fun s -> dest := Some s); Configuration.attribute ~name:"dest" (fun s -> dest := Some s); Configuration.attribute ~name:"fullrewrite" (fun s -> fullrewrite := (s = "fullrewrite" || s = "true")); Configuration.attribute ~name:"continue" (fun s -> continue := (s = "continue" || s = "true")); ] ()] element ); match !dest with | None -> raise (Ocsigen_extensions.Error_in_config_file "url attribute expected for ") | Some dest -> gen (Regexp ((Ocsigen_lib.Netstring_pcre.regexp ("^" ^ !regexp ^ "$")), dest, !fullrewrite)) !continue (** Registration of the extension *) let () = Ocsigen_extensions.register ~name:"rewritemod" ~fun_site:(fun _ _ _ _ _ _ -> parse_config) () ocsigenserver-5.0.1/src/extensions/staticmod.ml000066400000000000000000000263511417255654100217230ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module staticmod.ml * Copyright (C) 2005 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) open Lwt.Infix let name = "staticmod" let section = Lwt_log.Section.make "ocsigen:ext:staticmod" exception Not_concerned (* Structures describing the static pages a each virtual server *) (* A static site is either an entire directory served unconditionally, or a more elaborate redirection based on regexpes and http error codes. See the web documentation of staticmod for detail *) type static_site_kind = | Dir of string (* Serves an entire directory *) | Regexp of regexp_site and regexp_site = { source_regexp: Pcre.regexp; dest: Ocsigen_extensions.ud_string; http_status_filter: Pcre.regexp option; root_checks: Ocsigen_extensions.ud_string option; } (* Finding files *) (* Does the http status code returned for the page match the given filter ? *) let http_status_match status_filter status = match status_filter with | None -> true | Some r -> Ocsigen_lib.Netstring_pcre.string_match r (string_of_int Cohttp.Code.(code_of_status (status :> status_code))) 0 <> None (* Checks that the path specified in a userconf is correct. Currently, we check that the path does not contain ".." *) let correct_user_local_file = let regexp = Ocsigen_lib.Netstring_pcre.regexp "(/\\.\\./)|(/\\.\\.$)" in fun path -> try ignore(Ocsigen_lib.Netstring_pcre.search_forward regexp path 0); false with Not_found -> true (* Find the local file corresponding to [path] in the static site [dir], with [err] as the current http status (in case [dir] is a filter). Raises [Not_Concerned] if [dir] does not match, or returns - a boolean indicating that [dir] is an error handler - the local file If the parameter [usermode] is true, we check that the path is valid. *) let find_static_page ~request ~usermode ~dir ~(err : Cohttp.Code.status) ~pathstring = let status_filter, filename, root = match dir with | Dir d -> (false, Filename.concat d pathstring, (match usermode with | None -> Some d | Some { Ocsigen_extensions.localfiles_root } -> Some localfiles_root )) | Regexp { source_regexp = source; dest = dest; http_status_filter = status_filter; root_checks = rc } when http_status_match status_filter err -> let status_filter = status_filter <> None and file = match Ocsigen_lib.Netstring_pcre.string_match source pathstring 0 with | None -> raise Not_concerned | Some _ -> Ocsigen_extensions.replace_user_dir source dest pathstring and root_checks = (match rc, usermode with | None, Some { Ocsigen_extensions.localfiles_root = r } -> Some r | Some _, Some _ -> raise (Ocsigen_extensions.Error_in_user_config_file "Staticmod: cannot specify option 'root' in \ user configuration files") | None, None -> None | Some rc, None -> Some (Ocsigen_extensions.replace_user_dir source rc pathstring) ) in status_filter, file, root_checks | _ -> raise Not_concerned in if usermode = None || correct_user_local_file filename then (status_filter, Ocsigen_local_files.resolve ?no_check_for:root ~request ~filename ()) else raise (Ocsigen_extensions.Error_in_user_config_file "Staticmod: cannot use '..' in user paths") let gen ~usermode ?cache dir = function | Ocsigen_extensions.Req_found _ -> Lwt.return (Ocsigen_extensions.Ext_do_nothing) | Ocsigen_extensions.Req_not_found (err, ({ Ocsigen_extensions.request_info ; _ } as request)) -> let try_block () = Lwt_log.ign_info ~section "Is it a static file?"; let status_filter, page = let pathstring = Ocsigen_lib.Url.string_of_url_path ~encode:false (Ocsigen_request.sub_path request_info) in find_static_page ~request ~usermode ~dir ~err ~pathstring in let fname = match page with | Ocsigen_local_files.RFile fname -> fname | Ocsigen_local_files.RDir _ -> failwith "FIXME: staticmod dirs not implemented" in Cohttp_lwt_unix.Server.respond_file ~fname () >>= fun answer -> let answer = Ocsigen_response.of_cohttp answer in let answer = if not status_filter then answer else Ocsigen_response.set_status answer err in let answer = match cache with | None -> answer | Some duration -> let cache_control, expires = if duration = 0 then "no-cache", "0" else "max-age=" ^ string_of_int duration, Ocsigen_lib.Date.to_string (Unix.time () +. float_of_int duration) in Ocsigen_response.replace_headers answer [ Ocsigen_header.Name.cache_control , cache_control ; Ocsigen_header.Name.expires , expires ; ] in Lwt.return (Ocsigen_extensions.Ext_found (fun () -> Lwt.return answer)) and catch_block = function | Ocsigen_local_files.Failed_403 -> Lwt.return (Ocsigen_extensions.Ext_next `Forbidden) (* XXX We should try to leave an information about this error for later *) | Ocsigen_local_files.NotReadableDirectory -> Lwt.return (Ocsigen_extensions.Ext_next err) | Ocsigen_extensions.NoSuchUser | Ocsigen_extensions.Not_concerned | Ocsigen_local_files.Failed_404 -> Lwt.return (Ocsigen_extensions.Ext_next err) | e -> Lwt.fail e in Lwt.catch try_block catch_block (*****************************************************************************) (** Parsing of config file *) (* In userconf modes, paths must be relative to the root of the userconf config *) let rewrite_local_path userconf path = match userconf with | None -> path | Some { Ocsigen_extensions.localfiles_root } -> localfiles_root ^ "/" ^ path type options = { opt_dir: string option; opt_regexp: Pcre.regexp option; opt_code: Pcre.regexp option; opt_dest: Ocsigen_extensions.ud_string option; opt_root_checks: Ocsigen_extensions.ud_string option; opt_cache: int option; } let kind dir regexp code dest root_checks = match dir, regexp, code, dest, root_checks with | (None, None, None, _, _) -> Ocsigen_extensions.badconfig "Missing attribute dir, regexp, or code for " | (Some d, None, None, None, None) -> Dir (Ocsigen_lib.Url.remove_end_slash d) | (None, Some r, code, Some t, rc) -> Regexp { source_regexp = r; dest = t; http_status_filter = code; root_checks = rc; } | (None, None, (Some _ as code), Some t, None) -> Regexp { dest = t; http_status_filter = code; root_checks = None; source_regexp = Ocsigen_lib.Netstring_pcre.regexp "^.*$" } | _ -> Ocsigen_extensions.badconfig "Wrong attributes for " let parse_config userconf _ : Ocsigen_extensions.parse_config_aux = fun _ _ _ element -> let opt = ref { opt_dir = None; opt_regexp = None; opt_code = None; opt_dest = None; opt_root_checks = None; opt_cache = None; } in Ocsigen_extensions.( Configuration.process_element ~in_tag:"host" ~other_elements:(fun t _ _ -> raise (Bad_config_tag_for_extension t)) ~elements:[ Configuration.element ~name:"static" ~attributes:[ Configuration.attribute ~name:"dir" (fun s -> opt := { !opt with opt_dir = Some (rewrite_local_path userconf s) }); Configuration.attribute ~name:"regexp" (fun s -> let s = try Ocsigen_lib.Netstring_pcre.regexp ("^"^s^"$") with Pcre.Error (Pcre.BadPattern _) -> badconfig "Bad regexp \"%s\" in " s in opt := { !opt with opt_regexp = Some s}); Configuration.attribute ~name:"code" (fun s -> let c = try Ocsigen_lib.Netstring_pcre.regexp ("^" ^ s ^"$") with Pcre.Error (Pcre.BadPattern _) -> badconfig "Bad regexp \"%s\" in " s in opt := { !opt with opt_code = Some c }); Configuration.attribute ~name:"dest" (fun s -> let s = Some (parse_user_dir (rewrite_local_path userconf s)) in opt := { !opt with opt_dest = s }); Configuration.attribute ~name:"root" (fun s -> let s = Some (parse_user_dir s) in opt := { !opt with opt_root_checks = s }); Configuration.attribute ~name:"cache" (fun s -> let duration = match s with | "no" -> 0 | s -> try int_of_string s with Failure _ -> badconfig "Bad integer \"%s\" in " s in opt := { !opt with opt_cache = Some duration }); ] () ] element ); gen ~usermode:userconf ?cache:!opt.opt_cache @@ kind !opt.opt_dir !opt.opt_regexp !opt.opt_code !opt.opt_dest !opt.opt_root_checks let () = Ocsigen_extensions.register ~name ~fun_site:(fun path _ -> parse_config path) () (* TODO: fix names and types, preprocess as we do for XML *) let preprocess s = "^" ^ s ^ "$" let dir = Ocsigen_server.Site.Config.key () let regexp = Ocsigen_server.Site.Config.key ~preprocess () let code = Ocsigen_server.Site.Config.key ~preprocess () let dest = Ocsigen_server.Site.Config.key () let root_checks = Ocsigen_server.Site.Config.key () let extension = Ocsigen_server.Site.create_extension (fun {Ocsigen_server.Site.Config.accessor} -> let kind = kind (accessor dir) (Ocsigen_lib.Option.map Pcre.regexp (accessor regexp)) (Ocsigen_lib.Option.map Pcre.regexp (accessor code)) (accessor dest) (accessor root_checks) in gen ~usermode:None kind) ocsigenserver-5.0.1/src/extensions/staticmod.mli000066400000000000000000000006671417255654100220760ustar00rootroot00000000000000val section : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) val dir : string Ocsigen_server.Site.Config.key val regexp : string Ocsigen_server.Site.Config.key val code : string Ocsigen_server.Site.Config.key val dest : Ocsigen_extensions.ud_string Ocsigen_server.Site.Config.key val root_checks : Ocsigen_extensions.ud_string Ocsigen_server.Site.Config.key val extension : Ocsigen_server.Site.extension ocsigenserver-5.0.1/src/extensions/userconf.ml000066400000000000000000000171351417255654100215600ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module userconf.ml * Copyright (C) 2007 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (* Local (users) config files *) open Lwt.Infix exception NoConfFile let section = Lwt_log.Section.make "ocsigen:ext:userconf" let err_500 = Ocsigen_extensions.Ext_stop_site (Ocsigen_cookie_map.empty, `Internal_server_error) let handle_parsing_error {Ocsigen_extensions.request_info ;_} = function | Ocsigen_extensions.Error_in_config_file s -> Lwt_log.ign_error_f ~section "Syntax error in userconf configuration file for url %s: %s" (Uri.to_string (Ocsigen_request.uri request_info)) s; Lwt.return err_500 | Ocsigen_extensions.Error_in_user_config_file s -> Lwt_log.ign_error_f ~section "Unauthorized option in user configuration for url %s: %s" (Uri.to_string (Ocsigen_request.uri request_info)) s; Lwt.return err_500 | e -> Lwt.fail e (* Answer returned by userconf when the url matches *) let subresult new_req user_parse_site conf previous_err req req_state = Ocsigen_extensions.Ext_sub_result (fun cookies_to_set _rs -> (* XXX why is rs above never used ?? *) Lwt.catch (fun () -> user_parse_site conf cookies_to_set (Ocsigen_extensions.Req_not_found (previous_err, new_req)) >>= fun (answer, cookies) -> (* If the request is not satisfied by userconf, the changes in configuration (in request_config) are preserved for the remainder of the enclosing (in the Ext_continue and Ext_found_continue cases below) *) let rec aux ((answer, cts) as r) = match answer with | Ocsigen_extensions.Ext_sub_result sr -> (* XXX Are these the good cookies ?? *) sr cookies_to_set req_state >>= aux | Ocsigen_extensions.Ext_continue_with ({Ocsigen_extensions.request_config ;_}, cookies, err) -> Lwt.return ((Ocsigen_extensions.Ext_continue_with ({req with Ocsigen_extensions.request_config}, cookies, err)), cts) | Ocsigen_extensions.Ext_found_continue_with r -> (* We keep config information outside userconf! *) Lwt.return (Ocsigen_extensions.Ext_found_continue_with (fun () -> r () >|= fun (r, {Ocsigen_extensions.request_config ;_}) -> r, { req with Ocsigen_extensions.request_config } ), cts) | _ -> Lwt.return r in aux (answer, cookies) ) (fun e -> handle_parsing_error req e >>= fun answer -> Lwt.return (answer, Ocsigen_cookie_map.empty)) ) let conf_to_xml conf = try [Xml.parse_file conf] with | Sys_error _ -> raise NoConfFile | Xml.Error (s, loc) -> let begin_char, end_char = Xml.range loc and line = Xml.line loc in raise (Ocsigen_extensions.Error_in_config_file (Printf.sprintf "%s, line %d, characters %d-%d" (Xml.error_msg s) line begin_char end_char)) let gen hostpattern sitepath (regexp, conf, url, prefix, localpath) = function | Ocsigen_extensions.Req_found _ -> (* We do not allow setting filters through userconf files right now *) Lwt.return Ocsigen_extensions.Ext_do_nothing | Ocsigen_extensions.Req_not_found (previous_err, ({Ocsigen_extensions.request_info ; request_config} as req)) as req_state -> let path = (Ocsigen_request.sub_path_string request_info) in match Ocsigen_lib.Netstring_pcre.string_match regexp path 0 with | None -> Lwt.return (Ocsigen_extensions.Ext_next previous_err) | Some _ -> try Lwt_log.ign_info ~section "Using user configuration"; let conf0 = Ocsigen_extensions.replace_user_dir regexp conf path in let uri = Uri.of_string (Ocsigen_lib.Netstring_pcre.global_replace regexp url path) and prefix = Ocsigen_lib.Netstring_pcre.global_replace regexp prefix path and userconf_options = { Ocsigen_extensions.localfiles_root = Ocsigen_extensions.replace_user_dir regexp localpath path } and conf = conf_to_xml conf0 in let user_parse_host = Ocsigen_extensions.parse_config_item (Some userconf_options) hostpattern request_config in (* Inside userconf, we create a new virtual site starting after [prefix], and use a request modified accordingly*) let user_parse_site = Ocsigen_extensions.make_parse_config (sitepath @ [prefix]) user_parse_host and req = { req with Ocsigen_extensions.request_info = Ocsigen_request.update ~uri request_info } in Lwt.return (subresult req user_parse_site conf previous_err req req_state) with | Ocsigen_extensions.NoSuchUser | NoConfFile | Unix.Unix_error (Unix.EACCES,_,_) | Unix.Unix_error (Unix.ENOENT, _, _) -> Lwt.return (Ocsigen_extensions.Ext_next previous_err) | e -> handle_parsing_error req e let parse_config _ hostpattern _ path _ _ config_elem = let regexp = ref None in let conf = ref None in let url = ref None in let prefix = ref None in let localpath = ref None in Ocsigen_extensions.( Configuration.process_element ~in_tag:"host" ~other_elements:(fun t _ _ -> raise (Bad_config_tag_for_extension t)) ~elements:[ Configuration.element ~name:"userconf" ~attributes:[ Configuration.attribute ~name:"regexp" ~obligatory:true (fun s -> let s = Ocsigen_lib.Netstring_pcre.regexp ("^" ^ s ^ "$") in regexp := Some s); Configuration.attribute ~name:"conf" ~obligatory:true (fun s -> let s = Ocsigen_extensions.parse_user_dir s in conf := Some s); Configuration.attribute ~name:"url" ~obligatory:true (fun s -> url := Some s); Configuration.attribute ~name:"prefix" ~obligatory:true (fun s -> prefix := Some s); Configuration.attribute ~name:"localpath" ~obligatory:true (fun s -> let s = Ocsigen_extensions.parse_user_dir s in localpath := Some s) ] ()] config_elem ); let info = match !regexp, !conf, !url, !prefix, !localpath with | (Some r, Some t, Some u, Some p, Some p') -> (r, t, u, p, p') | _ -> Ocsigen_extensions.badconfig "Missing attributes for " in gen hostpattern path info let () = Ocsigen_extensions.register ~name:"userconf" ~fun_site:parse_config () ocsigenserver-5.0.1/src/files/000077500000000000000000000000001417255654100162765ustar00rootroot00000000000000ocsigenserver-5.0.1/src/files/logrotate.in000066400000000000000000000005231417255654100206260ustar00rootroot00000000000000LOGDIR/*.log { weekly missingok rotate 52 compress delaycompress notifempty create 640 USER GROUP sharedscripts postrotate if fuser -s _COMMANDPIPE_; then echo reopen_logs > _COMMANDPIPE_ fi endscript } ocsigenserver-5.0.1/src/files/mime.types000066400000000000000000000354741417255654100203300ustar00rootroot00000000000000# This is a comment. I love comments. # This file controls what Internet media types are sent to the client for # given file extension(s). Sending the correct media type to the client # is important so they know how to handle the content of the file. # Extra types can either be added here or by using an AddType directive # in your config files. For more information about Internet media types, # please read RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type # registry is at . # MIME type Extensions application/activemessage application/andrew-inset ez application/applefile application/atom+xml atom application/atomicmail application/batch-smtp application/beep+xml application/cals-1840 application/cnrp+xml application/commonground application/cpl+xml application/cybercash application/dca-rft application/dec-dx application/dvcs application/edi-consent application/edifact application/edi-x12 application/eshop application/font-tdpfr application/http application/hyperstudio application/iges application/index application/index.cmd application/index.obj application/index.response application/index.vnd application/iotp application/ipp application/isup application/mac-binhex40 hqx application/mac-compactpro cpt application/macwriteii application/marc application/mathematica application/mathml+xml mathml application/msword doc application/news-message-id application/news-transmission application/ocsp-request application/ocsp-response application/octet-stream bin dms lha lzh exe class so dll dmg application/oda oda application/ogg ogg application/parityfec application/pdf pdf application/pgp-encrypted application/pgp-keys application/pgp-signature application/pkcs10 application/pkcs7-mime application/pkcs7-signature application/pkix-cert application/pkix-crl application/pkixcmp application/postscript ai eps ps application/prs.alvestrand.titrax-sheet application/prs.cww application/prs.nprend application/prs.plucker application/qsig application/rdf+xml rdf application/reginfo+xml application/remote-printing application/riscos application/rtf application/sdp application/set-payment application/set-payment-initiation application/set-registration application/set-registration-initiation application/sgml application/sgml-open-catalog application/sieve application/slate application/smil smi smil application/srgs gram application/srgs+xml grxml application/timestamp-query application/timestamp-reply application/tve-trigger application/vemmi application/vnd.3gpp.pic-bw-large application/vnd.3gpp.pic-bw-small application/vnd.3gpp.pic-bw-var application/vnd.3gpp.sms application/vnd.3m.post-it-notes application/vnd.accpac.simply.aso application/vnd.accpac.simply.imp application/vnd.acucobol application/vnd.acucorp application/vnd.adobe.xfdf application/vnd.aether.imp application/vnd.amiga.ami application/vnd.anser-web-certificate-issue-initiation application/vnd.anser-web-funds-transfer-initiation application/vnd.audiograph application/vnd.blueice.multipass application/vnd.bmi application/vnd.bw-fontobject eot application/vnd.businessobjects application/vnd.canon-cpdl application/vnd.canon-lips application/vnd.cinderella application/vnd.claymore application/vnd.commerce-battelle application/vnd.commonspace application/vnd.contact.cmsg application/vnd.cosmocaller application/vnd.criticaltools.wbs+xml application/vnd.ctc-posml application/vnd.cups-postscript application/vnd.cups-raster application/vnd.cups-raw application/vnd.curl application/vnd.cybank application/vnd.data-vision.rdz application/vnd.dna application/vnd.dpgraph application/vnd.dreamfactory application/vnd.dxr application/vnd.ecdis-update application/vnd.ecowin.chart application/vnd.ecowin.filerequest application/vnd.ecowin.fileupdate application/vnd.ecowin.series application/vnd.ecowin.seriesrequest application/vnd.ecowin.seriesupdate application/vnd.enliven application/vnd.epson.esf application/vnd.epson.msf application/vnd.epson.quickanime application/vnd.epson.salt application/vnd.epson.ssf application/vnd.ericsson.quickcall application/vnd.eudora.data application/vnd.fdf application/vnd.ffsns application/vnd.fints application/vnd.flographit application/vnd.framemaker application/vnd.fsc.weblaunch application/vnd.fujitsu.oasys application/vnd.fujitsu.oasys2 application/vnd.fujitsu.oasys3 application/vnd.fujitsu.oasysgp application/vnd.fujitsu.oasysprs application/vnd.fujixerox.ddd application/vnd.fujixerox.docuworks application/vnd.fujixerox.docuworks.binder application/vnd.fut-misnet application/vnd.grafeq application/vnd.groove-account application/vnd.groove-help application/vnd.groove-identity-message application/vnd.groove-injector application/vnd.groove-tool-message application/vnd.groove-tool-template application/vnd.groove-vcard application/vnd.hbci application/vnd.hhe.lesson-player application/vnd.hp-hpgl application/vnd.hp-hpid application/vnd.hp-hps application/vnd.hp-pcl application/vnd.hp-pclxl application/vnd.httphone application/vnd.hzn-3d-crossword application/vnd.ibm.afplinedata application/vnd.ibm.electronic-media application/vnd.ibm.minipay application/vnd.ibm.modcap application/vnd.ibm.rights-management application/vnd.ibm.secure-container application/vnd.informix-visionary application/vnd.intercon.formnet application/vnd.intertrust.digibox application/vnd.intertrust.nncp application/vnd.intu.qbo application/vnd.intu.qfx application/vnd.irepository.package+xml application/vnd.is-xpr application/vnd.japannet-directory-service application/vnd.japannet-jpnstore-wakeup application/vnd.japannet-payment-wakeup application/vnd.japannet-registration application/vnd.japannet-registration-wakeup application/vnd.japannet-setstore-wakeup application/vnd.japannet-verification application/vnd.japannet-verification-wakeup application/vnd.jisp application/vnd.kde.karbon application/vnd.kde.kchart application/vnd.kde.kformula application/vnd.kde.kivio application/vnd.kde.kontour application/vnd.kde.kpresenter application/vnd.kde.kspread application/vnd.kde.kword application/vnd.kenameaapp application/vnd.koan application/vnd.liberty-request+xml application/vnd.llamagraphics.life-balance.desktop application/vnd.llamagraphics.life-balance.exchange+xml application/vnd.lotus-1-2-3 application/vnd.lotus-approach application/vnd.lotus-freelance application/vnd.lotus-notes application/vnd.lotus-organizer application/vnd.lotus-screencam application/vnd.lotus-wordpro application/vnd.mcd application/vnd.mediastation.cdkey application/vnd.meridian-slingshot application/vnd.micrografx.flo application/vnd.micrografx.igx application/vnd.mif mif application/vnd.minisoft-hp3000-save application/vnd.mitsubishi.misty-guard.trustweb application/vnd.mobius.daf application/vnd.mobius.dis application/vnd.mobius.mbk application/vnd.mobius.mqy application/vnd.mobius.msl application/vnd.mobius.plc application/vnd.mobius.txf application/vnd.mophun.application application/vnd.mophun.certificate application/vnd.motorola.flexsuite application/vnd.motorola.flexsuite.adsi application/vnd.motorola.flexsuite.fis application/vnd.motorola.flexsuite.gotap application/vnd.motorola.flexsuite.kmr application/vnd.motorola.flexsuite.ttc application/vnd.motorola.flexsuite.wem application/vnd.mozilla.xul+xml xul application/vnd.ms-artgalry application/vnd.ms-asf application/vnd.ms-excel xls application/vnd.ms-fontobject eot application/vnd.ms-lrm application/vnd.ms-powerpoint ppt application/vnd.ms-project application/vnd.ms-tnef application/vnd.ms-works application/vnd.ms-wpl application/vnd.mseq application/vnd.msign application/vnd.music-niff application/vnd.musician application/vnd.netfpx application/vnd.noblenet-directory application/vnd.noblenet-sealer application/vnd.noblenet-web application/vnd.novadigm.edm application/vnd.novadigm.edx application/vnd.novadigm.ext application/vnd.obn application/vnd.osa.netdeploy application/vnd.palm application/vnd.pg.format application/vnd.pg.osasli application/vnd.powerbuilder6 application/vnd.powerbuilder6-s application/vnd.powerbuilder7 application/vnd.powerbuilder7-s application/vnd.powerbuilder75 application/vnd.powerbuilder75-s application/vnd.previewsystems.box application/vnd.publishare-delta-tree application/vnd.pvi.ptid1 application/vnd.pwg-multiplexed application/vnd.pwg-xhtml-print+xml application/vnd.quark.quarkxpress application/vnd.rapid application/vnd.s3sms application/vnd.sealed.net application/vnd.seemail application/vnd.shana.informed.formdata application/vnd.shana.informed.formtemplate application/vnd.shana.informed.interchange application/vnd.shana.informed.package application/vnd.smaf application/vnd.sss-cod application/vnd.sss-dtf application/vnd.sss-ntf application/vnd.street-stream application/vnd.svd application/vnd.swiftview-ics application/vnd.triscape.mxs application/vnd.trueapp application/vnd.truedoc application/vnd.ufdl application/vnd.uplanet.alert application/vnd.uplanet.alert-wbxml application/vnd.uplanet.bearer-choice application/vnd.uplanet.bearer-choice-wbxml application/vnd.uplanet.cacheop application/vnd.uplanet.cacheop-wbxml application/vnd.uplanet.channel application/vnd.uplanet.channel-wbxml application/vnd.uplanet.list application/vnd.uplanet.list-wbxml application/vnd.uplanet.listcmd application/vnd.uplanet.listcmd-wbxml application/vnd.uplanet.signal application/vnd.vcx application/vnd.vectorworks application/vnd.vidsoft.vidconference application/vnd.visio application/vnd.visionary application/vnd.vividence.scriptfile application/vnd.vsf application/vnd.wap.sic application/vnd.wap.slc application/vnd.wap.wbxml wbxml application/vnd.wap.wmlc wmlc application/vnd.wap.wmlscriptc wmlsc application/vnd.webturbo application/vnd.wrq-hp3000-labelled application/vnd.wt.stf application/vnd.wv.csp+wbxml application/vnd.xara application/vnd.xfdl application/vnd.yamaha.hv-dic application/vnd.yamaha.hv-script application/vnd.yamaha.hv-voice application/vnd.yellowriver-custom-menu application/voicexml+xml vxml application/watcherinfo+xml application/whoispp-query application/whoispp-response application/wita application/wordperfect5.1 application/x-bcpio bcpio application/x-cdlink vcd application/x-chess-pgn pgn application/x-compress application/x-cpio cpio application/x-csh csh application/x-director dcr dir dxr application/x-dvi dvi application/x-font-ttf ttf application/x-font-woff woff application/x-futuresplash spl application/x-gtar gtar application/x-gzip application/x-hdf hdf application/x-javascript js application/x-koan skp skd skt skm application/x-latex latex application/x-netcdf nc cdf application/x-sh sh application/x-shar shar application/x-shockwave-flash swf application/x-stuffit sit application/x-sv4cpio sv4cpio application/x-sv4crc sv4crc application/x-tar tar application/x-tcl tcl application/x-tex tex application/x-texinfo texinfo texi application/x-troff t tr roff application/x-troff-man man application/x-troff-me me application/x-troff-ms ms application/x-ustar ustar application/x-wais-source src application/x400-bp application/xhtml+xml xhtml xht application/xslt+xml xslt application/xml xml xsl application/xml-dtd dtd application/xml-external-parsed-entity application/zip zip audio/32kadpcm audio/amr audio/amr-wb audio/basic au snd audio/cn audio/dat12 audio/dsr-es201108 audio/dvi4 audio/evrc audio/evrc0 audio/g722 audio/g.722.1 audio/g723 audio/g726-16 audio/g726-24 audio/g726-32 audio/g726-40 audio/g728 audio/g729 audio/g729D audio/g729E audio/gsm audio/gsm-efr audio/l8 audio/l16 audio/l20 audio/l24 audio/lpc audio/midi mid midi kar audio/mpa audio/mpa-robust audio/mp4a-latm audio/mpeg mpga mp2 mp3 audio/parityfec audio/pcma audio/pcmu audio/prs.sid audio/qcelp audio/red audio/smv audio/smv0 audio/telephone-event audio/tone audio/vdvi audio/vnd.3gpp.iufp audio/vnd.cisco.nse audio/vnd.cns.anp1 audio/vnd.cns.inf1 audio/vnd.digital-winds audio/vnd.everad.plj audio/vnd.lucent.voice audio/vnd.nortel.vbk audio/vnd.nuera.ecelp4800 audio/vnd.nuera.ecelp7470 audio/vnd.nuera.ecelp9600 audio/vnd.octel.sbc audio/vnd.qcelp audio/vnd.rhetorex.32kadpcm audio/vnd.vmx.cvsd audio/x-aiff aif aiff aifc audio/x-alaw-basic audio/x-mpegurl m3u audio/x-pn-realaudio ram ra audio/x-pn-realaudio-plugin application/vnd.rn-realmedia rm audio/x-wav wav chemical/x-pdb pdb chemical/x-xyz xyz image/bmp bmp image/cgm cgm image/g3fax image/gif gif image/ief ief image/jpeg jpeg jpg jpe image/naplps image/png png image/prs.btif image/prs.pti image/svg+xml svg image/t38 image/tiff tiff tif image/tiff-fx image/vnd.cns.inf2 image/vnd.djvu djvu djv image/vnd.dwg image/vnd.dxf image/vnd.fastbidsheet image/vnd.fpx image/vnd.fst image/vnd.fujixerox.edmics-mmr image/vnd.fujixerox.edmics-rlc image/vnd.globalgraphics.pgb image/vnd.mix image/vnd.ms-modi image/vnd.net-fpx image/vnd.svf image/vnd.wap.wbmp wbmp image/vnd.xiff image/x-cmu-raster ras image/x-icon ico image/x-portable-anymap pnm image/x-portable-bitmap pbm image/x-portable-graymap pgm image/x-portable-pixmap ppm image/x-rgb rgb image/x-xbitmap xbm image/x-xpixmap xpm image/x-xwindowdump xwd message/delivery-status message/disposition-notification message/external-body message/http message/news message/partial message/rfc822 message/s-http message/sip message/sipfrag model/iges igs iges model/mesh msh mesh silo model/vnd.dwf model/vnd.flatland.3dml model/vnd.gdl model/vnd.gs-gdl model/vnd.gtw model/vnd.mts model/vnd.parasolid.transmit.binary model/vnd.parasolid.transmit.text model/vnd.vtu model/vrml wrl vrml multipart/alternative multipart/appledouble multipart/byteranges multipart/digest multipart/encrypted multipart/form-data multipart/header-set multipart/mixed multipart/parallel multipart/related multipart/report multipart/signed multipart/voice-message text/calendar ics ifb text/css css text/directory text/enriched text/html html htm text/parityfec text/plain asc txt text/prs.lines.tag text/rfc822-headers text/richtext rtx text/rtf rtf text/sgml sgml sgm text/t140 text/tab-separated-values tsv text/uri-list text/vnd.abc text/vnd.curl text/vnd.dmclientscript text/vnd.fly text/vnd.fmi.flexstor text/vnd.in3d.3dml text/vnd.in3d.spot text/vnd.iptc.nitf text/vnd.iptc.newsml text/vnd.latex-z text/vnd.motorola.reflex text/vnd.ms-mediapackage text/vnd.net2phone.commcenter.command text/vnd.sun.j2me.app-descriptor text/vnd.wap.si text/vnd.wap.sl text/vnd.wap.wml wml text/vnd.wap.wmlscript wmls text/x-setext etx text/xml text/xml-external-parsed-entity video/bmpeg video/bt656 video/celb video/dv video/h261 video/h263 video/h263-1998 video/h263-2000 video/jpeg video/mp1s video/mp2p video/mp2t video/mp4v-es video/mpv video/mpeg mpeg mpg mpe video/nv video/parityfec video/pointer video/quicktime qt mov video/smpte292m video/vnd.fvt video/vnd.motorola.video video/vnd.motorola.videop video/vnd.mpegurl mxu m4u video/vnd.nokia.interleaved-multimedia video/vnd.objectvideo video/vnd.vivo video/x-msvideo avi video/x-sgi-movie movie x-conference/x-cooltalk ice ocsigenserver-5.0.1/src/files/ocsigenserver.1000066400000000000000000000026721417255654100212450ustar00rootroot00000000000000.\" Hey, EMACS: -*- nroff -*- .TH OCSIGEN 1 2006-09-14 .SH NAME ocsigen \- web programming framework in OCaml .SH SYNOPSIS .B ocsigen .RI [ options ] .SH DESCRIPTION .B ocsigen is a programming framework providing a new way to create dynamic web sites. Its goal is to offer an alternative to Apache/PHP, based on cutting-edge technologies coming from research in programming languages. With .BR ocsigen , you program in a concise and modular way, with a strong type system which helps you to produce valid xhtml. The server handles sessions, URLs, and page parameters automatically. .SH OPTIONS .TP .BR \-c ,\ \-\-config Alternate configuration file. .TP .BR \-d ,\ \-\-daemon Daemon mode (detach the process). This is the default when there are more than 1 process. .TP .BR \-help ,\ \-\-help Show summary of options. .TP .BR \-p ,\ \-\-pidfile Specify a file where to write the PIDs of the servers. .TP .BR \-s ,\ \-\-silent Silent mode (error messages go in errors.log only). .TP .BR \-v ,\ \-\-verbose Verbose mode (notice). .TP .B \-vv ,\ \-\-veryverbose Very verbose mode (info). .TP .B \-vvv ,\ \-\-debug Extremely verbose mode (debug). .TP .B \-\-version Show version of program. .SH SEE ALSO .BR ocamlc (1). .SH AUTHOR ocsigen was written by Vincent Balat . .PP This manual page was written by Samuel Mimram , for the Debian project (but may be used by others). ocsigenserver-5.0.1/src/files/ocsigenserver.conf.in000066400000000000000000000021241417255654100224270ustar00rootroot00000000000000 80 _LOGDIR_ _DATADIR_ _OCSIGENUSER_ _OCSIGENGROUP_ utf-8 ocsigenserver-5.0.1/src/http/000077500000000000000000000000001417255654100161535ustar00rootroot00000000000000ocsigenserver-5.0.1/src/http/Makefile000066400000000000000000000001641417255654100176140ustar00rootroot00000000000000.PHONY: default default: build .PHONY: build build: dune build ## Clean up distclean: clean -rm -f *~ \#* .\#* ocsigenserver-5.0.1/src/http/dune000066400000000000000000000004561417255654100170360ustar00rootroot00000000000000(library (name ocsigen_cookie_map) (public_name ocsigenserver.cookies) (modules ocsigen_cookie_map) (libraries ocsigen_lib_base)) (library (name http) (public_name ocsigenserver.http) (wrapped false) (modules ocsigen_charset_mime ocsigen_header) (libraries cohttp-lwt-unix baselib)) ocsigenserver-5.0.1/src/http/ocsigen_charset_mime.ml000066400000000000000000000115441417255654100226610ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * ocsigen_charset_mime.ml Copyright (C) 2008 * Boris Yakobowski * Laboratoire PPS - CNRS Université Paris Diderot * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) open Ocsigen_lib module MapString = Map.Make(String) type extension = string type filename = string type file = string let section = Lwt_log.Section.make "ocsigen:mimetype" type 'a assoc_item = | Extension of extension * 'a | File of filename * 'a | Regexp of Pcre.regexp * 'a | Map of 'a MapString.t type 'a assoc = { assoc_list: 'a assoc_item list; assoc_default: 'a } let find_in_assoc file assoc = let filename = Filename.basename file in let ext = try String.lowercase_ascii (Filename.extension_no_directory file) with Not_found -> "" in let rec aux = function | [] -> assoc.assoc_default | Extension (ext', v) :: q -> if ext = ext' then v else aux q | File (filename', v) :: q -> if filename = filename' then v else aux q | Regexp (reg, v) :: q -> if Netstring_pcre.string_match reg file 0 <> None then v else aux q | Map m :: q -> try MapString.find ext m with Not_found -> aux q in aux assoc.assoc_list let default assoc = assoc.assoc_default let set_default assoc default = { assoc with assoc_default = default } let update_ext assoc (ext : extension) v = { assoc with assoc_list = Extension (String.lowercase_ascii ext, v) :: assoc.assoc_list} let update_file assoc (file : filename) v = { assoc with assoc_list = File (file, v) :: assoc.assoc_list} let update_regexp assoc r v = { assoc with assoc_list = Regexp (r, v) :: assoc.assoc_list} let empty default () = { assoc_list = []; assoc_default = default } (* Handling of charset and mime ; specific values and declarations *) type charset = string type mime_type = string type charset_assoc = charset assoc type mime_assoc = mime_type assoc let no_charset : charset = "" let default_mime_type : mime_type = "application/octet-stream" let empty_charset_assoc ?(default=no_charset) = empty default let empty_mime_assoc ?(default=default_mime_type) = empty default (* Generic functions *) let default_charset = default let default_mime = default let update_charset_ext = update_ext let update_mime_ext = update_ext let update_charset_file = update_file let update_mime_file = update_file let update_charset_regexp = update_regexp let update_mime_regexp = update_regexp let set_default_mime = set_default let set_default_charset = set_default let find_charset = find_in_assoc let find_mime = find_in_assoc (* Specific handling of content-type *) let parse_mime_types ~filename : mime_type assoc = let rec read_and_split mimemap in_ch = try let line = input_line in_ch in let line_upto = try let upto = String.index line '#' in String.sub line 0 upto with Not_found -> line in let strlist = Netstring_pcre.split (Netstring_pcre.regexp "\\s+") line_upto in match strlist with | [] | [_] -> (* No extension on this line *) read_and_split mimemap in_ch | mime :: extensions -> let mimemap = List.fold_left (fun mimemap ext -> MapString.add ext mime mimemap) mimemap extensions in read_and_split mimemap in_ch with End_of_file -> mimemap in { assoc_list = [ Map(try let in_ch = open_in filename in let map = (try read_and_split MapString.empty in_ch with e -> close_in in_ch; raise e) in close_in in_ch; map with exn -> Lwt_log.ign_error ~section ~exn "unable to read the mime.types file"; MapString.empty )]; assoc_default = default_mime_type; } let default_mime_assoc () = let parsed = ref None in match !parsed with | None -> let filename = !Ocsigen_config_static.mimefile in Lwt_log.ign_info_f ~section "Loading mime types in '%s'" filename; let map = parse_mime_types ~filename in parsed := Some map; map | Some map -> map ocsigenserver-5.0.1/src/http/ocsigen_charset_mime.mli000066400000000000000000000057241417255654100230350ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * ocsigen_charset_mime.mli Copyright (C) 2008 * Boris Yakobowski * Laboratoire PPS - CNRS Université Paris Diderot * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) type extension = string type file = string type filename = string (** Charset *) (** By convention, "no specified charset" is represented by the empty string *) type charset = string val no_charset: charset (** Association between extensions and charset, with a default value. *) type charset_assoc (** All files are mapped to [no_charset] *) val empty_charset_assoc : ?default:charset -> unit -> charset_assoc val empty_mime_assoc : ?default:charset -> unit -> charset_assoc val find_charset : string -> charset_assoc -> charset (** Functions related to the default charset in the association *) val default_charset : charset_assoc -> charset val set_default_charset : charset_assoc -> charset -> charset_assoc (** Updates the mapping between extensions from a file to its charset. The update can be specified using the extension of the file, the name of the file, or the entire file (with its path) *) val update_charset_ext : charset_assoc -> extension -> charset -> charset_assoc val update_charset_file : charset_assoc -> filename -> charset -> charset_assoc val update_charset_regexp : charset_assoc -> Pcre.regexp -> charset -> charset_assoc (** MIME types; the default value is ["application/octet-stream"] *) type mime_type = string val default_mime_type : mime_type (** association between extensions and mime types, with default value *) type mime_assoc (** Default values, obtained by reading the file specified by [Ocsigen_config_static.get_mimefile] *) val default_mime_assoc : unit -> mime_assoc (** Parsing of a file containing mime associations, such as /etc/mime-types *) val parse_mime_types : filename:string -> mime_assoc (* The other functions are as for charsets *) val find_mime : file -> mime_assoc -> string val default_mime : mime_assoc -> mime_type val set_default_mime : mime_assoc -> mime_type -> mime_assoc val update_mime_ext : mime_assoc -> extension -> mime_type -> mime_assoc val update_mime_file : mime_assoc -> filename -> mime_type -> mime_assoc val update_mime_regexp : mime_assoc -> Pcre.regexp -> mime_type -> mime_assoc ocsigenserver-5.0.1/src/http/ocsigen_cookie_map.ml000066400000000000000000000036371417255654100223330ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2010 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) module Map_path = Map.Make(struct type t = string list let compare = compare end) module Map_inner = Map.Make(String) type cookie = | OSet of float option * string * bool | OUnset type t = cookie Map_inner.t Map_path.t let empty = Map_path.empty let add ~path n v m = let m' = try Map_path.find path m with Not_found -> Map_inner.empty in (* We replace the old value if it exists *) Map_path.add path (Map_inner.add n v m') m (* [add_multi new old] adds the cookies from [new] to [old]. If cookies are already bound in oldcookies, the previous binding disappear. *) let add_multi = Map_path.fold @@ fun path -> Map_inner.fold @@ fun n v beg -> match v with | OSet (expo, v, secure) -> add ~path n (OSet (expo, v, secure)) beg | OUnset -> add ~path n OUnset beg let remove ~path n m = try let m' = Map_path.find path m in let m' = Map_inner.remove n m' in if Map_inner.is_empty m' then Map_path.remove path m else (* We replace the old value *) Map_path.add path m' m with Not_found -> m module Poly = struct let add = add let remove = remove end ocsigenserver-5.0.1/src/http/ocsigen_cookie_map.mli000066400000000000000000000046671417255654100225100ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2010 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** This type of maps is used to store cookie values for each path. The key has type Url.path option: it is for the path (default: root of the site). *) module Map_path : Map.S with type key := Ocsigen_lib_base.Url_base.path module Map_inner : Map.S with type key := string (** Type used for cookies to set. The float option is the timestamp for the expiration date. The string is the value. If the bool is true and the protocol is https, the cookie will be secure (will ask the browser to send it only through secure connections). *) type cookie = | OSet of float option * string * bool | OUnset type t = cookie Map_inner.t Map_path.t val empty : t (** [add ~path c v m] adds the cookie [c] to [m]. If the cookie is already bound, the previous binding disappear. *) val add : path:Ocsigen_lib_base.Url_base.path -> string -> cookie -> t -> t (** [add_multi new old] adds the cookies from [new] to [old]. If cookies are already bound in oldcookies, the previous binding disappear. *) val add_multi : t -> t -> t (** [remove c cookie_table] removes the cookie [c] from [m]. Warning: it is not equivalent to [add ... OUnset ...]). *) val remove : path:Ocsigen_lib_base.Url_base.path -> string -> t -> t (** Polymorphic versions of [add] and [remove] to use when we don't need to OUnset (client-side) *) module Poly : sig val add : path:Ocsigen_lib_base.Url_base.path -> string -> 'a -> 'a Map_inner.t Map_path.t -> 'a Map_inner.t Map_path.t val remove : path:Ocsigen_lib_base.Url_base.path -> string -> 'a Map_inner.t Map_path.t -> 'a Map_inner.t Map_path.t end ocsigenserver-5.0.1/src/http/ocsigen_header.ml000066400000000000000000000126031417255654100214460ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) type t = Cohttp.Header.t let of_option = function Some h -> h | None -> Cohttp.Header.init () module Name = struct type t = string let of_string = String.lowercase_ascii let to_string s = s let accept = of_string "Accept" let accept_charset = of_string "Accept-Charset" let accept_encoding = of_string "Accept-Encoding" let accept_language = of_string "Accept-Language" let accept_ranges = of_string "Accept-Ranges" let authorization = of_string "Authorization" let cache_control = of_string "Cache-Control" let connection = of_string "Connection" let content_disposition = of_string "Content-Disposition" let content_encoding = of_string "Content-Encoding" let content_range = of_string "Content-Range" let content_length = of_string "Content-Length" let content_type = of_string "Content-Type" let cookie = of_string "Cookie" let date = of_string "Date" let etag = of_string "ETag" let expect = of_string "Expect" let expires = of_string "Expires" let host = of_string "Host" let if_match = of_string "If-Match" let if_modified_since = of_string "If-Modified-Since" let if_none_match = of_string "If-None-Match" let if_unmodified_since = of_string "If-Unmodified-Since" let if_range = of_string "If-Range" let last_modified = of_string "Last-Modified" let location = of_string "Location" let pragma = of_string "Pragma" let server = of_string "Server" let set_cookie = of_string "Set-Cookie" let status = of_string "Status" let transfer_encoding = of_string "Transfer-Encoding" let user_agent = of_string "User-Agent" let referer = of_string "Referer" let range = of_string "Range" let x_forwarded_for = of_string "X-Forwarded-For" let x_forwarded_proto = of_string "X-Forwarded-Proto" (* CORS headers *) let origin = of_string "Origin" let access_control_request_method = of_string "Access-Control-Request-Method" let access_control_request_headers = of_string "Access-Control-Request-Headers" let access_control_allow_origin = of_string "Access-Control-Allow-Origin" let access_control_allow_credentials = of_string "Access-Control-Allow-Credentials" let access_control_expose_headers = of_string "Access-Control-Expose-Headers" let access_control_max_age = of_string "Access-Control-Max-Age" let access_control_allow_methods = of_string "Access-Control-Allow-Methods" let access_control_allow_headers = of_string "Access-Control-Allow-Headers" end let parse_star a = if a = "*" then None else Some a let parse_quality f s = try let a, b = Ocsigen_lib.String.sep ';' s in let q, qv = Ocsigen_lib.String.sep '=' b in if q = "q" then f a, Some (float_of_string qv) else failwith "Parse error" with _ -> f s, None module Mime_type = struct type t = string option * string option let parse a = let b, c = Ocsigen_lib.String.sep '/' a in parse_star b, parse_star c end module Accept = struct type t = (Mime_type.t * float option * (string * string) list) list let parse_extensions parse_name s = try let a, b = Ocsigen_lib.String.sep ';' s in parse_name a, List.map (Ocsigen_lib.String.sep '=') (Ocsigen_lib.String.split ';' b) with _ -> parse_name s, [] let parse_list_with_extensions parse_name s = List.map (Ocsigen_lib.String.split ',') s |> List.flatten |> List.map (parse_extensions parse_name) let parse s = try let l = parse_list_with_extensions Mime_type.parse s in let change_quality (a, l) = try let q, ll = Ocsigen_lib.List.assoc_remove "q" l in a, Some (float_of_string q), ll with _ -> a, None, l in List.map change_quality l with _ -> [] end module Accept_encoding = struct type t = (string option * float option) list let parse s = try List.map (Ocsigen_lib.String.split ',') s |> List.flatten |> List.map (parse_quality parse_star) with _ -> [] end module Accept_language = struct type t = (string * float option) list let parse s = try List.map (Ocsigen_lib.String.split ',') s |> List.flatten |> List.map (parse_quality (fun x -> x)) with _ -> [] end module Content_type = struct let choose accept default alt = try List.find (fun content_type -> let f = function | (Some a, Some b), _, _ -> a ^ "/" ^ b = content_type | _ -> false in List.exists f accept) (default :: alt) with Not_found -> default end ocsigenserver-5.0.1/src/http/ocsigen_header.mli000066400000000000000000000051041417255654100216150ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) type t = Cohttp.Header.t val of_option : t option -> t module Name : sig type t val to_string : t -> string val of_string : string -> t val accept : t val accept_charset : t val accept_encoding : t val accept_language : t val accept_ranges : t val authorization : t val cache_control : t val connection : t val content_disposition : t val content_encoding : t val content_length : t val content_type : t val content_range : t val cookie : t val date : t val etag : t val expect: t val expires : t val host : t val if_match : t val if_modified_since : t val if_none_match : t val if_unmodified_since : t val if_range : t val last_modified : t val location : t val pragma : t val server : t val set_cookie : t val status : t val transfer_encoding : t val user_agent : t val referer : t val range : t val x_forwarded_for : t val x_forwarded_proto : t val origin : t val access_control_request_method : t val access_control_request_headers : t val access_control_allow_origin : t val access_control_allow_credentials : t val access_control_expose_headers : t val access_control_max_age : t val access_control_allow_methods : t val access_control_allow_headers : t end module Mime_type : sig type t = string option * string option val parse : string -> t end module Accept : sig type t = (Mime_type.t * float option * (string * string) list) list val parse : string list -> t end module Accept_encoding : sig type t = (string option * float option) list val parse : string list -> t end module Accept_language : sig type t = (string * float option) list val parse : string list -> t end module Content_type : sig val choose : Accept.t -> string -> string list -> string end ocsigenserver-5.0.1/src/ocsigenserver.ml000066400000000000000000000032651417255654100204120ustar00rootroot00000000000000let () = let alt_msg = "Alternate config file (default " ^ Ocsigen_config.get_config_file () ^ ")" and silent_msg = "Silent mode (error messages in errors.log only)" and pid_msg = "Specify a file where to write the PIDs of servers" and daemon_msg = "Daemon mode (detach the process)" and verbose_msg = "Verbose mode" and veryverbose_msg = "Very verbose mode (info)" and debug_msg = "Extremely verbose mode (debug)" and version_msg = "Display version number and exit" in try Arg.parse_argv Sys.argv [ "-c", Arg.String Ocsigen_config.set_configfile, alt_msg; "--config", Arg.String Ocsigen_config.set_configfile, alt_msg; "-s", Arg.Unit Ocsigen_config.set_silent, silent_msg; "--silent", Arg.Unit Ocsigen_config.set_silent, silent_msg; "-p", Arg.String Ocsigen_config.set_pidfile, pid_msg; "--pidfile", Arg.String Ocsigen_config.set_pidfile, pid_msg; "-v", Arg.Unit Ocsigen_config.set_verbose, verbose_msg; "--verbose", Arg.Unit Ocsigen_config.set_verbose, verbose_msg; "-vv", Arg.Unit Ocsigen_config.set_veryverbose, veryverbose_msg; "--veryverbose", Arg.Unit Ocsigen_config.set_veryverbose, veryverbose_msg; "-vvv", Arg.Unit Ocsigen_config.set_debug, debug_msg; "--debug", Arg.Unit Ocsigen_config.set_debug, debug_msg; "-d", Arg.Unit Ocsigen_config.set_daemon, daemon_msg; "--daemon", Arg.Unit Ocsigen_config.set_daemon, daemon_msg; "--version", Arg.Unit Ocsigen_config.display_version, version_msg ] (fun _ -> ()) "usage: ocsigenserver [-c configfile]" with Arg.Help s -> print_endline s; exit 0 let () = Ocsigen_server.start ~config:(Ocsigen_parseconfig.parse_config ()) () ocsigenserver-5.0.1/src/server/000077500000000000000000000000001417255654100165025ustar00rootroot00000000000000ocsigenserver-5.0.1/src/server/Makefile000066400000000000000000000013601417255654100201420ustar00rootroot00000000000000include ../../Makefile.options include ../../Makefile.config .PHONY: default default: build .PHONY: build build: dune build ## Toplevel SERVERLIBS := ${BLD}/baselib/ocsigen_lib_base.cma \ ${BLD}/baselib/baselib.cma \ ${BLD}/baselib/polytables/polytables.cma \ ${BLD}/http/http.cma \ ${BLD}/http/ocsigen_cookie_map.cma \ ${BLD}/server/ocsigenserver.cma top: servertop OCAMLPATH=${SRC}/src/files/:${OCAMLPATH} ${RLWRAP} ./servertop servertop: build OCAMLPATH=${SRC}/src/files/:${OCAMLPATH} ${OCAMLFIND} ocamlmktop \ -o $@ -linkall -linkpkg ${THREAD} ${LIBS} ${SERVERLIBS} ## Clean up clean: dune clean distclean: clean -rm -f *~ \#* .\#* -rm -f servertop ocsigenserver-5.0.1/src/server/dune000066400000000000000000000002511417255654100173560ustar00rootroot00000000000000(library (name ocsigenserver) (public_name ocsigenserver) (wrapped false) (libraries xml-light cohttp-lwt-unix hmap polytables ocsigen_cookie_map baselib http)) ocsigenserver-5.0.1/src/server/ocsigen_cohttp.ml000066400000000000000000000224701417255654100220510ustar00rootroot00000000000000open Lwt.Infix let section = Lwt_log.Section.make "ocsigen:cohttp" exception Ocsigen_http_error of Ocsigen_cookie_map.t * Cohttp.Code.status exception Ext_http_error of Cohttp.Code.status * string option * Cohttp.Header.t option (** print_request Print request for debug @param out_ch output for debug @param request Cohttp request *) let _print_request fmt request = let print_list print_data out_ch lst = let rec aux = function | [] -> () | [ x ] -> print_data out_ch x | x :: r -> print_data out_ch x; aux r in aux lst in Format.fprintf fmt "%s [%s/%s]:\n" (Uri.to_string (Cohttp.Request.uri request)) Cohttp.(Code.string_of_version (Request.version request)) Cohttp.(Code.string_of_method (Request.meth request)); Cohttp.Header.iter (fun key values -> (print_list (fun fmt value -> Format.fprintf fmt "\t%s = %s\n" key value) fmt values)) (Cohttp.Request.headers request) let connections = Hashtbl.create 256 let get_number_of_connected, incr_connected, decr_connected, _wait_fewer_connected = let connected = ref 0 in let maxr = ref (-1000) in let mvar = Lwt_mvar.create_empty () in ((fun () -> !connected), (fun n -> connected := !connected + n), (fun () -> let c = !connected in connected := c - 1; if !connected < 0 then exit 1; if c = !maxr then begin Lwt_log.ign_warning ~section "Number of connections now ok"; maxr := -1000; Lwt_mvar.put mvar () end else Lwt.return () ), (fun max -> maxr := max; Lwt_mvar.take mvar) ) exception Ocsigen_is_dir of (Ocsigen_request.t -> Uri.t) module Cookie = struct let serialize_cookie_raw path exp name c secure = Format.sprintf "%s=%s; path=/%s%s%s" name c (Ocsigen_lib.Url.string_of_url_path ~encode:true path) (if secure then "; secure" else "") (match exp with | Some s -> "; expires=" ^ (Ocsigen_lib.Date.to_string s) | None -> "") let serialize_cookies path = Ocsigen_cookie_map.Map_inner.fold @@ fun name c h -> let open Ocsigen_cookie_map in let exp, v, secure = match c with | OUnset -> (Some 0., "", false) | OSet (t, v, secure) -> (t, v, secure) in Cohttp.Header.add h Ocsigen_header.Name.(to_string set_cookie) (serialize_cookie_raw path exp name v secure) let serialize cookies headers = Ocsigen_cookie_map.Map_path.fold serialize_cookies cookies headers end (* FIXME: secure *) let make_cookies_header path exp name c _secure = Format.sprintf "%s=%s%s%s" name c (*VVV encode = true? *) ("; path=/" ^ Ocsigen_lib.Url.string_of_url_path ~encode:true path) (* (if secure && slot.sl_ssl then "; secure" else "")^ *) "" ^ (match exp with | Some s -> "; expires=" ^ Ocsigen_lib.Date.to_string s | None -> "") let make_cookies_headers path t hds = Ocsigen_cookie_map.Map_inner.fold (fun name c h -> let open Ocsigen_cookie_map in let exp, v, secure = match c with | OUnset -> Some 0., "", false | OSet (t, v, secure) -> t, v, secure in Cohttp.Header.add h Ocsigen_header.Name.(to_string set_cookie) (make_cookies_header path exp name v secure) ) t hds let handler ~ssl ~address ~port ~connector (flow, conn) request body = let filenames = ref [] in let edn = Conduit_lwt_unix.endp_of_flow flow in let rec getsockname = function | `TCP (ip, port) -> Unix.ADDR_INET (Ipaddr_unix.to_inet_addr ip, port) | `Unix_domain_socket path -> Unix.ADDR_UNIX path | `TLS (_, edn) -> getsockname edn | `Unknown err -> raise (Failure ("resolution failed: " ^ err)) | `Vchan_direct _ -> raise (Failure "VChan not supported") | `Vchan_domain_socket _ -> raise (Failure "VChan not supported") in let sockaddr = getsockname edn in let connection_closed = try fst (Hashtbl.find connections conn) with Not_found -> let ((connection_closed, _) as p) = Lwt.wait () in Hashtbl.add connections conn p; incr_connected 1; connection_closed in let handle_error exn = Lwt_log.ign_debug ~section ~exn "Got exception while handling request." ; let headers, ret_code = match exn with | Ocsigen_http_error (cookies_to_set, code) -> let headers = Cookie.serialize cookies_to_set (Cohttp.Header.init ()) in Some headers, code | Ocsigen_stream.Interrupted Ocsigen_stream.Already_read -> None, `Internal_server_error | Unix.Unix_error (Unix.EACCES, _, _) -> None, `Forbidden | Ext_http_error (code, _, headers) -> headers, code | Ocsigen_lib.Ocsigen_Bad_Request -> None, `Bad_request | Ocsigen_lib.Ocsigen_Request_too_long -> None, `Request_entity_too_large | exn -> Lwt_log.ign_error ~section ~exn "Error while handling request." ; None, `Internal_server_error in let body = match ret_code with | `Not_found -> "Not Found" | _ -> Printexc.to_string exn in Cohttp_lwt_unix.Server.respond_error ?headers ~status:(ret_code :> Cohttp.Code.status_code) ~body () in (* TODO: equivalent of Ocsigen_range *) let request = Ocsigen_request.make ~address ~port ~ssl ~filenames ~sockaddr ~body ~connection_closed request in Lwt.finalize (fun () -> Ocsigen_messages.accesslog (Format.sprintf "connection for %s from %s (%s)%s: %s" (match Ocsigen_request.host request with | None -> "" | Some h -> h) (Ocsigen_request.remote_ip request) (Option.value ~default:"" (Ocsigen_request.header request Ocsigen_header.Name.user_agent)) (Option.fold ~none:"" ~some:(fun s -> " X-Forwarded-For: " ^ s) (Ocsigen_request.header request Ocsigen_header.Name.x_forwarded_for)) (Uri.path (Ocsigen_request.uri request)) ); Lwt.catch (fun () -> connector request >>= fun response -> let response, body = Ocsigen_response.to_cohttp response and cookies = Ocsigen_response.cookies response in let response = let headers = Cohttp.Header.add_unless_exists (Cohttp.Header.add_unless_exists (Ocsigen_cookie_map.Map_path.fold make_cookies_headers cookies (Cohttp.Response.headers response)) "server" Ocsigen_config.server_name) "date" (Ocsigen_lib.Date.to_string (Unix.time ())) in { response with Cohttp.Response.headers } in Lwt.return (response, body)) (function | Ocsigen_is_dir fun_request -> let headers = fun_request request |> Uri.to_string |> Cohttp.Header.init_with "location" and status = `Moved_permanently in Cohttp_lwt_unix.Server.respond ~headers ~status ~body:`Empty () | exn -> handle_error exn)) (fun () -> if !filenames <> [] then List.iter (fun a -> try Unix.unlink a with Unix.Unix_error _ as exn -> Lwt_log.ign_warning_f ~section ~exn "Error while removing file %s" a) !filenames; Lwt.return_unit) let conn_closed (_flow, conn) = try Lwt_log.ign_debug_f ~section "Connection closed:\n%s" (Cohttp.Connection.to_string conn); Lwt.wakeup (snd (Hashtbl.find connections conn)) (); Hashtbl.remove connections conn; Lwt.async decr_connected with Not_found -> () let stop, stop_wakener = Lwt.wait () let shutdown timeout = let process = match timeout with | Some f -> (fun () -> Lwt_unix.sleep f) | None -> (fun () -> Lwt.return ()) in ignore (Lwt.pick [process (); stop] >>= fun () -> exit 0) let service ?ssl ~address ~port ~connector () = let tls_own_key = match ssl with | Some (crt, key, Some password) -> `TLS (`Crt_file_path crt, `Key_file_path key, `Password password) | Some (crt, key, None) -> `TLS (`Crt_file_path crt, `Key_file_path key, `No_password) | None -> `None in (* We create a specific context for Conduit and Cohttp. *) Conduit_lwt_unix.init ~src:(Ocsigen_config.Socket_type.to_string address) ~tls_own_key () >>= fun conduit_ctx -> Lwt.return (Cohttp_lwt_unix.Net.init ~ctx:conduit_ctx ()) >>= fun ctx -> (* We catch the INET_ADDR of the server *) let callback = let address = Ocsigen_config.Socket_type.to_inet_addr address and ssl = match ssl with Some _ -> true | None -> false in handler ~ssl ~address ~port ~connector in let config = Cohttp_lwt_unix.Server.make ~conn_closed ~callback () in let mode = match tls_own_key with | `None -> `TCP (`Port port) | `TLS (crt, key, pass) -> `OpenSSL (crt, key, pass, `Port port) in Cohttp_lwt_unix.Server.create ~stop ~ctx ~mode config >>= fun () -> Lwt.return (Lwt.wakeup stop_wakener ()) ocsigenserver-5.0.1/src/server/ocsigen_cohttp.mli000066400000000000000000000017261417255654100222230ustar00rootroot00000000000000val section : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) exception Ocsigen_http_error of Ocsigen_cookie_map.t * Cohttp.Code.status (** Exception raised by exceptions to describe an HTTP error. It is possible to pass the code of the error, an optional comment, and optionally some headers. *) exception Ext_http_error of Cohttp.Code.status * string option * Cohttp.Header.t option (** compute a redirection if path links to a directory *) exception Ocsigen_is_dir of (Ocsigen_request.t -> Uri.t) (** accessor to get number of client (used by eliom monitoring) *) val get_number_of_connected : unit -> int (** Shutdown main loop of server *) val shutdown : float option -> unit (** initialize a main loop of http server *) val service : ?ssl:string * string * (bool -> string) option -> address:Ocsigen_config.socket_type -> port:int -> connector:(Ocsigen_request.t -> Ocsigen_response.t Lwt.t) -> unit -> unit Lwt.t ocsigenserver-5.0.1/src/server/ocsigen_command.ml000066400000000000000000000031101417255654100221540ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module ocsigen_extensions.ml * Copyright (C) 2015 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) exception Unknown_command let register_command_function, get_command_function = let command_function = ref (fun ?prefix:_ _ _ -> Lwt.fail Unknown_command) in ((fun ?prefix f -> let prefix' = prefix in let old_command_function = !command_function in command_function := (fun ?prefix s c -> Lwt.catch (fun () -> old_command_function ?prefix s c) (function | Unknown_command -> if prefix = prefix' then f s c else Lwt.fail Unknown_command | e -> Lwt.fail e))), (fun () -> !command_function)) let () = register_command_function ~prefix:"logs" (Ocsigen_messages.command_f Unknown_command) ocsigenserver-5.0.1/src/server/ocsigen_command.mli000066400000000000000000000032161417255654100223340ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module ocsigen_extensions.ml * Copyright (C) 2015 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** Extending server commands *) exception Unknown_command (** Use a prefix for all your commands when you want to create extension-specific commands. For example if the prefix is "myextension" and the commande "blah", the actual command to be written by the user is "myextension:blah". Give as parameter the function that will parse the command and do an action. Its first parameter is the full command as a string. The second one is the command without prefix, split by word. It must raise [ocsigen_extensions.Unknown_command] if it does not recognize the command. *) val register_command_function : ?prefix:string -> (string -> string list -> unit Lwt.t) -> unit (**/**) val get_command_function : unit -> (?prefix:string -> string -> string list -> unit Lwt.t) ocsigenserver-5.0.1/src/server/ocsigen_config.ml000066400000000000000000000161131417255654100220120ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2005-2017 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) include Ocsigen_config_static exception Config_file_error of string type ssl_info = { ssl_certificate : string option ; ssl_privatekey : string option ; ssl_ciphers : string option ; ssl_dhfile : string option ; ssl_curve : string option } module Socket_type = struct type t = [ | `All | `IPv4 of Unix.inet_addr | `IPv6 of Unix.inet_addr ] let to_string = function | `All -> Unix.string_of_inet_addr Unix.inet_addr_any | `IPv4 u -> Unix.string_of_inet_addr u | `IPv6 u -> Unix.string_of_inet_addr u let to_inet_addr = function | `All -> Unix.inet_addr_any | `IPv4 u -> u | `IPv6 u -> u end type socket_type = Socket_type.t (* General config *) let verbose = ref false let silent = ref false let daemon = ref false let veryverbose = ref false let debug = ref false let version_number = "0000000000000000" let pidfile = ref (None : string option) let server_name = "Ocsigen" let full_server_name = server_name^"/"^version_number let native_ext = if is_native then ".exe" else ".bc" let (uploaddir : string option ref) = ref None let syslog_facility = ref (None : Lwt_log.syslog_facility option) let minthreads = ref 10 let maxthreads = ref 30 let max_number_of_connections = ref 350 let silent_client_timeout = ref 30 (* without speaking during sending frame *) let silent_server_timeout = ref 30 (* without speaking during sending frame *) let filebuffersize = ref 8192 let maxrequestbodysize = ref (Some (Int64.of_int 8000000)) let maxrequestbodysizeinmemory = ref 8192 let maxuploadfilesize = ref (Some (Int64.of_int 2000000)) let defaultcharset = ref (None : string option) let user = ref (Some !default_user) let group = ref (Some !default_group) let debugmode = ref false let disablepartialrequests = ref false let usedefaulthostname = ref false let respectpipeline = ref false let maxretries = ref 10 let shutdowntimeout = ref (Some 10.) let ssl_info = ref None let ports = ref [] let ssl_ports = ref [] let set_uploaddir u = uploaddir := u let set_logdir s = logdir := Some s let set_syslog_facility f = syslog_facility := f; logdir := None let set_configfile s = config_file := s let set_pidfile s = pidfile := Some s let set_mimefile s = mimefile := s let () = Lwt_log.add_rule "ocsigen:*" Lwt_log.Warning (* without --verbose *) let set_verbose () = verbose := true; Lwt_log.add_rule "ocsigen:*" Lwt_log.Notice let set_silent () = silent := true let set_daemon () = set_silent (); daemon := true let set_veryverbose () = verbose := true; veryverbose := true; Lwt_log.add_rule "ocsigen:*" Lwt_log.Info let set_debug () = verbose := true; veryverbose := true; debug := true; Lwt_log.add_rule "ocsigen:*" Lwt_log.Debug let set_minthreads i = minthreads := i let set_maxthreads i = maxthreads := i let set_max_number_of_threads_queued = Lwt_preemptive.set_max_number_of_threads_queued let set_max_number_of_connections i = max_number_of_connections := i let set_client_timeout i = silent_client_timeout := i let set_server_timeout i = silent_server_timeout := i (* let set_keepalive_timeout i = keepalive_timeout := i let set_keepopen_timeout i = keepopen_timeout := i *) let set_filebuffersize i = filebuffersize := i let set_maxuploadfilesize i = maxuploadfilesize := i let set_maxrequestbodysize i = maxrequestbodysize := i let set_maxrequestbodysizeinmemory i = maxrequestbodysizeinmemory := i let set_default_charset o = defaultcharset := o let set_datadir o = datadir := o let set_bindir o = bindir := o let set_extdir o = extdir := o let set_user o = user := o let set_group o = group := o let set_command_pipe s = command_pipe := s let set_debugmode s = debugmode := s let set_disablepartialrequests s = disablepartialrequests := s let set_usedefaulthostname s = usedefaulthostname := s let set_respect_pipeline () = respectpipeline := true let set_maxretries i = maxretries := i let set_shutdown_timeout s = shutdowntimeout := s let set_ssl_info i = ssl_info := i let set_ports l = ports := l let set_ssl_ports l = ssl_ports := l let get_uploaddir () = !uploaddir let get_logdir () = match !logdir with | Some s -> s | None -> raise ( Config_file_error ("Log directory requested, but not set"));; let get_syslog_facility () = !syslog_facility let get_config_file () = !config_file let get_pidfile () = !pidfile let get_mimefile () = !mimefile let get_verbose () = !verbose let get_silent () = !silent let get_daemon () = !daemon let get_veryverbose () = !veryverbose let get_debug () = !debug let get_default_user () = !default_user let get_default_group () = !default_group let get_minthreads () = !minthreads let get_maxthreads () = !maxthreads let get_max_number_of_threads_queued = Lwt_preemptive.get_max_number_of_threads_queued let get_max_number_of_connections () = !max_number_of_connections let get_client_timeout () = !silent_client_timeout let get_server_timeout () = !silent_server_timeout let get_filebuffersize () = !filebuffersize let get_maxuploadfilesize () = !maxuploadfilesize let get_maxrequestbodysize () = !maxrequestbodysize let get_maxrequestbodysizeinmemory () = !maxrequestbodysizeinmemory let get_default_charset () = !defaultcharset let get_datadir () = !datadir let get_bindir () = !bindir let get_extdir () = !extdir let get_user () = !user let get_group () = !group let get_command_pipe () = !command_pipe let get_debugmode () = !debugmode let get_disablepartialrequests () = !disablepartialrequests let get_usedefaulthostname () = !usedefaulthostname let get_respect_pipeline () = !respectpipeline let get_maxretries () = !maxretries let get_shutdown_timeout () = !shutdowntimeout let get_ssl_info () = !ssl_info let get_ports () = !ports let get_ssl_ports () = !ssl_ports let get_default_port () = match !ports with | (_, p) :: _ -> p | [] -> 80 let get_default_sslport () = match !ssl_ports with | (_, p) :: _ -> p | [] -> 443 let display_version () = print_string version_number; print_newline (); exit 0 module Custom = struct let m = ref Hmap.empty (* TODO : two type variables? *) type 'a key = ('a -> 'a) option * 'a Hmap.key let key ?preprocess () = preprocess, Hmap.Key.create () let find (_, k) = Hmap.find k !m let set (f, k) v = let v = match f with | Some f -> f v | None -> v in m := Hmap.add k v !m let unset (_, k) = m := Hmap.rem k !m end ocsigenserver-5.0.1/src/server/ocsigen_config.mli000066400000000000000000000122221417255654100221600ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2005 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** Configuring Ocsigen server *) open Ocsigen_lib type ssl_info = { ssl_certificate : string option ; ssl_privatekey : string option ; ssl_ciphers : string option ; ssl_dhfile : string option ; ssl_curve : string option } module Socket_type : sig type t = [ | `All | `IPv4 of Unix.inet_addr | `IPv6 of Unix.inet_addr ] val to_string : t -> string val to_inet_addr : t -> Unix.inet_addr end type socket_type = Socket_type.t exception Config_file_error of string val server_name : string val full_server_name : string val version_number : string val is_native : bool val native_ext : string val builtin_packages : String.Set.t val set_logdir : string -> unit val set_syslog_facility: Lwt_log.syslog_facility option -> unit val set_configfile : string -> unit val set_pidfile : string -> unit val set_mimefile : string -> unit val set_verbose : unit -> unit val set_silent : unit -> unit val set_daemon : unit -> unit val set_veryverbose : unit -> unit val set_debug : unit -> unit val set_minthreads : int -> unit val set_maxthreads : int -> unit val set_max_number_of_threads_queued : int -> unit val set_max_number_of_connections : int -> unit val set_client_timeout : int -> unit val set_server_timeout : int -> unit (* val set_keepalive_timeout : int -> unit val set_keepopen_timeout : int -> unit *) val set_filebuffersize : int -> unit val set_maxrequestbodysize : int64 option -> unit val set_maxrequestbodysizeinmemory : int -> unit val set_default_charset : string option -> unit val set_datadir : string -> unit val set_bindir : string -> unit val set_extdir : string -> unit val set_user : string option -> unit val set_group : string option -> unit val set_command_pipe : string -> unit val set_debugmode : bool -> unit val set_disablepartialrequests : bool -> unit val set_usedefaulthostname : bool -> unit val set_respect_pipeline : unit -> unit val set_maxretries : int -> unit val set_shutdown_timeout : float option -> unit val set_ssl_info : ssl_info option -> unit val set_ports : (socket_type * int) list -> unit val set_ssl_ports : (socket_type * int) list -> unit val get_logdir : unit -> string val get_syslog_facility: unit -> Lwt_log.syslog_facility option val get_config_file : unit -> string val get_pidfile : unit -> string option val get_mimefile : unit -> string val get_verbose : unit -> bool val get_silent : unit -> bool val get_daemon : unit -> bool val get_veryverbose : unit -> bool val get_debug : unit -> bool val get_default_user : unit -> string val get_default_group : unit -> string val get_minthreads : unit -> int val get_maxthreads : unit -> int val get_max_number_of_threads_queued : unit -> int val get_max_number_of_connections : unit -> int val get_client_timeout : unit -> int val get_server_timeout : unit -> int (*val get_keepalive_timeout : unit -> int val get_keepopen_timeout : unit -> int*) val get_filebuffersize : unit -> int val get_maxrequestbodysize : unit -> int64 option val get_maxrequestbodysizeinmemory : unit -> int val get_default_charset : unit -> string option val get_datadir : unit -> string val get_bindir : unit -> string val get_extdir : unit -> string val get_user : unit -> string option val get_group : unit -> string option val get_command_pipe : unit -> string val get_debugmode : unit -> bool val get_disablepartialrequests : unit -> bool val get_usedefaulthostname : unit -> bool val get_respect_pipeline : unit -> bool val get_default_port : unit -> int val get_default_sslport : unit -> int val get_maxretries : unit -> int val get_shutdown_timeout : unit -> float option val get_ssl_info : unit -> ssl_info option val get_ports : unit -> (socket_type * int) list val get_ssl_ports : unit -> (socket_type * int) list val display_version : unit -> 'a (**/**) (* Global setting for upload directory. This can be overwritten on a per-site basis. Thus, use only the value inside the [ri.request_config] field of a request (which can be changed by the extension [Extendconfiguration]) *) val set_uploaddir : string option -> unit val get_uploaddir : unit -> string option (* Same thing for upload size *) val set_maxuploadfilesize : int64 option -> unit val get_maxuploadfilesize : unit -> int64 option module Custom : sig type 'a key val key : ?preprocess:('a -> 'a) -> unit -> 'a key val find : 'a key -> 'a option val set : 'a key -> 'a -> unit val unset : 'a key -> unit end ocsigenserver-5.0.1/src/server/ocsigen_extensions.ml000066400000000000000000001013501417255654100227420ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module ocsigen_extensions.ml * Copyright (C) 2005 2007 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) let section = Lwt_log.Section.make "ocsigen:ext" open Lwt.Infix module Url = Ocsigen_lib.Url include Ocsigen_command exception Ocsigen_http_error = Ocsigen_cohttp.Ocsigen_http_error exception Ocsigen_Looping_request (** Xml tag not recognized by an extension (usually not a real error) *) exception Bad_config_tag_for_extension of string (** Error in a tag inside the main ocsigen.conf file *) exception Error_in_config_file of string (** Option incorrect in a userconf file *) exception Error_in_user_config_file of string type file_info = Ocsigen_multipart.file_info = { tmp_filename : string ; filesize : int64 ; raw_original_filename : string ; file_content_type : ((string * string) * (string * string) list) option } let badconfig fmt = Printf.ksprintf (fun s -> raise (Error_in_config_file s)) fmt (* virtual hosts: *) type virtual_hosts = (string * Pcre.regexp * int option) list (* We cannot use generic comparison, as regexpes are abstract values that cannot be compared or hashed. However the string essentially contains the value that is compiled into a regexp, and we compare this instead *) let hash_virtual_hosts (l : virtual_hosts) = Hashtbl.hash (List.map (fun (s, _, p) -> (s, p)) l) let rec equal_virtual_hosts (l1 : virtual_hosts) (l2 : virtual_hosts) = match l1, l2 with | [], [] -> true | [], _::_ | _::_, [] -> false | (s1, _, p1) :: q1, (s2, _, p2) :: q2 -> s1 = s2 && p1 = p2 && equal_virtual_hosts q1 q2 (* Server configuration, for local files that must not be sent *) type do_not_serve = { do_not_serve_regexps: string list; do_not_serve_files: string list; do_not_serve_extensions: string list; } let serve_everything = { do_not_serve_regexps = []; do_not_serve_files = []; do_not_serve_extensions = [] } (* BY TODO : Use unbalanced trees instead *) let join_do_not_serve d1 d2 = { do_not_serve_regexps = d1.do_not_serve_regexps @ d2.do_not_serve_regexps; do_not_serve_files = d1.do_not_serve_files @ d2.do_not_serve_files; do_not_serve_extensions = d1.do_not_serve_extensions @ d2.do_not_serve_extensions; } let hash_consed_do_not_serve = Hashtbl.create 17 exception IncorrectRegexpes of do_not_serve let do_not_serve_to_regexp d = try Hashtbl.find hash_consed_do_not_serve d with Not_found -> let wrap l = if l = [] then None else Some l and bind f = function None -> None | Some v -> Some (f v) in let files, extensions, regexps = wrap d.do_not_serve_files, wrap d.do_not_serve_extensions, wrap d.do_not_serve_regexps in let paren_quote l = String.concat "|" (List.map (fun s -> Printf.sprintf "(%s)" (Pcre.quote s)) l) and paren l = String.concat "|" (List.map (fun s -> Printf.sprintf "(%s)" s) l) in let files = bind paren_quote files and extensions = bind paren_quote extensions and regexps = bind paren regexps in let files = bind (Printf.sprintf ".*/(%s)") files and extensions = bind (Printf.sprintf ".*\\.(%s)") extensions in let l = List.fold_left (fun r -> function None -> r | Some v -> v :: r) [] [files;extensions;regexps] in let regexp = if l = [] then (* This regexp should not never match *) "$^" else Printf.sprintf "^(%s)$" (paren l) in (try Lwt_log.ign_info_f ~section "Compiling exclusion regexp %s" regexp; let r = Ocsigen_lib.Netstring_pcre.regexp regexp in Hashtbl.add hash_consed_do_not_serve d r; r with _ -> raise (IncorrectRegexpes d) ) type config_info = { default_hostname: string; default_httpport: int; default_httpsport: int; default_protocol_is_https: bool; mime_assoc: Ocsigen_charset_mime.mime_assoc; charset_assoc : Ocsigen_charset_mime.charset_assoc; default_directory_index : string list; (** Default name to use as index file when a directory is requested. Use [None] if no index should be tried. The various indexes are tried in the given order. If no index is specified, or the index does not exists, the content of the directory might be listed, according to [list_directry_content] *) list_directory_content : bool; (** Should the list of files in a directory be displayed if there is no index in this directory ? *) follow_symlinks: [`No | `Owner_match | `Always]; (** Should symlinks be followed when accessign a local file? *) do_not_serve_404: do_not_serve; do_not_serve_403: do_not_serve; uploaddir: string option; maxuploadfilesize: int64 option; } let default_config_info () = let do_not_serve_404 = { do_not_serve_regexps = []; do_not_serve_files = []; do_not_serve_extensions = []; } in { default_hostname = Unix.gethostname (); default_httpport = Ocsigen_config.get_default_port (); default_httpsport = Ocsigen_config.get_default_sslport (); default_protocol_is_https = false; mime_assoc = Ocsigen_charset_mime.default_mime_assoc (); charset_assoc = Ocsigen_charset_mime.empty_charset_assoc ?default:(Ocsigen_config.get_default_charset ()) (); default_directory_index = ["index.html"]; list_directory_content = false; follow_symlinks = `Owner_match; do_not_serve_404 ; do_not_serve_403 = do_not_serve_404 ; uploaddir = Ocsigen_config.get_uploaddir (); maxuploadfilesize = Ocsigen_config.get_maxuploadfilesize (); } (* Requests *) type request = { request_info : Ocsigen_request.t; request_config : config_info; } exception Ocsigen_is_dir = Ocsigen_cohttp.Ocsigen_is_dir type answer = | Ext_do_nothing (** I don't want to do anything *) | Ext_found of (unit -> Ocsigen_response.t Lwt.t) (** "OK stop! I will take the page. You can start the following request of the same pipelined connection. Here is the function to generate the page". The extension must return Ext_found as soon as possible when it is sure it is safe to start next request. Usually immediately. But in some case, for example proxies, you don't want the request of one connection to be handled in different order. (for example revproxy.ml starts its requests to another server before returning Ext_found, to ensure that all requests are done in same order). *) | Ext_found_stop of (unit -> Ocsigen_response.t Lwt.t) (** Found but do not try next extensions *) | Ext_next of Cohttp.Code.status (** Page not found. Try next extension. The status is usually `Not_found, but may be for example `Forbidden (403) if you want to try another extension afterwards. Same as Ext_continue_with but does not change the request. *) | Ext_stop_site of (Ocsigen_cookie_map.t * Cohttp.Code.status) (** Error. Do not try next extension, but try next site. *) | Ext_stop_host of (Ocsigen_cookie_map.t * Cohttp.Code.status) (** Error. Do not try next extension, do not try next site, but try next host. *) | Ext_stop_all of (Ocsigen_cookie_map.t * Cohttp.Code.status) (** Error. Do not try next extension, do not try next site, do not try next host. *) | Ext_continue_with of (request * Ocsigen_cookie_map.t * Cohttp.Code.status) (** Used to modify the request before giving it to next extension. The extension returns the request (possibly modified) and a set of cookies if it wants to set or cookies ({!Ocsigen_cookie_set.empty} for no cookies). You must add these cookies yourself in request if you want them to be seen by subsequent extensions, for example using {!Ocsigen_http_frame.compute_new_ri_cookies}. The status is usually equal to the one received from preceding extension (but you may want to modify it). *) | Ext_retry_with of request * Ocsigen_cookie_map.t (** Used to retry all the extensions with a new request. The extension returns the request (possibly modified) and a set of cookies if it wants to set or cookies ({!Ocsigen_cookie_set.empty} for no cookies). You must add these cookies yourself in request if you want them to be seen by subsequent extensions, for example using {!Ocsigen_http_frame.compute_new_ri_cookies}. *) | Ext_sub_result of extension_composite (** Used if your extension want to define option that may contain other options from other extensions. In that case, while parsing the configuration file, call the parsing function (of type [parse_fun]), that will return something of type [extension_composite]. *) | Ext_found_continue_with of (unit -> (Ocsigen_response.t * request) Lwt.t) (** Same as [Ext_found] but may modify the request. *) | Ext_found_continue_with' of (Ocsigen_response.t * request) (** Same as [Ext_found_continue_with] but does not allow to delay the computation of the page. You should probably not use it, but for output filters. *) and request_state = | Req_not_found of (Cohttp.Code.status * request) | Req_found of (request * Ocsigen_response.t) and extension_composite = Ocsigen_cookie_map.t -> request_state -> (answer * Ocsigen_cookie_map.t) Lwt.t type extension = request_state -> answer Lwt.t type parse_fun = Xml.xml list -> extension_composite type parse_host = Parse_host of (Url.path -> parse_host -> parse_fun -> Xml.xml -> extension) let hosts : (virtual_hosts * config_info * extension_composite) list ref = ref [] let set_hosts v = hosts := v let get_hosts () = !hosts (* Default hostname is either the Host header or the hostname set in the configuration file. *) let get_hostname {request_info ; request_config = {default_hostname;_};_} = if Ocsigen_config.get_usedefaulthostname () then default_hostname else match Ocsigen_request.host request_info with | None -> default_hostname | Some host -> host (* Default port is either - the port the server is listening at - or the port in the Host header - or the default port set in the configuration file. *) let get_port { request_info ; request_config = { default_httpport ; default_httpsport ;_ } } = if Ocsigen_config.get_usedefaulthostname () then if Ocsigen_request.ssl request_info then default_httpsport else default_httpport else Ocsigen_request.port request_info let new_url_of_directory_request request ri = Lwt_log.ign_info ~section "Sending 301 Moved permanently"; let ssl = Ocsigen_request.ssl ri in let scheme = if ssl then "https" else "http" and host = get_hostname request and port = let port = get_port request in if port = if ssl then 443 else 80 then None else Some port and path = let path = Ocsigen_request.path_string ri in if path.[String.length path - 1] = '/' then path else path ^ "/" and query = Ocsigen_request.get_params ri in Uri.make ~scheme ~host ?port ~path ~query () (* To give parameters to extensions: *) let dynlinkconfig = ref ([] : Xml.xml list) let set_config s = dynlinkconfig := s let get_config () = !dynlinkconfig let site_match request (site_path : string list) url = (* We are sure that there is no / at the end or beginning of site_path *) (* and no / at the beginning of url *) (* and no // or ../ inside both of them *) (* We return the subpath without / at beginning *) let rec aux site_path url = match site_path, url with | [], [] -> raise (Ocsigen_is_dir (new_url_of_directory_request request)) | [], p -> Some p | a::l, aa::ll when a = aa -> aux l ll | _ -> None in match site_path, url with | [], [] -> Some [] | _ -> aux site_path url let default_extension_composite : extension_composite = fun cookies_to_set -> function | Req_found (ri, res) -> Lwt.return (Ext_found_continue_with' (res, ri), cookies_to_set) | Req_not_found (e, ri) -> Lwt.return (Ext_continue_with (ri, Ocsigen_cookie_map.empty, e), cookies_to_set) let compose_step (f : extension) (g : extension_composite) : extension_composite = fun cookies_to_set req_state -> f req_state >>= fun res -> let rec aux cookies_to_set = function | Ext_do_nothing -> g cookies_to_set req_state | Ext_found r -> r () >>= fun r' -> let ri = match req_state with | Req_found (ri, _) -> ri | Req_not_found (_, ri) -> ri in g Ocsigen_cookie_map.empty (Req_found (ri, Ocsigen_response.add_cookies r' cookies_to_set)) | Ext_found_continue_with r -> r () >>= fun (r', req) -> g Ocsigen_cookie_map.empty (Req_found (req, Ocsigen_response.add_cookies r' cookies_to_set)) | Ext_found_continue_with' (r', req) -> g Ocsigen_cookie_map.empty (Req_found (req, Ocsigen_response.add_cookies r' cookies_to_set)) | Ext_next e -> let ri = match req_state with | Req_found (ri, _) -> ri | Req_not_found (_, ri) -> ri in g cookies_to_set (Req_not_found (e, ri)) | Ext_continue_with (ri, cook, e) -> g (Ocsigen_cookie_map.add_multi cook cookies_to_set) (Req_not_found (e, ri)) | Ext_found_stop _ | Ext_stop_site _ | Ext_stop_host _ | Ext_stop_all _ | Ext_retry_with _ as res -> Lwt.return (res, cookies_to_set) | Ext_sub_result sr -> sr cookies_to_set req_state >>= fun (res, cookies_to_set) -> aux cookies_to_set res in aux cookies_to_set res let rec compose = function | [] -> default_extension_composite | e :: rest -> compose_step e (compose rest) let fun_end = ref (fun () -> ()) let fun_exn = ref (fun exn -> (raise exn : string)) let rec parse_site_attrs (enc, dir) = function | [] -> (match dir with | None -> raise (Ocsigen_config.Config_file_error ("Missing dir attribute in ")) | Some s -> enc, s) | ("path", s) :: rest | ("dir", s) :: rest -> (match dir with | None -> parse_site_attrs (enc, Some s) rest | _ -> raise (Ocsigen_config.Config_file_error ("Duplicate attribute dir in "))) | ("charset", s) :: rest -> (match enc with | None -> parse_site_attrs ((Some s), dir) rest | _ -> raise (Ocsigen_config.Config_file_error ("Duplicate attribute charset in "))) | (s, _) :: _ -> raise (Ocsigen_config.Config_file_error ("Wrong attribute for : "^s)) let make_parse_config path parse_host l : extension_composite = let f = parse_host path (Parse_host parse_host) in (* creates all site data, if any *) let rec parse_config : _ -> extension_composite = function | [] -> default_extension_composite | xmltag :: ll -> try (* The evaluation order is important here *) let f = f parse_config xmltag in compose_step f (parse_config ll) with | Bad_config_tag_for_extension t -> (* This case happens only if no extension has recognized the tag at all *) badconfig "Unexpected tag <%s> inside " t (Url.string_of_url_path ~encode:true path) | Error_in_config_file _ as e -> raise e | e -> badconfig "Error while parsing configuration file: %s" (try !fun_exn e with e -> Printexc.to_string e) in let r = try parse_config l with e -> !fun_end (); raise e (*VVV Maybe we should avoid calling fun_end after parsing user config files (with extension userconf) ... See eliommod.ml *) in !fun_end (); r let site_ext ext_of_children charset path cookies_to_set = function | Req_found (ri, res) -> Lwt.return (Ext_found_continue_with' (res, ri), cookies_to_set) | Req_not_found (e, oldri) -> let oldri = match charset with | None -> oldri | Some charset -> { oldri with request_config = { oldri.request_config with charset_assoc = Ocsigen_charset_mime.set_default_charset oldri.request_config.charset_assoc charset } } in match site_match oldri path (Ocsigen_request.path oldri.request_info) with | None -> Lwt_log.ign_info_f ~section "site \"%a\" does not match url \"%a\"." (fun () path -> Url.string_of_url_path ~encode:true path) path (fun () oldri -> Url.string_of_url_path ~encode:true (Ocsigen_request.path oldri.request_info)) oldri; Lwt.return (Ext_next e, cookies_to_set) | Some sub_path -> Lwt_log.ign_info_f ~section "site found: url \"%a\" matches \"%a\"." (fun () oldri -> Url.string_of_url_path ~encode:true (Ocsigen_request.path oldri.request_info)) oldri (fun () path -> Url.string_of_url_path ~encode:true path) path; let ri = { oldri with request_info = Ocsigen_request.update oldri.request_info ~sub_path: (Url.string_of_url_path ~encode:true sub_path) } in ext_of_children cookies_to_set (Req_not_found (e, ri)) >>= function (* After a site, we turn back to old ri *) | (Ext_stop_site (cs, err), cookies_to_set) | (Ext_continue_with (_, cs, err), cookies_to_set) -> Lwt.return (Ext_continue_with (oldri, cs, err), cookies_to_set) | (Ext_found_continue_with r, cookies_to_set) -> r () >>= fun (r', _req) -> Lwt.return (Ext_found_continue_with' (r', oldri), cookies_to_set) | (Ext_found_continue_with' (r, _req), cookies_to_set) -> Lwt.return (Ext_found_continue_with' (r, oldri), cookies_to_set) | (Ext_do_nothing, cookies_to_set) -> Lwt.return (Ext_continue_with (oldri, Ocsigen_cookie_map.empty, e), cookies_to_set) | r -> Lwt.return r let site_ext ext_of_children charset path : extension = function | Req_found (ri, r) -> Lwt.return (Ext_found_continue_with' (r, ri)) | Req_not_found _ -> Lwt.return (Ext_sub_result (site_ext ext_of_children charset path)) let preprocess_site_path p = Url.( remove_dotdot p |> remove_slash_at_beginning |> remove_slash_at_end ) (* Implements only parsing. Uses parse_host to recursively parse children of . *) let default_parse_config _userconf_info (_host : virtual_hosts) _config_info prevpath (Parse_host parse_host) (_parse_fun : parse_fun) = function | Xml.Element ("site", atts, l) -> let charset, dir = parse_site_attrs (None, None) atts in let path = prevpath @ preprocess_site_path (Url.split_path dir) in let ext_of_children = make_parse_config path parse_host l in site_ext ext_of_children charset path | Xml.Element (tag,_,_) -> raise (Bad_config_tag_for_extension tag) | _ -> raise (Ocsigen_config.Config_file_error ("Unexpected content inside ")) type userconf_info = { localfiles_root : string; } type parse_config = userconf_info option -> virtual_hosts -> config_info -> parse_config_aux and parse_config_aux = Url.path -> parse_host -> (parse_fun -> Xml.xml -> extension ) let _extension_void_fun_site : parse_config = fun _ _ _ _ _ _ -> function | Xml.Element (t, _, _) -> raise (Bad_config_tag_for_extension t) | _ -> raise (Error_in_config_file "Unexpected data in config file") let register, parse_config_item, get_init_exn_handler = let ref_fun_site = ref default_parse_config in (fun ?fun_site ?end_init ?(exn_handler=raise) ?(respect_pipeline=false) () -> if respect_pipeline then Ocsigen_config.set_respect_pipeline (); (match fun_site with | None -> () | Some fun_site -> let old_fun_site = !ref_fun_site in ref_fun_site := (fun path host conf_info -> let oldf = old_fun_site path host conf_info in let newf = fun_site path host conf_info in fun path parse_host -> let oldf = oldf path parse_host in let newf = newf path parse_host in fun parse_config config_tag -> try oldf parse_config config_tag with | Bad_config_tag_for_extension _c -> newf parse_config config_tag )); (match end_init with | Some end_init -> fun_end := Ocsigen_lib.comp end_init !fun_end; | None -> ()); let curexnfun = !fun_exn in fun_exn := fun e -> try curexnfun e with e -> exn_handler e), (fun path host conf -> !ref_fun_site path host conf), (fun () -> !fun_exn) let default_parse_extension ext_name = function | [] -> () | _ -> raise (Error_in_config_file (Printf.sprintf "Unexpected content found in configuration of extension %s: %s does not accept options" ext_name ext_name)) let register ~name ?fun_site ?end_init ?init_fun ?exn_handler ?respect_pipeline () = Ocsigen_loader.set_module_init_function name (fun () -> (match init_fun with | None -> default_parse_extension name (get_config ()) | Some f -> f (get_config ())); register ?fun_site ?end_init ?exn_handler ?respect_pipeline ()) module Configuration = struct type attribute' = { attribute_obligatory : bool; attribute_value_func : string -> unit } type attribute = string * attribute' type element' = { obligatory : bool; init : unit -> unit; elements : element list; attributes : attribute list; pcdata : (string -> unit) option; other_elements : (string -> (string * string) list -> Xml.xml list -> unit) option; other_attributes : (string -> string -> unit) option; } and element = string * element' let element ~name ?(obligatory=false) ?(init=ignore) ?(elements=[]) ?(attributes=[]) ?pcdata ?other_elements ?other_attributes () : element = name, { obligatory; init; elements; attributes; pcdata; other_elements; other_attributes } let attribute ~name ?(obligatory=false) f : attribute = name, { attribute_obligatory = obligatory; attribute_value_func = f } let ignore_blank_pcdata ~in_tag = fun str -> String.iter (fun c -> if not (List.mem c [' '; '\n'; '\r'; '\t']) then raise (Error_in_user_config_file ("Non-blank PCDATA in tag "^in_tag))) str let refuse_pcdata ~in_tag = fun _ -> raise (Error_in_user_config_file ("No PCDATA allowed in tag "^in_tag)) let check_attribute_occurrence ~in_tag attributes = function | name, { attribute_obligatory = true ;_ } -> (try ignore (List.assoc name attributes) with Not_found -> raise (Error_in_user_config_file ("Obligatory attribute "^name^" not in tag "^in_tag))) | _ -> () let check_element_occurrence ~in_tag elements = function | name, { obligatory = true ;_ } -> let corresponding_element = function | Xml.Element (name', _, _) -> name = name' | _ -> false in if not (List.exists corresponding_element elements) then raise (Error_in_user_config_file ("Obligatory element "^name^" not in tag "^in_tag)) | _ -> () let process_attribute = fun ~in_tag ~attributes:spec_attributes ?other_attributes:spec_other_attributes (attribute, value) -> try (List.assoc attribute spec_attributes).attribute_value_func value with Not_found -> match spec_other_attributes with | Some spec_other_attributes -> spec_other_attributes attribute value | None -> raise (Error_in_user_config_file ("Unexpected attribute "^attribute^" in tag "^in_tag)) let rec process_element ~in_tag ~elements:spec_elements ?pcdata:spec_pcdata ?other_elements:spec_other_elements = function | Xml.PCData str -> let spec_pcdata = Ocsigen_lib.Option.get (fun () -> ignore_blank_pcdata ~in_tag) spec_pcdata in spec_pcdata str | Xml.Element (name, attributes, elements) -> try let spec = List.assoc name spec_elements in List.iter (check_attribute_occurrence ~in_tag:name attributes) spec.attributes; List.iter (check_element_occurrence ~in_tag:name elements) spec.elements; spec.init (); List.iter (process_attribute ~in_tag:name ~attributes:spec.attributes ?other_attributes:spec.other_attributes) attributes; List.iter (process_element ~in_tag:name ~elements:spec.elements ?pcdata:spec.pcdata ?other_elements:spec.other_elements) elements with Not_found -> match spec_other_elements with | Some spec_other_elements -> spec_other_elements name attributes elements | None -> raise (Error_in_config_file ("Unknown tag "^name^" in tag "^in_tag)) let process_elements ~in_tag ~elements:spec_elements ?pcdata ?other_elements ?(init=ignore) elements = List.iter (check_element_occurrence ~in_tag elements) spec_elements; init (); List.iter (process_element ~in_tag ~elements:spec_elements ?pcdata ?other_elements) elements end let start_initialisation, during_initialisation, end_initialisation, get_numberofreloads = let init = ref true in let nb = ref (-1) in ((fun () -> init := true; nb := !nb+1; ), (fun () -> !init), (fun () -> init := false; ), (fun () -> !nb)) let host_match ~(virtual_hosts : virtual_hosts) ~host ~port = let port_match = function | None -> true | Some p -> p = port in match host with | None -> List.exists (fun (_, _, p) -> port_match p) virtual_hosts (*VVV Warning! For HTTP/1.0, when host is absent, we take the first one, even if it doesn't match! *) | Some host -> let host_match regexp = (Ocsigen_lib.Netstring_pcre.string_match regexp host 0 <> None) in let rec aux = function | [] -> false | (_, a, p)::l -> (port_match p && host_match a) || aux l in aux virtual_hosts (* Currently used only for error messages. *) let string_of_host (h : virtual_hosts) = let aux1 (host, _, port) = match port with | None -> host | Some p -> host ^ ":" ^ string_of_int p in List.fold_left (fun d arg -> d ^ aux1 arg ^" ") "" h let compute_result ?(previous_cookies = Ocsigen_cookie_map.empty) request_info = let host = Ocsigen_request.host request_info and port = Ocsigen_request.port request_info in let string_of_host_option = function | None -> ":"^(string_of_int port) | Some h -> h^":"^(string_of_int port) in let rec fold_hosts request_info (prev_err : Cohttp.Code.status) cookies_to_set = function | [] -> Lwt.fail (Ocsigen_http_error (cookies_to_set, prev_err)) | (virtual_hosts, request_config, host_function) :: l when host_match ~virtual_hosts ~host ~port -> Lwt_log.ign_info_f ~section "host found! %a matches %a" (fun () -> string_of_host_option) host (fun () -> string_of_host) virtual_hosts; host_function cookies_to_set (Req_not_found (prev_err, { request_info ; request_config })) >>= fun (res_ext, cookies_to_set) -> (match res_ext with | Ext_found r | Ext_found_stop r -> r () >>= fun r' -> Lwt.return (Ocsigen_response.add_cookies r' cookies_to_set) | Ext_do_nothing -> fold_hosts request_info prev_err cookies_to_set l | Ext_found_continue_with r -> r () >>= fun (r', _) -> Lwt.return (Ocsigen_response.add_cookies r' cookies_to_set) | Ext_found_continue_with' (r, _) -> Lwt.return (Ocsigen_response.add_cookies r cookies_to_set) | Ext_next e -> fold_hosts request_info e cookies_to_set l (* try next site *) | Ext_stop_host (cook, e) | Ext_stop_site (cook, e) -> fold_hosts request_info e (Ocsigen_cookie_map.add_multi cook cookies_to_set) l (* try next site *) | Ext_stop_all (_cook, e) -> Lwt.fail (Ocsigen_http_error (cookies_to_set, e)) | Ext_continue_with (_, cook, e) -> fold_hosts request_info e (Ocsigen_cookie_map.add_multi cook cookies_to_set) l | Ext_retry_with (request2, cook) -> fold_hosts_limited (get_hosts ()) (Ocsigen_cookie_map.add_multi cook cookies_to_set) request2.request_info (* retry all *) | Ext_sub_result _sr -> assert false ) | (h, _, _)::l -> Lwt_log.ign_info_f ~section "host = %a does not match %a" (fun () -> string_of_host_option) host (fun () -> string_of_host) h; fold_hosts request_info prev_err cookies_to_set l and fold_hosts_limited sites cookies_to_set request_info = Ocsigen_request.incr_tries request_info; if Ocsigen_request.tries request_info > Ocsigen_config.get_maxretries () then Lwt.fail Ocsigen_Looping_request else fold_hosts request_info `Not_found cookies_to_set sites in fold_hosts_limited (get_hosts ()) previous_cookies request_info let get_number_of_connected = Ocsigen_cohttp.get_number_of_connected (* user directories *) exception NoSuchUser type ud_string = Nodir of string | Withdir of string * string * string let user_dir_regexp = Ocsigen_lib.Netstring_pcre.regexp "(.*)\\$u\\(([^\\)]*)\\)(.*)" let parse_user_dir s = match Pcre.full_split ~rex:user_dir_regexp ~max:(-1) s with | [ Pcre.Delim _; Pcre.Group (1, s1); Pcre.Group (2, u); Pcre.Group (3, s2)] -> Withdir (s1, u, s2) | _ -> Nodir s let replace_user_dir regexp dest pathstring = match dest with | Nodir dest -> Ocsigen_lib.Netstring_pcre.global_replace regexp dest pathstring | Withdir (s1, u, s2) -> try let s1 = Ocsigen_lib.Netstring_pcre.global_replace regexp s1 pathstring in let u = Ocsigen_lib.Netstring_pcre.global_replace regexp u pathstring in let s2 = Ocsigen_lib.Netstring_pcre.global_replace regexp s2 pathstring in let userdir = (Unix.getpwnam u).Unix.pw_dir in Lwt_log.ign_info_f ~section "User %s" u; s1^userdir^s2 with Not_found -> Lwt_log.ign_info_f ~section "No such user %s" u; raise NoSuchUser exception Not_concerned let (>|!) v f = match v with | None -> raise Not_concerned | Some v -> f v let find_redirection regexp full_url dest r = if full_url then Ocsigen_request.host r >|! fun host -> let path = let full_path = Ocsigen_request.path_string r in match Ocsigen_request.query r with | None -> full_path | Some g -> full_path ^ "?" ^ g in let path = Url.make_absolute_url ~https:(Ocsigen_request.ssl r) ~host ~port:(Ocsigen_request.port r) ("/" ^ path) in Ocsigen_lib.Netstring_pcre.string_match regexp path 0 >|! fun _ -> (* Matching regexp found! *) Ocsigen_lib.Netstring_pcre.global_replace regexp dest path else let path = let sub_path = Ocsigen_request.sub_path_string r in match Ocsigen_request.query r with | None -> sub_path | Some g -> sub_path ^ "?" ^ g in Ocsigen_lib.Netstring_pcre.string_match regexp path 0 >|! fun _ -> (* Matching regexp found! *) Ocsigen_lib.Netstring_pcre.global_replace regexp dest path ocsigenserver-5.0.1/src/server/ocsigen_extensions.mli000066400000000000000000000415221417255654100231170ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module pagesearch.mli * Copyright (C) 2005 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** Extensions interface for Ocsigen Server *) val section : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) include (module type of Ocsigen_command) exception Ocsigen_http_error of Ocsigen_cookie_map.t * Cohttp.Code.status (** Xml tag not recognized by an extension (usually not a real error) *) exception Bad_config_tag_for_extension of string (** Error in a tag inside the main ocsigen.conf file *) exception Error_in_config_file of string (** Option incorrect in a userconf file *) exception Error_in_user_config_file of string type file_info = Ocsigen_multipart.file_info = { tmp_filename : string ; filesize : int64 ; raw_original_filename : string ; file_content_type : ((string * string) * (string * string) list) option } val badconfig : ('a, unit, string, 'b) format4 -> 'a (** Convenient function for raising Error_in_config_file exceptions with a sprintf-formatted argument. *) (*****************************************************************************) (** Type of the result of parsing the field [hostfiler] in the configuration file. Inside the list, the first argument is the host itself (which is a glob-like pattern that can contains [*]), a regexp parsing this pattern, and optionally a port. *) type virtual_hosts = (string * Pcre.regexp * int option) list val hash_virtual_hosts : virtual_hosts -> int val equal_virtual_hosts : virtual_hosts -> virtual_hosts -> bool val host_match: virtual_hosts:virtual_hosts -> host:string option -> port:int -> bool (*****************************************************************************) (** Configuration to hide/forbid local files *) type do_not_serve = { do_not_serve_regexps: string list; do_not_serve_files: string list; do_not_serve_extensions: string list; } val serve_everything : do_not_serve exception IncorrectRegexpes of do_not_serve (** Compile a do_not_serve structure into a regexp. Raises [IncorrectRegexpes] if the compilation fails. The result is memoized for subsequent calls with the same argument *) val do_not_serve_to_regexp: do_not_serve -> Pcre.regexp val join_do_not_serve : do_not_serve -> do_not_serve -> do_not_serve (** Configuration options, passed to (and modified by) extensions *) type config_info = { default_hostname: string; default_httpport: int; default_httpsport: int; default_protocol_is_https: bool; mime_assoc: Ocsigen_charset_mime.mime_assoc; charset_assoc : Ocsigen_charset_mime.charset_assoc; default_directory_index : string list; (** Default name to use as index file when a directory is requested. Use [None] if no index should be tried. The various indexes are tried in the given order. If no index is specified, or the index does not exists, the content of the directory might be listed, according to [list_directory_content] *) list_directory_content : bool; (** Should the list of files in a directory be displayed if there is no index in this directory ? *) follow_symlinks: [`No | `Owner_match | `Always]; (** Should symlinks be followed when accessing a local file? *) do_not_serve_404: do_not_serve; do_not_serve_403: do_not_serve; uploaddir: string option; maxuploadfilesize: int64 option; } val default_config_info : unit -> config_info type request = { request_info: Ocsigen_request.t; request_config: config_info; } exception Ocsigen_is_dir of (Ocsigen_request.t -> Uri.t) type answer = | Ext_do_nothing (** I don't want to do anything *) | Ext_found of (unit -> Ocsigen_response.t Lwt.t) (** "OK stop! I will take the page. You can start the following request of the same pipelined connection. Here is the function to generate the page". The extension must return Ext_found as soon as possible when it is sure it is safe to start next request. Usually immediately. But in some case, for example proxies, you don't want the request of one connection to be handled in different order. (for example revproxy.ml starts its requests to another server before returning Ext_found, to ensure that all requests are done in same order). *) | Ext_found_stop of (unit -> Ocsigen_response.t Lwt.t) (** Found but do not try next extensions *) | Ext_next of Cohttp.Code.status (** Page not found. Try next extension. The status is usually `Not_found, but may be for example `Forbidden (403) if you want to try another extension afterwards. Same as Ext_continue_with but does not change the request. *) | Ext_stop_site of (Ocsigen_cookie_map.t * Cohttp.Code.status) (** Error. Do not try next extension, but try next site. *) | Ext_stop_host of (Ocsigen_cookie_map.t * Cohttp.Code.status) (** Error. Do not try next extension, do not try next site, but try next host. *) | Ext_stop_all of (Ocsigen_cookie_map.t * Cohttp.Code.status) (** Error. Do not try next extension, do not try next site, do not try next host. *) | Ext_continue_with of (request * Ocsigen_cookie_map.t * Cohttp.Code.status) (** Used to modify the request before giving it to next extension. The extension returns the request (possibly modified) and a set of cookies if it wants to set or cookies ({!Ocsigen_cookie_set.empty} for no cookies). You must add these cookies yourself in request if you want them to be seen by subsequent extensions, for example using {!Ocsigen_http_frame.compute_new_ri_cookies}. The status is usually equal to the one received from preceding extension (but you may want to modify it). *) | Ext_retry_with of request * Ocsigen_cookie_map.t (** Used to retry all the extensions with a new request. The extension returns the request (possibly modified) and a set of cookies if it wants to set or cookies ({!Ocsigen_cookie_set.empty} for no cookies). You must add these cookies yourself in request if you want them to be seen by subsequent extensions, for example using {!Ocsigen_http_frame.compute_new_ri_cookies}. *) | Ext_sub_result of extension_composite (** Used if your extension want to define option that may contain other options from other extensions. In that case, while parsing the configuration file, call the parsing function (of type [parse_fun]), that will return something of type [extension_composite]. *) | Ext_found_continue_with of (unit -> (Ocsigen_response.t * request) Lwt.t) (** Same as [Ext_found] but may modify the request. *) | Ext_found_continue_with' of (Ocsigen_response.t * request) (** Same as [Ext_found_continue_with] but does not allow to delay the computation of the page. You should probably not use it, but for output filters. *) and request_state = | Req_not_found of (Cohttp.Code.status * request) | Req_found of (request * Ocsigen_response.t) and extension_composite = Ocsigen_cookie_map.t -> request_state -> (answer * Ocsigen_cookie_map.t) Lwt.t type extension = request_state -> answer Lwt.t (** For each tag in the configuration file, you can set the extensions you want. Each extension is implemented as a function, taking the charset found in configuration file, the current state of the request, and returning an answer. If no page has been generated so far ([Req_not_found]), it receive the error code given by the previous extension (default 404), and the request information. If a page has been generated by previous extensions (case [Req_found]), the extension may want to modify the result (filters). *) type parse_fun = Xml.xml list -> extension_composite (** Type of the functions parsing the content of a tag *) type parse_host (** Information received by extensions accepting userconf files. The parameter [localfiles_root] is an absolute path to the directory that the user is allowed to serve. This is used by staticmod, to disallow the user from allowing access to outside of this directory *) type userconf_info = { localfiles_root : string; } (** [parse_config] is the type of the functions parsing a tag (and returning an extension). Those are functions taking {ul {- the name of the virtual }} that will be called for each , and that will generate a function taking: {ul {- the path attribute of a tag}} that will be called for each , and that will generate a function taking: {ul {- an item of the config file}} that will be called on each tag inside and: {ul {- raise [Bad_config_tag_for_extension] if it does not recognize that tag} {- return something of type [extension] (filter or page generator)}} [parse_config_user] is the type of functions parsing a site tag inside an userconf file. They take one more parameter, of type userconf_info *) type parse_config = userconf_info option -> virtual_hosts -> config_info -> parse_config_aux and parse_config_aux = Ocsigen_lib.Url.path -> parse_host -> (parse_fun -> Xml.xml -> extension ) (** For each extension generating pages, we register its name and six functions: - a function [fun_site] of type [parse_config]. This function will be responsible for handling the options of the configuration files that are recognized by the extension, and potentially generating a page. - a function [end_init] that will be called at the end of the initialisation phase of each site - a function [init_fun] that will be called just before registering the extension, taking as parameter the configuration options between [] and []. This allows to give configuration options to extensions. If no function is supplied, the extension is supposed to accept no option (and loading will fail if an option is supplied) See <> for the easy construction of such a function. - a function [exn_handler] that will create an error message from the exceptions that may be raised during the initialisation phase, and raise again all other exceptions Moreover, if the optional parameter [?respect_pipeline] is [true], the extension will ask the server to respect the order of the pipeline. That means that it will wait to be sure that the previous request from the same connection has been taken by an extension before giving a request to an extension. Use this to write proxies extensions, when you want to be able to pipeline the requests you to another server. It is false by default. *) val register : name:string -> ?fun_site:parse_config -> ?end_init:(unit -> unit) -> ?init_fun:(Xml.xml list -> unit) -> ?exn_handler:(exn -> string) -> ?respect_pipeline:bool -> unit -> unit (** This modules contains types and constructor for the description of XML configurations and the accordingly parsing. *) module Configuration : sig (** Specification of a XML element. *) type element (** Specification of a XML attribute. *) type attribute (** Create the specification of a XML element. @param name Name of the XML tag @param init A function to be executed before processing the child elements and attributes @param obligatory Whether the element is obligatory ([false] by default) @param elements Specifications of the child elements @param attribute Specifications of the attributes @param pcdata Function to be applied on the pcdata ([ignore_blank_pcdata] by default) @param other_elements Optional function to be applied on the content of unspecified tags @param other_attributes Optional function to be applied on the unspecfied attributes *) val element : name:string -> ?obligatory:bool -> ?init:(unit -> unit) -> ?elements:element list -> ?attributes:attribute list -> ?pcdata:(string -> unit) -> ?other_elements:(string -> (string * string) list -> Xml.xml list -> unit) -> ?other_attributes:(string -> string -> unit) -> unit -> element (** [attribute ~name f] create a specification of a XML attribute. @param name The name of the XML attribute @param obligatory Whether the attribute is obligatory ([false] by default) @param f Function to be applied on the value string of the attribute *) val attribute : name:string -> ?obligatory:bool -> (string -> unit) -> attribute (** Process an XML element by the specifications. @param in_tag Name of the enclosing XML tag (just for generating error messages) @param elements Specifications of the child elements @param pcdata Function to be applied on the PCDATA ([ignore_blank_pcdata] by default) @param other_elements Optional function to be applied on unexpected child elements @raise Error_in_config_file If an element (resp. attribute) occurs which is not specified by the [element] (resp. [attribute]) parameter and no function [other_elements] (resp. other_attributes) is provided *) val process_element : in_tag:string -> elements:element list -> ?pcdata:(string -> unit) -> ?other_elements:(string -> (string * string) list -> Xml.xml list -> unit) -> Xml.xml -> unit (** Application of [process_element] on a list of XML elements. *) val process_elements : in_tag:string -> elements:element list -> ?pcdata:(string -> unit) -> ?other_elements:(string -> (string * string) list -> Xml.xml list -> unit) -> ?init:(unit -> unit) -> Xml.xml list -> unit (** The specification for ignoring blank PCDATA ('\n', '\r', ' ', '\t') and failing otherwise (a reasonable default). *) val ignore_blank_pcdata : in_tag:string -> string -> unit val refuse_pcdata : in_tag:string -> string -> unit end (** Returns the hostname to be used for absolute links or redirections. It is either the Host header or the hostname set in the configuration file. *) val get_hostname : request -> string (** Returns the port to be used for absolute links or redirections. It is either: - the port the server is listening at - or the port in the Host header - or the default port set in the configuration file. *) val get_port : request -> int (** new_url_of_directory_request create a redirection and generating a new url for the client (depending on the server configuration and request) @param request configuration of the server @param ri request *) val new_url_of_directory_request : request -> Ocsigen_request.t -> Uri.t (** {3 User directories} *) (** Exception raised when an non-existing user is found *) exception NoSuchUser (** The type for string that may contain a $u(...) *) type ud_string val parse_user_dir : string -> ud_string val replace_user_dir : Pcre.regexp -> ud_string -> string -> string (** raises [Not_found] is the directory does not exist *) (** {3 Regular expressions for redirections} *) exception Not_concerned val find_redirection : Pcre.regexp -> bool -> string -> Ocsigen_request.t -> string (**/**) val preprocess_site_path : Ocsigen_lib.Url.path -> Ocsigen_lib.Url.path val compose : extension list -> extension_composite val make_parse_config : Ocsigen_lib.Url.path -> parse_config_aux -> parse_fun val parse_config_item : parse_config val site_ext : extension_composite -> Ocsigen_charset_mime.charset option -> Ocsigen_lib.Url.path -> extension val set_hosts : (virtual_hosts * config_info * extension_composite) list -> unit val get_hosts : unit -> (virtual_hosts * config_info * extension_composite) list (** Compute the answer to be sent to the client, by trying all extensions according the configuration file. *) val compute_result : ?previous_cookies:Ocsigen_cookie_map.t -> Ocsigen_request.t -> Ocsigen_response.t Lwt.t (** Profiling *) val get_number_of_connected : unit -> int val during_initialisation : unit -> bool val start_initialisation : unit -> unit val end_initialisation : unit -> unit val get_numberofreloads : unit -> int val get_init_exn_handler : unit -> exn -> string val set_config : Xml.xml list -> unit ocsigenserver-5.0.1/src/server/ocsigen_local_files.ml000066400000000000000000000213511417255654100230210ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Copyright (C) 2009 Boris Yakobowski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (* Display of a local file or directory. Currently used in staticmod and eliom_predefmod *) let section = Lwt_log.Section.make "ocsigen:local-file" exception Failed_403 exception Failed_404 exception NotReadableDirectory (* Policies for following symlinks *) type symlink_policy = stat:Unix.LargeFile.stats -> lstat:Unix.LargeFile.stats -> bool let never_follow_symlinks : symlink_policy = fun ~stat:_ ~lstat:_ -> false let follow_symlinks_if_owner_match : symlink_policy = fun ~stat ~lstat -> stat.Unix.LargeFile.st_uid = lstat.Unix.LargeFile.st_uid (* checks that [filename] can be followed depending on the predicate [policy] which must receives as argument both the results of calling [stat] and [lstat] on filenam. If supplied, [stat] must be the result of calling [Unix.stat] on [filename] *) let check_symlinks_aux filename ?(stat=Unix.LargeFile.stat filename) (policy : symlink_policy) = let lstat = Unix.LargeFile.lstat filename in if lstat.Unix.LargeFile.st_kind = Unix.S_LNK then policy ~stat ~lstat else true (* Check that there are no invalid symlinks in the directories leading to [filename]. Paths upwards [no_check_for] are not checked. *) let rec check_symlinks_parent_directories ~filename ~no_check_for (policy : symlink_policy) = if filename = "/" || filename = "." || Some filename = no_check_for then true else let dirname = Filename.dirname filename in check_symlinks_aux dirname policy && check_symlinks_parent_directories ~filename:dirname ~no_check_for policy (* Check that [filename] can be reached according to the given symlink policy *) let check_symlinks ~no_check_for ~filename policy = let aux policy = if filename = "/" then (* The root cannot be a symlink, and this avoids some degenerate cases later on *) true else let filename = (* [filename] should start by at least a slash, as [Filename.is_relative filename] should be false. Hence the length should be at least 1 *) (* We remove an eventual trailing slash, in order to avoid a needless recursion in check_symlinks_parent_directories, and so that Unix.lstat returns the correct result (Unix.lstat "foo/" and Unix.lstat "foo" return two different results...) *) let len = String.length filename - 1 in if filename.[len] = '/' then String.sub filename 0 len else filename in check_symlinks_aux filename policy && check_symlinks_parent_directories ~filename ~no_check_for policy in match policy with | `Always -> true | `No -> aux never_follow_symlinks | `Owner_match -> aux follow_symlinks_if_owner_match let check_dotdot = let regexp = Ocsigen_lib.Netstring_pcre.regexp "(/\\.\\./)|(/\\.\\.$)" in fun ~filename -> (* We always reject .. in filenames. In URLs, .. have already been removed by the server, but the filename may come from somewhere else than URLs ... *) try ignore (Ocsigen_lib.Netstring_pcre.search_forward regexp filename 0); false with Not_found -> true let can_send filename request = let filename = Ocsigen_lib.Url.split_path filename |> Ocsigen_lib.Url.norm_path |> Ocsigen_lib.Url.join_path in Lwt_log.ign_info_f ~section "checking if file %s can be sent" filename; let matches arg = Ocsigen_lib.Netstring_pcre.string_match (Ocsigen_extensions.do_not_serve_to_regexp arg) filename 0 <> None in if matches request.Ocsigen_extensions.do_not_serve_403 then ( Lwt_log.ign_info ~section "this file is forbidden"; raise Failed_403) else if matches request.Ocsigen_extensions.do_not_serve_404 then ( Lwt_log.ign_info ~section "this file must be hidden"; raise Failed_404) (* Return type of a request for a local file. The string argument represents the real file/directory to serve, eg. foo/index.html instead of foo *) type resolved = | RFile of string | RDir of string (* given [filename], we search for it in the local filesystem and - we return ["filename/index.html"] if [filename] corresponds to a directory, ["filename/index.html"] is valid, and ["index.html"] is one possible index (trying all possible indexes in order) - we raise [Failed_404] if [filename] corresponds to a directory, no index exists and [list_dir_content] is false. Warning: this behaviour is not the same as Apache's but it corresponds to a missing service in Eliom (answers 404). This also allows to have an Eliom service after a "forbidden" directory - we raise [Failed_403] if [filename] is a symlink that must not be followed - raises [Failed_404] if [filename] does not exist, or is a special file - otherwise returns [filename] *) (* See also module Files in eliom.ml *) let resolve ?no_check_for ~request:({Ocsigen_extensions.request_config ;_} as request) ~filename () = (* We only accept absolute filenames in daemon mode, as we do not really know what is the current directory *) let filename = if Filename.is_relative filename && Ocsigen_config.get_daemon () then "/"^filename else filename in try Lwt_log.ign_info_f ~section "Testing \"%s\"." filename; let stat = Unix.LargeFile.stat filename in let (filename, stat) = if stat.Unix.LargeFile.st_kind = Unix.S_DIR then if filename.[String.length filename - 1] <> '/' then begin (* In this case, [filename] is a directory but this is not visible in its name as there is no final slash. We signal this fact to Ocsigen, which will then issue a 301 redirection to "filename/" *) Lwt_log.ign_info_f ~section "LocalFiles: %s is a directory" filename; raise (Ocsigen_extensions.Ocsigen_is_dir (Ocsigen_extensions.new_url_of_directory_request request)) end else let rec find_index = function | [] -> (* No suitable index, we try to list the directory *) if request_config.Ocsigen_extensions.list_directory_content then ( Lwt_log.ign_info ~section "Displaying directory content"; (filename, stat) ) else ( (* No suitable index *) Lwt_log.ign_info ~section "No index and no listing"; raise NotReadableDirectory) | e :: q -> let index = filename ^ e in Lwt_log.ign_info_f ~section "Testing \"%s\" as possible index." index; try (index, Unix.LargeFile.stat index) with | Unix.Unix_error (Unix.ENOENT, _, _) -> find_index q in find_index request_config.Ocsigen_extensions.default_directory_index else (filename, stat) in if not (check_dotdot ~filename) then (Lwt_log.ign_info_f ~section "Filenames cannot contain .. as in \"%s\"." filename; raise Failed_403) else if check_symlinks ~filename ~no_check_for request_config.Ocsigen_extensions.follow_symlinks then ( can_send filename request_config; (* If the previous function did not fail, we are authorized to send this file *) Lwt_log.ign_info_f ~section "Returning \"%s\"." filename; if stat.Unix.LargeFile.st_kind = Unix.S_REG then RFile filename else if stat.Unix.LargeFile.st_kind = Unix.S_DIR then RDir filename else raise Failed_404 ) else ( (* [filename] is accessed through as symlink which we should not follow according to the current policy *) Lwt_log.ign_info_f ~section "Failed symlink check for \"%s\"." filename; raise Failed_403) with (* We can get an EACCESS here, if are missing some rights on a directory *) | Unix.Unix_error (Unix.EACCES,_,_) -> raise Failed_403 | Unix.Unix_error (Unix.ENOENT,_,_) -> raise Failed_404 ocsigenserver-5.0.1/src/server/ocsigen_local_files.mli000066400000000000000000000053741417255654100232010ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Copyright (C) 2009 Boris Yakobowski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) val section : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) (** The requested file does not exists *) exception Failed_404 (** The requested file cannot be served: does not exists, not enough permissions ... *) exception Failed_403 (** The file is a directory which we should not display *) exception NotReadableDirectory (* (** Default options: - never follow symlinks - use "index.html" as default index - do not list the content of directories *) val default_options : options *) (** Local file corresponding to a request. The string argument represents the real file or directory to serve, eg. foo/index.html instead of foo *) type resolved = | RFile of string | RDir of string (** Finds [filename] in the filesystem, with a possible redirection if it is a directory. Takes into account the fact that [filename] does not exists, is a symlink or is a directory, and raises Failed_404 or Failed_403 accordingly. - we return ["filename/index.html"] if [filename] corresponds to a directory, ["filename/index.html"] is valid, and ["index.html"] is one possible index (trying all possible indexes in order) - we raise [Failed_404] if [filename] corresponds to a directory, no index exists and [list_dir_content] is false. Warning: this behaviour is not the same as Apache's but it corresponds to a missing service in Eliom (answers 404). This also allows to have an Eliom service after a "forbidden" directory - we raise [Failed_403] if [filename] is a symlink that must not be followed - raises [Failed_404] if [filename] does not exist, or is a special file - otherwise returns [filename] [no_check_for] is supposed to be a prefix of [filename] ; directories above [no_check_for] are not checked for symlinks *) val resolve : ?no_check_for:string -> request:Ocsigen_extensions.request -> filename:string -> unit -> resolved ocsigenserver-5.0.1/src/server/ocsigen_messages.ml000066400000000000000000000125001417255654100223500ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2005 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** Writing messages in the logs *) let (>>=) = Lwt.bind let access_file = "access.log" let warning_file = "warnings.log" let error_file = "errors.log" let access_sect = Lwt_log.Section.make "ocsigen:access" let full_path f = Filename.concat (Ocsigen_config.get_logdir ()) f let error_log_path () = full_path error_file let stderr = Lwt_log.channel ~close_mode:`Keep ~channel:Lwt_io.stderr () let stdout = Lwt_log.channel ~close_mode:`Keep ~channel:Lwt_io.stdout () let loggers = ref [] let access_logger = ref Lwt_log_core.null let open_files ?(user = Ocsigen_config.get_user ()) ?(group = Ocsigen_config.get_group ()) () = (* CHECK: we are closing asynchronously! That should be ok, though. *) List.iter (fun l -> ignore (Lwt_log.close l : unit Lwt.t)) !loggers; match Ocsigen_config.get_syslog_facility () with | Some facility -> (* log to syslog *) let syslog = Lwt_log.syslog ~facility () in loggers := [syslog]; Lwt_log.default := Lwt_log.broadcast [syslog; stderr]; Lwt.return () | None -> (* log to files *) let open_log path = let path = full_path path in Lwt.catch (fun () -> Lwt_log.file ~file_name:path ()) (function | Unix.Unix_error (error, _, _) -> Lwt.fail (Ocsigen_config.Config_file_error (Printf.sprintf "can't open log file %s: %s" path (Unix.error_message error))) | exn -> Lwt.fail exn) in open_log access_file >>= fun acc -> access_logger := acc; open_log warning_file >>= fun war -> open_log error_file >>= fun err -> loggers := [acc; war; err]; Lwt_log.default := Lwt_log.broadcast [Lwt_log.dispatch (fun _sect lev -> match lev with | Lwt_log.Error | Lwt_log.Fatal -> err | Lwt_log.Warning -> war | _ -> Lwt_log.null); Lwt_log.dispatch (fun _sect lev -> if Ocsigen_config.get_silent () then Lwt_log.null else match lev with | Lwt_log.Warning | Lwt_log.Error | Lwt_log.Fatal -> stderr | _ -> stdout)]; let gid = match group with | None -> Unix.getgid () | Some group -> (try (Unix.getgrnam group).Unix.gr_gid with Not_found as e -> ignore (Lwt_log.error "Error: Wrong group"); raise e) in let uid = match user with | None -> Unix.getuid () | Some user -> (try (Unix.getpwnam user).Unix.pw_uid with Not_found as e -> ignore (Lwt_log.error "Error: Wrong user"); raise e) in Lwt.catch (fun () -> Lwt_unix.chown (full_path access_file) uid gid >>= fun () -> Lwt_unix.chown (full_path warning_file) uid gid >>= fun () -> Lwt_unix.chown (full_path error_file) uid gid) (fun e -> match e with | Unix.Unix_error (Unix.EPERM, _, _) -> (* to allow for symlinks to /dev/null *) Lwt.return_unit | _ -> Lwt.fail e) (****) let accesslog s = (* not really fatal, but log in all cases; does not affect console *) Lwt_log.ign_fatal ~section:access_sect ~logger:!access_logger s; Lwt_log.ign_notice ~section:access_sect s let errlog ?section s = Lwt_log.ign_error ?section s let warning ?section s = Lwt_log.ign_warning ?section s let unexpected_exception e s = Lwt_log.ign_warning_f ~exn:e "Unexpected exception in %s" s (****) let console = if (not (Ocsigen_config.get_silent ())) then (fun s -> print_endline (s ())) else (fun _s -> ()) let level_of_string = function | "debug" -> Some Lwt_log.Debug | "info" -> Some Lwt_log.Info | "notice" -> Some Lwt_log.Notice | "warning"-> Some Lwt_log.Warning | "error" -> Some Lwt_log.Error | "fatal" -> Some Lwt_log.Fatal | _ -> None let command_f exc _ = function | [sect_name] -> (* Lwt_log.Section.make : if a section with the same name already exists, it is returned. *) let sect = Lwt_log.Section.make sect_name in Lwt_log.Section.reset_level sect; Lwt.return_unit | [sect_name; level_name] -> (* Lwt_log.Section.make : if a section with the same name already exists, it is returned. *) let sect = Lwt_log.Section.make sect_name in (match level_of_string (String.lowercase_ascii level_name) with | None -> Lwt_log.Section.reset_level sect | Some l -> Lwt_log.Section.set_level sect l); Lwt.return () | _ -> Lwt.fail exc ocsigenserver-5.0.1/src/server/ocsigen_messages.mli000066400000000000000000000035701417255654100225300ustar00rootroot00000000000000(* Ocsigen * Copyright (C) 2005 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** Writing messages in the logs *) val access_sect : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) (** Write a message in access.log *) val accesslog : string -> unit (** Write a message in errors.log *) val errlog : ?section:Lwt_log.section -> string -> unit (** Write a message in warnings.log *) val warning : ?section:Lwt_log.section -> string -> unit (** Write a message in the console (if not called in silent mode) *) val console : (unit -> string) -> unit (** Use that function for all impossible cases in exception handlers ([try ... with ... | e -> unexpected_exception ...] or [Lwt.catch ...]). A message will be written in [warnings.log]. Put something in the string to help locating the problem (usually the name of the function where is has been called). *) val unexpected_exception : exn -> string -> unit (** Path to the error log file *) val error_log_path : unit -> string (**/**) val open_files : ?user:string option -> ?group:string option -> unit -> unit Lwt.t val command_f : exn -> string -> string list -> unit Lwt.t ocsigenserver-5.0.1/src/server/ocsigen_multipart.ml000066400000000000000000000324201417255654100225650ustar00rootroot00000000000000(* This code is inspired by mimestring.ml from OcamlNet *) (* Copyright Gerd Stolpmann, Patrick Doane *) (* Modified for Ocsigen/Lwt by Nataliya Guts and Vincent Balat *) (*VVV Check wether we should support int64 for large files? *) open Lwt.Infix module S = Ocsigen_lib.Netstring_pcre let section = Lwt_log.Section.make "ocsigen:server:multipart" exception Multipart_error of string exception Ocsigen_upload_forbidden let match_end result = snd (Pcre.get_substring_ofs result 0) let cr_or_lf_re = S.regexp "[\013\n]" let header_stripped_re = S.regexp "([^ \t\r\n:]+):[ \t]*((.*[^ \t\r\n])?([ \t\r]*\n[ \t](.*[^ \t\r\n])?)*)[ \t\r]*\n" let header_unstripped_re = S.regexp "([^ \t\r\n:]+):([ \t]*.*\n([ \t].*\n)*)" (* This much simpler expression returns the name and the unstripped value. *) let empty_line_re = S.regexp "\013?\n";; let end_of_header_re = S.regexp "\n\013?\n";; let scan_header ?(downcase = true) ?(unfold = true) ?(strip = false) parstr ~start_pos ~end_pos = let header_re = if unfold || strip then header_stripped_re else header_unstripped_re in let rec parse_header i l = match S.string_match header_re parstr i with | Some r -> let i' = match_end r in if i' > end_pos then raise (Multipart_error "Mimestring.scan_header"); let name = if downcase then String.lowercase_ascii (S.matched_group r 1 parstr) else S.matched_group r 1 parstr in let value_with_crlf = S.matched_group r 2 parstr in let value = if unfold then S.global_replace cr_or_lf_re "" value_with_crlf else value_with_crlf in parse_header i' ((name, value) :: l) | None -> (* The header must end with an empty line *) (match S.string_match empty_line_re parstr i with | Some r' -> List.rev l, match_end r' | None -> raise (Multipart_error "Mimestring.scan_header")) in parse_header start_pos [] let read_header ?downcase ?unfold ?strip s = let rec find_end_of_header s = Lwt.catch (fun () -> let b = Ocsigen_stream.current_buffer s in (* Maybe the header is empty. In this case, there is an empty line right at the beginning *) match S.string_match empty_line_re b 0 with | Some r -> Lwt.return (s, match_end r) | None -> (* Search for an empty line *) Lwt.return (s, match_end (snd (S.search_forward end_of_header_re b 0))) ) (function | Not_found -> Ocsigen_stream.enlarge_stream s >>= (function | Ocsigen_stream.Finished _ -> Lwt.fail Ocsigen_stream.Stream_too_small | Ocsigen_stream.Cont _ as s -> find_end_of_header s) | e -> Lwt.fail e) in find_end_of_header s >>= fun (s, end_pos) -> let b = Ocsigen_stream.current_buffer s in let h, _ = scan_header ?downcase ?unfold ?strip b ~start_pos:0 ~end_pos in Ocsigen_stream.skip s (Int64.of_int end_pos) >>= fun s -> Lwt.return (s, h) let lf_re = S.regexp "[\n]" let rec search_window s re start = try Lwt.return (s, snd (S.search_forward re (Ocsigen_stream.current_buffer s) start)) with Not_found -> Ocsigen_stream.enlarge_stream s >>= function | Ocsigen_stream.Finished _ -> Lwt.fail Ocsigen_stream.Stream_too_small | Ocsigen_stream.Cont _ as s -> search_window s re start let search_end_of_line s k = (* Search LF beginning at position k *) Lwt.catch (fun () -> search_window s lf_re k >>= fun (s, x) -> Lwt.return (s, match_end x)) (function | Not_found -> Lwt.fail (Multipart_error "read_multipart_body: MIME boundary without line end") | e -> Lwt.fail e) let search_first_boundary ~boundary s = (* Search boundary per regexp; return the position of the character immediately following the boundary (on the same line), or raise Not_found. *) let re = S.regexp ("\n--" ^ Pcre.quote boundary) in search_window s re 0 >>= fun (s, x) -> Lwt.return (s, match_end x) let check_beginning_is_boundary ~boundary s = let del = "--" ^ boundary in let ldel = String.length del in Ocsigen_stream.stream_want s (ldel + 2) >>= function | Ocsigen_stream.Finished _ as str2 -> Lwt.return (str2, false, false) | Ocsigen_stream.Cont (ss, _f) as str2 -> let long = String.length ss in let isdelim = (long >= ldel) && (String.sub ss 0 ldel = del) in let islast = isdelim && (String.sub ss ldel 2 = "--") in Lwt.return (str2, isdelim, islast) let rec parse_parts ~boundary ~decode_part s uses_crlf = (* PRE: [s] is at the beginning of the next part. [uses_crlf] must be true if CRLF is used as EOL sequence, and false if only LF is used as EOL sequence. *) let delimiter = (if uses_crlf then "\r" else "" ) ^ "\n--" ^ boundary in Ocsigen_stream.substream delimiter s >>= fun a -> decode_part a >>= fun (y, s) -> (* Now the position of [s] is at the beginning of the delimiter. Check if there is a "--" after the delimiter (==> last part) *) let l_delimiter = String.length delimiter in Ocsigen_stream.next s >>= fun s -> Ocsigen_stream.stream_want s (l_delimiter+2) >>= fun s -> let last_part = match s with | Ocsigen_stream.Finished _ -> false | Ocsigen_stream.Cont (ss, _f) -> let long = String.length ss in long >= l_delimiter + 2 && ss.[l_delimiter] = '-' && ss.[l_delimiter + 1] = '-' in if last_part then Lwt.return [y] else search_end_of_line s 2 >>= fun (s, k) -> (* [k]: Beginning of next part *) Ocsigen_stream.skip s (Int64.of_int k) >>= fun s -> parse_parts ~boundary ~decode_part s uses_crlf >>= fun l -> Lwt.return (y :: l) let read_multipart_body ~boundary ~decode_part s = (* Check whether s directly begins with a boundary *) check_beginning_is_boundary ~boundary s >>= fun (s, b, islast) -> if islast then Lwt.return [] else if b then (* Move to the beginning of the next line *) search_end_of_line s 0 >>= fun (s, k_eol) -> let uses_crlf = (Ocsigen_stream.current_buffer s).[k_eol-2] = '\r' in Ocsigen_stream.skip s (Int64.of_int k_eol) >>= fun s -> (* Begin with first part: *) parse_parts ~boundary ~decode_part s uses_crlf else (* Look for the first boundary *) Lwt.catch (fun () -> search_first_boundary ~boundary s >>= fun (s, k_eob) -> search_end_of_line s k_eob >>= fun (s, k_eol) -> let uses_crlf = (Ocsigen_stream.current_buffer s).[k_eol-2] = '\r' in (* Printf.printf "k_eol=%d\n" k_eol; *) Ocsigen_stream.skip s (Int64.of_int k_eol) >>= fun s -> (* Begin with first part: *) parse_parts ~boundary ~decode_part s uses_crlf) (function | Not_found -> (* No boundary at all, empty body *) Lwt.return [] | e -> Lwt.fail e) let empty_stream = Ocsigen_stream.get (Ocsigen_stream.make (fun () -> Ocsigen_stream.empty None)) let decode_part ~max_size ~create ~add ~stop stream = read_header stream >>= fun (s, header) -> let p = create header in let rec while_stream size = function | Ocsigen_stream.Finished None -> Lwt.return (size, empty_stream) | Ocsigen_stream.Finished (Some ss) -> Lwt.return (size, ss) | Ocsigen_stream.Cont (stri, f) -> let long = String.length stri in let size2 = Int64.add size (Int64.of_int long) in if match max_size with | None -> false | Some m -> Int64.compare size2 m > 0 then Lwt.fail Ocsigen_lib.Ocsigen_Request_too_long else if stri = "" then Ocsigen_stream.next f >>= while_stream size else add p stri >>= fun () -> Ocsigen_stream.next f >>= while_stream size2 in Lwt.catch (fun () -> while_stream Int64.zero s >>= fun (size, s) -> stop size p >>= fun r -> Lwt.return (r, s)) (fun error -> stop Int64.zero p >>= fun _ -> Lwt.fail error) let scan_multipart_body_from_stream ?max_size ~boundary ~create ~add ~stop s = let decode_part = decode_part ~max_size ~create ~add ~stop in Lwt.catch (fun () -> (* read the multipart body: *) Ocsigen_stream.next s >>= fun s -> read_multipart_body ~boundary ~decode_part s >>= fun _ -> Lwt.return ()) (function | Ocsigen_stream.Stream_too_small -> Lwt.fail Ocsigen_lib.Ocsigen_Bad_Request | e -> Lwt.fail e) let get_boundary ctparams = List.assoc "boundary" ctparams let counter = let c = ref (Random.int 1000000) in fun () -> c := !c + 1 ; !c let field field content_disp = let (_, res) = S.search_forward (S.regexp (field^"=.([^\"]*).;?")) content_disp 0 in S.matched_group res 1 content_disp let parse_content_type s = match Ocsigen_lib.String.split ';' s with | [] -> None | a :: l -> try let typ, subtype = Ocsigen_lib.String.sep '/' a in let params = try List.map (Ocsigen_lib.String.sep '=') l with Not_found -> [] in (*VVV If syntax error, we return no parameter at all *) Some ((typ, subtype), params) (*VVV If syntax error in type, we return None *) with Not_found -> None type content_type = (string * string) * (string * string) list type file_info = { tmp_filename : string ; filesize : int64 ; raw_original_filename : string ; file_content_type : ((string * string) * (string * string) list) option } type post_data = (string * string) list * (string * file_info) list let post_params_form_urlencoded body_gen _ _ = Lwt.catch (fun () -> let body = Ocsigen_stream.get body_gen in (* BY, adapted from a previous comment. Should this stream be consumed in case of error? *) Ocsigen_stream.string_of_stream (Ocsigen_config.get_maxrequestbodysizeinmemory ()) body >>= fun r -> let r = Ocsigen_lib.Url.fixup_url_string r in let l = Uri.query_of_encoded r |> List.map (fun (s, l) -> List.map (fun v -> s, v) l) |> List.concat in Lwt.return (l, [])) (function | Ocsigen_stream.String_too_large -> Lwt.fail Ocsigen_lib.Input_is_too_large | e -> Lwt.fail e) let post_params_multipart_form_data ctparams body_gen upload_dir max_size = (* Same question here, should this stream be consumed after an error? *) let body = Ocsigen_stream.get body_gen and boundary = get_boundary ctparams and params = ref [] and files = ref [] and filenames = ref [] in let rec add p s = match p with | _, `No_file to_buf -> Buffer.add_string to_buf s; Lwt.return () | _, `Some_file (_, _, wh, _) -> let len = String.length s in let r = Unix.write_substring wh s 0 len in if r < len then (*XXXX Inefficient if s is long *) add p (String.sub s r (len - r)) else Lwt.pause () in let create hs = let content_type = try let ct = List.assoc "content-type" hs in parse_content_type ct with _ -> None in let cd = List.assoc "content-disposition" hs in let p_name = field "name" cd in try let store = field "filename" cd in match upload_dir with | Some dname -> let fname = Printf.sprintf "%s/%f-%d" dname (Unix.gettimeofday ()) (counter ()) in let fd = Unix.openfile fname [Unix.O_CREAT; Unix.O_TRUNC; Unix.O_WRONLY; Unix.O_NONBLOCK] 0o666 in Lwt_log.ign_info ~section ("Upload file opened: " ^ fname); filenames := fname :: !filenames; p_name, `Some_file (fname, store, fd, content_type) | None -> raise Ocsigen_upload_forbidden with Not_found -> p_name, `No_file (Buffer.create 1024) and stop filesize = function | p_name, `No_file to_buf -> params := !params @ [p_name, Buffer.contents to_buf]; Lwt.return () (* in the end ? *) | p_name, `Some_file (tmp_filename, raw_original_filename, wh, file_content_type) -> let file_info = { tmp_filename ; filesize ; raw_original_filename ; file_content_type ; } in files := !files @ [p_name, file_info]; Unix.close wh; Lwt.return () in scan_multipart_body_from_stream ?max_size ~boundary ~create ~add ~stop body >>= fun () -> (*VVV Does scan_multipart_body_from_stream read until the end or only what it needs? If we do not consume here, the following request will be read only when this one is finished ... *) Ocsigen_stream.consume body_gen >>= fun () -> Lwt.return (!params, !files) let post_params ~content_type body_gen = let (ct, cst), ctparams = content_type in match String.lowercase_ascii ct, String.lowercase_ascii cst with | "application", "x-www-form-urlencoded" -> Some (body_gen |> Cohttp_lwt.Body.to_stream |> Ocsigen_stream.of_lwt_stream |> post_params_form_urlencoded) | "multipart", "form-data" -> Some (body_gen |> Cohttp_lwt.Body.to_stream |> Ocsigen_stream.of_lwt_stream |> post_params_multipart_form_data ctparams) | _ -> None ocsigenserver-5.0.1/src/server/ocsigen_multipart.mli000066400000000000000000000014621417255654100227400ustar00rootroot00000000000000val section : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) val scan_multipart_body_from_stream: ?max_size : Int64.t -> boundary : string -> create : ((string * string) list -> 'a) -> add : ('a -> string -> unit Lwt.t) -> stop : (int64 -> 'a -> 'b Lwt.t) -> string Ocsigen_stream.stream -> unit Lwt.t type content_type = (string * string) * (string * string) list type file_info = { tmp_filename : string ; filesize : int64 ; raw_original_filename : string ; file_content_type : content_type option } type post_data = (string * string) list * (string * file_info) list val post_params : content_type : content_type -> Cohttp_lwt.Body.t -> (string option -> Int64.t option -> post_data Lwt.t) option val parse_content_type : string -> content_type option ocsigenserver-5.0.1/src/server/ocsigen_parseconfig.ml000066400000000000000000000616111417255654100230500ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module ocsigen_parseconfig.ml * Copyright (C) 2005-2008 Vincent Balat, Nataliya Guts, Stéphane Glondu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (******************************************************************) (** Config file parsing *) open Xml open Ocsigen_config module Netstring_pcre = Ocsigen_lib.Netstring_pcre let section = Lwt_log.Section.make "ocsigen:config" let blah_of_string f tag s = try f (Ocsigen_lib.String.remove_spaces s 0 ((String.length s) -1)) with Failure _ -> raise (Ocsigen_config.Config_file_error ("While parsing <"^tag^"> - "^s^ " is not a valid value.")) let int_of_string = blah_of_string int_of_string let float_of_string = blah_of_string float_of_string let default_default_hostname = let hostname = Unix.gethostname () in try (*VVV Is it ok? Is it reliable? *) (List.hd (Unix.getaddrinfo hostname "www" [Unix.AI_CANONNAME; Unix.AI_SOCKTYPE Unix.SOCK_STREAM])).Unix.ai_canonname with Failure _ -> Lwt_log.ign_warning_f ~section "Cannot determine default host name. Will use \"%s\" \ to create absolute links or redirections dynamically \ if you do not set \ in config file." hostname; (*VVV Is it the right behaviour? *) hostname let parse_size = let kilo = Int64.of_int 1000 in let mega = Int64.of_int 1000000 in let giga = Int64.mul kilo mega in let tera = Int64.mul mega mega in let kibi = Int64.of_int 1024 in let mebi = Int64.of_int 1048576 in let gibi = Int64.mul kibi mebi in let tebi = Int64.mul mebi mebi in fun s -> let l = String.length s in let s = Ocsigen_lib.String.remove_spaces s 0 (l-1) in let v l = try Int64.of_string (String.sub s 0 l) with Failure _ -> failwith "Ocsigen_parseconfig.parse_size" in let o l = let l1 = l-1 in if l1>0 then let c1 = s.[l1] in if (c1 = 'o') || (c1 = 'B') then v l1 else v l else v l in if (s = "") || (s = "infinity") then None else Some (let l = String.length s in let l1 = l-1 in if l1>0 then let c1 = String.sub s l1 1 in if (c1 = "T") then Int64.mul tebi (v l1) else if (c1 = "G") then Int64.mul gibi (v l1) else if (c1 = "M") then Int64.mul mebi (v l1) else if (c1 = "k") then Int64.mul kibi (v l1) else let l2 = l-2 in if l2>0 then let c2 = String.sub s l2 2 in if (c2 = "To") || (c2 = "TB") then Int64.mul tera (v l2) else if (c2 = "Go") || (c2 = "GB") then Int64.mul giga (v l2) else if (c2 = "Mo") || (c2 = "MB") then Int64.mul mega (v l2) else if (c2 = "ko") || (c2 = "kB") then Int64.mul kilo (v l2) else let l3 = l-3 in if l3>0 then let c3 = String.sub s l3 3 in if (c3 = "Tio") || (c3 = "TiB") then Int64.mul tebi (v l3) else if (c3 = "Gio") || (c3 = "GiB") then Int64.mul gibi (v l3) else if (c3 = "Mio") || (c3 = "MiB") then Int64.mul mebi (v l3) else if (c3 = "kio") || (c3 = "kiB") then Int64.mul kibi (v l3) else o l else o l else o l else o l) let parse_size_tag tag s = try parse_size s with Failure _ -> raise (Ocsigen_config.Config_file_error ("While parsing <"^tag^"> - "^s^" is not a valid size.")) let rec parse_string = function | [] -> "" | PCData s :: l -> s ^ parse_string l | _ -> failwith "ocsigen_parseconfig.parse_string" let parse_string_tag tag s = try parse_string s with Failure _ -> raise (Ocsigen_config.Config_file_error ("While parsing <"^tag^"> - String expected.")) let parser_config = let rec parse_servers n = function | [] -> (match n with | [] -> raise (Config_file_error (" tag expected")) | _ -> n) | (Element ("server", [], nouveau))::ll -> (match ll with | [] -> () | _ -> Lwt_log.ign_warning ~section "At most one tag possible in config file. \ Ignoring trailing data."); parse_servers (n@[nouveau]) [] (* ll *) (* Multiple server not supported any more *) (* nouveau at the end *) | _ -> raise (Config_file_error ("syntax error inside ")) in function | Element ("ocsigen", [], l) -> parse_servers [] l | _ -> raise (Config_file_error " tag expected") let parse_ext file = parser_config (Xml.parse_file file) let preloadfile config () = Ocsigen_extensions.set_config config let postloadfile () = Ocsigen_extensions.set_config [] (* Checking hostnames. We make only make looze efforts. See RFC 921 and 952 for further details *) let correct_hostname = let regexp = Netstring_pcre.regexp "^[a-zA-Z0-9]+((\\.|-)[a-zA-Z0-9]+)*$" in fun h -> Netstring_pcre.string_match regexp h 0 <> None (* Splits the [host] field, first according to spaces (which encode disjunction), and then according to wildcards '*' ; we then transform the hosts-with-regexp into a regepx that matches a potential host. The whole result is cached because user config files (for userconf) are read at each request. *) let parse_host_field = let h = Hashtbl.create 17 in (fun (hostfilter : string option) -> try Hashtbl.find h hostfilter with Not_found -> let r = match hostfilter with | None -> ["*", Netstring_pcre.regexp ".*$", None] (* default = "*:*" *) | Some s -> let parse_one_host ss = let host, port = try let dppos = String.index ss ':' and len = String.length ss in let host = String.sub ss 0 dppos and port = match String.sub ss (dppos+1) ((len - dppos) - 1) with | "*" -> None | p -> Some (int_of_string "host" p) in host, port with | Not_found -> ss, None | Failure _ -> raise (Config_file_error "bad port number") in let split_host = function | Str.Delim _ -> ".*" | Str.Text t -> Pcre.quote t in (host, Netstring_pcre.regexp (String.concat "" ((List.map split_host (Str.full_split (Str.regexp "[*]+") host))@["$"])), port) in List.map parse_one_host (Str.split (Str.regexp "[ \t]+") s) in Hashtbl.add h hostfilter r; (r : Ocsigen_extensions.virtual_hosts) ) (* Extract a default hostname from the "host" field if no default is provided *) let get_defaulthostname ~defaulthostname ~host = match defaulthostname with | Some d -> d | None -> (* We look for a hostname without wildcard (second case). Something more clever could be envisioned *) let rec aux = function | [] -> default_default_hostname | (t, _, (Some 80 | None)) :: _ when (not (String.contains t '*')) -> t | _ :: q -> aux q in let host = aux host in Lwt_log.ign_warning_f ~section "While parsing config file, tag : No defaulthostname, \ assuming it is \"%s\"" host; if correct_hostname host then host else raise (Ocsigen_config.Config_file_error ("Incorrect hostname " ^ host)) let later_pass_host_attr (name, charset, defaulthostname, defaulthttpport, defaulthttpsport, ishttps) = function | "hostfilter", s -> (match name with | None -> Some s, charset, defaulthostname, defaulthttpport, defaulthttpsport, ishttps | _ -> raise (Ocsigen_config.Config_file_error ("Duplicate attribute name in "))) | "charset", s -> (match charset with | None -> name, Some s, defaulthostname, defaulthttpport, defaulthttpsport, ishttps | _ -> raise (Ocsigen_config.Config_file_error ("Duplicate attribute charset in "))) | "defaulthostname", s -> (match defaulthostname with | None -> if correct_hostname s then name, charset, Some s, defaulthttpport, defaulthttpsport, ishttps else raise (Ocsigen_config.Config_file_error ("Incorrect hostname " ^ s)) | _ -> raise (Ocsigen_config.Config_file_error "Duplicate attribute defaulthostname in ")) | "defaulthttpport", s -> (match defaulthttpport with | None -> name, charset, defaulthostname, Some s, defaulthttpsport, ishttps | _ -> raise (Ocsigen_config.Config_file_error ("Duplicate attribute defaulthttpport in "))) | "defaulthttpsport", s -> (match defaulthttpsport with | None -> name, charset, defaulthostname, defaulthttpport, Some s, ishttps | _ -> raise (Ocsigen_config.Config_file_error ("Duplicate attribute defaulthttpsport in "))) | "defaultprotocol", s -> (match ishttps with | None -> name, charset, defaulthostname, defaulthttpport, defaulthttpsport, Some s | _ -> raise (Ocsigen_config.Config_file_error ("Duplicate attribute defaultprotocol in "))) | attr, _ -> raise (Ocsigen_config.Config_file_error ("Wrong attribute for : " ^ attr)) let later_pass_host attrs l = let host, charset, defaulthostname, defaulthttpport, defaulthttpsport, defaultprotocol = List.fold_left later_pass_host_attr (None, None, None, None, None, None) (List.rev attrs) in let host = parse_host_field host in let charset = match charset, Ocsigen_config.get_default_charset () with | Some charset, _ | None, Some charset -> charset | None, None -> "utf-8" and defaulthttpport = match defaulthttpport with | None -> Ocsigen_config.get_default_port () | Some p -> int_of_string "host" p and defaulthostname = get_defaulthostname ~defaulthostname ~host and defaulthttpsport = match defaulthttpsport with | None -> Ocsigen_config.get_default_sslport () | Some p -> int_of_string "host" p and serve_everything = { Ocsigen_extensions.do_not_serve_regexps = []; do_not_serve_files = []; do_not_serve_extensions = []; } in let conf = { Ocsigen_extensions.default_hostname = defaulthostname; default_httpport = defaulthttpport; default_httpsport = defaulthttpsport; default_protocol_is_https = defaultprotocol = Some "https"; mime_assoc = Ocsigen_charset_mime.default_mime_assoc (); charset_assoc = Ocsigen_charset_mime.empty_charset_assoc ~default:charset (); default_directory_index = ["index.html"]; list_directory_content = false; follow_symlinks = `Owner_match; do_not_serve_404 = serve_everything; do_not_serve_403 = serve_everything; uploaddir = Ocsigen_config.get_uploaddir (); maxuploadfilesize = Ocsigen_config.get_maxuploadfilesize (); } in let parse_config = Ocsigen_extensions.make_parse_config [] (Ocsigen_extensions.parse_config_item None host conf) in (* default site for host *) host, conf, parse_config l let later_pass_extension tag attrs l = (* We do not reload extensions *) match attrs with | [] -> raise (Config_file_error ("missing module, name or findlib-package attribute in " ^ tag)) | ["name", s] -> Ocsigen_loader.init_module (preloadfile l) postloadfile false s | ["module", s] -> Ocsigen_loader.loadfiles (preloadfile l) postloadfile false [s]; | ["findlib-package", s] -> Ocsigen_loader.loadfiles (preloadfile l) postloadfile false (Ocsigen_loader.findfiles s) | _ -> raise (Config_file_error ("Wrong attribute for " ^ tag)) let rec later_pass_extconf dir = let f acc s = if Filename.check_suffix s "conf" then match let filename = dir^"/"^s in try Lwt_log.ign_info_f ~section "Parsing configuration file %s" filename; parse_ext filename with e -> Lwt_log.ign_error_f ~section ~exn:e "Error while loading configuration file %s (ignored)" filename; [] with | [] -> acc | s :: _ -> acc @ later_pass s else acc in try let files = Sys.readdir dir in Array.sort compare files; Array.fold_left f [] files with | Sys_error _ as e -> Lwt_log.ign_error ~section ~exn:e "Error while loading configuration file (ignored)"; [] (* Config file is parsed twice. This is the second parsing (site loading). *) and later_pass = function | [] -> [] | Element ("port", _atts, _p) :: ll -> later_pass ll | Element ("charset" as st, _atts, p) :: ll -> set_default_charset (Some (parse_string_tag st p)); later_pass ll | Element ("logdir", [], _p) :: ll -> later_pass ll | Element ("syslog", [], _p) :: ll -> later_pass ll | Element ("ssl", [], _p) :: ll -> later_pass ll | Element ("user", [], _p) :: ll -> later_pass ll | Element ("group", [], _p) :: ll -> later_pass ll | Element ("uploaddir" as st, [], p) :: ll -> set_uploaddir (Some (parse_string_tag st p)); later_pass ll | Element ("datadir" as st, [], p) :: ll -> set_datadir (parse_string_tag st p); later_pass ll | Element ("minthreads", [], _p) :: ll -> later_pass ll | Element ("maxthreads", [], _p) :: ll -> later_pass ll | Element ("maxdetachedcomputationsqueued" as st, [], p) :: ll -> set_max_number_of_threads_queued (int_of_string st (parse_string_tag st p)); later_pass ll | Element ("maxconnected" as st, [], p) :: ll -> set_max_number_of_connections (int_of_string st (parse_string_tag st p)); later_pass ll | Element ("mimefile" as st, [], p) :: ll -> Ocsigen_config.set_mimefile (parse_string_tag st p); later_pass ll | Element ("maxretries" as st, [], p) :: ll -> set_maxretries (int_of_string st (parse_string_tag st p)); later_pass ll | Element ("timeout" as st, [], p) :: ll | Element ("clienttimeout" as st, [], p) :: ll -> set_client_timeout (int_of_string st (parse_string_tag st p)); later_pass ll | Element ("servertimeout" as st, [], p) :: ll -> set_server_timeout (int_of_string st (parse_string_tag st p)); later_pass ll | Element ("netbuffersize" as st, [], p) :: ll -> Ocsigen_stream.set_net_buffer_size (int_of_string st (parse_string_tag st p)); later_pass ll | Element ("filebuffersize" as st, [], p) :: ll -> set_filebuffersize (int_of_string st (parse_string_tag st p)); later_pass ll | Element ("maxrequestbodysize" as st, [], p) :: ll -> set_maxrequestbodysize (parse_size_tag st (parse_string_tag st p)); later_pass ll | Element ("maxuploadfilesize" as st, [], p) :: ll -> set_maxuploadfilesize (parse_size_tag st (parse_string_tag st p)); later_pass ll | Element ("commandpipe" as st, [], p) :: ll -> set_command_pipe (parse_string_tag st p); later_pass ll | Element ("shutdowntimeout" as st, [], p) :: ll -> set_shutdown_timeout (match parse_string_tag st p with | "notimeout" -> None | p -> Some (float_of_string st p)); later_pass ll | Element ("debugmode", [], []) :: ll -> set_debugmode true; later_pass ll | Element ("usedefaulthostname", [], []) :: ll -> set_usedefaulthostname true; later_pass ll | Element ("disablepartialrequests", [], []) :: ll -> set_disablepartialrequests true; later_pass ll | Element ("respectpipeline", [], []) :: ll -> set_respect_pipeline (); later_pass ll | Element ("findlib", ["path",p], []) :: ll -> Ocsigen_loader.add_ocamlpath p; later_pass ll | Element ("require", atts, l) :: ll | Element ("extension", atts, l) :: ll -> later_pass_extension "" atts l; later_pass ll | Element ("library", atts, l) :: ll -> later_pass_extension "" atts l; later_pass ll | Element ("host", atts, l) :: ll -> (* The evaluation order is important here *) let h = later_pass_host atts l in h :: later_pass ll | Element ("extconf", [("dir", dir)], []) :: ll -> (* The evaluation order is important here *) let h = later_pass_extconf dir in h @ later_pass ll | Element (tag, _, _) :: _ -> raise (Config_file_error ("tag <"^tag^"> unexpected inside ")) | _ -> raise (Config_file_error "Syntax error") let later_pass l = Ocsigen_extensions.set_hosts (later_pass l) (* Parsing tags *) let parse_port = let all_ipv6 = Netstring_pcre.regexp "^\\[::\\]:([0-9]+)$" in let all_ipv4 = Netstring_pcre.regexp "^\\*:([0-9]+)$" in let single_ipv6 = Netstring_pcre.regexp "^\\[([0-9A-Fa-f.:]+)\\]:([0-9]+)$" in let single_ipv4 = Netstring_pcre.regexp "^([0-9.]+):([0-9]+)$" in fun s -> let do_match r = Netstring_pcre.string_match r s 0 in let get x i = Netstring_pcre.matched_group x i s in match do_match all_ipv6 with | Some r -> `IPv6 (Unix.inet6_addr_any), int_of_string "port" (get r 1) | None -> match do_match all_ipv4 with | Some r -> `IPv4 (Unix.inet_addr_any), int_of_string "port" (get r 1) | None -> match do_match single_ipv6 with | Some r -> `IPv6 (Unix.inet_addr_of_string (get r 1)), int_of_string "port" (get r 2) | None -> match do_match single_ipv4 with | Some r -> `IPv4 (Unix.inet_addr_of_string (get r 1)), int_of_string "port" (get r 2) | None -> `All, int_of_string "port" s let parse_facility = function | "auth" -> `Auth | "authpriv" -> `Authpriv | "console" -> `Console | "cron" -> `Cron | "daemon" -> `Daemon | "ftp" -> `FTP | "kernel" -> `Kernel | "lpr" -> `LPR | "local0" -> `Local0 | "local1" -> `Local1 | "local2" -> `Local2 | "local3" -> `Local3 | "local4" -> `Local4 | "local5" -> `Local5 | "local6" -> `Local6 | "local7" -> `Local7 | "mail" -> `Mail | "ntp" -> `NTP | "news" -> `News | "security" -> `Security | "syslog" -> `Syslog | "uucp" -> `UUCP | "user" -> `User | t -> raise (Config_file_error ("Unknown " ^ t ^ " facility in ")) (* First parsing of config file *) let config_error_for_some s = function | None -> () | _ -> raise (Config_file_error s) let make_ssl_info ~certificate ~privatekey ~ciphers ~dhfile ~curve = { Ocsigen_config. ssl_certificate = certificate; ssl_privatekey = privatekey; ssl_ciphers = ciphers; ssl_dhfile = dhfile; ssl_curve = curve } let rec parse_ssl l ~certificate ~privatekey ~ciphers ~dhfile ~curve = match l with | [] -> Some (make_ssl_info ~certificate ~privatekey ~ciphers ~dhfile ~curve) | Element ("certificate" as st, [], p) :: l -> config_error_for_some "Two certificates inside " certificate; let certificate = Some (parse_string_tag st p) in parse_ssl ~certificate ~privatekey ~ciphers ~dhfile ~curve l | Element ("privatekey" as st, [], p) ::l -> config_error_for_some "Two private keys inside " privatekey; let privatekey = Some (parse_string_tag st p) in parse_ssl ~certificate ~privatekey ~ciphers ~dhfile ~curve l | Element ("ciphers" as st, [], p) :: l -> config_error_for_some "Two cipher strings inside " ciphers; let ciphers = Some (parse_string_tag st p) in parse_ssl ~certificate ~privatekey ~ciphers ~dhfile ~curve l | Element ("dhfile" as st, [], p) :: l -> config_error_for_some "Two DH files inside " dhfile; let dhfile = Some (parse_string_tag st p) in parse_ssl ~certificate ~privatekey ~ciphers ~dhfile ~curve l | Element ("curve" as st, [], p) :: l -> config_error_for_some "Two (EC) curves inside " curve; let curve = Some (parse_string_tag st p) in parse_ssl ~certificate ~privatekey ~ciphers ~dhfile ~curve l | Element (tag, _, _) :: _l -> raise (Config_file_error ("<"^tag^"> tag unexpected inside ")) | _ -> raise (Config_file_error ("Unexpected content inside ")) let first_pass c = let rec aux user group ssl ports sslports = function [] -> ((user, group), (ssl, ports, sslports)) | Element ("logdir" as st, [], p) :: ll -> set_logdir (parse_string_tag st p); aux user group ssl ports sslports ll | Element ("syslog" as st, [], p) :: ll -> let str = String.lowercase_ascii (parse_string_tag st p) in set_syslog_facility (Some (parse_facility str)); aux user group ssl ports sslports ll | Element ("port" as st, atts, p) :: ll -> (match atts with [] | [("protocol", "HTTP")] -> let po = try parse_port (parse_string_tag st p) with Failure _ -> raise (Config_file_error "Wrong value for tag") in aux user group ssl (po::ports) sslports ll | [("protocol", "HTTPS")] -> let po = try parse_port (parse_string_tag st p) with Failure _ -> raise (Config_file_error "Wrong value for tag") in aux user group ssl ports (po::sslports) ll | _ -> raise (Config_file_error "Wrong attribute for ")) | Element ("minthreads" as st, [], p) :: ll -> set_minthreads (int_of_string st (parse_string_tag st p)); aux user group ssl ports sslports ll | Element ("maxthreads" as st, [], p) :: ll -> set_maxthreads (int_of_string st (parse_string_tag st p)); aux user group ssl ports sslports ll | Element ("ssl", [], p) :: ll -> (match ssl with None -> let ssl = let certificate = None and privatekey = None and ciphers = None and dhfile = None and curve = None in parse_ssl ~certificate ~privatekey ~ciphers ~dhfile ~curve p in aux user group ssl ports sslports ll | _ -> raise (Config_file_error "Only one ssl certificate for each server supported for now")) | Element ("user" as st, [], p) :: ll -> (match user with None -> aux (Some (parse_string_tag st p)) group ssl ports sslports ll | _ -> raise (Config_file_error "Only one tag for each server allowed")) | Element ("group" as st, [], p) :: ll -> (match group with None -> aux user (Some (parse_string_tag st p)) ssl ports sslports ll | _ -> raise (Config_file_error "Only one tag for each server allowed")) | Element ("commandpipe" as st, [], p) :: ll -> set_command_pipe (parse_string_tag st p); aux user group ssl ports sslports ll | Element _ :: ll -> aux user group ssl ports sslports ll | _ -> raise (Config_file_error "Syntax error") in let (user, group), (si, ports, ssl_ports) = aux None None None [] [] c in let user = match user with None -> None (* Some (get_default_user ()) *) | Some s -> if s = "" then None else Some s in let group = match group with None -> None (* Some (get_default_group ()) *) | Some s -> if s = "" then None else Some s in Ocsigen_config.set_user user; Ocsigen_config.set_group group; Ocsigen_config.set_ssl_info si; Ocsigen_config.set_ports ports; Ocsigen_config.set_ssl_ports ssl_ports; () let parse_config ?file () = let file = match file with | None -> Ocsigen_config.get_config_file () | Some f -> f in parser_config (Xml.parse_file file) ocsigenserver-5.0.1/src/server/ocsigen_parseconfig.mli000066400000000000000000000040341417255654100232150ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Module ocsigen_parseconfig.ml * Copyright (C) 2005 Vincent Balat, Nataliya Guts * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) (** Config file parsing. See also module {! Ocsigen_extensions.​Configuration } *) (**/**) val section : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) (** [parse_size_tag tag s] parses a size. The size can be either "infinity" or use SI or binary units, e.g., 10 10B 10o 10ko 10kB 10kiB 10MiB 10TB ... . In case of error, raises [Ocsigen_config.Config_file_error m] where [m] is an error message explaining that a size was expected in tag []. *) val parse_size_tag : string -> string -> int64 option (** Extracts (and stores via Ocsigen_config) the following information: {ul {- user to execute OcsigenServer (ex: www-data) } {- group to execute OcsigenServer (ex: www-data) } {- SSL key, SSL certificate, SSL ciphers list, SSL DH file, SSL EC curve } {- list of HTTP port to listen on (ex: 80) } {- list of HTTPS port to listen on (ex: 443) } {- minimum and maximum number of threads } } To be called early by [Ocsigen_server]. *) val first_pass : Xml.xml list -> unit val later_pass : Xml.xml list -> unit val parse_config : ?file:string -> unit -> Xml.xml list list ocsigenserver-5.0.1/src/server/ocsigen_request.ml000066400000000000000000000224371417255654100222430ustar00rootroot00000000000000open Lwt.Infix let post_data_of_body ~content_type b = Ocsigen_multipart.post_params ~content_type b type content_type = Ocsigen_multipart.content_type type file_info = Ocsigen_multipart.file_info = { tmp_filename : string ; filesize : int64 ; raw_original_filename : string ; file_content_type : content_type option } type post_data = Ocsigen_multipart.post_data type body = [ | `Unparsed of Cohttp_lwt.Body.t | `Parsed of post_data Lwt.t ] (* Wrapper around Uri providing our derived fields. Is the laziness too fine-grained? *) type uri = { u_uri : Uri.t Lazy.t ; u_get_params : (string * string list) list Lazy.t ; u_get_params_flat : (string * string) list Lazy.t ; u_path_string : string Lazy.t ; u_path : string list Lazy.t ; } let unflatten_get_params l = let module M = Ocsigen_lib.String.Table in M.bindings (List.fold_left (fun acc (id, v) -> M.add id (try v :: M.find id acc with Not_found -> [v]) acc) M.empty l) let flatten_get_params l = List.concat (List.map (fun (s, l) -> List.map (fun v -> s, v) l) l) let remove_trailing_slash_string s = if String.length s > 0 && String.get s 0 = '/' then String.sub s 1 (String.length s - 1) else s let make_uri u = let u_uri = lazy u and u_get_params = lazy (Uri.query u) and u_path_string = lazy (remove_trailing_slash_string (Uri.path u)) in let u_path = lazy (Ocsigen_lib.Url.split_path (Lazy.force u_path_string)) and u_get_params_flat = lazy ( flatten_get_params (Lazy.force u_get_params) ) in { u_uri ; u_get_params ; u_get_params_flat ; u_path ; u_path_string } type t = { r_address : Unix.inet_addr ; r_port : int ; r_ssl : bool ; r_filenames : string list ref ; r_sockaddr : Lwt_unix.sockaddr ; r_remote_ip : string Lazy.t ; r_remote_ip_parsed : Ipaddr.t Lazy.t ; r_forward_ip : string list ; r_uri : uri ; r_meth : Cohttp.Code.meth ; r_encoding : Cohttp.Transfer.encoding ; r_version : Cohttp.Code.version ; r_headers : Cohttp.Header.t ; r_body : body ref ; r_original_full_path : string option ; r_sub_path : string option ; r_cookies_override : string Ocsigen_cookie_map.Map_inner.t option ; mutable r_request_cache : Polytables.t ; mutable r_tries : int ; r_connection_closed : unit Lwt.t; r_timeofday : float } let make ?(forward_ip = []) ?sub_path ?original_full_path ?(request_cache = Polytables.create ()) ?cookies_override ~address ~port ~ssl ~filenames ~sockaddr ~body ~connection_closed request = let r_remote_ip = lazy (Unix.string_of_inet_addr (Ocsigen_lib.Ip_address.of_sockaddr sockaddr)) in let r_remote_ip_parsed = lazy (Ipaddr.of_string_exn (Lazy.force r_remote_ip)) in { r_address = address ; r_port = port ; r_ssl = ssl ; r_filenames = filenames ; r_sockaddr = sockaddr ; r_remote_ip ; r_remote_ip_parsed ; r_forward_ip = forward_ip ; r_uri = make_uri (Cohttp.Request.uri request) ; r_encoding = Cohttp.Request.encoding request ; r_meth = Cohttp.Request.meth request ; r_version = Cohttp.Request.version request ; r_headers = Cohttp.Request.headers request ; r_body = ref (`Unparsed body); r_sub_path = sub_path ; r_original_full_path = original_full_path ; r_cookies_override = cookies_override ; r_request_cache = request_cache ; r_tries = 0 ; r_connection_closed = connection_closed ; r_timeofday = Unix.gettimeofday () } let path_string {r_uri = {u_path_string;_};_} = Lazy.force u_path_string let path {r_uri = {u_path;_};_} = Lazy.force u_path let update ?ssl ?forward_ip ?remote_ip ?sub_path ?meth ?get_params_flat ?post_data ?cookies_override ?(full_rewrite = false) ?uri ({ r_ssl ; r_uri = {u_uri;_} as r_uri; r_meth ; r_forward_ip ; r_remote_ip ; r_remote_ip_parsed ; r_cookies_override ; r_body ; r_sub_path ; r_original_full_path ;_ } as r) = let r_ssl = match ssl with | Some ssl -> ssl | None -> r_ssl and r_forward_ip = match forward_ip with | Some forward_ip -> forward_ip | None -> r_forward_ip and r_remote_ip, r_remote_ip_parsed = match remote_ip with | Some remote_ip -> lazy remote_ip, lazy (Ipaddr.of_string_exn remote_ip) | None -> r_remote_ip, r_remote_ip_parsed and r_sub_path = match sub_path with | Some _ -> sub_path | None -> r_sub_path and r_body = match post_data with | Some (Some post_data) -> ref (`Parsed (Lwt.return post_data)) | Some None -> ref (`Parsed (Lwt.return ([], []))) | None -> r_body and r_cookies_override = match cookies_override with | Some _ -> cookies_override | None -> r_cookies_override and r_meth = match meth with | Some meth -> meth | None -> r_meth and r_original_full_path, r_uri = match uri with | Some uri -> (match full_rewrite, r_original_full_path with | true, _ -> None | false, Some _ -> r_original_full_path | false, _ -> Some (Uri.path (Lazy.force u_uri))), make_uri uri | None -> r_original_full_path, r_uri in let r_uri = match get_params_flat with | Some l -> let u_get_params = lazy (unflatten_get_params l) in let u_uri = lazy ( Uri.with_query (Lazy.force r_uri.u_uri) (Lazy.force u_get_params) ) in { r_uri with u_uri ; u_get_params ; u_get_params_flat = lazy l } | None -> r_uri in { r with r_ssl ; r_uri ; r_meth ; r_forward_ip ; r_remote_ip ; r_remote_ip_parsed ; r_body ; r_cookies_override ; r_sub_path ; r_original_full_path ; } let uri {r_uri = {u_uri;_};_} = Lazy.force u_uri let to_cohttp ({ r_meth ; r_encoding ; r_version ; r_headers ;_} as r) = Cohttp.Request.make ~meth:r_meth ~encoding:r_encoding ~version:r_version ~headers:r_headers (uri r) let body = function | {r_body = {contents = `Unparsed body;_};_} -> body | _ -> failwith "Ocsigen_request.body: body has already been parsed" let address {r_address;_} = r_address let host {r_uri = {u_uri;_};_} = Uri.host (Lazy.force u_uri) let meth {r_meth;_} = r_meth let port {r_port;_} = r_port let ssl {r_ssl;_} = r_ssl let version {r_version;_} = r_version let query {r_uri = {u_uri;_};_} = Uri.verbatim_query (Lazy.force u_uri) let get_params {r_uri = { u_get_params;_};_} = Lazy.force u_get_params let get_params_flat {r_uri = { u_get_params_flat;_};_} = Lazy.force u_get_params_flat let sub_path_string req = remove_trailing_slash_string (match req with | {r_sub_path = Some r_sub_path;_} -> r_sub_path | r -> path_string r) let sub_path r = Ocsigen_lib.Url.split_path (sub_path_string r) let original_full_path_string = function | {r_original_full_path = Some r_original_full_path;_} -> r_original_full_path | r -> path_string r let original_full_path r = Ocsigen_lib.Url.split_path (original_full_path_string r) let header {r_headers;_} id = Cohttp.Header.get r_headers (Ocsigen_header.Name.to_string id) let header_multi {r_headers;_} id = Cohttp.Header.get_multi r_headers (Ocsigen_header.Name.to_string id) let add_header ({r_headers;_} as r) id v = { r with r_headers = Cohttp.Header.add r_headers (Ocsigen_header.Name.to_string id) v } let parse_cookies s = let splitted = Ocsigen_lib.String.split ';' s in try List.fold_left (fun beg a -> try let (n, v) = Ocsigen_lib.String.sep '=' a in Ocsigen_cookie_map.Map_inner.add n v beg with Not_found -> beg) Ocsigen_cookie_map.Map_inner.empty splitted with _ -> Ocsigen_cookie_map.Map_inner.empty let cookies = function | {r_cookies_override = Some cookies;_} -> cookies | r -> match header r Ocsigen_header.Name.cookie with | Some cookies -> parse_cookies cookies | None -> Ocsigen_cookie_map.Map_inner.empty let content_type r = match header r Ocsigen_header.Name.content_type with | Some content_type -> Ocsigen_multipart.parse_content_type content_type | None -> None let force_post_data ({r_body;_} as r) s i = match !r_body with | `Parsed post_data -> Some post_data | `Unparsed body -> match content_type r with | Some content_type -> (match post_data_of_body ~content_type body with | Some f -> let v = f s i in r.r_body := `Parsed v; Some v | None -> None) | None -> None let post_params r s i = match force_post_data r s i with | Some v -> Some (v >|= fst) | None -> None let files r s i = match force_post_data r s i with | Some v -> Some (v >|= snd) | None -> None let remote_ip {r_remote_ip;_} = Lazy.force r_remote_ip let remote_ip_parsed {r_remote_ip_parsed;_} = Lazy.force r_remote_ip_parsed let forward_ip {r_forward_ip;_} = r_forward_ip let request_cache {r_request_cache;_} = r_request_cache let tries {r_tries;_} = r_tries let incr_tries r = r.r_tries <- r.r_tries + 1 let connection_closed {r_connection_closed;_} = r_connection_closed let timeofday {r_timeofday;_} = r_timeofday ocsigenserver-5.0.1/src/server/ocsigen_request.mli000066400000000000000000000046231417255654100224110ustar00rootroot00000000000000type t type content_type = (string * string) * (string * string) list type file_info = Ocsigen_multipart.file_info = { tmp_filename : string ; filesize : int64 ; raw_original_filename : string ; file_content_type : content_type option } type post_data = (string * string) list * (string * file_info) list val make : ?forward_ip : string list -> ?sub_path : string -> ?original_full_path : string -> ?request_cache : Polytables.t -> ?cookies_override : string Ocsigen_cookie_map.Map_inner.t -> address : Unix.inet_addr -> port : int -> ssl : bool -> filenames : string list ref -> sockaddr : Lwt_unix.sockaddr -> body : Cohttp_lwt.Body.t -> connection_closed : unit Lwt.t -> Cohttp.Request.t -> t val update : ?ssl : bool -> ?forward_ip : string list -> ?remote_ip : string -> ?sub_path : string -> ?meth : Cohttp.Code.meth -> ?get_params_flat : (string * string) list -> ?post_data : post_data option -> ?cookies_override : string Ocsigen_cookie_map.Map_inner.t -> ?full_rewrite : bool -> ?uri : Uri.t -> t -> t val to_cohttp : t -> Cohttp.Request.t val uri : t -> Uri.t val body : t -> Cohttp_lwt.Body.t val address : t -> Unix.inet_addr val host : t -> string option val meth : t -> Cohttp.Code.meth val port : t -> int val ssl : t -> bool val version : t -> Cohttp.Code.version val query : t -> string option val get_params : t -> (string * string list) list val get_params_flat : t -> (string * string) list val path : t -> string list val path_string : t -> string val sub_path : t -> string list val sub_path_string : t -> string val original_full_path : t -> string list val original_full_path_string : t -> string val header : t -> Ocsigen_header.Name.t -> string option val header_multi : t -> Ocsigen_header.Name.t -> string list val add_header : t -> Ocsigen_header.Name.t -> string -> t val cookies : t -> string Ocsigen_cookie_map.Map_inner.t val files : t -> string option -> Int64.t option -> (string * file_info) list Lwt.t option val post_params : t -> string option -> Int64.t option -> (string * string) list Lwt.t option val remote_ip : t -> string val remote_ip_parsed : t -> Ipaddr.t val forward_ip : t -> string list val content_type : t -> content_type option val request_cache : t -> Polytables.t val tries : t -> int val incr_tries : t -> unit val connection_closed : t -> unit Lwt.t val timeofday : t -> float ocsigenserver-5.0.1/src/server/ocsigen_response.ml000066400000000000000000000063011417255654100224010ustar00rootroot00000000000000type t = { a_response : Cohttp.Response.t ; a_body : Cohttp_lwt.Body.t ; a_cookies : Ocsigen_cookie_map.t } let make ?(body = Cohttp_lwt.Body.empty) ?(cookies = Ocsigen_cookie_map.empty) a_response = { a_response ; a_body = body ; a_cookies = cookies } let update ?response ?body ?cookies { a_response ; a_body ; a_cookies } = let a_response = match response with | Some response -> response | None -> a_response and a_body = match body with | Some body -> body | None -> a_body and a_cookies = match cookies with | Some cookies -> cookies | None -> a_cookies in { a_response ; a_body ; a_cookies } let of_cohttp ?(cookies = Ocsigen_cookie_map.empty) (a_response, a_body) = { a_response ; a_body ; a_cookies = cookies } let to_cohttp { a_response ; a_body ; _ } = a_response, a_body let status { a_response = { Cohttp.Response.status; _ } ; _} = match status with | `Code _ -> failwith "FIXME: Cohttp.Code.status_code -> status" | #Cohttp.Code.status as a -> a let set_status ({ a_response ; _} as a) status = { a with a_response = { a_response with Cohttp.Response.status = (status :> Cohttp.Code.status_code) } } let cookies {a_cookies; _} = a_cookies let add_cookies ({ a_cookies; _ } as a) cookies = if cookies = Ocsigen_cookie_map.empty then a else { a with a_cookies = Ocsigen_cookie_map.add_multi a_cookies cookies } let header {a_response; _} id = let h = Cohttp.Response.headers a_response in Cohttp.Header.get h (Ocsigen_header.Name.to_string id) let header_multi {a_response; _} id = let h = Cohttp.Response.headers a_response in Cohttp.Header.get_multi h (Ocsigen_header.Name.to_string id) let add_header ({a_response = ({Cohttp.Response.headers; _} as a_response); _} as a) id v = { a with a_response = { a_response with Cohttp.Response.headers = Cohttp.Header.add headers (Ocsigen_header.Name.to_string id) v } } let add_header_multi ({a_response = ({Cohttp.Response.headers; _} as a_response); _} as a) id l = let id = Ocsigen_header.Name.to_string id in let headers = List.fold_left (fun headers -> Cohttp.Header.add headers id) headers l in { a with a_response = { a_response with Cohttp.Response.headers } } let replace_header ({a_response = ({Cohttp.Response.headers; _} as a_response); _} as a) id v = { a with a_response = { a_response with Cohttp.Response.headers = Cohttp.Header.replace headers (Ocsigen_header.Name.to_string id) v } } let replace_headers ({a_response; _} as a) l = let headers = List.fold_left (fun headers (id, content) -> Cohttp.Header.replace headers (Ocsigen_header.Name.to_string id) content) (Cohttp.Response.headers a_response) l in { a with a_response = { a_response with Cohttp.Response.headers } } let remove_header ({a_response; _} as a) id = let headers = Cohttp.Response.headers a_response and id = Ocsigen_header.Name.to_string id in let headers = Cohttp.Header.remove headers id in { a with a_response = { a_response with Cohttp.Response.headers } } ocsigenserver-5.0.1/src/server/ocsigen_response.mli000066400000000000000000000017741417255654100225630ustar00rootroot00000000000000type t val make : ?body : Cohttp_lwt.Body.t -> ?cookies : Ocsigen_cookie_map.t -> Cohttp.Response.t -> t val update : ?response : Cohttp.Response.t -> ?body : Cohttp_lwt.Body.t -> ?cookies : Ocsigen_cookie_map.t -> t -> t val of_cohttp : ?cookies : Ocsigen_cookie_map.t -> (Cohttp.Response.t * Cohttp_lwt.Body.t) -> t val to_cohttp : t -> Cohttp.Response.t * Cohttp_lwt.Body.t val status : t -> Cohttp.Code.status val set_status : t -> Cohttp.Code.status -> t val cookies : t -> Ocsigen_cookie_map.t val add_cookies : t -> Ocsigen_cookie_map.t -> t val header : t -> Ocsigen_header.Name.t -> string option val header_multi : t -> Ocsigen_header.Name.t -> string list val add_header : t -> Ocsigen_header.Name.t -> string -> t val add_header_multi : t -> Ocsigen_header.Name.t -> string list -> t val replace_header : t -> Ocsigen_header.Name.t -> string -> t val replace_headers : t -> (Ocsigen_header.Name.t * string) list -> t val remove_header : t -> Ocsigen_header.Name.t -> t ocsigenserver-5.0.1/src/server/ocsigen_server.ml000066400000000000000000000447641417255654100220700ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Copyright (C) 2005 * Vincent Balat, Denis Berthod, Nataliya Guts, Jérôme Vouillon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) open Lwt.Infix let () = Random.self_init () (* Without the following line, it stops with "Broken Pipe" without raising an exception ... *) let _ = Sys.set_signal Sys.sigpipe Sys.Signal_ignore (* Exit gracefully on SIGINT so that profiling will work *) let _ = Sys.set_signal Sys.sigint (Sys.Signal_handle(fun _ -> exit 0)) let section = Lwt_log.Section.make "ocsigen:main" (* Initialize exception handler for Lwt timeouts: *) let _ = Lwt_timeout.set_exn_handler (fun e -> Lwt_log.ign_error ~section ~exn:e "Uncaught Exception after lwt \ timeout") let _warn sockaddr s = Lwt_log.ign_warning_f ~section "While talking to %a:%s" (fun () sockaddr -> Unix.string_of_inet_addr (Ocsigen_lib.Ip_address.of_sockaddr sockaddr)) sockaddr s let _dbg sockaddr s = Lwt_log.ign_info_f ~section "While talking to %a:%s" (fun () sockaddr -> Unix.string_of_inet_addr (Ocsigen_lib.Ip_address.of_sockaddr sockaddr)) sockaddr s (* fatal errors messages *) let errmsg = function | Dynlink_wrapper.Error e -> (("Fatal - Dynamic linking error: "^(Dynlink_wrapper.error_message e)), 6) | (Unix.Unix_error _) as e -> (("Fatal - "^(Printexc.to_string e)), 9) | Ssl.Private_key_error msg -> (("Fatal - bad password: " ^ msg), 10) | Ocsigen_config.Config_file_error msg | Ocsigen_extensions.Error_in_config_file msg -> (("Fatal - Error in configuration file: "^msg), 50) | Xml.Error (s, loc) -> let begin_char, end_char = Xml.range loc and line = Xml.line loc in Printf.sprintf "Fatal - Error in configuration file, line %d, characters %d-%d: %s" line begin_char end_char (Xml.error_msg s), 51 | Ocsigen_loader.Dynlink_error (s, (Dynlink.Error err)) -> (("Fatal - While loading "^s^": "^(Dynlink.error_message err)), 52) | Ocsigen_loader.Dynlink_error (s, exn) -> (("Fatal - While loading "^s^": "^(Printexc.to_string exn)), 52) | Ocsigen_loader.Findlib_error _ as e -> (("Fatal - " ^ Printexc.to_string e), 53) | exn -> try ((Ocsigen_extensions.get_init_exn_handler () exn), 20) with exn -> (("Fatal - Uncaught exception: "^Printexc.to_string exn), 100) (* loading new configuration *) let reload_conf s = try Ocsigen_extensions.start_initialisation (); Ocsigen_parseconfig.later_pass s; Ocsigen_extensions.end_initialisation (); with e -> Ocsigen_extensions.end_initialisation (); Lwt_log.ign_error ~section (fst (errmsg e)) (* reloading the config file *) let reload ?file () = (* That function cannot be interrupted??? *) Lwt_log.ign_warning ~section "Reloading config file" ; (try match Ocsigen_parseconfig.parse_config ?file () with | [] -> () | s::_ -> reload_conf s with e -> Ocsigen_messages.errlog (fst (errmsg e))); (try match Ocsigen_parseconfig.parse_config ?file () with | [] -> () | s::_ -> reload_conf s with e -> Lwt_log.ign_error ~section (fst (errmsg e))); Lwt_log.ign_warning ~section "Config file reloaded" let _ = let f _s = function | ["reopen_logs"] -> Ocsigen_messages.open_files () >>= fun () -> Lwt_log.ign_warning ~section "Log files reopened"; Lwt.return () | ["reload"] -> reload (); Lwt.return () | ["reload"; file] -> reload ~file (); Lwt.return () | ["shutdown"] -> Ocsigen_cohttp.shutdown None; Lwt.return () | ["shutdown"; f] -> Ocsigen_cohttp.shutdown (Some (float_of_string f)); Lwt.return () | ["gc"] -> Gc.compact (); Lwt_log.ign_warning ~section "Heap compaction requested by user"; Lwt.return () | ["clearcache"] -> Ocsigen_cache.clear_all_caches (); Lwt.return () | _ -> Lwt.fail Ocsigen_command.Unknown_command in Ocsigen_command.register_command_function f type accessor = { accessor : 'a . (('a -> 'a) option * 'a Hmap.key) -> 'a option } module type Hmap_wrapped = sig type t val get : t -> Hmap.t val do_ : t -> (Hmap.t -> Hmap.t) -> unit end module type Config_nested = sig type t type 'a key val key : ?preprocess:('a -> 'a) -> unit -> 'a key val find : t -> 'a key -> 'a option val set : t -> 'a key -> 'a -> unit val unset : t -> 'a key -> unit type accessor = { accessor : 'a . 'a key -> 'a option } end module Make_config_nested (W : Hmap_wrapped) = struct type 'a key = ('a -> 'a) option * 'a Hmap.key type nonrec accessor = accessor = { accessor : 'a . 'a key -> 'a option } let key ?preprocess () = preprocess, Hmap.Key.create () let find w (_, k) = Hmap.find k (W.get w) let set w (f, k) v = let v = match f with | Some f -> f v | None -> v in W.do_ w (Hmap.add k v) let unset w (_, k) = W.do_ w (Hmap.rem k) end module Site = struct type extension_simple = accessor -> Ocsigen_extensions.extension type extension = [ `Simple of extension_simple | `Intrusive of Ocsigen_extensions.virtual_hosts -> Ocsigen_extensions.config_info -> Ocsigen_lib.Url.path -> extension_simple ] let registered_extensions = ref [] let create_extension f = let v = `Simple f in registered_extensions := v :: !registered_extensions; v let create_extension_intrusive f = let v = `Intrusive f in registered_extensions := v :: !registered_extensions; v type t = { s_id : [ `Host of Ocsigen_extensions.virtual_hosts | `Attach of (t * Ocsigen_lib.Url.path) ]; s_config_info : Ocsigen_extensions.config_info ; s_charset : Ocsigen_charset_mime.charset option ; mutable s_config_map : Hmap.t ; mutable s_children_l : [ `Extension of extension_simple | `Child of t ] list ; } let l = ref [] let default_re_string = ".*" let default_re = Ocsigen_lib.Netstring_pcre.regexp default_re_string let rec path_and_hosts {s_id; _} = match s_id with | `Host hosts -> [], hosts | `Attach (s, path') -> let path, hosts = path_and_hosts s in path @ path', hosts let register ({ s_config_info ; s_children_l ; _ } as s) = function | `Simple f -> s.s_children_l <- `Extension f :: s_children_l | `Intrusive f -> let path, hosts = path_and_hosts s in s.s_children_l <- `Extension (f hosts s_config_info path) :: s_children_l let create ?(config_info = Ocsigen_extensions.default_config_info ()) ?(id = `Host (default_re_string, None)) ?charset ?(auto_load_extensions = false) () = let s_id = match id with | `Host (host_regexp, port) when host_regexp = default_re_string -> `Host [default_re_string, default_re, port] | `Host (host_regexp, port) -> `Host [host_regexp, Ocsigen_lib.Netstring_pcre.regexp host_regexp, port] | `Attach (parent, path) -> `Attach (parent, Ocsigen_extensions.preprocess_site_path path) in let s = { s_id ; s_charset = charset ; s_config_info = config_info ; s_config_map = Hmap.empty ; s_children_l = [] } in (match s_id with | `Host _ -> l := s :: !l; | `Attach (parent, _) -> parent.s_children_l <- `Child s :: parent.s_children_l); if auto_load_extensions then List.iter (register s) (List.rev !registered_extensions); s let rec dump_host path { s_config_map ; s_children_l ; _} = let f = function | `Extension f -> f {accessor = fun (_, k) -> Hmap.find k s_config_map} | `Child ({s_charset ; s_id = `Attach (_, path');_} as s) -> let path = path @ path' in Ocsigen_extensions.site_ext (dump_host path s) s_charset path | `Child _ -> failwith "Ocsigen_server.dump_host" in Ocsigen_extensions.compose (List.map f s_children_l) let dump () = let f acc = function | { s_config_info ; s_id = `Host l ; s_children_l = _ :: _ ;_} as s -> (l, s_config_info, dump_host [] s) :: acc | _ -> acc in Ocsigen_extensions.set_hosts (List.fold_left f [] !l) module Config = Make_config_nested (struct type nonrec t = t let get {s_config_map;_} = s_config_map let do_ ({s_config_map;_} as vh) f = vh.s_config_map <- f s_config_map end) end let start ?config () = try (* initialization functions for modules (Ocsigen extensions or application code) loaded from now on will be executed directly. *) Ocsigen_loader.set_init_on_load true; (match config with | Some (_ :: _ :: _) -> Lwt_log.ign_warning ~section "Multiple servers not supported anymore" | _ -> ()); let ask_for_passwd sslports _ = print_string "Please enter the password for the HTTPS server listening \ on port(s) "; print_string (String.concat ", " (List.map (fun (_,p) -> string_of_int p) sslports)); print_string ": "; let old_term= Unix.tcgetattr Unix.stdin in let old_echo = old_term.Unix.c_echo in old_term.Unix.c_echo <- false; Unix.tcsetattr Unix.stdin Unix.TCSAFLUSH old_term; try let r = read_line () in print_newline (); old_term.Unix.c_echo <- old_echo; Unix.tcsetattr Unix.stdin Unix.TCSAFLUSH old_term; r with exn -> old_term.Unix.c_echo <- old_echo; Unix.tcsetattr Unix.stdin Unix.TCSAFLUSH old_term; raise exn in let extensions_connector = Ocsigen_extensions.compute_result in let run s = let user = Ocsigen_config.get_user () and group = Ocsigen_config.get_group () in Lwt_main.run (Ocsigen_messages.open_files ~user ~group ()); let ports = Ocsigen_config.get_ports () and ssl_ports = Ocsigen_config.get_ssl_ports () in let connection = match ports with | [] -> [`All, 80] | l -> l in let ssl_connection = let ssl = match Ocsigen_config.get_ssl_info () with | None | Some { Ocsigen_config.ssl_certificate = None ; Ocsigen_config.ssl_privatekey = None ; _ } -> None | Some { Ocsigen_config.ssl_certificate = Some crt ; Ocsigen_config.ssl_privatekey = Some key ; _ } -> Some (crt, key) | Some { Ocsigen_config.ssl_privatekey = None ;_ } -> raise (Ocsigen_config.Config_file_error "SSL key is missing") | Some { Ocsigen_config.ssl_certificate = None ; _} -> raise (Ocsigen_config.Config_file_error "SSL certificate is missing") in match ssl_ports, ssl with | [], Some (crt, key) -> [`All, 443, (crt, key)] | l, Some (crt, key) -> List.map (fun (a, p) -> (a, p, (crt, key))) l | _ -> [] in let current_uid = Unix.getuid () in let gid = match group with | None -> Unix.getgid () | Some group -> try (Unix.getgrnam group).Unix.gr_gid with Not_found as e -> Ocsigen_messages.errlog ("Error: Wrong group"); raise e in let uid = match user with | None -> current_uid | Some user -> try (Unix.getpwnam user).Unix.pw_uid with Not_found as e -> Ocsigen_messages.errlog ("Error: Wrong user"); raise e in (* A pipe to communicate with the server *) let commandpipe = Ocsigen_config.get_command_pipe () in begin try ignore (Unix.stat commandpipe); with Unix.Unix_error _ -> try let umask = Unix.umask 0 in Unix.mkfifo commandpipe 0o660; Unix.chown commandpipe uid gid; ignore (Unix.umask umask); Lwt_log.ign_warning ~section "Command pipe created"; with e -> Lwt_log.ign_error ~section ~exn:e "Cannot create the command pipe"; end ; (* I change the user for the process *) begin try if current_uid = 0 then begin match user with | None -> () | Some user -> Unix.initgroups user gid end; Unix.setgid gid; Unix.setuid uid; with (Unix.Unix_error _ | Failure _) as e -> Lwt_log.ign_error ~section "Error: Wrong user or group"; raise e end; let minthreads = Ocsigen_config.get_minthreads () and maxthreads = Ocsigen_config.get_maxthreads () in if minthreads > maxthreads then raise (Ocsigen_config.Config_file_error "maxthreads should be greater than minthreads"); ignore (Lwt_preemptive.init minthreads maxthreads (fun s -> Lwt_log.ign_error ~section s)); Lwt.async_exception_hook := (fun e -> (* replace the default "exit 2" behaviour *) match e with | Unix.Unix_error (Unix.EPIPE, _, _) -> () | _ -> Lwt_log.ign_error ~section ~exn:e "Uncaught Exception" ); (match s with | Some s -> (* Now I can load the modules *) Dynlink_wrapper.allow_unsafe_modules true; Ocsigen_extensions.start_initialisation (); Ocsigen_parseconfig.later_pass s; (* As libraries are reloaded each time the config file is read, we do not allow to register extensions in libraries. Seems it does not work :-/ *) Dynlink_wrapper.prohibit ["Ocsigen_extensions.R"] | None -> (Ocsigen_extensions.start_initialisation (); Site.dump ())); if (Ocsigen_config.get_silent ()) then begin (* Close stderr, stdout stdin if silent *) (* redirect stdout and stderr to /dev/null *) let devnull = Unix.openfile "/dev/null" [Unix.O_WRONLY] 0 in Unix.dup2 devnull Unix.stdout; Unix.dup2 devnull Unix.stderr; Unix.close devnull; Unix.close Unix.stdin; end; (* detach from the terminal *) if (Ocsigen_config.get_daemon ()) then ignore (Unix.setsid ()); Ocsigen_extensions.end_initialisation (); let pipe = Unix.(openfile commandpipe [O_RDWR; O_NONBLOCK; O_APPEND]) 0o660 |> Lwt_unix.of_unix_file_descr |> Lwt_io.(of_fd ~mode:input) in let rec f () = Lwt_io.read_line pipe >>= fun s -> Ocsigen_messages.warning ("Command received: "^s); (Lwt.catch (fun () -> let prefix, c = match Ocsigen_lib.String.split ~multisep:true ' ' s with | [] -> raise Ocsigen_command.Unknown_command | a::l -> try let aa, ab = Ocsigen_lib.String.sep ':' a in (Some aa, (ab::l)) with Not_found -> None, (a::l) in Ocsigen_command.get_command_function () ?prefix s c) (function | Ocsigen_command.Unknown_command -> Lwt_log.ign_warning ~section "Unknown command"; Lwt.return () | e -> Lwt_log.ign_error ~section ~exn:e "Uncaught Exception after \ command"; Lwt.fail e)) >>= f in ignore (f ()); Lwt_main.run @@ Lwt.join ((List.map (fun (address, port) -> Ocsigen_cohttp.service ~address ~port ~connector:extensions_connector ()) connection) @ (List.map (fun (address, port, (crt, key)) -> Ocsigen_cohttp.service ~ssl:(crt, key, Some (ask_for_passwd [(address, port)])) ~address ~port ~connector:extensions_connector ())) ssl_connection) (* Ocsigen_messages.warning "Ocsigen has been launched (initialisations ok)"; fst (Lwt.wait ()) *) in (* let set_passwd_if_needed (ssl, ports, sslports) = if sslports <> [] then match ssl with | None | Some (None, None) -> () | Some (None, _) -> raise (Ocsigen_config.Config_file_error "SSL certificate is missing") | Some (_, None) -> raise (Ocsigen_config.Config_file_error "SSL key is missing") | Some ((Some c), (Some k)) -> Ssl.set_password_callback !Server.ssl_context (ask_for_passwd sslports); Ssl.use_certificate !Server.ssl_context c k in *) let write_pid pid = match Ocsigen_config.get_pidfile () with None -> () | Some p -> let spid = (string_of_int pid)^"\n" in let len = String.length spid in let f = Unix.openfile p [Unix.O_WRONLY; Unix.O_CREAT; Unix.O_TRUNC] 0o640 in ignore (Unix.write_substring f spid 0 len); Unix.close f in let launch h = Ocsigen_lib.Option.iter Ocsigen_parseconfig.first_pass h; (* set_passwd_if_needed sslinfo; *) if Ocsigen_config.get_daemon () then let pid = Unix.fork () in if pid = 0 then run h else begin Ocsigen_messages.console (fun () -> "Process " ^ string_of_int pid ^ " detached"); write_pid pid end else begin write_pid (Unix.getpid ()); run h end in let launch = function | Some [] -> () | Some [h] -> launch (Some h) | None -> launch None | Some (_ :: _ :: _) -> () (* Multiple servers not supported any more *) in launch config with e -> let msg, errno = errmsg e in Ocsigen_messages.errlog msg; exit errno ocsigenserver-5.0.1/src/server/ocsigen_server.mli000066400000000000000000000045651417255654100222340ustar00rootroot00000000000000(* Ocsigen * http://www.ocsigen.org * Copyright (C) 2005 * Vincent Balat, Denis Berthod, Nataliya Guts, Jérôme Vouillon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) val section : Lwt_log_core.section (** use Lwt_log.Section.set_level in order to debug *) (** Reload the configuration of the server. The optional parameter [?file] may be used to read the configuration from another file. *) val reload : ?file : string -> unit -> unit (** Start the server. Never returns. *) val start : ?config : Xml.xml list list -> unit -> unit module type Config_nested = sig type t type 'a key val key : ?preprocess:('a -> 'a) -> unit -> 'a key val find : t -> 'a key -> 'a option val set : t -> 'a key -> 'a -> unit val unset : t -> 'a key -> unit type accessor = { accessor : 'a . 'a key -> 'a option } end module Site : sig type t val create : ?config_info:Ocsigen_extensions.config_info -> ?id: [ `Attach of t * Ocsigen_lib.Url.path | `Host of string * int option ] -> ?charset:Ocsigen_charset_mime.charset -> ?auto_load_extensions:bool -> unit -> t module Config : Config_nested with type t := t type extension val create_extension : (Config.accessor -> Ocsigen_extensions.extension) -> extension val register : t -> extension -> unit (**/**) (** Lower-level interface for creating extensions that gives the extension more info. To be avoided. Currently used by Eliom. *) val create_extension_intrusive : (Ocsigen_extensions.virtual_hosts -> Ocsigen_extensions.config_info -> Ocsigen_lib.Url.path -> Config.accessor -> Ocsigen_extensions.extension) -> extension end