pax_global_header00006660000000000000000000000064151523440410014511gustar00rootroot0000000000000052 comment=d39388d1edcc9fe7a35449fc5c23d222d20d6f81 sslh-2.3.1/000077500000000000000000000000001515234404100124655ustar00rootroot00000000000000sslh-2.3.1/.github/000077500000000000000000000000001515234404100140255ustar00rootroot00000000000000sslh-2.3.1/.github/workflows/000077500000000000000000000000001515234404100160625ustar00rootroot00000000000000sslh-2.3.1/.github/workflows/container-build.yaml000066400000000000000000000030431515234404100220250ustar00rootroot00000000000000name: Create and publish Container image on: push: branches: - master tags: - 'v*' pull_request: branches: - master env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: build-and-push-image: runs-on: ubuntu-latest permissions: contents: read packages: write steps: - name: Checkout repository uses: actions/checkout@v3 - name: Set up QEMU uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Login to Container registry uses: docker/login-action@v2 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Docker meta id: meta uses: docker/metadata-action@v4 with: images: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch type=ref,event=pr type=edge type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} - name: Build and push uses: docker/build-push-action@v4 with: platforms: linux/amd64,linux/386,linux/arm64,linux/arm/v6,linux/arm/v7 context: . file: Dockerfile push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} sslh-2.3.1/.gitignore000066400000000000000000000002501515234404100144520ustar00rootroot00000000000000*.swp *.swo *.o cscope.* echosrv libsslh.a sslh-fork sslh-select sslh-ev systemd-sslh-generator sslh.8.gz tags version.h /config.status /config.log /config.h /Makefile sslh-2.3.1/COPYING000066400000000000000000000432541515234404100135300ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, 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. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 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 Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. 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 program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. sslh-2.3.1/ChangeLog000066400000000000000000000373421515234404100142500ustar00rootroot00000000000000v2.3.1: Fix segmentation fault in sslh-fork. Add file access when using Landlock and Libwrap together. Mixed IPv4/IPv6 proxyprotocol setups will move both addresses to IPv6 format on the server side. Add CAP_NET_RAW to systemd config so transparent proxying can work. Removed sslh-select systemd file: don't repeat the same configuration file! Changed SNI matching log messages from `msg_probe_error` to `msg_probe_info`: beware if you happen to use them... Close unused file descriptors upon forking a worker for a connection (in sslh-ev and sslh-select). In particular, this prevents forked processes to inherit the listen sockets and block a new main process from starting. More configuration sanity checks (e.g. using regex or proxyprotocol options if libraries are not compiled in) -V now outputs compile-time options so it is possible to know what is compiled in. v2.3.0: Added `max_connections` setting to `listen` and `protocol` configuration; see the [guide](doc/max_connections.md) for more information. accept() is now disabled for some time when ulimit -n is reached. Support proxyprotocol on incoming connections. See the [guide](doc/proxyprotocol.md) for information. Fix proxyprotocol target field (Thanks to Github user 404-Not-Found) Fix memory leak in regex probe. v2.2.4: Fix CVE-2025-46806 for "Misaligned Memory Accesses in `is_openvpn_protocol()`" Fix CVE-2025-46807 for "File Descriptor Exhaustion in sslh-select and sslh-ev" Fix potential parsing of undefined data in syslog probe (no CVE assigned) Thanks to Matthias Gerstner of the SUSE security team for the security review that found these defects! v2.2.3: Reverse older commit: version.h cannot be included without breaking the build (everything recompiles every time) and the release archive creation (which relies on git tags). v2.2.2: Fix potential vulnerability similar to CVE-2020-28935 v2.2.1: Added a boolean setting "is_unix" for listen and protocol entries. This will use the 'host' setting as a path name to a socket file, and connections (listening or connecting) will be performed on Unix socket instead of Internet sockets. Support HAProxy's proxyprotocol on the backend server side. Lots of documentation about a new, simpler way to perform transparent proxying. New "verbose" option that overrides all other verbose settings. v2.1.3: Fix Landlock access to /etc/hosts.deny and /etc/hosts.allow. v2.1.2: Fix inetd mode. v2.1.1: Various minor fixes. v2.1.0: Support for the Landlock LSM. After initial setup, sslh gives up all local file access rights. Reintroduced --ssl as an alias to --tls. Introduce autoconf to adapt to landlock presence. Close connexion without error message if remote client forcefully closes connexion, for Windows. v2.0.1: Fix resolve_on_forward setting, which would crash sslh reliably. v2.0.0: v2.0: New sslh-ev: this is functionally equivalent to sslh-select (mono-process, only forks for specified protocols), but based on libev, which should make it scalable to large numbers of connections. New log system: instead of --verbose with arbitrary levels, there are now several message classes. Each message class can be set to go to stderr, syslog, or both. Classes are documented in example.cfg. UDP connections are now managed in a hash to avoid linear searches. The downside is that the number of UDP connections is a hard limit, configurable with the 'udp_max_connections', which defaults to 1024. Timeouts are managed with lists. inetd merges stderr output to what is sent to the client, which is a security issue as it might give information to an attacker. When inetd is activated, stderr is forcibly closed. New protocol-level option `resolve_on_forward`, requests that target names are resolved at each connection instead of at startup. Useful for dynamic DNS situations. (Paul Schroeder/milkpirate) New probe for MSRDP (akappner). v1.22: 17AUG2021 sslh-select now supports UDP protocols. Probes specified in the `protocols` configuration entry are tried on incoming packets, TCP or UDP, and forwarded based on the input protocol (an incoming TCP connection will be forwarded as TCP, and same with UDP). This has been tested with DNS as shown in udp.cfg: incoming packets that contain my domain name are assumed to be a DNS request and forwarded accordingly. Note this could cause problems if combined with incoming TLS with SNI. UDP clients and servers need to agree on the IPv4/IPv6 they use: use the same protocol on all sides! Often, this means explicitly using 'ip4-localhost'. UDP sender-receiver pairs (connections, so to speak) are kept for 60s, which can be changed with `udp_timeout` in the configuration. Added probes for UDP protocols QUICK and Teamspeak. Added probes for syslog protocol. sslh-select refactored to change linear searches through connections to linear searches through fd_set. Fixed a libconfig call to support libconfig 1.7.3. Added symbol to support libconfig 1.4.9, still in use in CentOS7. Warn about unknown settings in the configuration file. Added per-protocol `transparent` option. sslh-fork drops the capability after creating the server-side transparent socket. Transparent now uses CAP_NET_RAW instead of CAP_NET_ADMIN. Removed compile-time option to use POSIX regex. Now regex must be PCRE2 (Perl-Compatible). This was in fact the case since v1.21, as PCRE are used to parse the config file. v1.21: 11JUL2020 WARNING: Moved configuration and command-line management to use conf2struct. Changes are: * `--ssl` and using `name: 'ssl'` in config file is no longer supported, use `tls` instead. * command line option <-F|--config> no longer defaults to /etc/sslh.cfg, so you have to specify it explicitly. * command line option <-v|--verbose> takes a mandatory integer parameter Added TCP_FASTOPEN support for client sockets (if tfo_ok is specified in their configuration) and for listening socket, if all client protocols support it. (Craig Andrews) Added 'minlength' option to skip a probe if less than that many bytes have been received (mostly for regex) Update Let's Encrypt entry in example.cfg for tls-alpn-01 challenges; tls-sni-* challenges are now deprecated. Log to syslog even if in foreground (for people who use fail2ban) Use syslog_facility: "none" to disable syslog output. Changed exit code for illegal command line parameter from 1 to 6 (for testing purposes) v1.20: 20NOV2018 Added support for socks5 protocol (Eugene Protozanov) New probing method: Before, probes were tried in order, repeating on the same probe as long it returned PROBE_AGAIN before moving to the next one. This means a probe which requires a lot of data (i.e. return PROBE_AGAIN for a long time) could prevent successful matches from subsequent probes. The configuration file needed to take that into account. Now, all probes are tried each time new data is found. If any probe matches, use it. If at least one probe requires more data, wait for more. If all probes failed, connect to the last one. So the only thing to know when writing the configuration file is that 'anyprot' needs to be last. Test suite heavily refactored; `t` uses `test.cfg` to decide which probes to test and all setup is automatic; probes get tested with 'fast' (entire first message in one packet) and 'slow' (one byte at a time); when SNI/ALPN are defined, all combinations are tested. Old 'tls' probe removed, 'sni_alpn' probe renamed as 'tls'. You'll need to change 'sni_alpn' to 'tls' in your configuration file, if ever you used it. v1.19: 20JAN2018 Added 'syslog_facility' configuration option to specify where to log. TLS now supports SNI and ALPN (Travis Burtrum), including support for Let's Encrypt challenges (Jonathan McCrohan) ADB probe. (Mike Frysinger) Added per-protocol 'fork' option. (Oleg Oshmyan) Added chroot option. (Mike Frysinger) A truckload of bug fixes and documentation improvements (Various contributors) v1.18: 29MAR2016 Added USELIBPCRE to make use of regex engine optional. Added support for RFC4366 SNI and RFC7301 ALPN (Travis Burtrum) Changed connection log to include the name of the probe that triggered. Changed configuration file format: 'probe' field is no longer required, 'name' field can now contain 'tls' or 'regex', with corresponding options (see example.cfg) Added 'log_level' option to each protocol, which allows to turn off generation of log at each connection. Added 'keepalive' option. v1.17: 09MAR2015 Support RFC5952-style IPv6 addresses, e.g. [::]:443. Transparent proxy support for FreeBSD. (Ruben van Staveren) Using -F with no argument will try /etc/sslh/sslh.cfg and then /etc/sslh.cfg as configuration files. (argument to -F can no longer be separated from the option by a space, e.g. must be -Ffoo.cfg) Call setgroups() before setgid() (fixes potential privilege escalation). (Lars Vogdt) Use portable way of getting modified time for OSX support. (Aaron Madlon-Kay) Example configuration for fail2ban. (Every Mouw) v1.16: 11FEB2014 Probes made more resilient, to incoming data containing NULLs. Also made them behave properly when receiving too short packets to probe on the first incoming packet. (Ondrej Kuzník) Libcap support: Keep only CAP_NET_ADMIN if started as root with transparent proxying and dropping privileges (enable USELIBCAP in Makefile). This avoids having to mess with filesystem capabilities. (Sebastian Schmidt/yath) Fixed bugs related to getpeername that would cause sslh to quit erroneously (getpeername can return actual errors if connections are dropped before getting to getpeername). Set IP_FREEBIND if available to bind to addresses that don't yet exist. v1.15: 27JUL2013 Added --transparent option for transparent proxying. See README for iptables magic and capability management. Fixed bug in sslh-select: if number of opened file descriptor became bigger than FD_SETSIZE, bad things would happen. Fixed bug in sslh-select: if socket dropped while deferred_data was present, sslh-select would crash. Increased FD_SETSIZE for Cygwin, as the default 64 is too low for even moderate load. v1.14: 21DEC2012 Corrected OpenVPN probe to support pre-shared secret mode (OpenVPN port-sharing code is... wrong). Thanks to Kai Ellinger for help in investigating and testing. Added an actual TLS/SSL probe. Added configurable --on-timeout protocol specification. Added a --anyprot protocol probe (equivalent to what --ssl was). Makefile respects the user's compiler and CFLAG choices (falling back to the current values if undefined), as well as LDFLAGS. (Michael Palimaka) Added "After" and "KillMode" to systemd.sslh.service (Thomas Weißschuh). Added LSB tags to etc.init.d.sslh (Thomas Varis). v1.13: 18MAY2012 Write PID file before dropping privileges. Added --background, which overrides 'foreground' configuration file setting. Added example systemd service file from Archlinux in scripts/ https://projects.archlinux.org/svntogit/community.git/tree/trunk/sslh.service?h=packages/sslh (Sébastien Luttringer) v1.12: 08MAY2012 Added support for configuration file. New protocol probes can be defined using regular expressions that match the first packet sent by the client. sslh now connects timed out connections to the first configured protocol instead of 'ssh' (just make sure ssh is the first defined protocol). sslh now tries protocols in the order in which they are defined (just make sure sslh is the last defined protocol). v1.11: 21APR2012 WARNING: defaults have been removed for --user and --pidfile options, update your start-up scripts! No longer stop sslh when reverse DNS requests fail for logging. Added HTTP probe. No longer create new session if running in foreground. No longer default to changing user to 'nobody'. If --user isn't specified, just run as current user. No longer create PID file by default, it should be explicitly set with --pidfile. No longer log to syslog if in foreground. Logs are instead output to stderr. The four changes above make it straightforward to integrate sslh with systemd, and should help with launchd. v1.10: 27NOV2011 Fixed calls referring to sockaddr length so they work with FreeBSD. Try target addresses in turn until one works if there are several (e.g. "localhost:22" resolves to an IPv6 address and an IPv4 address and sshd does not listen on IPv6). Fixed sslh-fork so killing the head process kills the listener processes. Heavily cleaned up test suite. Added stress test t_load script. Added coverage (requires lcov). Support for XMPP (Arnaud Gendre). Updated README.MacOSX (Aaron Madlon-Kay). v1.9: 02AUG2011 WARNING: This version does not work with FreeBSD and derivatives! WARNING: Options changed, you'll need to update your start-up scripts! Log format changed, you'll need to update log processing scripts! Now supports IPv6 throughout (both on listening and forwarding) Logs now contain IPv6 addresses, local forwarding address, and resolves names (unless --numeric is specified). Introduced long options. Options -l, -s and -o replaced by their long counterparts. Defaults for SSL and SSH options suppressed (it's legitimate to want to use sslh to mux OpenVPN and tinc while not caring about SSH nor SSL). Bind to multiple addresses with multiple -p options. Support for tinc VPN (experimental). Numeric logging option. v1.8: 15JUL2011 Changed log format to make it possible to link connections to subsequent logs from other services. Updated CentOS init.d script (Andre Krajnik). Fixed zombie issue with OpenBSD (The SA_NOCLDWAIT flag is not propagated to the child process, so we set up signals after the fork.) (François FRITZ) Added -o "OpenVPN" and OpenVPN probing and support. Added single-threaded, select(2)-based version. Added support for "Bold" SSH clients (clients that speak first) Thanks to Guillaume Ricaud for spotting a regression bug. Added -f "foreground" option. Added test suite. (only tests connexions. No test for libwrap, setsid, setuid and so on) and corresponding 'make test' target. Added README.MacOSX (thanks Aaron Madlon-Kay) Documented use with proxytunnel and corkscrew in README. v1.7: 01FEB2010 Added CentOS init.d script (Andre Krajnik). Fixed default ssl address inconsistency, now defaults to "localhost:443" and fixed documentation accordingly (pointed by Markus Schalke). Children no longer bind to the listen socket, so parent server can be stopped without killing an active child (pointed by Matthias Buecher). Inetd support (Dima Barsky). v1.6: 25APR2009 Added -V, version option. Install target directory configurable in Makefile Changed syslog prefix in auth.log to "sslh[%pid]" Man page new 'make install' and 'make install-debian' targets PID file now specified using -P command line option Actually fixed zombie generation (the v1.5 patch got lost, doh!) v1.5: 10DEC2008 Fixed zombie generation. Added support scripts (), Makefile. Changed all 'connexions' to 'connections' to please pesky users. Damn users. v1.4: 13JUL2008 Added libwrap support for ssh service (Christian Weinberger) Only SSH is libwraped, not SSL. v1.3: 14MAY2008 Added parsing for local interface to listen on Changed default SSL connection to port 442 (443 doesn't make sense as a default as we're already listening on 443) Syslog incoming connections v1.2: 12MAY2008 Fixed compilation warning for AMD64 (Thx Daniel Lange) v1.1: 21MAY2007 Making sslhc more like a real daemon: * If $PIDFILE is defined, write first PID to it upon startup * Fork at startup (detach from terminal) (thanks to http://www.enderunix.org/docs/eng/daemon.php -- good checklist) * Less memory usage (?) v1.0: Basic functionality: privilege dropping, target hostnames and ports configurable. sslh-2.3.1/Dockerfile000066400000000000000000000031421515234404100144570ustar00rootroot00000000000000ARG ALPINE_VERSION="latest" ARG TARGET_ARCH="library" FROM docker.io/${TARGET_ARCH}/alpine:${ALPINE_VERSION} AS build # Install build dependencies for sslh and libproxyprotocol RUN apk add --no-cache \ 'gcc' \ 'libconfig-dev' \ 'make' \ 'musl-dev' \ 'pcre2-dev' \ 'perl' \ 'git' \ 'autoconf' \ 'automake' \ 'libtool' \ ; # Build libproxyprotocol WORKDIR /tmp RUN git clone https://github.com/kosmas-valianos/libproxyprotocol.git && \ cd libproxyprotocol && \ make && \ mkdir -p /usr/local/include/ && \ mv libs/libproxyprotocol.so /usr/local/lib/ && \ mv src/* /usr/local/include/ # Set environment variables for sslh to find libproxyprotocol ENV C_INCLUDE_PATH=/usr/local/include ENV LIBRARY_PATH=/usr/local/lib ENV LD_LIBRARY_PATH=/usr/local/lib WORKDIR /sslh COPY . /sslh # Configure and build sslh # The configure script should automatically detect libproxyprotocol RUN ./configure && make sslh-select && strip sslh-select FROM docker.io/${TARGET_ARCH}/alpine:${ALPINE_VERSION} # Copy libproxyprotocol.so from the build stage COPY --from=build /usr/local/lib/libproxyprotocol.so* /usr/local/lib/ COPY --from=build "/sslh/sslh-select" "/usr/local/bin/sslh" RUN apk add --no-cache \ 'libconfig' \ 'pcre2' \ 'iptables' \ 'ip6tables' \ 'libcap' \ && \ adduser -s '/bin/sh' -S -D sslh && \ setcap cap_net_bind_service,cap_net_raw+ep /usr/local/bin/sslh COPY "./container-entrypoint.sh" "/init" ENTRYPOINT [ "/init" ] # required for updating iptables USER root:rootsslh-2.3.1/Makefile.in000066400000000000000000000110401515234404100145260ustar00rootroot00000000000000 VERSION=$(shell ./genver.sh -r) # Configuration -- you probably need to `make clean` if you # change any of these # uncomment the following line to disable landlock # override undefine HAVE_LANDLOCK ENABLE_SANITIZER= # Enable ASAN/LSAN/UBSAN ENABLE_REGEX=1 # Enable regex probes USELIBCONFIG=1 # Use libconfig? (necessary to use configuration files) USELIBEV=1 # Use libev? USESYSTEMD= # Make use of systemd socket activation COV_TEST= # Perform test coverage? PREFIX?=/usr BINDIR?=$(PREFIX)/sbin MANDIR?=$(PREFIX)/share/man/man8 MAN=sslh.8.gz # man page name # End of configuration -- the rest should take care of # itself ifneq ($(strip $(ENABLE_SANITIZER)),) CFLAGS_SAN=-DENABLE_SANITIZER -fsanitize=address -fsanitize=leak -fsanitize=undefined -fsanitize=alignment endif ifneq ($(strip $(COV_TEST)),) CFLAGS_COV=-DCOV_TEST -fprofile-arcs -ftest-coverage endif CC ?= gcc AR ?= ar CFLAGS +=-Wall -O2 -DLIBPCRE -g $(CFLAGS_COV) $(CFLAGS_SAN) LIBS=-lm -lpcre2-8 @LIBS@ OBJS=sslh-conf.o common.o log.o sslh-main.o probe.o tls.o argtable3.o collection.o gap.o tcp-probe.o landlock.o proxyprotocol.o OBJS_A=libsslh.a FORK_OBJS=sslh-fork.o $(OBJS_A) SELECT_OBJS=processes.o udp-listener.o sslh-select.o hash.o tcp-listener.o $(OBJS_A) EV_OBJS=processes.o udp-listener.o sslh-ev.o hash.o tcp-listener.o $(OBJS_A) CONDITIONAL_TARGETS= ifneq ($(strip $(ENABLE_REGEX)),) CPPFLAGS+=-DENABLE_REGEX endif ifneq ($(strip $(USELIBCONFIG)),) LIBS:=$(LIBS) -lconfig CPPFLAGS+=-DLIBCONFIG endif ifneq ($(strip $(USESYSTEMD)),) LIBS:=$(LIBS) -lsystemd CPPFLAGS+=-DSYSTEMD CONDITIONAL_TARGETS+=systemd-sslh-generator endif ifneq ($(strip $(USELIBEV)),) CONDITIONAL_TARGETS+=sslh-ev endif all: sslh-fork sslh-select $(MAN) echosrv $(CONDITIONAL_TARGETS) %.o: %.c %.h version.h $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(OBJS_A): $(OBJS) $(AR) rcs $(OBJS_A) $(OBJS) version.h: ./genver.sh >version.h $(OBJS) $(FORK_OBJS) $(SELECT_OBJS) $(EV_OBJS): argtable3.h collection.h common.h gap.h hash.h log.h probe.h processes.h sslh-conf.h tcp-listener.h tcp-probe.h tls.h udp-listener.h version.h c2s: conf2struct sslhconf.cfg conf2struct echosrv.cfg sslh-conf.c sslh-conf.h: sslhconf.cfg $(warning "sslhconf.cfg is more recent than sslh-conf.[ch]. Use `make c2s` to rebuild using `conf2struct`") sslh-fork: version.h Makefile $(FORK_OBJS) $(CC) $(CFLAGS) $(LDFLAGS) -o sslh-fork $(FORK_OBJS) $(LIBS) sslh-select: version.h $(SELECT_OBJS) Makefile $(CC) $(CFLAGS) $(LDFLAGS) -o sslh-select $(SELECT_OBJS) $(LIBS) sslh-ev: version.h $(EV_OBJS) Makefile $(CC) $(CFLAGS) $(LDFLAGS) -o sslh-ev $(EV_OBJS) $(LIBS) -lev systemd-sslh-generator: systemd-sslh-generator.o $(CC) $(CFLAGS) $(LDFLAGS) -o systemd-sslh-generator systemd-sslh-generator.o -lconfig echosrv-conf.c echosrv-conf.h: echosrv.cfg $(warning "echosrv.cfg is more recent than echosrv-conf.[ch]. Use `make c2s` to rebuild using `conf2struct`") echosrv: version.h echosrv-conf.c echosrv.o echosrv-conf.o argtable3.o $(CC) $(CFLAGS) $(LDFLAGS) -o echosrv echosrv.o echosrv-conf.o argtable3.o $(LIBS) landlock.o: config.h $(MAN): sslh.pod Makefile pod2man --section=8 --release=$(VERSION) --center=" " sslh.pod | gzip -9 - > $(MAN) # Create release: export clean tree and tag current # configuration release: git archive $(VERSION) --prefix="sslh-$(VERSION)/" | gzip > /tmp/sslh-$(VERSION).tar.gz gpg --detach-sign --armor /tmp/sslh-$(VERSION).tar.gz # Build docker image docker: docker image build -t "sslh:${VERSION}" . docker image tag "sslh:${VERSION}" sslh:latest docker-clean: yes | docker image rm "sslh:${VERSION}" sslh:latest yes | docker image prune # generic install: install binary and man page install: sslh-fork $(MAN) mkdir -p $(DESTDIR)/$(BINDIR) mkdir -p $(DESTDIR)/$(MANDIR) install -p sslh-fork $(DESTDIR)/$(BINDIR)/sslh install -p -m 0644 $(MAN) $(DESTDIR)/$(MANDIR)/$(MAN) # "extended" install for Debian: install startup script install-debian: install sslh $(MAN) sed -e "s+^PREFIX=+PREFIX=$(PREFIX)+" scripts/etc.init.d.sslh > /etc/init.d/sslh chmod 755 /etc/init.d/sslh update-rc.d sslh defaults uninstall: rm -f $(DESTDIR)$(BINDIR)/sslh $(DESTDIR)$(MANDIR)/$(MAN) $(DESTDIR)/etc/init.d/sslh $(DESTDIR)/etc/default/sslh update-rc.d sslh remove distclean: clean rm -f tags sslh-conf.[ch] echosrv-conf.[ch] cscope.* clean: rm -f sslh-fork sslh-select $(CONDITIONAL_TARGETS) echosrv version.h $(MAN) systemd-sslh-generator *.o *.gcov *.gcno *.gcda *.png *.html *.css *.info tags: *.c *.h ctags *.[ch] cscope: -find . -name "*.[chS]" >cscope.files -cscope -b -R test: ./t sslh-2.3.1/README.md000066400000000000000000000140641515234404100137510ustar00rootroot00000000000000sslh -- A ssl/ssh multiplexer ============================= `sslh` accepts connections on specified ports, and forwards them further based on tests performed on the first data packet sent by the remote client. Probes for HTTP, TLS/SSL (including SNI and ALPN), SSH, OpenVPN, tinc, XMPP, SOCKS5, are implemented, and any other protocol that can be tested using a regular expression, can be recognised. A typical use case is to allow serving several services on port 443 (e.g. to connect to SSH from inside a corporate firewall, which almost never block port 443) while still serving HTTPS on that port. Hence `sslh` acts as a protocol demultiplexer, or a switchboard. With the SNI and ALPN probe, it makes a good front-end to a virtual host farm hosted behind a single IP address. `sslh` has the bells and whistles expected from a mature daemon: privilege and capabilities dropping, inetd support, systemd support, transparent proxying, support for HAProxy's proxyprotocol, chroot, logging, IPv4 and IPv6, TCP and UDP, a fork-based, a select-based model, and yet another based on libev for larger installations. Install ======= Please refer to the [install guide](doc/INSTALL.md). Security ======== Matthias Gerstner from OpenSUSE has performed a code review of `sslh` from a security point of view, which revealed a number of problems, including two CVE. His findings have already been taken partly into account for the more critical ones. The [full review](https://security.opensuse.org/2025/06/13/sslh-denial-of-service-vulnerabilities.html) is well worth reading if you are using `sslh` in production. Part of the securing your installation involves configuring connection limits. This is described in [this guide](doc/max_connections.md). Configuration ============= Please refer to the [configuration guide](doc/config.md). Transparent proxying -------------------- Transparent proxying allows the target server to see the original client IP address, i.e. `sslh` becomes invisible. The same result can be achieved more easily by using `proxyprotocol` if the backend server supports it. This is a simple setting to add to the `sslh` protocol configuration, usually with an equivalently simple setting to add in the backend server configuration, so try that first. This is explained in a [separate document](doc/proxyprotocol.md). This means services behind `sslh` (Apache, `sshd` and so on) will see the external IP and ports as if the external world connected directly to them. This simplifies IP-based access control (or makes it possible at all), and makes it possible to use IP-based banning tools such as `fail2ban`. There are two methods. One uses additional virtual network interfaces. The principle and basic setup is described [here](doc/simple_transparent_proxy.md), with further scenarios described [there](doc/scenarios-for-simple-transparent-proxy.md). There is also a guide to use [podman](doc/podman.md). Another method uses iptable packet marking features, and is highly dependent on your network environment and infrastructure setup. There is no known generic approach, and if you do not find directions for your exact setup, you will probably need an extensive knowledge of network management and iptables setup". It is described in its own [document](doc/tproxy.md). In most cases, you will be better off following the first method. Docker image ------------ How to use --- ```bash docker run \ --cap-add CAP_NET_RAW \ --cap-add CAP_NET_BIND_SERVICE \ --rm \ -it \ ghcr.io/yrutschle/sslh:latest \ --foreground \ --listen=0.0.0.0:443 \ --ssh=hostname:22 \ --tls=hostname:443 ``` docker-compose example ```yaml version: "3" services: sslh: image: ghcr.io/yrutschle/sslh:latest hostname: sslh ports: - 443:443 command: --foreground --listen=0.0.0.0:443 --tls=nginx:443 --openvpn=openvpn:1194 depends_on: - nginx - openvpn nginx: image: nginx openvpn: image: openvpn ``` Transparent mode 1: using sslh container for networking _Note: For transparent mode to work, the sslh container must be able to reach your services via **localhost**_ ```yaml version: "3" services: sslh: build: https://github.com/yrutschle/sslh.git container_name: sslh environment: - TZ=${TZ} cap_add: - NET_ADMIN - NET_RAW - NET_BIND_SERVICE sysctls: - net.ipv4.conf.default.route_localnet=1 - net.ipv4.conf.all.route_localnet=1 command: --transparent --foreground --listen=0.0.0.0:443 --tls=localhost:8443 --openvpn=localhost:1194 ports: - 443:443 #sslh - 80:80 #nginx - 8443:8443 #nginx - 1194:1194 #openvpn extra_hosts: - localbox:host-gateway restart: unless-stopped nginx: image: nginx:latest ..... network_mode: service:sslh #set nginx container to use sslh networking. # ^^^ This is required. This makes nginx reachable by sslh via localhost openvpn: image: openvpn:latest ..... network_mode: service:sslh #set openvpn container to use sslh networking ``` Transparent mode 2: using host networking ```yaml version: "3" services: sslh: build: https://github.com/yrutschle/sslh.git container_name: sslh environment: - TZ=${TZ} cap_add: - NET_ADMIN - NET_RAW - NET_BIND_SERVICE # must be set manually #sysctls: # - net.ipv4.conf.default.route_localnet=1 # - net.ipv4.conf.all.route_localnet=1 command: --transparent --foreground --listen=0.0.0.0:443 --tls=localhost:8443 --openvpn=localhost:1194 network_mode: host restart: unless-stopped nginx: image: nginx:latest ..... ports: - 8443:8443 # bind to docker host on port 8443 openvpn: image: openvpn:latest ..... ports: - 1194:1194 # bind to docker host on port 1194 ``` Comments? Questions? ==================== You can subscribe to the `sslh` mailing list here: This mailing list should be used for discussion, feature requests, and will be the preferred channel for announcements. Of course, check the [FAQ](doc/FAQ.md) first! sslh-2.3.1/TODO000066400000000000000000000017221515234404100131570ustar00rootroot00000000000000Here's a list of features that have been suggested or sometimes requested. This list is not a roadmap and shouldn't be construed to mean that any of this will happen. - configurable behaviour depending on services (e.g. select() for ssl but fork() for ssh). - have certain services available only from specified subnets - some sort of "service knocking" allowing to activate a service upon some external even, similar to port knocking; for example, go to a specific URL to enable sslh forwarding to sshd for a set period of time: * sslh listens on 443 and only directs to httpd * user goes somewhere to https://example.org/open_ssh.cgi * open_ssh.cgi tells sslh * sslh starts checking if incoming connections are ssh, and if they are, forward to sshd * 10 minutes later, sslh stops forwarding to ssh That would make it almost impossible for an observer (someone who'd telnet regularly on 443) to ever notice both services are available on 443. sslh-2.3.1/argtable3.c000066400000000000000000006264641515234404100145170ustar00rootroot00000000000000/******************************************************************************* * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #define ARG_AMALGAMATION /******************************************************************************* * argtable3_private: Declares private types, constants, and interfaces * * This file is part of the argtable3 library. * * Copyright (C) 2013-2019 Tom G. Huang * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #ifndef ARG_UTILS_H #define ARG_UTILS_H #include #define ARG_ENABLE_TRACE 0 #define ARG_ENABLE_LOG 1 #ifdef __cplusplus extern "C" { #endif enum { ARG_ERR_MINCOUNT = 1, ARG_ERR_MAXCOUNT, ARG_ERR_BADINT, ARG_ERR_OVERFLOW, ARG_ERR_BADDOUBLE, ARG_ERR_BADDATE, ARG_ERR_REGNOMATCH }; typedef void(arg_panicfn)(const char* fmt, ...); #if defined(_MSC_VER) #define ARG_TRACE(x) \ __pragma(warning(push)) __pragma(warning(disable : 4127)) do { \ if (ARG_ENABLE_TRACE) \ dbg_printf x; \ } \ while (0) \ __pragma(warning(pop)) #define ARG_LOG(x) \ __pragma(warning(push)) __pragma(warning(disable : 4127)) do { \ if (ARG_ENABLE_LOG) \ dbg_printf x; \ } \ while (0) \ __pragma(warning(pop)) #else #define ARG_TRACE(x) \ do { \ if (ARG_ENABLE_TRACE) \ dbg_printf x; \ } while (0) #define ARG_LOG(x) \ do { \ if (ARG_ENABLE_LOG) \ dbg_printf x; \ } while (0) #endif /* * Rename a few generic names to unique names. * They can be a problem for the platforms like NuttX, where * the namespace is flat for everything including apps and libraries. */ #define xmalloc argtable3_xmalloc #define xcalloc argtable3_xcalloc #define xrealloc argtable3_xrealloc #define xfree argtable3_xfree extern void dbg_printf(const char* fmt, ...); extern void arg_set_panic(arg_panicfn* proc); extern void* xmalloc(size_t size); extern void* xcalloc(size_t count, size_t size); extern void* xrealloc(void* ptr, size_t size); extern void xfree(void* ptr); struct arg_hashtable_entry { void *k, *v; unsigned int h; struct arg_hashtable_entry* next; }; typedef struct arg_hashtable { unsigned int tablelength; struct arg_hashtable_entry** table; unsigned int entrycount; unsigned int loadlimit; unsigned int primeindex; unsigned int (*hashfn)(const void* k); int (*eqfn)(const void* k1, const void* k2); } arg_hashtable_t; /** * @brief Create a hash table. * * @param minsize minimum initial size of hash table * @param hashfn function for hashing keys * @param eqfn function for determining key equality * @return newly created hash table or NULL on failure */ arg_hashtable_t* arg_hashtable_create(unsigned int minsize, unsigned int (*hashfn)(const void*), int (*eqfn)(const void*, const void*)); /** * @brief This function will cause the table to expand if the insertion would take * the ratio of entries to table size over the maximum load factor. * * This function does not check for repeated insertions with a duplicate key. * The value returned when using a duplicate key is undefined -- when * the hash table changes size, the order of retrieval of duplicate key * entries is reversed. * If in doubt, remove before insert. * * @param h the hash table to insert into * @param k the key - hash table claims ownership and will free on removal * @param v the value - does not claim ownership * @return non-zero for successful insertion */ void arg_hashtable_insert(arg_hashtable_t* h, void* k, void* v); #define ARG_DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \ int fnname(arg_hashtable_t* h, keytype* k, valuetype* v) { return arg_hashtable_insert(h, k, v); } /** * @brief Search the specified key in the hash table. * * @param h the hash table to search * @param k the key to search for - does not claim ownership * @return the value associated with the key, or NULL if none found */ void* arg_hashtable_search(arg_hashtable_t* h, const void* k); #define ARG_DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \ valuetype* fnname(arg_hashtable_t* h, keytype* k) { return (valuetype*)(arg_hashtable_search(h, k)); } /** * @brief Remove the specified key from the hash table. * * @param h the hash table to remove the item from * @param k the key to search for - does not claim ownership */ void arg_hashtable_remove(arg_hashtable_t* h, const void* k); #define ARG_DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \ void fnname(arg_hashtable_t* h, keytype* k) { arg_hashtable_remove(h, k); } /** * @brief Return the number of keys in the hash table. * * @param h the hash table * @return the number of items stored in the hash table */ unsigned int arg_hashtable_count(arg_hashtable_t* h); /** * @brief Change the value associated with the key. * * function to change the value associated with a key, where there already * exists a value bound to the key in the hash table. * Source due to Holger Schemel. * * @name hashtable_change * @param h the hash table * @param key * @param value */ int arg_hashtable_change(arg_hashtable_t* h, void* k, void* v); /** * @brief Free the hash table and the memory allocated for each key-value pair. * * @param h the hash table * @param free_values whether to call 'free' on the remaining values */ void arg_hashtable_destroy(arg_hashtable_t* h, int free_values); typedef struct arg_hashtable_itr { arg_hashtable_t* h; struct arg_hashtable_entry* e; struct arg_hashtable_entry* parent; unsigned int index; } arg_hashtable_itr_t; arg_hashtable_itr_t* arg_hashtable_itr_create(arg_hashtable_t* h); void arg_hashtable_itr_destroy(arg_hashtable_itr_t* itr); /** * @brief Return the value of the (key,value) pair at the current position. */ extern void* arg_hashtable_itr_key(arg_hashtable_itr_t* i); /** * @brief Return the value of the (key,value) pair at the current position. */ extern void* arg_hashtable_itr_value(arg_hashtable_itr_t* i); /** * @brief Advance the iterator to the next element. Returns zero if advanced to end of table. */ int arg_hashtable_itr_advance(arg_hashtable_itr_t* itr); /** * @brief Remove current element and advance the iterator to the next element. */ int arg_hashtable_itr_remove(arg_hashtable_itr_t* itr); /** * @brief Search and overwrite the supplied iterator, to point to the entry matching the supplied key. * * @return Zero if not found. */ int arg_hashtable_itr_search(arg_hashtable_itr_t* itr, arg_hashtable_t* h, void* k); #define ARG_DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \ int fnname(arg_hashtable_itr_t* i, arg_hashtable_t* h, keytype* k) { return (arg_hashtable_iterator_search(i, h, k)); } #ifdef __cplusplus } #endif #endif /******************************************************************************* * arg_utils: Implements memory, panic, and other utility functions * * This file is part of the argtable3 library. * * Copyright (C) 2013-2019 Tom G. Huang * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include #include #include #include static void panic(const char* fmt, ...); static arg_panicfn* s_panic = panic; void dbg_printf(const char* fmt, ...) { va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); } static void panic(const char* fmt, ...) { va_list args; char* s; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable : 4996) #endif s = getenv("EF_DUMPCORE"); #if defined(_MSC_VER) #pragma warning(pop) #endif if (s != NULL && *s != '\0') { abort(); } else { exit(EXIT_FAILURE); } } void arg_set_panic(arg_panicfn* proc) { s_panic = proc; } void* xmalloc(size_t size) { void* ret = malloc(size); if (!ret) { s_panic("Out of memory!\n"); } return ret; } void* xcalloc(size_t count, size_t size) { size_t allocated_count = count && size ? count : 1; size_t allocated_size = count && size ? size : 1; void* ret = calloc(allocated_count, allocated_size); if (!ret) { s_panic("Out of memory!\n"); } return ret; } void* xrealloc(void* ptr, size_t size) { size_t allocated_size = size ? size : 1; void* ret = realloc(ptr, allocated_size); if (!ret) { s_panic("Out of memory!\n"); } return ret; } void xfree(void* ptr) { free(ptr); } static void merge(void* data, int esize, int i, int j, int k, arg_comparefn* comparefn) { char* a = (char*)data; char* m; int ipos, jpos, mpos; /* Initialize the counters used in merging. */ ipos = i; jpos = j + 1; mpos = 0; /* Allocate storage for the merged elements. */ m = (char*)xmalloc(esize * ((k - i) + 1)); /* Continue while either division has elements to merge. */ while (ipos <= j || jpos <= k) { if (ipos > j) { /* The left division has no more elements to merge. */ while (jpos <= k) { memcpy(&m[mpos * esize], &a[jpos * esize], esize); jpos++; mpos++; } continue; } else if (jpos > k) { /* The right division has no more elements to merge. */ while (ipos <= j) { memcpy(&m[mpos * esize], &a[ipos * esize], esize); ipos++; mpos++; } continue; } /* Append the next ordered element to the merged elements. */ if (comparefn(&a[ipos * esize], &a[jpos * esize]) < 0) { memcpy(&m[mpos * esize], &a[ipos * esize], esize); ipos++; mpos++; } else { memcpy(&m[mpos * esize], &a[jpos * esize], esize); jpos++; mpos++; } } /* Prepare to pass back the merged data. */ memcpy(&a[i * esize], m, esize * ((k - i) + 1)); xfree(m); } void arg_mgsort(void* data, int size, int esize, int i, int k, arg_comparefn* comparefn) { int j; /* Stop the recursion when no more divisions can be made. */ if (i < k) { /* Determine where to divide the elements. */ j = (int)(((i + k - 1)) / 2); /* Recursively sort the two divisions. */ arg_mgsort(data, size, esize, i, j, comparefn); arg_mgsort(data, size, esize, j + 1, k, comparefn); merge(data, esize, i, j, k, comparefn); } } /******************************************************************************* * arg_hashtable: Implements the hash table utilities * * This file is part of the argtable3 library. * * Copyright (C) 2013-2019 Tom G. Huang * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include #include #include #include /* * This hash table module is adapted from the C hash table implementation by * Christopher Clark. Here is the copyright notice from the library: * * Copyright (c) 2002, Christopher Clark * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Credit for primes table: Aaron Krowne * http://br.endernet.org/~akrowne/ * http://planetmath.org/encyclopedia/GoodHashTablePrimes.html */ static const unsigned int primes[] = {53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; const unsigned int prime_table_length = sizeof(primes) / sizeof(primes[0]); const float max_load_factor = (float)0.65; static unsigned int enhanced_hash(arg_hashtable_t* h, const void* k) { /* * Aim to protect against poor hash functions by adding logic here. * The logic is taken from Java 1.4 hash table source. */ unsigned int i = h->hashfn(k); i += ~(i << 9); i ^= ((i >> 14) | (i << 18)); /* >>> */ i += (i << 4); i ^= ((i >> 10) | (i << 22)); /* >>> */ return i; } static unsigned int index_for(unsigned int tablelength, unsigned int hashvalue) { return (hashvalue % tablelength); } arg_hashtable_t* arg_hashtable_create(unsigned int minsize, unsigned int (*hashfn)(const void*), int (*eqfn)(const void*, const void*)) { arg_hashtable_t* h; unsigned int pindex; unsigned int size = primes[0]; /* Check requested hash table isn't too large */ if (minsize > (1u << 30)) return NULL; /* * Enforce size as prime. The reason is to avoid clustering of values * into a small number of buckets (yes, distribution). A more even * distributed hash table will perform more consistently. */ for (pindex = 0; pindex < prime_table_length; pindex++) { if (primes[pindex] > minsize) { size = primes[pindex]; break; } } h = (arg_hashtable_t*)xmalloc(sizeof(arg_hashtable_t)); h->table = (struct arg_hashtable_entry**)xmalloc(sizeof(struct arg_hashtable_entry*) * size); memset(h->table, 0, size * sizeof(struct arg_hashtable_entry*)); h->tablelength = size; h->primeindex = pindex; h->entrycount = 0; h->hashfn = hashfn; h->eqfn = eqfn; h->loadlimit = (unsigned int)ceil(size * max_load_factor); return h; } static int arg_hashtable_expand(arg_hashtable_t* h) { /* Double the size of the table to accommodate more entries */ struct arg_hashtable_entry** newtable; struct arg_hashtable_entry* e; unsigned int newsize; unsigned int i; unsigned int index; /* Check we're not hitting max capacity */ if (h->primeindex == (prime_table_length - 1)) return 0; newsize = primes[++(h->primeindex)]; newtable = (struct arg_hashtable_entry**)xmalloc(sizeof(struct arg_hashtable_entry*) * newsize); memset(newtable, 0, newsize * sizeof(struct arg_hashtable_entry*)); /* * This algorithm is not 'stable': it reverses the list * when it transfers entries between the tables */ for (i = 0; i < h->tablelength; i++) { while (NULL != (e = h->table[i])) { h->table[i] = e->next; index = index_for(newsize, e->h); e->next = newtable[index]; newtable[index] = e; } } xfree(h->table); h->table = newtable; h->tablelength = newsize; h->loadlimit = (unsigned int)ceil(newsize * max_load_factor); return -1; } unsigned int arg_hashtable_count(arg_hashtable_t* h) { return h->entrycount; } void arg_hashtable_insert(arg_hashtable_t* h, void* k, void* v) { /* This method allows duplicate keys - but they shouldn't be used */ unsigned int index; struct arg_hashtable_entry* e; if ((h->entrycount + 1) > h->loadlimit) { /* * Ignore the return value. If expand fails, we should * still try cramming just this value into the existing table * -- we may not have memory for a larger table, but one more * element may be ok. Next time we insert, we'll try expanding again. */ arg_hashtable_expand(h); } e = (struct arg_hashtable_entry*)xmalloc(sizeof(struct arg_hashtable_entry)); e->h = enhanced_hash(h, k); index = index_for(h->tablelength, e->h); e->k = k; e->v = v; e->next = h->table[index]; h->table[index] = e; h->entrycount++; } void* arg_hashtable_search(arg_hashtable_t* h, const void* k) { struct arg_hashtable_entry* e; unsigned int hashvalue; unsigned int index; hashvalue = enhanced_hash(h, k); index = index_for(h->tablelength, hashvalue); e = h->table[index]; while (e != NULL) { /* Check hash value to short circuit heavier comparison */ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v; e = e->next; } return NULL; } void arg_hashtable_remove(arg_hashtable_t* h, const void* k) { /* * TODO: consider compacting the table when the load factor drops enough, * or provide a 'compact' method. */ struct arg_hashtable_entry* e; struct arg_hashtable_entry** pE; unsigned int hashvalue; unsigned int index; hashvalue = enhanced_hash(h, k); index = index_for(h->tablelength, hashvalue); pE = &(h->table[index]); e = *pE; while (NULL != e) { /* Check hash value to short circuit heavier comparison */ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { *pE = e->next; h->entrycount--; xfree(e->k); xfree(e->v); xfree(e); return; } pE = &(e->next); e = e->next; } } void arg_hashtable_destroy(arg_hashtable_t* h, int free_values) { unsigned int i; struct arg_hashtable_entry *e, *f; struct arg_hashtable_entry** table = h->table; if (free_values) { for (i = 0; i < h->tablelength; i++) { e = table[i]; while (NULL != e) { f = e; e = e->next; xfree(f->k); xfree(f->v); xfree(f); } } } else { for (i = 0; i < h->tablelength; i++) { e = table[i]; while (NULL != e) { f = e; e = e->next; xfree(f->k); xfree(f); } } } xfree(h->table); xfree(h); } arg_hashtable_itr_t* arg_hashtable_itr_create(arg_hashtable_t* h) { unsigned int i; unsigned int tablelength; arg_hashtable_itr_t* itr = (arg_hashtable_itr_t*)xmalloc(sizeof(arg_hashtable_itr_t)); itr->h = h; itr->e = NULL; itr->parent = NULL; tablelength = h->tablelength; itr->index = tablelength; if (0 == h->entrycount) return itr; for (i = 0; i < tablelength; i++) { if (h->table[i] != NULL) { itr->e = h->table[i]; itr->index = i; break; } } return itr; } void arg_hashtable_itr_destroy(arg_hashtable_itr_t* itr) { xfree(itr); } void* arg_hashtable_itr_key(arg_hashtable_itr_t* i) { return i->e->k; } void* arg_hashtable_itr_value(arg_hashtable_itr_t* i) { return i->e->v; } int arg_hashtable_itr_advance(arg_hashtable_itr_t* itr) { unsigned int j; unsigned int tablelength; struct arg_hashtable_entry** table; struct arg_hashtable_entry* next; if (itr->e == NULL) return 0; /* stupidity check */ next = itr->e->next; if (NULL != next) { itr->parent = itr->e; itr->e = next; return -1; } tablelength = itr->h->tablelength; itr->parent = NULL; if (tablelength <= (j = ++(itr->index))) { itr->e = NULL; return 0; } table = itr->h->table; while (NULL == (next = table[j])) { if (++j >= tablelength) { itr->index = tablelength; itr->e = NULL; return 0; } } itr->index = j; itr->e = next; return -1; } int arg_hashtable_itr_remove(arg_hashtable_itr_t* itr) { struct arg_hashtable_entry* remember_e; struct arg_hashtable_entry* remember_parent; int ret; /* Do the removal */ if ((itr->parent) == NULL) { /* element is head of a chain */ itr->h->table[itr->index] = itr->e->next; } else { /* element is mid-chain */ itr->parent->next = itr->e->next; } /* itr->e is now outside the hashtable */ remember_e = itr->e; itr->h->entrycount--; xfree(remember_e->k); xfree(remember_e->v); /* Advance the iterator, correcting the parent */ remember_parent = itr->parent; ret = arg_hashtable_itr_advance(itr); if (itr->parent == remember_e) { itr->parent = remember_parent; } xfree(remember_e); return ret; } int arg_hashtable_itr_search(arg_hashtable_itr_t* itr, arg_hashtable_t* h, void* k) { struct arg_hashtable_entry* e; struct arg_hashtable_entry* parent; unsigned int hashvalue; unsigned int index; hashvalue = enhanced_hash(h, k); index = index_for(h->tablelength, hashvalue); e = h->table[index]; parent = NULL; while (e != NULL) { /* Check hash value to short circuit heavier comparison */ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { itr->index = index; itr->e = e; itr->parent = parent; itr->h = h; return -1; } parent = e; e = e->next; } return 0; } int arg_hashtable_change(arg_hashtable_t* h, void* k, void* v) { struct arg_hashtable_entry* e; unsigned int hashvalue; unsigned int index; hashvalue = enhanced_hash(h, k); index = index_for(h->tablelength, hashvalue); e = h->table[index]; while (e != NULL) { /* Check hash value to short circuit heavier comparison */ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { xfree(e->v); e->v = v; return -1; } e = e->next; } return 0; } /******************************************************************************* * arg_dstr: Implements the dynamic string utilities * * This file is part of the argtable3 library. * * Copyright (C) 2013-2019 Tom G. Huang * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include #include #include #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable : 4996) #endif #define START_VSNBUFF 16 /* * This dynamic string module is adapted from TclResult.c in the Tcl library. * Here is the copyright notice from the library: * * This software is copyrighted by the Regents of the University of * California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState * Corporation and other parties. The following terms apply to all files * associated with the software unless explicitly disclaimed in * individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. * * GOVERNMENT USE: If you are acquiring this software on behalf of the * U.S. government, the Government shall have only "Restricted Rights" * in the software and related documentation as defined in the Federal * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you * are acquiring the software on behalf of the Department of Defense, the * software shall be classified as "Commercial Computer Software" and the * Government shall have only "Restricted Rights" as defined in Clause * 252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the * authors grant the U.S. Government and others acting in its behalf * permission to use and distribute the software in accordance with the * terms specified in this license. */ typedef struct _internal_arg_dstr { char* data; arg_dstr_freefn* free_proc; char sbuf[ARG_DSTR_SIZE + 1]; char* append_data; int append_data_size; int append_used; } _internal_arg_dstr_t; static void setup_append_buf(arg_dstr_t res, int newSpace); arg_dstr_t arg_dstr_create(void) { _internal_arg_dstr_t* h = (_internal_arg_dstr_t*)xmalloc(sizeof(_internal_arg_dstr_t)); memset(h, 0, sizeof(_internal_arg_dstr_t)); h->sbuf[0] = 0; h->data = h->sbuf; h->free_proc = ARG_DSTR_STATIC; return h; } void arg_dstr_destroy(arg_dstr_t ds) { if (ds == NULL) return; arg_dstr_reset(ds); xfree(ds); return; } void arg_dstr_set(arg_dstr_t ds, char* str, arg_dstr_freefn* free_proc) { int length; register arg_dstr_freefn* old_free_proc = ds->free_proc; char* old_result = ds->data; if (str == NULL) { ds->sbuf[0] = 0; ds->data = ds->sbuf; ds->free_proc = ARG_DSTR_STATIC; } else if (free_proc == ARG_DSTR_VOLATILE) { length = (int)strlen(str); if (length > ARG_DSTR_SIZE) { ds->data = (char*)xmalloc((unsigned)length + 1); ds->free_proc = ARG_DSTR_DYNAMIC; } else { ds->data = ds->sbuf; ds->free_proc = ARG_DSTR_STATIC; } strcpy(ds->data, str); } else { ds->data = str; ds->free_proc = free_proc; } /* * If the old result was dynamically-allocated, free it up. Do it here, * rather than at the beginning, in case the new result value was part of * the old result value. */ if ((old_free_proc != 0) && (old_result != ds->data)) { if (old_free_proc == ARG_DSTR_DYNAMIC) { xfree(old_result); } else { (*old_free_proc)(old_result); } } if ((ds->append_data != NULL) && (ds->append_data_size > 0)) { xfree(ds->append_data); ds->append_data = NULL; ds->append_data_size = 0; } } char* arg_dstr_cstr(arg_dstr_t ds) /* Interpreter whose result to return. */ { return ds->data; } void arg_dstr_cat(arg_dstr_t ds, const char* str) { setup_append_buf(ds, (int)strlen(str) + 1); memcpy(ds->data + strlen(ds->data), str, strlen(str)); } void arg_dstr_catc(arg_dstr_t ds, char c) { setup_append_buf(ds, 2); memcpy(ds->data + strlen(ds->data), &c, 1); } /* * The logic of the `arg_dstr_catf` function is adapted from the `bformat` * function in The Better String Library by Paul Hsieh. Here is the copyright * notice from the library: * * Copyright (c) 2014, Paul Hsieh * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * * Neither the name of bstrlib nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ void arg_dstr_catf(arg_dstr_t ds, const char* fmt, ...) { va_list arglist; char* buff; int n, r; size_t slen; if (fmt == NULL) return; /* Since the length is not determinable beforehand, a search is performed using the truncating "vsnprintf" call (to avoid buffer overflows) on increasing potential sizes for the output result. */ if ((n = (int)(2 * strlen(fmt))) < START_VSNBUFF) n = START_VSNBUFF; buff = (char*)xmalloc(n + 2); memset(buff, 0, n + 2); for (;;) { va_start(arglist, fmt); r = vsnprintf(buff, n + 1, fmt, arglist); va_end(arglist); slen = strlen(buff); if (slen < (size_t)n) break; if (r > n) n = r; else n += n; xfree(buff); buff = (char*)xmalloc(n + 2); memset(buff, 0, n + 2); } arg_dstr_cat(ds, buff); xfree(buff); } static void setup_append_buf(arg_dstr_t ds, int new_space) { int total_space; /* * Make the append buffer larger, if that's necessary, then copy the * data into the append buffer and make the append buffer the official * data. */ if (ds->data != ds->append_data) { /* * If the buffer is too big, then free it up so we go back to a * smaller buffer. This avoids tying up memory forever after a large * operation. */ if (ds->append_data_size > 500) { xfree(ds->append_data); ds->append_data = NULL; ds->append_data_size = 0; } ds->append_used = (int)strlen(ds->data); } else if (ds->data[ds->append_used] != 0) { /* * Most likely someone has modified a result created by * arg_dstr_cat et al. so that it has a different size. Just * recompute the size. */ ds->append_used = (int)strlen(ds->data); } total_space = new_space + ds->append_used; if (total_space >= ds->append_data_size) { char* newbuf; if (total_space < 100) { total_space = 200; } else { total_space *= 2; } newbuf = (char*)xmalloc((unsigned)total_space); memset(newbuf, 0, total_space); strcpy(newbuf, ds->data); if (ds->append_data != NULL) { xfree(ds->append_data); } ds->append_data = newbuf; ds->append_data_size = total_space; } else if (ds->data != ds->append_data) { strcpy(ds->append_data, ds->data); } arg_dstr_free(ds); ds->data = ds->append_data; } void arg_dstr_free(arg_dstr_t ds) { if (ds->free_proc != NULL) { if (ds->free_proc == ARG_DSTR_DYNAMIC) { xfree(ds->data); } else { (*ds->free_proc)(ds->data); } ds->free_proc = NULL; } } void arg_dstr_reset(arg_dstr_t ds) { arg_dstr_free(ds); if ((ds->append_data != NULL) && (ds->append_data_size > 0)) { xfree(ds->append_data); ds->append_data = NULL; ds->append_data_size = 0; } ds->data = ds->sbuf; ds->sbuf[0] = 0; } #if defined(_MSC_VER) #pragma warning(pop) #endif /* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ /* $FreeBSD$ */ /*- * SPDX-License-Identifier: BSD-2-Clause-NetBSD * * Copyright (c) 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Dieter Baron and Thomas Klausner. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #if ARG_REPLACE_GETOPT == 1 #ifndef _GETOPT_H_ #define _GETOPT_H_ /* * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension. * getopt() is declared here too for GNU programs. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 struct option { /* name of long option */ const char *name; /* * one of no_argument, required_argument, and optional_argument: * whether option takes an argument */ int has_arg; /* if not NULL, set *flag to val when option found */ int *flag; /* if flag not NULL, value to set *flag to; else return value */ int val; }; #ifdef __cplusplus extern "C" { #endif int getopt_long(int, char * const *, const char *, const struct option *, int *); int getopt_long_only(int, char * const *, const char *, const struct option *, int *); #ifndef _GETOPT_DECLARED #define _GETOPT_DECLARED int getopt(int, char * const [], const char *); extern char *optarg; /* getopt(3) external variables */ extern int optind, opterr, optopt; #endif #ifndef _OPTRESET_DECLARED #define _OPTRESET_DECLARED extern int optreset; /* getopt(3) external variable */ #endif #ifdef __cplusplus } #endif #endif /* !_GETOPT_H_ */ #endif /* ARG_REPLACE_GETOPT == 1 */ /* $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $ */ /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ /* * Copyright (c) 2002 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Sponsored in part by the Defense Advanced Research Projects * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Dieter Baron and Thomas Klausner. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "argtable3.h" #if ARG_REPLACE_GETOPT == 1 #ifndef ARG_AMALGAMATION #include "arg_getopt.h" #endif #include #include #include #define GNU_COMPATIBLE /* Be more compatible, configure's use us! */ int opterr = 1; /* if error message should be printed */ int optind = 1; /* index into parent argv vector */ int optopt = '?'; /* character checked for validity */ int optreset; /* reset getopt */ char *optarg; /* argument associated with option */ #define PRINT_ERROR ((opterr) && (*options != ':')) #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ /* return values */ #define BADCH (int)'?' #define BADARG ((*options == ':') ? (int)':' : (int)'?') #define INORDER (int)1 #define EMSG "" #ifdef GNU_COMPATIBLE #define NO_PREFIX (-1) #define D_PREFIX 0 #define DD_PREFIX 1 #define W_PREFIX 2 #endif static int getopt_internal(int, char * const *, const char *, const struct option *, int *, int); static int parse_long_options(char * const *, const char *, const struct option *, int *, int, int); static int gcd(int, int); static void permute_args(int, int, int, char * const *); static char *place = EMSG; /* option letter processing */ /* XXX: set optreset to 1 rather than these two */ static int nonopt_start = -1; /* first non option argument (for permute) */ static int nonopt_end = -1; /* first option after non options (for permute) */ /* Error messages */ static const char recargchar[] = "option requires an argument -- %c"; static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */ #ifdef GNU_COMPATIBLE static int dash_prefix = NO_PREFIX; static const char gnuoptchar[] = "invalid option -- %c"; static const char recargstring[] = "option `%s%s' requires an argument"; static const char ambig[] = "option `%s%.*s' is ambiguous"; static const char noarg[] = "option `%s%.*s' doesn't allow an argument"; static const char illoptstring[] = "unrecognized option `%s%s'"; #else static const char recargstring[] = "option requires an argument -- %s"; static const char ambig[] = "ambiguous option -- %.*s"; static const char noarg[] = "option doesn't take an argument -- %.*s"; static const char illoptstring[] = "unknown option -- %s"; #endif #ifdef _WIN32 /* * Windows needs warnx(). We change the definition though: * 1. (another) global is defined, opterrmsg, which holds the error message * 2. errors are always printed out on stderr w/o the program name * Note that opterrmsg always gets set no matter what opterr is set to. The * error message will not be printed if opterr is 0 as usual. */ #include #include #define MAX_OPTERRMSG_SIZE 128 extern char opterrmsg[MAX_OPTERRMSG_SIZE]; char opterrmsg[MAX_OPTERRMSG_SIZE]; /* buffer for the last error message */ static void warnx(const char* fmt, ...) { va_list ap; va_start(ap, fmt); /* * Make sure opterrmsg is always zero-terminated despite the _vsnprintf() * implementation specifics and manually suppress the warning. */ memset(opterrmsg, 0, sizeof(opterrmsg)); if (fmt != NULL) #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) _vsnprintf_s(opterrmsg, sizeof(opterrmsg), sizeof(opterrmsg) - 1, fmt, ap); #else _vsnprintf(opterrmsg, sizeof(opterrmsg) - 1, fmt, ap); #endif va_end(ap); #ifdef _MSC_VER #pragma warning(suppress : 6053) #endif fprintf(stderr, "%s\n", opterrmsg); } #else #include #endif /*_WIN32*/ /* * Compute the greatest common divisor of a and b. */ static int gcd(int a, int b) { int c; c = a % b; while (c != 0) { a = b; b = c; c = a % b; } return (b); } /* * Exchange the block from nonopt_start to nonopt_end with the block * from nonopt_end to opt_end (keeping the same order of arguments * in each block). */ static void permute_args(int panonopt_start, int panonopt_end, int opt_end, char * const *nargv) { int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; char *swap; /* * compute lengths of blocks and number and size of cycles */ nnonopts = panonopt_end - panonopt_start; nopts = opt_end - panonopt_end; ncycle = gcd(nnonopts, nopts); cyclelen = (opt_end - panonopt_start) / ncycle; for (i = 0; i < ncycle; i++) { cstart = panonopt_end+i; pos = cstart; for (j = 0; j < cyclelen; j++) { if (pos >= panonopt_end) pos -= nnonopts; else pos += nopts; swap = nargv[pos]; /* LINTED const cast */ ((char **) nargv)[pos] = nargv[cstart]; /* LINTED const cast */ ((char **)nargv)[cstart] = swap; } } } /* * parse_long_options -- * Parse long options in argc/argv argument vector. * Returns -1 if short_too is set and the option does not match long_options. */ static int parse_long_options(char * const *nargv, const char *options, const struct option *long_options, int *idx, int short_too, int flags) { char *current_argv, *has_equal; #ifdef GNU_COMPATIBLE char *current_dash; #endif size_t current_argv_len; int i, match, exact_match, second_partial_match; current_argv = place; #ifdef GNU_COMPATIBLE switch (dash_prefix) { case D_PREFIX: current_dash = "-"; break; case DD_PREFIX: current_dash = "--"; break; case W_PREFIX: current_dash = "-W "; break; default: current_dash = ""; break; } #endif match = -1; exact_match = 0; second_partial_match = 0; optind++; if ((has_equal = strchr(current_argv, '=')) != NULL) { /* argument found (--option=arg) */ current_argv_len = has_equal - current_argv; has_equal++; } else current_argv_len = strlen(current_argv); for (i = 0; long_options[i].name; i++) { /* find matching long option */ if (strncmp(current_argv, long_options[i].name, current_argv_len)) continue; if (strlen(long_options[i].name) == current_argv_len) { /* exact match */ match = i; exact_match = 1; break; } /* * If this is a known short option, don't allow * a partial match of a single character. */ if (short_too && current_argv_len == 1) continue; if (match == -1) /* first partial match */ match = i; else if ((flags & FLAG_LONGONLY) || long_options[i].has_arg != long_options[match].has_arg || long_options[i].flag != long_options[match].flag || long_options[i].val != long_options[match].val) second_partial_match = 1; } if (!exact_match && second_partial_match) { /* ambiguous abbreviation */ if (PRINT_ERROR) warnx(ambig, #ifdef GNU_COMPATIBLE current_dash, #endif (int)current_argv_len, current_argv); optopt = 0; return (BADCH); } if (match != -1) { /* option found */ if (long_options[match].has_arg == no_argument && has_equal) { if (PRINT_ERROR) warnx(noarg, #ifdef GNU_COMPATIBLE current_dash, #endif (int)current_argv_len, current_argv); /* * XXX: GNU sets optopt to val regardless of flag */ if (long_options[match].flag == NULL) optopt = long_options[match].val; else optopt = 0; #ifdef GNU_COMPATIBLE return (BADCH); #else return (BADARG); #endif } if (long_options[match].has_arg == required_argument || long_options[match].has_arg == optional_argument) { if (has_equal) optarg = has_equal; else if (long_options[match].has_arg == required_argument) { /* * optional argument doesn't use next nargv */ optarg = nargv[optind++]; } } if ((long_options[match].has_arg == required_argument) && (optarg == NULL)) { /* * Missing argument; leading ':' indicates no error * should be generated. */ if (PRINT_ERROR) warnx(recargstring, #ifdef GNU_COMPATIBLE current_dash, #endif current_argv); /* * XXX: GNU sets optopt to val regardless of flag */ if (long_options[match].flag == NULL) optopt = long_options[match].val; else optopt = 0; --optind; return (BADARG); } } else { /* unknown option */ if (short_too) { --optind; return (-1); } if (PRINT_ERROR) warnx(illoptstring, #ifdef GNU_COMPATIBLE current_dash, #endif current_argv); optopt = 0; return (BADCH); } if (idx) *idx = match; if (long_options[match].flag) { *long_options[match].flag = long_options[match].val; return (0); } else return (long_options[match].val); } /* * getopt_internal -- * Parse argc/argv argument vector. Called by user level routines. */ static int getopt_internal(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx, int flags) { char *oli; /* option letter list index */ int optchar, short_too; static int posixly_correct = -1; if (options == NULL) return (-1); /* * XXX Some GNU programs (like cvs) set optind to 0 instead of * XXX using optreset. Work around this braindamage. */ if (optind == 0) optind = optreset = 1; /* * Disable GNU extensions if POSIXLY_CORRECT is set or options * string begins with a '+'. */ if (posixly_correct == -1 || optreset) { #if defined(_WIN32) && ((defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))) size_t requiredSize; getenv_s(&requiredSize, NULL, 0, "POSIXLY_CORRECT"); posixly_correct = requiredSize != 0; #else posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); #endif } if (*options == '-') flags |= FLAG_ALLARGS; else if (posixly_correct || *options == '+') flags &= ~FLAG_PERMUTE; if (*options == '+' || *options == '-') options++; optarg = NULL; if (optreset) nonopt_start = nonopt_end = -1; start: if (optreset || !*place) { /* update scanning pointer */ optreset = 0; if (optind >= nargc) { /* end of argument vector */ place = EMSG; if (nonopt_end != -1) { /* do permutation, if we have to */ permute_args(nonopt_start, nonopt_end, optind, nargv); optind -= nonopt_end - nonopt_start; } else if (nonopt_start != -1) { /* * If we skipped non-options, set optind * to the first of them. */ optind = nonopt_start; } nonopt_start = nonopt_end = -1; return (-1); } if (*(place = nargv[optind]) != '-' || #ifdef GNU_COMPATIBLE place[1] == '\0') { #else (place[1] == '\0' && strchr(options, '-') == NULL)) { #endif place = EMSG; /* found non-option */ if (flags & FLAG_ALLARGS) { /* * GNU extension: * return non-option as argument to option 1 */ optarg = nargv[optind++]; return (INORDER); } if (!(flags & FLAG_PERMUTE)) { /* * If no permutation wanted, stop parsing * at first non-option. */ return (-1); } /* do permutation */ if (nonopt_start == -1) nonopt_start = optind; else if (nonopt_end != -1) { permute_args(nonopt_start, nonopt_end, optind, nargv); nonopt_start = optind - (nonopt_end - nonopt_start); nonopt_end = -1; } optind++; /* process next argument */ goto start; } if (nonopt_start != -1 && nonopt_end == -1) nonopt_end = optind; /* * If we have "-" do nothing, if "--" we are done. */ if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { optind++; place = EMSG; /* * We found an option (--), so if we skipped * non-options, we have to permute. */ if (nonopt_end != -1) { permute_args(nonopt_start, nonopt_end, optind, nargv); optind -= nonopt_end - nonopt_start; } nonopt_start = nonopt_end = -1; return (-1); } } /* * Check long options if: * 1) we were passed some * 2) the arg is not just "-" * 3) either the arg starts with -- we are getopt_long_only() */ if (long_options != NULL && place != nargv[optind] && (*place == '-' || (flags & FLAG_LONGONLY))) { short_too = 0; #ifdef GNU_COMPATIBLE dash_prefix = D_PREFIX; #endif if (*place == '-') { place++; /* --foo long option */ if (*place == '\0') return (BADARG); /* malformed option */ #ifdef GNU_COMPATIBLE dash_prefix = DD_PREFIX; #endif } else if (*place != ':' && strchr(options, *place) != NULL) short_too = 1; /* could be short option too */ optchar = parse_long_options(nargv, options, long_options, idx, short_too, flags); if (optchar != -1) { place = EMSG; return (optchar); } } if ((optchar = (int)*place++) == (int)':' || (optchar == (int)'-' && *place != '\0') || (oli = strchr(options, optchar)) == NULL) { /* * If the user specified "-" and '-' isn't listed in * options, return -1 (non-option) as per POSIX. * Otherwise, it is an unknown option character (or ':'). */ if (optchar == (int)'-' && *place == '\0') return (-1); if (!*place) ++optind; #ifdef GNU_COMPATIBLE if (PRINT_ERROR) warnx(posixly_correct ? illoptchar : gnuoptchar, optchar); #else if (PRINT_ERROR) warnx(illoptchar, optchar); #endif optopt = optchar; return (BADCH); } if (long_options != NULL && optchar == 'W' && oli[1] == ';') { /* -W long-option */ if (*place) /* no space */ /* NOTHING */; else if (++optind >= nargc) { /* no arg */ place = EMSG; if (PRINT_ERROR) warnx(recargchar, optchar); optopt = optchar; return (BADARG); } else /* white space */ place = nargv[optind]; #ifdef GNU_COMPATIBLE dash_prefix = W_PREFIX; #endif optchar = parse_long_options(nargv, options, long_options, idx, 0, flags); place = EMSG; return (optchar); } if (*++oli != ':') { /* doesn't take argument */ if (!*place) ++optind; } else { /* takes (optional) argument */ optarg = NULL; if (*place) /* no white space */ optarg = place; else if (oli[1] != ':') { /* arg not optional */ if (++optind >= nargc) { /* no arg */ place = EMSG; if (PRINT_ERROR) warnx(recargchar, optchar); optopt = optchar; return (BADARG); } else optarg = nargv[optind]; } place = EMSG; ++optind; } /* dump back option letter */ return (optchar); } /* * getopt -- * Parse argc/argv argument vector. * * [eventually this will replace the BSD getopt] */ int getopt(int nargc, char * const *nargv, const char *options) { /* * We don't pass FLAG_PERMUTE to getopt_internal() since * the BSD getopt(3) (unlike GNU) has never done this. * * Furthermore, since many privileged programs call getopt() * before dropping privileges it makes sense to keep things * as simple (and bug-free) as possible. */ return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); } /* * getopt_long -- * Parse argc/argv argument vector. */ int getopt_long(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx) { return (getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE)); } /* * getopt_long_only -- * Parse argc/argv argument vector. */ int getopt_long_only(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx) { return (getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE|FLAG_LONGONLY)); } #endif /* ARG_REPLACE_GETOPT == 1 */ /******************************************************************************* * arg_date: Implements the date command-line option * * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include #include char* arg_strptime(const char* buf, const char* fmt, struct tm* tm); static void arg_date_resetfn(struct arg_date* parent) { ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); parent->count = 0; } static int arg_date_scanfn(struct arg_date* parent, const char* argval) { int errorcode = 0; if (parent->count == parent->hdr.maxcount) { errorcode = ARG_ERR_MAXCOUNT; } else if (!argval) { /* no argument value was given, leave parent->tmval[] unaltered but still count it */ parent->count++; } else { const char* pend; struct tm tm = parent->tmval[parent->count]; /* parse the given argument value, store result in parent->tmval[] */ pend = arg_strptime(argval, parent->format, &tm); if (pend && pend[0] == '\0') parent->tmval[parent->count++] = tm; else errorcode = ARG_ERR_BADDATE; } ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } static int arg_date_checkfn(struct arg_date* parent) { int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } static void arg_date_errorfn(struct arg_date* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { const char* shortopts = parent->hdr.shortopts; const char* longopts = parent->hdr.longopts; const char* datatype = parent->hdr.datatype; /* make argval NULL safe */ argval = argval ? argval : ""; arg_dstr_catf(ds, "%s: ", progname); switch (errorcode) { case ARG_ERR_MINCOUNT: arg_dstr_cat(ds, "missing option "); arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); break; case ARG_ERR_MAXCOUNT: arg_dstr_cat(ds, "excess option "); arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); break; case ARG_ERR_BADDATE: { struct tm tm; char buff[200]; arg_dstr_catf(ds, "illegal timestamp format \"%s\"\n", argval); memset(&tm, 0, sizeof(tm)); arg_strptime("1999-12-31 23:59:59", "%F %H:%M:%S", &tm); strftime(buff, sizeof(buff), parent->format, &tm); arg_dstr_catf(ds, "correct format is \"%s\"\n", buff); break; } } } struct arg_date* arg_date0(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary) { return arg_daten(shortopts, longopts, format, datatype, 0, 1, glossary); } struct arg_date* arg_date1(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary) { return arg_daten(shortopts, longopts, format, datatype, 1, 1, glossary); } struct arg_date* arg_daten(const char* shortopts, const char* longopts, const char* format, const char* datatype, int mincount, int maxcount, const char* glossary) { size_t nbytes; struct arg_date* result; /* foolproof things by ensuring maxcount is not less than mincount */ maxcount = (maxcount < mincount) ? mincount : maxcount; /* default time format is the national date format for the locale */ if (!format) format = "%x"; nbytes = sizeof(struct arg_date) /* storage for struct arg_date */ + maxcount * sizeof(struct tm); /* storage for tmval[maxcount] array */ /* allocate storage for the arg_date struct + tmval[] array. */ /* we use calloc because we want the tmval[] array zero filled. */ result = (struct arg_date*)xcalloc(1, nbytes); /* init the arg_hdr struct */ result->hdr.flag = ARG_HASVALUE; result->hdr.shortopts = shortopts; result->hdr.longopts = longopts; result->hdr.datatype = datatype ? datatype : format; result->hdr.glossary = glossary; result->hdr.mincount = mincount; result->hdr.maxcount = maxcount; result->hdr.parent = result; result->hdr.resetfn = (arg_resetfn*)arg_date_resetfn; result->hdr.scanfn = (arg_scanfn*)arg_date_scanfn; result->hdr.checkfn = (arg_checkfn*)arg_date_checkfn; result->hdr.errorfn = (arg_errorfn*)arg_date_errorfn; /* store the tmval[maxcount] array immediately after the arg_date struct */ result->tmval = (struct tm*)(result + 1); /* init the remaining arg_date member variables */ result->count = 0; result->format = format; ARG_TRACE(("arg_daten() returns %p\n", result)); return result; } /*- * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc. * All rights reserved. * * This code was contributed to The NetBSD Foundation by Klaus Klein. * Heavily optimised by David Laight * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include /* * We do not implement alternate representations. However, we always * check whether a given modifier is allowed for a certain conversion. */ #define ALT_E 0x01 #define ALT_O 0x02 #define LEGAL_ALT(x) \ { \ if (alt_format & ~(x)) \ return (0); \ } #define TM_YEAR_BASE (1900) static int conv_num(const char**, int*, int, int); static const char* day[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; static const char* abday[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static const char* mon[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; static const char* abmon[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; static const char* am_pm[2] = {"AM", "PM"}; static int arg_strcasecmp(const char* s1, const char* s2) { const unsigned char* us1 = (const unsigned char*)s1; const unsigned char* us2 = (const unsigned char*)s2; while (tolower(*us1) == tolower(*us2++)) if (*us1++ == '\0') return 0; return tolower(*us1) - tolower(*--us2); } static int arg_strncasecmp(const char* s1, const char* s2, size_t n) { if (n != 0) { const unsigned char* us1 = (const unsigned char*)s1; const unsigned char* us2 = (const unsigned char*)s2; do { if (tolower(*us1) != tolower(*us2++)) return tolower(*us1) - tolower(*--us2); if (*us1++ == '\0') break; } while (--n != 0); } return 0; } char* arg_strptime(const char* buf, const char* fmt, struct tm* tm) { char c; const char* bp; size_t len = 0; int alt_format, i, split_year = 0; bp = buf; while ((c = *fmt) != '\0') { /* Clear `alternate' modifier prior to new conversion. */ alt_format = 0; /* Eat up white-space. */ if (isspace(c)) { while (isspace((int)(*bp))) bp++; fmt++; continue; } if ((c = *fmt++) != '%') goto literal; again: switch (c = *fmt++) { case '%': /* "%%" is converted to "%". */ literal: if (c != *bp++) return (0); break; /* * "Alternative" modifiers. Just set the appropriate flag * and start over again. */ case 'E': /* "%E?" alternative conversion modifier. */ LEGAL_ALT(0); alt_format |= ALT_E; goto again; case 'O': /* "%O?" alternative conversion modifier. */ LEGAL_ALT(0); alt_format |= ALT_O; goto again; /* * "Complex" conversion rules, implemented through recursion. */ case 'c': /* Date and time, using the locale's format. */ LEGAL_ALT(ALT_E); bp = arg_strptime(bp, "%x %X", tm); if (!bp) return (0); break; case 'D': /* The date as "%m/%d/%y". */ LEGAL_ALT(0); bp = arg_strptime(bp, "%m/%d/%y", tm); if (!bp) return (0); break; case 'R': /* The time as "%H:%M". */ LEGAL_ALT(0); bp = arg_strptime(bp, "%H:%M", tm); if (!bp) return (0); break; case 'r': /* The time in 12-hour clock representation. */ LEGAL_ALT(0); bp = arg_strptime(bp, "%I:%M:%S %p", tm); if (!bp) return (0); break; case 'T': /* The time as "%H:%M:%S". */ LEGAL_ALT(0); bp = arg_strptime(bp, "%H:%M:%S", tm); if (!bp) return (0); break; case 'X': /* The time, using the locale's format. */ LEGAL_ALT(ALT_E); bp = arg_strptime(bp, "%H:%M:%S", tm); if (!bp) return (0); break; case 'x': /* The date, using the locale's format. */ LEGAL_ALT(ALT_E); bp = arg_strptime(bp, "%m/%d/%y", tm); if (!bp) return (0); break; /* * "Elementary" conversion rules. */ case 'A': /* The day of week, using the locale's form. */ case 'a': LEGAL_ALT(0); for (i = 0; i < 7; i++) { /* Full name. */ len = strlen(day[i]); if (arg_strncasecmp(day[i], bp, len) == 0) break; /* Abbreviated name. */ len = strlen(abday[i]); if (arg_strncasecmp(abday[i], bp, len) == 0) break; } /* Nothing matched. */ if (i == 7) return (0); tm->tm_wday = i; bp += len; break; case 'B': /* The month, using the locale's form. */ case 'b': case 'h': LEGAL_ALT(0); for (i = 0; i < 12; i++) { /* Full name. */ len = strlen(mon[i]); if (arg_strncasecmp(mon[i], bp, len) == 0) break; /* Abbreviated name. */ len = strlen(abmon[i]); if (arg_strncasecmp(abmon[i], bp, len) == 0) break; } /* Nothing matched. */ if (i == 12) return (0); tm->tm_mon = i; bp += len; break; case 'C': /* The century number. */ LEGAL_ALT(ALT_E); if (!(conv_num(&bp, &i, 0, 99))) return (0); if (split_year) { tm->tm_year = (tm->tm_year % 100) + (i * 100); } else { tm->tm_year = i * 100; split_year = 1; } break; case 'd': /* The day of month. */ case 'e': LEGAL_ALT(ALT_O); if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) return (0); break; case 'k': /* The hour (24-hour clock representation). */ LEGAL_ALT(0); /* FALLTHROUGH */ case 'H': LEGAL_ALT(ALT_O); if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) return (0); break; case 'l': /* The hour (12-hour clock representation). */ LEGAL_ALT(0); /* FALLTHROUGH */ case 'I': LEGAL_ALT(ALT_O); if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) return (0); if (tm->tm_hour == 12) tm->tm_hour = 0; break; case 'j': /* The day of year. */ LEGAL_ALT(0); if (!(conv_num(&bp, &i, 1, 366))) return (0); tm->tm_yday = i - 1; break; case 'M': /* The minute. */ LEGAL_ALT(ALT_O); if (!(conv_num(&bp, &tm->tm_min, 0, 59))) return (0); break; case 'm': /* The month. */ LEGAL_ALT(ALT_O); if (!(conv_num(&bp, &i, 1, 12))) return (0); tm->tm_mon = i - 1; break; case 'p': /* The locale's equivalent of AM/PM. */ LEGAL_ALT(0); /* AM? */ if (arg_strcasecmp(am_pm[0], bp) == 0) { if (tm->tm_hour > 11) return (0); bp += strlen(am_pm[0]); break; } /* PM? */ else if (arg_strcasecmp(am_pm[1], bp) == 0) { if (tm->tm_hour > 11) return (0); tm->tm_hour += 12; bp += strlen(am_pm[1]); break; } /* Nothing matched. */ return (0); case 'S': /* The seconds. */ LEGAL_ALT(ALT_O); if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) return (0); break; case 'U': /* The week of year, beginning on sunday. */ case 'W': /* The week of year, beginning on monday. */ LEGAL_ALT(ALT_O); /* * XXX This is bogus, as we can not assume any valid * information present in the tm structure at this * point to calculate a real value, so just check the * range for now. */ if (!(conv_num(&bp, &i, 0, 53))) return (0); break; case 'w': /* The day of week, beginning on sunday. */ LEGAL_ALT(ALT_O); if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) return (0); break; case 'Y': /* The year. */ LEGAL_ALT(ALT_E); if (!(conv_num(&bp, &i, 0, 9999))) return (0); tm->tm_year = i - TM_YEAR_BASE; break; case 'y': /* The year within 100 years of the epoch. */ LEGAL_ALT(ALT_E | ALT_O); if (!(conv_num(&bp, &i, 0, 99))) return (0); if (split_year) { tm->tm_year = ((tm->tm_year / 100) * 100) + i; break; } split_year = 1; if (i <= 68) tm->tm_year = i + 2000 - TM_YEAR_BASE; else tm->tm_year = i + 1900 - TM_YEAR_BASE; break; /* * Miscellaneous conversions. */ case 'n': /* Any kind of white-space. */ case 't': LEGAL_ALT(0); while (isspace((int)(*bp))) bp++; break; default: /* Unknown/unsupported conversion. */ return (0); } } /* LINTED functional specification */ return ((char*)bp); } static int conv_num(const char** buf, int* dest, int llim, int ulim) { int result = 0; /* The limit also determines the number of valid digits. */ int rulim = ulim; if (**buf < '0' || **buf > '9') return (0); do { result *= 10; result += *(*buf)++ - '0'; rulim /= 10; } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); if (result < llim || result > ulim) return (0); *dest = result; return (1); } /******************************************************************************* * arg_dbl: Implements the double command-line option * * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include static void arg_dbl_resetfn(struct arg_dbl* parent) { ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); parent->count = 0; } static int arg_dbl_scanfn(struct arg_dbl* parent, const char* argval) { int errorcode = 0; if (parent->count == parent->hdr.maxcount) { /* maximum number of arguments exceeded */ errorcode = ARG_ERR_MAXCOUNT; } else if (!argval) { /* a valid argument with no argument value was given. */ /* This happens when an optional argument value was invoked. */ /* leave parent argument value unaltered but still count the argument. */ parent->count++; } else { double val; char* end; /* extract double from argval into val */ val = strtod(argval, &end); /* if success then store result in parent->dval[] array otherwise return error*/ if (*end == 0) parent->dval[parent->count++] = val; else errorcode = ARG_ERR_BADDOUBLE; } ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } static int arg_dbl_checkfn(struct arg_dbl* parent) { int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } static void arg_dbl_errorfn(struct arg_dbl* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { const char* shortopts = parent->hdr.shortopts; const char* longopts = parent->hdr.longopts; const char* datatype = parent->hdr.datatype; /* make argval NULL safe */ argval = argval ? argval : ""; arg_dstr_catf(ds, "%s: ", progname); switch (errorcode) { case ARG_ERR_MINCOUNT: arg_dstr_cat(ds, "missing option "); arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); break; case ARG_ERR_MAXCOUNT: arg_dstr_cat(ds, "excess option "); arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); break; case ARG_ERR_BADDOUBLE: arg_dstr_catf(ds, "invalid argument \"%s\" to option ", argval); arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); break; } } struct arg_dbl* arg_dbl0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { return arg_dbln(shortopts, longopts, datatype, 0, 1, glossary); } struct arg_dbl* arg_dbl1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { return arg_dbln(shortopts, longopts, datatype, 1, 1, glossary); } struct arg_dbl* arg_dbln(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) { size_t nbytes; struct arg_dbl* result; size_t addr; size_t rem; /* foolproof things by ensuring maxcount is not less than mincount */ maxcount = (maxcount < mincount) ? mincount : maxcount; nbytes = sizeof(struct arg_dbl) /* storage for struct arg_dbl */ + (maxcount + 1) * sizeof(double); /* storage for dval[maxcount] array plus one extra for padding to memory boundary */ result = (struct arg_dbl*)xmalloc(nbytes); /* init the arg_hdr struct */ result->hdr.flag = ARG_HASVALUE; result->hdr.shortopts = shortopts; result->hdr.longopts = longopts; result->hdr.datatype = datatype ? datatype : ""; result->hdr.glossary = glossary; result->hdr.mincount = mincount; result->hdr.maxcount = maxcount; result->hdr.parent = result; result->hdr.resetfn = (arg_resetfn*)arg_dbl_resetfn; result->hdr.scanfn = (arg_scanfn*)arg_dbl_scanfn; result->hdr.checkfn = (arg_checkfn*)arg_dbl_checkfn; result->hdr.errorfn = (arg_errorfn*)arg_dbl_errorfn; /* Store the dval[maxcount] array on the first double boundary that * immediately follows the arg_dbl struct. We do the memory alignment * purely for SPARC and Motorola systems. They require floats and * doubles to be aligned on natural boundaries. */ addr = (size_t)(result + 1); rem = addr % sizeof(double); result->dval = (double*)(addr + sizeof(double) - rem); ARG_TRACE(("addr=%p, dval=%p, sizeof(double)=%d rem=%d\n", addr, result->dval, (int)sizeof(double), (int)rem)); result->count = 0; ARG_TRACE(("arg_dbln() returns %p\n", result)); return result; } /******************************************************************************* * arg_end: Implements the error handling utilities * * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include static void arg_end_resetfn(struct arg_end* parent) { ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); parent->count = 0; } static void arg_end_errorfn(void* parent, arg_dstr_t ds, int error, const char* argval, const char* progname) { /* suppress unreferenced formal parameter warning */ (void)parent; progname = progname ? progname : ""; argval = argval ? argval : ""; arg_dstr_catf(ds, "%s: ", progname); switch (error) { case ARG_ELIMIT: arg_dstr_cat(ds, "too many errors to display"); break; case ARG_EMALLOC: arg_dstr_cat(ds, "insufficient memory"); break; case ARG_ENOMATCH: arg_dstr_catf(ds, "unexpected argument \"%s\"", argval); break; case ARG_EMISSARG: arg_dstr_catf(ds, "option \"%s\" requires an argument", argval); break; case ARG_ELONGOPT: arg_dstr_catf(ds, "invalid option \"%s\"", argval); break; default: arg_dstr_catf(ds, "invalid option \"-%c\"", error); break; } arg_dstr_cat(ds, "\n"); } struct arg_end* arg_end(int maxcount) { size_t nbytes; struct arg_end* result; nbytes = sizeof(struct arg_end) + maxcount * sizeof(int) /* storage for int error[maxcount] array*/ + maxcount * sizeof(void*) /* storage for void* parent[maxcount] array */ + maxcount * sizeof(char*); /* storage for char* argval[maxcount] array */ result = (struct arg_end*)xmalloc(nbytes); /* init the arg_hdr struct */ result->hdr.flag = ARG_TERMINATOR; result->hdr.shortopts = NULL; result->hdr.longopts = NULL; result->hdr.datatype = NULL; result->hdr.glossary = NULL; result->hdr.mincount = 1; result->hdr.maxcount = maxcount; result->hdr.parent = result; result->hdr.resetfn = (arg_resetfn*)arg_end_resetfn; result->hdr.scanfn = NULL; result->hdr.checkfn = NULL; result->hdr.errorfn = (arg_errorfn*)arg_end_errorfn; /* store error[maxcount] array immediately after struct arg_end */ result->error = (int*)(result + 1); /* store parent[maxcount] array immediately after error[] array */ result->parent = (void**)(result->error + maxcount); /* store argval[maxcount] array immediately after parent[] array */ result->argval = (const char**)(result->parent + maxcount); ARG_TRACE(("arg_end(%d) returns %p\n", maxcount, result)); return result; } void arg_print_errors_ds(arg_dstr_t ds, struct arg_end* end, const char* progname) { int i; ARG_TRACE(("arg_errors()\n")); for (i = 0; i < end->count; i++) { struct arg_hdr* errorparent = (struct arg_hdr*)(end->parent[i]); if (errorparent->errorfn) errorparent->errorfn(end->parent[i], ds, end->error[i], end->argval[i], progname); } } void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname) { arg_dstr_t ds = arg_dstr_create(); arg_print_errors_ds(ds, end, progname); fputs(arg_dstr_cstr(ds), fp); arg_dstr_destroy(ds); } /******************************************************************************* * arg_file: Implements the file command-line option * * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include #include #ifdef WIN32 #define FILESEPARATOR1 '\\' #define FILESEPARATOR2 '/' #else #define FILESEPARATOR1 '/' #define FILESEPARATOR2 '/' #endif static void arg_file_resetfn(struct arg_file* parent) { ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); parent->count = 0; } /* Returns ptr to the base filename within *filename */ static const char* arg_basename(const char* filename) { const char *result = NULL, *result1, *result2; /* Find the last occurrence of other file separator character. */ /* Two alternative file separator chars are supported as legal */ /* file separators but not both together in the same filename. */ result1 = (filename ? strrchr(filename, FILESEPARATOR1) : NULL); result2 = (filename ? strrchr(filename, FILESEPARATOR2) : NULL); if (result2) result = result2 + 1; /* using FILESEPARATOR2 (the alternative file separator) */ if (result1) result = result1 + 1; /* using FILESEPARATOR1 (the preferred file separator) */ if (!result) result = filename; /* neither file separator was found so basename is the whole filename */ /* special cases of "." and ".." are not considered basenames */ if (result && (strcmp(".", result) == 0 || strcmp("..", result) == 0)) result = filename + strlen(filename); return result; } /* Returns ptr to the file extension within *basename */ static const char* arg_extension(const char* basename) { /* find the last occurrence of '.' in basename */ const char* result = (basename ? strrchr(basename, '.') : NULL); /* if no '.' was found then return pointer to end of basename */ if (basename && !result) result = basename + strlen(basename); /* special case: basenames with a single leading dot (eg ".foo") are not considered as true extensions */ if (basename && result == basename) result = basename + strlen(basename); /* special case: empty extensions (eg "foo.","foo..") are not considered as true extensions */ if (basename && result && strlen(result) == 1) result = basename + strlen(basename); return result; } static int arg_file_scanfn(struct arg_file* parent, const char* argval) { int errorcode = 0; if (parent->count == parent->hdr.maxcount) { /* maximum number of arguments exceeded */ errorcode = ARG_ERR_MAXCOUNT; } else if (!argval) { /* a valid argument with no argument value was given. */ /* This happens when an optional argument value was invoked. */ /* leave parent argument value unaltered but still count the argument. */ parent->count++; } else { parent->filename[parent->count] = argval; parent->basename[parent->count] = arg_basename(argval); parent->extension[parent->count] = arg_extension(parent->basename[parent->count]); /* only seek extensions within the basename (not the file path)*/ parent->count++; } ARG_TRACE(("%s4:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } static int arg_file_checkfn(struct arg_file* parent) { int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } static void arg_file_errorfn(struct arg_file* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { const char* shortopts = parent->hdr.shortopts; const char* longopts = parent->hdr.longopts; const char* datatype = parent->hdr.datatype; /* make argval NULL safe */ argval = argval ? argval : ""; arg_dstr_catf(ds, "%s: ", progname); switch (errorcode) { case ARG_ERR_MINCOUNT: arg_dstr_cat(ds, "missing option "); arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); break; case ARG_ERR_MAXCOUNT: arg_dstr_cat(ds, "excess option "); arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); break; default: arg_dstr_catf(ds, "unknown error at \"%s\"\n", argval); } } struct arg_file* arg_file0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { return arg_filen(shortopts, longopts, datatype, 0, 1, glossary); } struct arg_file* arg_file1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { return arg_filen(shortopts, longopts, datatype, 1, 1, glossary); } struct arg_file* arg_filen(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) { size_t nbytes; struct arg_file* result; int i; /* foolproof things by ensuring maxcount is not less than mincount */ maxcount = (maxcount < mincount) ? mincount : maxcount; nbytes = sizeof(struct arg_file) /* storage for struct arg_file */ + sizeof(char*) * maxcount /* storage for filename[maxcount] array */ + sizeof(char*) * maxcount /* storage for basename[maxcount] array */ + sizeof(char*) * maxcount; /* storage for extension[maxcount] array */ result = (struct arg_file*)xmalloc(nbytes); /* init the arg_hdr struct */ result->hdr.flag = ARG_HASVALUE; result->hdr.shortopts = shortopts; result->hdr.longopts = longopts; result->hdr.glossary = glossary; result->hdr.datatype = datatype ? datatype : ""; result->hdr.mincount = mincount; result->hdr.maxcount = maxcount; result->hdr.parent = result; result->hdr.resetfn = (arg_resetfn*)arg_file_resetfn; result->hdr.scanfn = (arg_scanfn*)arg_file_scanfn; result->hdr.checkfn = (arg_checkfn*)arg_file_checkfn; result->hdr.errorfn = (arg_errorfn*)arg_file_errorfn; /* store the filename,basename,extension arrays immediately after the arg_file struct */ result->filename = (const char**)(result + 1); result->basename = result->filename + maxcount; result->extension = result->basename + maxcount; result->count = 0; /* foolproof the string pointers by initialising them with empty strings */ for (i = 0; i < maxcount; i++) { result->filename[i] = ""; result->basename[i] = ""; result->extension[i] = ""; } ARG_TRACE(("arg_filen() returns %p\n", result)); return result; } /******************************************************************************* * arg_int: Implements the int command-line option * * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include #include #include static void arg_int_resetfn(struct arg_int* parent) { ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); parent->count = 0; } /* strtol0x() is like strtol() except that the numeric string is */ /* expected to be prefixed by "0X" where X is a user supplied char. */ /* The string may optionally be prefixed by white space and + or - */ /* as in +0X123 or -0X123. */ /* Once the prefix has been scanned, the remainder of the numeric */ /* string is converted using strtol() with the given base. */ /* eg: to parse hex str="-0X12324", specify X='X' and base=16. */ /* eg: to parse oct str="+0o12324", specify X='O' and base=8. */ /* eg: to parse bin str="-0B01010", specify X='B' and base=2. */ /* Failure of conversion is indicated by result where *endptr==str. */ static long int strtol0X(const char* str, const char** endptr, char X, int base) { long int val; /* stores result */ int s = 1; /* sign is +1 or -1 */ const char* ptr = str; /* ptr to current position in str */ /* skip leading whitespace */ while (isspace((int)(*ptr))) ptr++; /* printf("1) %s\n",ptr); */ /* scan optional sign character */ switch (*ptr) { case '+': ptr++; s = 1; break; case '-': ptr++; s = -1; break; default: s = 1; break; } /* printf("2) %s\n",ptr); */ /* '0X' prefix */ if ((*ptr++) != '0') { /* printf("failed to detect '0'\n"); */ *endptr = str; return 0; } /* printf("3) %s\n",ptr); */ if (toupper(*ptr++) != toupper(X)) { /* printf("failed to detect '%c'\n",X); */ *endptr = str; return 0; } /* printf("4) %s\n",ptr); */ /* attempt conversion on remainder of string using strtol() */ val = strtol(ptr, (char**)endptr, base); if (*endptr == ptr) { /* conversion failed */ *endptr = str; return 0; } /* success */ return s * val; } /* Returns 1 if str matches suffix (case insensitive). */ /* Str may contain trailing whitespace, but nothing else. */ static int detectsuffix(const char* str, const char* suffix) { /* scan pairwise through strings until mismatch detected */ while (toupper(*str) == toupper(*suffix)) { /* printf("'%c' '%c'\n", *str, *suffix); */ /* return 1 (success) if match persists until the string terminator */ if (*str == '\0') return 1; /* next chars */ str++; suffix++; } /* printf("'%c' '%c' mismatch\n", *str, *suffix); */ /* return 0 (fail) if the matching did not consume the entire suffix */ if (*suffix != 0) return 0; /* failed to consume entire suffix */ /* skip any remaining whitespace in str */ while (isspace((int)(*str))) str++; /* return 1 (success) if we have reached end of str else return 0 (fail) */ return (*str == '\0') ? 1 : 0; } static int arg_int_scanfn(struct arg_int* parent, const char* argval) { int errorcode = 0; if (parent->count == parent->hdr.maxcount) { /* maximum number of arguments exceeded */ errorcode = ARG_ERR_MAXCOUNT; } else if (!argval) { /* a valid argument with no argument value was given. */ /* This happens when an optional argument value was invoked. */ /* leave parent argument value unaltered but still count the argument. */ parent->count++; } else { long int val; const char* end; /* attempt to extract hex integer (eg: +0x123) from argval into val conversion */ val = strtol0X(argval, &end, 'X', 16); if (end == argval) { /* hex failed, attempt octal conversion (eg +0o123) */ val = strtol0X(argval, &end, 'O', 8); if (end == argval) { /* octal failed, attempt binary conversion (eg +0B101) */ val = strtol0X(argval, &end, 'B', 2); if (end == argval) { /* binary failed, attempt decimal conversion with no prefix (eg 1234) */ val = strtol(argval, (char**)&end, 10); if (end == argval) { /* all supported number formats failed */ return ARG_ERR_BADINT; } } } } /* Safety check for integer overflow. WARNING: this check */ /* achieves nothing on machines where size(int)==size(long). */ if (val > INT_MAX || val < INT_MIN) errorcode = ARG_ERR_OVERFLOW; /* Detect any suffixes (KB,MB,GB) and multiply argument value appropriately. */ /* We need to be mindful of integer overflows when using such big numbers. */ if (detectsuffix(end, "KB")) /* kilobytes */ { if (val > (INT_MAX / 1024) || val < (INT_MIN / 1024)) errorcode = ARG_ERR_OVERFLOW; /* Overflow would occur if we proceed */ else val *= 1024; /* 1KB = 1024 */ } else if (detectsuffix(end, "MB")) /* megabytes */ { if (val > (INT_MAX / 1048576) || val < (INT_MIN / 1048576)) errorcode = ARG_ERR_OVERFLOW; /* Overflow would occur if we proceed */ else val *= 1048576; /* 1MB = 1024*1024 */ } else if (detectsuffix(end, "GB")) /* gigabytes */ { if (val > (INT_MAX / 1073741824) || val < (INT_MIN / 1073741824)) errorcode = ARG_ERR_OVERFLOW; /* Overflow would occur if we proceed */ else val *= 1073741824; /* 1GB = 1024*1024*1024 */ } else if (!detectsuffix(end, "")) errorcode = ARG_ERR_BADINT; /* invalid suffix detected */ /* if success then store result in parent->ival[] array */ if (errorcode == 0) parent->ival[parent->count++] = (int)val; } /* printf("%s:scanfn(%p,%p) returns %d\n",__FILE__,parent,argval,errorcode); */ return errorcode; } static int arg_int_checkfn(struct arg_int* parent) { int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; /*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/ return errorcode; } static void arg_int_errorfn(struct arg_int* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { const char* shortopts = parent->hdr.shortopts; const char* longopts = parent->hdr.longopts; const char* datatype = parent->hdr.datatype; /* make argval NULL safe */ argval = argval ? argval : ""; arg_dstr_catf(ds, "%s: ", progname); switch (errorcode) { case ARG_ERR_MINCOUNT: arg_dstr_cat(ds, "missing option "); arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); break; case ARG_ERR_MAXCOUNT: arg_dstr_cat(ds, "excess option "); arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); break; case ARG_ERR_BADINT: arg_dstr_catf(ds, "invalid argument \"%s\" to option ", argval); arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); break; case ARG_ERR_OVERFLOW: arg_dstr_cat(ds, "integer overflow at option "); arg_print_option_ds(ds, shortopts, longopts, datatype, " "); arg_dstr_catf(ds, "(%s is too large)\n", argval); break; } } struct arg_int* arg_int0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { return arg_intn(shortopts, longopts, datatype, 0, 1, glossary); } struct arg_int* arg_int1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { return arg_intn(shortopts, longopts, datatype, 1, 1, glossary); } struct arg_int* arg_intn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) { size_t nbytes; struct arg_int* result; /* foolproof things by ensuring maxcount is not less than mincount */ maxcount = (maxcount < mincount) ? mincount : maxcount; nbytes = sizeof(struct arg_int) /* storage for struct arg_int */ + maxcount * sizeof(int); /* storage for ival[maxcount] array */ result = (struct arg_int*)xmalloc(nbytes); /* init the arg_hdr struct */ result->hdr.flag = ARG_HASVALUE; result->hdr.shortopts = shortopts; result->hdr.longopts = longopts; result->hdr.datatype = datatype ? datatype : ""; result->hdr.glossary = glossary; result->hdr.mincount = mincount; result->hdr.maxcount = maxcount; result->hdr.parent = result; result->hdr.resetfn = (arg_resetfn*)arg_int_resetfn; result->hdr.scanfn = (arg_scanfn*)arg_int_scanfn; result->hdr.checkfn = (arg_checkfn*)arg_int_checkfn; result->hdr.errorfn = (arg_errorfn*)arg_int_errorfn; /* store the ival[maxcount] array immediately after the arg_int struct */ result->ival = (int*)(result + 1); result->count = 0; ARG_TRACE(("arg_intn() returns %p\n", result)); return result; } /******************************************************************************* * arg_lit: Implements the literature command-line option * * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include static void arg_lit_resetfn(struct arg_lit* parent) { ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); parent->count = 0; } static int arg_lit_scanfn(struct arg_lit* parent, const char* argval) { int errorcode = 0; if (parent->count < parent->hdr.maxcount) parent->count++; else errorcode = ARG_ERR_MAXCOUNT; ARG_TRACE(("%s:scanfn(%p,%s) returns %d\n", __FILE__, parent, argval, errorcode)); return errorcode; } static int arg_lit_checkfn(struct arg_lit* parent) { int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } static void arg_lit_errorfn(struct arg_lit* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { const char* shortopts = parent->hdr.shortopts; const char* longopts = parent->hdr.longopts; const char* datatype = parent->hdr.datatype; switch (errorcode) { case ARG_ERR_MINCOUNT: arg_dstr_catf(ds, "%s: missing option ", progname); arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); arg_dstr_cat(ds, "\n"); break; case ARG_ERR_MAXCOUNT: arg_dstr_catf(ds, "%s: extraneous option ", progname); arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); break; } ARG_TRACE(("%s:errorfn(%p, %p, %d, %s, %s)\n", __FILE__, parent, ds, errorcode, argval, progname)); } struct arg_lit* arg_lit0(const char* shortopts, const char* longopts, const char* glossary) { return arg_litn(shortopts, longopts, 0, 1, glossary); } struct arg_lit* arg_lit1(const char* shortopts, const char* longopts, const char* glossary) { return arg_litn(shortopts, longopts, 1, 1, glossary); } struct arg_lit* arg_litn(const char* shortopts, const char* longopts, int mincount, int maxcount, const char* glossary) { struct arg_lit* result; /* foolproof things by ensuring maxcount is not less than mincount */ maxcount = (maxcount < mincount) ? mincount : maxcount; result = (struct arg_lit*)xmalloc(sizeof(struct arg_lit)); /* init the arg_hdr struct */ result->hdr.flag = 0; result->hdr.shortopts = shortopts; result->hdr.longopts = longopts; result->hdr.datatype = NULL; result->hdr.glossary = glossary; result->hdr.mincount = mincount; result->hdr.maxcount = maxcount; result->hdr.parent = result; result->hdr.resetfn = (arg_resetfn*)arg_lit_resetfn; result->hdr.scanfn = (arg_scanfn*)arg_lit_scanfn; result->hdr.checkfn = (arg_checkfn*)arg_lit_checkfn; result->hdr.errorfn = (arg_errorfn*)arg_lit_errorfn; /* init local variables */ result->count = 0; ARG_TRACE(("arg_litn() returns %p\n", result)); return result; } /******************************************************************************* * arg_rem: Implements the rem command-line option * * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include struct arg_rem* arg_rem(const char* datatype, const char* glossary) { struct arg_rem* result = (struct arg_rem*)xmalloc(sizeof(struct arg_rem)); result->hdr.flag = 0; result->hdr.shortopts = NULL; result->hdr.longopts = NULL; result->hdr.datatype = datatype; result->hdr.glossary = glossary; result->hdr.mincount = 1; result->hdr.maxcount = 1; result->hdr.parent = result; result->hdr.resetfn = NULL; result->hdr.scanfn = NULL; result->hdr.checkfn = NULL; result->hdr.errorfn = NULL; ARG_TRACE(("arg_rem() returns %p\n", result)); return result; } /******************************************************************************* * arg_rex: Implements the regex command-line option * * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include #include #ifndef _TREX_H_ #define _TREX_H_ /* * This module uses the T-Rex regular expression library to implement the regex * logic. Here is the copyright notice of the library: * * Copyright (C) 2003-2006 Alberto Demichelis * * This software is provided 'as-is', without any express * or implied warranty. In no event will the authors be held * liable for any damages arising from the use of this software. * * Permission is granted to anyone to use this software for * any purpose, including commercial applications, and to alter * it and redistribute it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; * you must not claim that you wrote the original software. * If you use this software in a product, an acknowledgment * in the product documentation would be appreciated but * is not required. * * 2. Altered source versions must be plainly marked as such, * and must not be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any * source distribution. */ #ifdef __cplusplus extern "C" { #endif #define TRexChar char #define MAX_CHAR 0xFF #define _TREXC(c) (c) #define trex_strlen strlen #define trex_printf printf #ifndef TREX_API #define TREX_API extern #endif #define TRex_True 1 #define TRex_False 0 #define TREX_ICASE ARG_REX_ICASE typedef unsigned int TRexBool; typedef struct TRex TRex; typedef struct { const TRexChar* begin; int len; } TRexMatch; #ifdef __GNUC__ TREX_API TRex* trex_compile(const TRexChar* pattern, const TRexChar** error, int flags) __attribute__((optimize(0))); #else TREX_API TRex* trex_compile(const TRexChar* pattern, const TRexChar** error, int flags); #endif TREX_API void trex_free(TRex* exp); TREX_API TRexBool trex_match(TRex* exp, const TRexChar* text); TREX_API TRexBool trex_search(TRex* exp, const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end); TREX_API TRexBool trex_searchrange(TRex* exp, const TRexChar* text_begin, const TRexChar* text_end, const TRexChar** out_begin, const TRexChar** out_end); TREX_API int trex_getsubexpcount(TRex* exp); TREX_API TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch* subexp); #ifdef __cplusplus } #endif #endif struct privhdr { const char* pattern; int flags; }; static void arg_rex_resetfn(struct arg_rex* parent) { ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); parent->count = 0; } static int arg_rex_scanfn(struct arg_rex* parent, const char* argval) { int errorcode = 0; const TRexChar* error = NULL; TRex* rex = NULL; TRexBool is_match = TRex_False; if (parent->count == parent->hdr.maxcount) { /* maximum number of arguments exceeded */ errorcode = ARG_ERR_MAXCOUNT; } else if (!argval) { /* a valid argument with no argument value was given. */ /* This happens when an optional argument value was invoked. */ /* leave parent argument value unaltered but still count the argument. */ parent->count++; } else { struct privhdr* priv = (struct privhdr*)parent->hdr.priv; /* test the current argument value for a match with the regular expression */ /* if a match is detected, record the argument value in the arg_rex struct */ rex = trex_compile(priv->pattern, &error, priv->flags); is_match = trex_match(rex, argval); if (!is_match) errorcode = ARG_ERR_REGNOMATCH; else parent->sval[parent->count++] = argval; trex_free(rex); } ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } static int arg_rex_checkfn(struct arg_rex* parent) { int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; #if 0 struct privhdr *priv = (struct privhdr*)parent->hdr.priv; /* free the regex "program" we constructed in resetfn */ regfree(&(priv->regex)); /*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/ #endif return errorcode; } static void arg_rex_errorfn(struct arg_rex* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { const char* shortopts = parent->hdr.shortopts; const char* longopts = parent->hdr.longopts; const char* datatype = parent->hdr.datatype; /* make argval NULL safe */ argval = argval ? argval : ""; arg_dstr_catf(ds, "%s: ", progname); switch (errorcode) { case ARG_ERR_MINCOUNT: arg_dstr_cat(ds, "missing option "); arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); break; case ARG_ERR_MAXCOUNT: arg_dstr_cat(ds, "excess option "); arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); break; case ARG_ERR_REGNOMATCH: arg_dstr_cat(ds, "illegal value "); arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); break; default: { #if 0 char errbuff[256]; regerror(errorcode, NULL, errbuff, sizeof(errbuff)); printf("%s\n", errbuff); #endif } break; } } struct arg_rex* arg_rex0(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int flags, const char* glossary) { return arg_rexn(shortopts, longopts, pattern, datatype, 0, 1, flags, glossary); } struct arg_rex* arg_rex1(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int flags, const char* glossary) { return arg_rexn(shortopts, longopts, pattern, datatype, 1, 1, flags, glossary); } struct arg_rex* arg_rexn(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int mincount, int maxcount, int flags, const char* glossary) { size_t nbytes; struct arg_rex* result; struct privhdr* priv; int i; const TRexChar* error = NULL; TRex* rex = NULL; if (!pattern) { printf("argtable: ERROR - illegal regular expression pattern \"(NULL)\"\n"); printf("argtable: Bad argument table.\n"); return NULL; } /* foolproof things by ensuring maxcount is not less than mincount */ maxcount = (maxcount < mincount) ? mincount : maxcount; nbytes = sizeof(struct arg_rex) /* storage for struct arg_rex */ + sizeof(struct privhdr) /* storage for private arg_rex data */ + maxcount * sizeof(char*); /* storage for sval[maxcount] array */ /* init the arg_hdr struct */ result = (struct arg_rex*)xmalloc(nbytes); result->hdr.flag = ARG_HASVALUE; result->hdr.shortopts = shortopts; result->hdr.longopts = longopts; result->hdr.datatype = datatype ? datatype : pattern; result->hdr.glossary = glossary; result->hdr.mincount = mincount; result->hdr.maxcount = maxcount; result->hdr.parent = result; result->hdr.resetfn = (arg_resetfn*)arg_rex_resetfn; result->hdr.scanfn = (arg_scanfn*)arg_rex_scanfn; result->hdr.checkfn = (arg_checkfn*)arg_rex_checkfn; result->hdr.errorfn = (arg_errorfn*)arg_rex_errorfn; /* store the arg_rex_priv struct immediately after the arg_rex struct */ result->hdr.priv = result + 1; priv = (struct privhdr*)(result->hdr.priv); priv->pattern = pattern; priv->flags = flags; /* store the sval[maxcount] array immediately after the arg_rex_priv struct */ result->sval = (const char**)(priv + 1); result->count = 0; /* foolproof the string pointers by initializing them to reference empty strings */ for (i = 0; i < maxcount; i++) result->sval[i] = ""; /* here we construct and destroy a regex representation of the regular * expression for no other reason than to force any regex errors to be * trapped now rather than later. If we don't, then errors may go undetected * until an argument is actually parsed. */ rex = trex_compile(priv->pattern, &error, priv->flags); if (rex == NULL) { ARG_LOG(("argtable: %s \"%s\"\n", error ? error : _TREXC("undefined"), priv->pattern)); ARG_LOG(("argtable: Bad argument table.\n")); } trex_free(rex); ARG_TRACE(("arg_rexn() returns %p\n", result)); return result; } /* see copyright notice in trex.h */ #include #include #include #include #ifdef _UINCODE #define scisprint iswprint #define scstrlen wcslen #define scprintf wprintf #define _SC(x) L(x) #else #define scisprint isprint #define scstrlen strlen #define scprintf printf #define _SC(x) (x) #endif #ifdef ARG_REX_DEBUG #include static const TRexChar* g_nnames[] = {_SC("NONE"), _SC("OP_GREEDY"), _SC("OP_OR"), _SC("OP_EXPR"), _SC("OP_NOCAPEXPR"), _SC("OP_DOT"), _SC("OP_CLASS"), _SC("OP_CCLASS"), _SC("OP_NCLASS"), _SC("OP_RANGE"), _SC("OP_CHAR"), _SC("OP_EOL"), _SC("OP_BOL"), _SC("OP_WB")}; #endif #define OP_GREEDY (MAX_CHAR + 1) /* * + ? {n} */ #define OP_OR (MAX_CHAR + 2) #define OP_EXPR (MAX_CHAR + 3) /* parenthesis () */ #define OP_NOCAPEXPR (MAX_CHAR + 4) /* parenthesis (?:) */ #define OP_DOT (MAX_CHAR + 5) #define OP_CLASS (MAX_CHAR + 6) #define OP_CCLASS (MAX_CHAR + 7) #define OP_NCLASS (MAX_CHAR + 8) /* negates class the [^ */ #define OP_RANGE (MAX_CHAR + 9) #define OP_CHAR (MAX_CHAR + 10) #define OP_EOL (MAX_CHAR + 11) #define OP_BOL (MAX_CHAR + 12) #define OP_WB (MAX_CHAR + 13) #define TREX_SYMBOL_ANY_CHAR ('.') #define TREX_SYMBOL_GREEDY_ONE_OR_MORE ('+') #define TREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*') #define TREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?') #define TREX_SYMBOL_BRANCH ('|') #define TREX_SYMBOL_END_OF_STRING ('$') #define TREX_SYMBOL_BEGINNING_OF_STRING ('^') #define TREX_SYMBOL_ESCAPE_CHAR ('\\') typedef int TRexNodeType; typedef struct tagTRexNode { TRexNodeType type; int left; int right; int next; } TRexNode; struct TRex { const TRexChar* _eol; const TRexChar* _bol; const TRexChar* _p; int _first; int _op; TRexNode* _nodes; int _nallocated; int _nsize; int _nsubexpr; TRexMatch* _matches; int _currsubexp; void* _jmpbuf; const TRexChar** _error; int _flags; }; static int trex_list(TRex* exp); static int trex_newnode(TRex* exp, TRexNodeType type) { TRexNode n; int newid; n.type = type; n.next = n.right = n.left = -1; if (type == OP_EXPR) n.right = exp->_nsubexpr++; if (exp->_nallocated < (exp->_nsize + 1)) { exp->_nallocated *= 2; exp->_nodes = (TRexNode*)xrealloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode)); } exp->_nodes[exp->_nsize++] = n; newid = exp->_nsize - 1; return (int)newid; } static void trex_error(TRex* exp, const TRexChar* error) { if (exp->_error) *exp->_error = error; longjmp(*((jmp_buf*)exp->_jmpbuf), -1); } static void trex_expect(TRex* exp, int n) { if ((*exp->_p) != n) trex_error(exp, _SC("expected paren")); exp->_p++; } static TRexChar trex_escapechar(TRex* exp) { if (*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) { exp->_p++; switch (*exp->_p) { case 'v': exp->_p++; return '\v'; case 'n': exp->_p++; return '\n'; case 't': exp->_p++; return '\t'; case 'r': exp->_p++; return '\r'; case 'f': exp->_p++; return '\f'; default: return (*exp->_p++); } } else if (!scisprint((int)(*exp->_p))) trex_error(exp, _SC("letter expected")); return (*exp->_p++); } static int trex_charclass(TRex* exp, int classid) { int n = trex_newnode(exp, OP_CCLASS); exp->_nodes[n].left = classid; return n; } static int trex_charnode(TRex* exp, TRexBool isclass) { TRexChar t; if (*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) { exp->_p++; switch (*exp->_p) { case 'n': exp->_p++; return trex_newnode(exp, '\n'); case 't': exp->_p++; return trex_newnode(exp, '\t'); case 'r': exp->_p++; return trex_newnode(exp, '\r'); case 'f': exp->_p++; return trex_newnode(exp, '\f'); case 'v': exp->_p++; return trex_newnode(exp, '\v'); case 'a': case 'A': case 'w': case 'W': case 's': case 'S': case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': case 'p': case 'P': case 'l': case 'u': { t = *exp->_p; exp->_p++; return trex_charclass(exp, t); } case 'b': case 'B': if (!isclass) { int node = trex_newnode(exp, OP_WB); exp->_nodes[node].left = *exp->_p; exp->_p++; return node; } /* fall through */ default: t = *exp->_p; exp->_p++; return trex_newnode(exp, t); } } else if (!scisprint((int)(*exp->_p))) { trex_error(exp, _SC("letter expected")); } t = *exp->_p; exp->_p++; return trex_newnode(exp, t); } static int trex_class(TRex* exp) { int ret = -1; int first = -1, chain; if (*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) { ret = trex_newnode(exp, OP_NCLASS); exp->_p++; } else ret = trex_newnode(exp, OP_CLASS); if (*exp->_p == ']') trex_error(exp, _SC("empty class")); chain = ret; while (*exp->_p != ']' && exp->_p != exp->_eol) { if (*exp->_p == '-' && first != -1) { int r, t; if (*exp->_p++ == ']') trex_error(exp, _SC("unfinished range")); r = trex_newnode(exp, OP_RANGE); if (first > *exp->_p) trex_error(exp, _SC("invalid range")); if (exp->_nodes[first].type == OP_CCLASS) trex_error(exp, _SC("cannot use character classes in ranges")); exp->_nodes[r].left = exp->_nodes[first].type; t = trex_escapechar(exp); exp->_nodes[r].right = t; exp->_nodes[chain].next = r; chain = r; first = -1; } else { if (first != -1) { int c = first; exp->_nodes[chain].next = c; chain = c; first = trex_charnode(exp, TRex_True); } else { first = trex_charnode(exp, TRex_True); } } } if (first != -1) { int c = first; exp->_nodes[chain].next = c; chain = c; first = -1; } /* hack? */ exp->_nodes[ret].left = exp->_nodes[ret].next; exp->_nodes[ret].next = -1; return ret; } static int trex_parsenumber(TRex* exp) { int ret = *exp->_p - '0'; int positions = 10; exp->_p++; while (isdigit((int)(*exp->_p))) { ret = ret * 10 + (*exp->_p++ - '0'); if (positions == 1000000000) trex_error(exp, _SC("overflow in numeric constant")); positions *= 10; }; return ret; } static int trex_element(TRex* exp) { int ret = -1; switch (*exp->_p) { case '(': { int expr, newn; exp->_p++; if (*exp->_p == '?') { exp->_p++; trex_expect(exp, ':'); expr = trex_newnode(exp, OP_NOCAPEXPR); } else expr = trex_newnode(exp, OP_EXPR); newn = trex_list(exp); exp->_nodes[expr].left = newn; ret = expr; trex_expect(exp, ')'); } break; case '[': exp->_p++; ret = trex_class(exp); trex_expect(exp, ']'); break; case TREX_SYMBOL_END_OF_STRING: exp->_p++; ret = trex_newnode(exp, OP_EOL); break; case TREX_SYMBOL_ANY_CHAR: exp->_p++; ret = trex_newnode(exp, OP_DOT); break; default: ret = trex_charnode(exp, TRex_False); break; } { TRexBool isgreedy = TRex_False; unsigned short p0 = 0, p1 = 0; switch (*exp->_p) { case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; case TREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = TRex_True; break; case '{': exp->_p++; if (!isdigit((int)(*exp->_p))) trex_error(exp, _SC("number expected")); p0 = (unsigned short)trex_parsenumber(exp); /*******************************/ switch (*exp->_p) { case '}': p1 = p0; exp->_p++; break; case ',': exp->_p++; p1 = 0xFFFF; if (isdigit((int)(*exp->_p))) { p1 = (unsigned short)trex_parsenumber(exp); } trex_expect(exp, '}'); break; default: trex_error(exp, _SC(", or } expected")); } /*******************************/ isgreedy = TRex_True; break; } if (isgreedy) { int nnode = trex_newnode(exp, OP_GREEDY); exp->_nodes[nnode].left = ret; exp->_nodes[nnode].right = ((p0) << 16) | p1; ret = nnode; } } if ((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { int nnode = trex_element(exp); exp->_nodes[ret].next = nnode; } return ret; } static int trex_list(TRex* exp) { int ret = -1, e; if (*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) { exp->_p++; ret = trex_newnode(exp, OP_BOL); } e = trex_element(exp); if (ret != -1) { exp->_nodes[ret].next = e; } else ret = e; if (*exp->_p == TREX_SYMBOL_BRANCH) { int temp, tright; exp->_p++; temp = trex_newnode(exp, OP_OR); exp->_nodes[temp].left = ret; tright = trex_list(exp); exp->_nodes[temp].right = tright; ret = temp; } return ret; } static TRexBool trex_matchcclass(int cclass, TRexChar c) { switch (cclass) { case 'a': return isalpha(c) ? TRex_True : TRex_False; case 'A': return !isalpha(c) ? TRex_True : TRex_False; case 'w': return (isalnum(c) || c == '_') ? TRex_True : TRex_False; case 'W': return (!isalnum(c) && c != '_') ? TRex_True : TRex_False; case 's': return isspace(c) ? TRex_True : TRex_False; case 'S': return !isspace(c) ? TRex_True : TRex_False; case 'd': return isdigit(c) ? TRex_True : TRex_False; case 'D': return !isdigit(c) ? TRex_True : TRex_False; case 'x': return isxdigit(c) ? TRex_True : TRex_False; case 'X': return !isxdigit(c) ? TRex_True : TRex_False; case 'c': return iscntrl(c) ? TRex_True : TRex_False; case 'C': return !iscntrl(c) ? TRex_True : TRex_False; case 'p': return ispunct(c) ? TRex_True : TRex_False; case 'P': return !ispunct(c) ? TRex_True : TRex_False; case 'l': return islower(c) ? TRex_True : TRex_False; case 'u': return isupper(c) ? TRex_True : TRex_False; } return TRex_False; /*cannot happen*/ } static TRexBool trex_matchclass(TRex* exp, TRexNode* node, TRexChar c) { do { switch (node->type) { case OP_RANGE: if (exp->_flags & TREX_ICASE) { if (c >= toupper(node->left) && c <= toupper(node->right)) return TRex_True; if (c >= tolower(node->left) && c <= tolower(node->right)) return TRex_True; } else { if (c >= node->left && c <= node->right) return TRex_True; } break; case OP_CCLASS: if (trex_matchcclass(node->left, c)) return TRex_True; break; default: if (exp->_flags & TREX_ICASE) { if (c == tolower(node->type) || c == toupper(node->type)) return TRex_True; } else { if (c == node->type) return TRex_True; } } } while ((node->next != -1) && ((node = &exp->_nodes[node->next]) != NULL)); return TRex_False; } static const TRexChar* trex_matchnode(TRex* exp, TRexNode* node, const TRexChar* str, TRexNode* next) { TRexNodeType type = node->type; switch (type) { case OP_GREEDY: { /* TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; */ TRexNode* greedystop = NULL; int p0 = (node->right >> 16) & 0x0000FFFF, p1 = node->right & 0x0000FFFF, nmaches = 0; const TRexChar *s = str, *good = str; if (node->next != -1) { greedystop = &exp->_nodes[node->next]; } else { greedystop = next; } while ((nmaches == 0xFFFF || nmaches < p1)) { const TRexChar* stop; if ((s = trex_matchnode(exp, &exp->_nodes[node->left], s, greedystop)) == NULL) break; nmaches++; good = s; if (greedystop) { /* checks that 0 matches satisfy the expression(if so skips) */ /* if not would always stop(for instance if is a '?') */ if (greedystop->type != OP_GREEDY || (greedystop->type == OP_GREEDY && ((greedystop->right >> 16) & 0x0000FFFF) != 0)) { TRexNode* gnext = NULL; if (greedystop->next != -1) { gnext = &exp->_nodes[greedystop->next]; } else if (next && next->next != -1) { gnext = &exp->_nodes[next->next]; } stop = trex_matchnode(exp, greedystop, s, gnext); if (stop) { /* if satisfied stop it */ if (p0 == p1 && p0 == nmaches) break; else if (nmaches >= p0 && p1 == 0xFFFF) break; else if (nmaches >= p0 && nmaches <= p1) break; } } } if (s >= exp->_eol) break; } if (p0 == p1 && p0 == nmaches) return good; else if (nmaches >= p0 && p1 == 0xFFFF) return good; else if (nmaches >= p0 && nmaches <= p1) return good; return NULL; } case OP_OR: { const TRexChar* asd = str; TRexNode* temp = &exp->_nodes[node->left]; while ((asd = trex_matchnode(exp, temp, asd, NULL)) != NULL) { if (temp->next != -1) temp = &exp->_nodes[temp->next]; else return asd; } asd = str; temp = &exp->_nodes[node->right]; while ((asd = trex_matchnode(exp, temp, asd, NULL)) != NULL) { if (temp->next != -1) temp = &exp->_nodes[temp->next]; else return asd; } return NULL; break; } case OP_EXPR: case OP_NOCAPEXPR: { TRexNode* n = &exp->_nodes[node->left]; const TRexChar* cur = str; int capture = -1; if (node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { capture = exp->_currsubexp; exp->_matches[capture].begin = cur; exp->_currsubexp++; } do { TRexNode* subnext = NULL; if (n->next != -1) { subnext = &exp->_nodes[n->next]; } else { subnext = next; } if ((cur = trex_matchnode(exp, n, cur, subnext)) == NULL) { if (capture != -1) { exp->_matches[capture].begin = 0; exp->_matches[capture].len = 0; } return NULL; } } while ((n->next != -1) && ((n = &exp->_nodes[n->next]) != NULL)); if (capture != -1) exp->_matches[capture].len = (int)(cur - exp->_matches[capture].begin); return cur; } case OP_WB: if ((str == exp->_bol && !isspace((int)(*str))) || (str == exp->_eol && !isspace((int)(*(str - 1)))) || (!isspace((int)(*str)) && isspace((int)(*(str + 1)))) || (isspace((int)(*str)) && !isspace((int)(*(str + 1))))) { return (node->left == 'b') ? str : NULL; } return (node->left == 'b') ? NULL : str; case OP_BOL: if (str == exp->_bol) return str; return NULL; case OP_EOL: if (str == exp->_eol) return str; return NULL; case OP_DOT: { str++; } return str; case OP_NCLASS: case OP_CLASS: if (trex_matchclass(exp, &exp->_nodes[node->left], *str) ? (type == OP_CLASS ? TRex_True : TRex_False) : (type == OP_NCLASS ? TRex_True : TRex_False)) { str++; return str; } return NULL; case OP_CCLASS: if (trex_matchcclass(node->left, *str)) { str++; return str; } return NULL; default: /* char */ if (exp->_flags & TREX_ICASE) { if (*str != tolower(node->type) && *str != toupper(node->type)) return NULL; } else { if (*str != node->type) return NULL; } str++; return str; } } /* public api */ TRex* trex_compile(const TRexChar* pattern, const TRexChar** error, int flags) { TRex* exp = (TRex*)xmalloc(sizeof(TRex)); exp->_eol = exp->_bol = NULL; exp->_p = pattern; exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar); exp->_nodes = (TRexNode*)xmalloc(exp->_nallocated * sizeof(TRexNode)); exp->_nsize = 0; exp->_matches = 0; exp->_nsubexpr = 0; exp->_first = trex_newnode(exp, OP_EXPR); exp->_error = error; exp->_jmpbuf = xmalloc(sizeof(jmp_buf)); exp->_flags = flags; if (setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { int res = trex_list(exp); exp->_nodes[exp->_first].left = res; if (*exp->_p != '\0') trex_error(exp, _SC("unexpected character")); #ifdef ARG_REX_DEBUG { int nsize, i; nsize = exp->_nsize; scprintf(_SC("\n")); for (i = 0; i < nsize; i++) { if (exp->_nodes[i].type > MAX_CHAR) scprintf(_SC("[%02d] %10s "), i, g_nnames[exp->_nodes[i].type - MAX_CHAR]); else scprintf(_SC("[%02d] %10c "), i, exp->_nodes[i].type); scprintf(_SC("left %02d right %02d next %02d\n"), exp->_nodes[i].left, exp->_nodes[i].right, exp->_nodes[i].next); } scprintf(_SC("\n")); } #endif exp->_matches = (TRexMatch*)xmalloc(exp->_nsubexpr * sizeof(TRexMatch)); memset(exp->_matches, 0, exp->_nsubexpr * sizeof(TRexMatch)); } else { trex_free(exp); return NULL; } return exp; } void trex_free(TRex* exp) { if (exp) { xfree(exp->_nodes); xfree(exp->_jmpbuf); xfree(exp->_matches); xfree(exp); } } TRexBool trex_match(TRex* exp, const TRexChar* text) { const TRexChar* res = NULL; exp->_bol = text; exp->_eol = text + scstrlen(text); exp->_currsubexp = 0; res = trex_matchnode(exp, exp->_nodes, text, NULL); if (res == NULL || res != exp->_eol) return TRex_False; return TRex_True; } TRexBool trex_searchrange(TRex* exp, const TRexChar* text_begin, const TRexChar* text_end, const TRexChar** out_begin, const TRexChar** out_end) { const TRexChar* cur = NULL; int node = exp->_first; if (text_begin >= text_end) return TRex_False; exp->_bol = text_begin; exp->_eol = text_end; do { cur = text_begin; while (node != -1) { exp->_currsubexp = 0; cur = trex_matchnode(exp, &exp->_nodes[node], cur, NULL); if (!cur) break; node = exp->_nodes[node].next; } text_begin++; } while (cur == NULL && text_begin != text_end); if (cur == NULL) return TRex_False; --text_begin; if (out_begin) *out_begin = text_begin; if (out_end) *out_end = cur; return TRex_True; } TRexBool trex_search(TRex* exp, const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end) { return trex_searchrange(exp, text, text + scstrlen(text), out_begin, out_end); } int trex_getsubexpcount(TRex* exp) { return exp->_nsubexpr; } TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch* subexp) { if (n < 0 || n >= exp->_nsubexpr) return TRex_False; *subexp = exp->_matches[n]; return TRex_True; } /******************************************************************************* * arg_str: Implements the str command-line option * * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include static void arg_str_resetfn(struct arg_str* parent) { int i; ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); for (i = 0; i < parent->count; i++) { parent->sval[i] = ""; } parent->count = 0; } static int arg_str_scanfn(struct arg_str* parent, const char* argval) { int errorcode = 0; if (parent->count == parent->hdr.maxcount) { /* maximum number of arguments exceeded */ errorcode = ARG_ERR_MAXCOUNT; } else if (!argval) { /* a valid argument with no argument value was given. */ /* This happens when an optional argument value was invoked. */ /* leave parent argument value unaltered but still count the argument. */ parent->count++; } else { parent->sval[parent->count++] = argval; } ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } static int arg_str_checkfn(struct arg_str* parent) { int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } static void arg_str_errorfn(struct arg_str* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { const char* shortopts = parent->hdr.shortopts; const char* longopts = parent->hdr.longopts; const char* datatype = parent->hdr.datatype; /* make argval NULL safe */ argval = argval ? argval : ""; arg_dstr_catf(ds, "%s: ", progname); switch (errorcode) { case ARG_ERR_MINCOUNT: arg_dstr_cat(ds, "missing option "); arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); break; case ARG_ERR_MAXCOUNT: arg_dstr_cat(ds, "excess option "); arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); break; } } struct arg_str* arg_str0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { return arg_strn(shortopts, longopts, datatype, 0, 1, glossary); } struct arg_str* arg_str1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { return arg_strn(shortopts, longopts, datatype, 1, 1, glossary); } struct arg_str* arg_strn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) { size_t nbytes; struct arg_str* result; int i; /* should not allow this stupid error */ /* we should return an error code warning this logic error */ /* foolproof things by ensuring maxcount is not less than mincount */ maxcount = (maxcount < mincount) ? mincount : maxcount; nbytes = sizeof(struct arg_str) /* storage for struct arg_str */ + maxcount * sizeof(char*); /* storage for sval[maxcount] array */ result = (struct arg_str*)xmalloc(nbytes); /* init the arg_hdr struct */ result->hdr.flag = ARG_HASVALUE; result->hdr.shortopts = shortopts; result->hdr.longopts = longopts; result->hdr.datatype = datatype ? datatype : ""; result->hdr.glossary = glossary; result->hdr.mincount = mincount; result->hdr.maxcount = maxcount; result->hdr.parent = result; result->hdr.resetfn = (arg_resetfn*)arg_str_resetfn; result->hdr.scanfn = (arg_scanfn*)arg_str_scanfn; result->hdr.checkfn = (arg_checkfn*)arg_str_checkfn; result->hdr.errorfn = (arg_errorfn*)arg_str_errorfn; /* store the sval[maxcount] array immediately after the arg_str struct */ result->sval = (const char**)(result + 1); result->count = 0; /* foolproof the string pointers by initializing them to reference empty strings */ for (i = 0; i < maxcount; i++) result->sval[i] = ""; ARG_TRACE(("arg_strn() returns %p\n", result)); return result; } /******************************************************************************* * arg_cmd: Provides the sub-command mechanism * * This file is part of the argtable3 library. * * Copyright (C) 2013-2019 Tom G. Huang * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #endif #include #include #include #define MAX_MODULE_VERSION_SIZE 128 static arg_hashtable_t* s_hashtable = NULL; static char* s_module_name = NULL; static int s_mod_ver_major = 0; static int s_mod_ver_minor = 0; static int s_mod_ver_patch = 0; static char* s_mod_ver_tag = NULL; static char* s_mod_ver = NULL; void arg_set_module_name(const char* name) { size_t slen; xfree(s_module_name); slen = strlen(name); s_module_name = (char*)xmalloc(slen + 1); memset(s_module_name, 0, slen + 1); #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) strncpy_s(s_module_name, slen + 1, name, slen); #else memcpy(s_module_name, name, slen); #endif } void arg_set_module_version(int major, int minor, int patch, const char* tag) { size_t slen_tag, slen_ds; arg_dstr_t ds; s_mod_ver_major = major; s_mod_ver_minor = minor; s_mod_ver_patch = patch; xfree(s_mod_ver_tag); slen_tag = strlen(tag); s_mod_ver_tag = (char*)xmalloc(slen_tag + 1); memset(s_mod_ver_tag, 0, slen_tag + 1); #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) strncpy_s(s_mod_ver_tag, slen_tag + 1, tag, slen_tag); #else memcpy(s_mod_ver_tag, tag, slen_tag); #endif ds = arg_dstr_create(); arg_dstr_catf(ds, "%d.", s_mod_ver_major); arg_dstr_catf(ds, "%d.", s_mod_ver_minor); arg_dstr_catf(ds, "%d.", s_mod_ver_patch); arg_dstr_cat(ds, s_mod_ver_tag); xfree(s_mod_ver); slen_ds = strlen(arg_dstr_cstr(ds)); s_mod_ver = (char*)xmalloc(slen_ds + 1); memset(s_mod_ver, 0, slen_ds + 1); #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) strncpy_s(s_mod_ver, slen_ds + 1, arg_dstr_cstr(ds), slen_ds); #else memcpy(s_mod_ver, arg_dstr_cstr(ds), slen_ds); #endif arg_dstr_destroy(ds); } static unsigned int hash_key(const void* key) { const char* str = (const char*)key; int c; unsigned int hash = 5381; while ((c = *str++) != 0) hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ return hash; } static int equal_keys(const void* key1, const void* key2) { char* k1 = (char*)key1; char* k2 = (char*)key2; return (0 == strcmp(k1, k2)); } void arg_cmd_init(void) { s_hashtable = arg_hashtable_create(32, hash_key, equal_keys); } void arg_cmd_uninit(void) { arg_hashtable_destroy(s_hashtable, 1); } void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description) { arg_cmd_info_t* cmd_info; size_t slen_name; void* k; assert(strlen(name) < ARG_CMD_NAME_LEN); assert(strlen(description) < ARG_CMD_DESCRIPTION_LEN); /* Check if the command already exists. */ /* If the command exists, replace the existing command. */ /* If the command doesn't exist, insert the command. */ cmd_info = (arg_cmd_info_t*)arg_hashtable_search(s_hashtable, name); if (cmd_info) { arg_hashtable_remove(s_hashtable, name); cmd_info = NULL; } cmd_info = (arg_cmd_info_t*)xmalloc(sizeof(arg_cmd_info_t)); memset(cmd_info, 0, sizeof(arg_cmd_info_t)); #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) strncpy_s(cmd_info->name, ARG_CMD_NAME_LEN, name, strlen(name)); strncpy_s(cmd_info->description, ARG_CMD_DESCRIPTION_LEN, description, strlen(description)); #else memcpy(cmd_info->name, name, strlen(name)); memcpy(cmd_info->description, description, strlen(description)); #endif cmd_info->proc = proc; slen_name = strlen(name); k = xmalloc(slen_name + 1); memset(k, 0, slen_name + 1); #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) strncpy_s((char*)k, slen_name + 1, name, slen_name); #else memcpy((char*)k, name, slen_name); #endif arg_hashtable_insert(s_hashtable, k, cmd_info); } void arg_cmd_unregister(const char* name) { arg_hashtable_remove(s_hashtable, name); } int arg_cmd_dispatch(const char* name, int argc, char* argv[], arg_dstr_t res) { arg_cmd_info_t* cmd_info = arg_cmd_info(name); assert(cmd_info != NULL); assert(cmd_info->proc != NULL); return cmd_info->proc(argc, argv, res); } arg_cmd_info_t* arg_cmd_info(const char* name) { return (arg_cmd_info_t*)arg_hashtable_search(s_hashtable, name); } unsigned int arg_cmd_count(void) { return arg_hashtable_count(s_hashtable); } arg_cmd_itr_t arg_cmd_itr_create(void) { return (arg_cmd_itr_t)arg_hashtable_itr_create(s_hashtable); } int arg_cmd_itr_advance(arg_cmd_itr_t itr) { return arg_hashtable_itr_advance((arg_hashtable_itr_t*)itr); } char* arg_cmd_itr_key(arg_cmd_itr_t itr) { return (char*)arg_hashtable_itr_key((arg_hashtable_itr_t*)itr); } arg_cmd_info_t* arg_cmd_itr_value(arg_cmd_itr_t itr) { return (arg_cmd_info_t*)arg_hashtable_itr_value((arg_hashtable_itr_t*)itr); } void arg_cmd_itr_destroy(arg_cmd_itr_t itr) { arg_hashtable_itr_destroy((arg_hashtable_itr_t*)itr); } int arg_cmd_itr_search(arg_cmd_itr_t itr, void* k) { return arg_hashtable_itr_search((arg_hashtable_itr_t*)itr, s_hashtable, k); } static const char* module_name(void) { if (s_module_name == NULL || strlen(s_module_name) == 0) return ""; return s_module_name; } static const char* module_version(void) { if (s_mod_ver == NULL || strlen(s_mod_ver) == 0) return "0.0.0.0"; return s_mod_ver; } void arg_make_get_help_msg(arg_dstr_t res) { arg_dstr_catf(res, "%s v%s\n", module_name(), module_version()); arg_dstr_catf(res, "Please type '%s help' to get more information.\n", module_name()); } void arg_make_help_msg(arg_dstr_t ds, char* cmd_name, void** argtable) { arg_cmd_info_t* cmd_info = (arg_cmd_info_t*)arg_hashtable_search(s_hashtable, cmd_name); if (cmd_info) { arg_dstr_catf(ds, "%s: %s\n", cmd_name, cmd_info->description); } arg_dstr_cat(ds, "Usage:\n"); arg_dstr_catf(ds, " %s", module_name()); arg_print_syntaxv_ds(ds, argtable, "\n \nAvailable options:\n"); arg_print_glossary_ds(ds, argtable, " %-23s %s\n"); arg_dstr_cat(ds, "\n"); } void arg_make_syntax_err_msg(arg_dstr_t ds, void** argtable, struct arg_end* end) { arg_print_errors_ds(ds, end, module_name()); arg_dstr_cat(ds, "Usage: \n"); arg_dstr_catf(ds, " %s", module_name()); arg_print_syntaxv_ds(ds, argtable, "\n"); arg_dstr_cat(ds, "\n"); } int arg_make_syntax_err_help_msg(arg_dstr_t ds, char* name, int help, int nerrors, void** argtable, struct arg_end* end, int* exitcode) { /* help handling * note: '-h|--help' takes precedence over error reporting */ if (help > 0) { arg_make_help_msg(ds, name, argtable); *exitcode = EXIT_SUCCESS; return 1; } /* syntax error handling */ if (nerrors > 0) { arg_make_syntax_err_msg(ds, argtable, end); *exitcode = EXIT_FAILURE; return 1; } return 0; } /******************************************************************************* * argtable3: Implements the main interfaces of the library * * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #include "argtable3.h" #ifndef ARG_AMALGAMATION #include "argtable3_private.h" #if ARG_REPLACE_GETOPT == 1 #include "arg_getopt.h" #else #include #endif #else #if ARG_REPLACE_GETOPT == 0 #include #endif #endif #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN #endif #include #include #include #include #include static void arg_register_error(struct arg_end* end, void* parent, int error, const char* argval) { /* printf("arg_register_error(%p,%p,%d,%s)\n",end,parent,error,argval); */ if (end->count < end->hdr.maxcount) { end->error[end->count] = error; end->parent[end->count] = parent; end->argval[end->count] = argval; end->count++; } else { end->error[end->hdr.maxcount - 1] = ARG_ELIMIT; end->parent[end->hdr.maxcount - 1] = end; end->argval[end->hdr.maxcount - 1] = NULL; } } /* * Return index of first table entry with a matching short option * or -1 if no match was found. */ static int find_shortoption(struct arg_hdr** table, char shortopt) { int tabindex; for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { if (table[tabindex]->shortopts && strchr(table[tabindex]->shortopts, shortopt)) return tabindex; } return -1; } struct longoptions { int getoptval; int noptions; struct option* options; }; #if 0 static void dump_longoptions(struct longoptions * longoptions) { int i; printf("getoptval = %d\n", longoptions->getoptval); printf("noptions = %d\n", longoptions->noptions); for (i = 0; i < longoptions->noptions; i++) { printf("options[%d].name = \"%s\"\n", i, longoptions->options[i].name); printf("options[%d].has_arg = %d\n", i, longoptions->options[i].has_arg); printf("options[%d].flag = %p\n", i, longoptions->options[i].flag); printf("options[%d].val = %d\n", i, longoptions->options[i].val); } } #endif static struct longoptions* alloc_longoptions(struct arg_hdr** table) { struct longoptions* result; size_t nbytes; int noptions = 1; size_t longoptlen = 0; int tabindex; int option_index = 0; char* store; /* * Determine the total number of option structs required * by counting the number of comma separated long options * in all table entries and return the count in noptions. * note: noptions starts at 1 not 0 because we getoptlong * requires a NULL option entry to terminate the option array. * While we are at it, count the number of chars required * to store private copies of all the longoption strings * and return that count in logoptlen. */ tabindex = 0; do { const char* longopts = table[tabindex]->longopts; longoptlen += (longopts ? strlen(longopts) : 0) + 1; while (longopts) { noptions++; longopts = strchr(longopts + 1, ','); } } while (!(table[tabindex++]->flag & ARG_TERMINATOR)); /*printf("%d long options consuming %d chars in total\n",noptions,longoptlen);*/ /* allocate storage for return data structure as: */ /* (struct longoptions) + (struct options)[noptions] + char[longoptlen] */ nbytes = sizeof(struct longoptions) + sizeof(struct option) * noptions + longoptlen; result = (struct longoptions*)xmalloc(nbytes); result->getoptval = 0; result->noptions = noptions; result->options = (struct option*)(result + 1); store = (char*)(result->options + noptions); for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { const char* longopts = table[tabindex]->longopts; while (longopts && *longopts) { char* storestart = store; /* copy progressive longopt strings into the store */ while (*longopts != 0 && *longopts != ',') *store++ = *longopts++; *store++ = 0; if (*longopts == ',') longopts++; /*fprintf(stderr,"storestart=\"%s\"\n",storestart);*/ result->options[option_index].name = storestart; result->options[option_index].flag = &(result->getoptval); result->options[option_index].val = tabindex; if (table[tabindex]->flag & ARG_HASOPTVALUE) result->options[option_index].has_arg = 2; else if (table[tabindex]->flag & ARG_HASVALUE) result->options[option_index].has_arg = 1; else result->options[option_index].has_arg = 0; option_index++; } } /* terminate the options array with a zero-filled entry */ result->options[option_index].name = 0; result->options[option_index].has_arg = 0; result->options[option_index].flag = 0; result->options[option_index].val = 0; /*dump_longoptions(result);*/ return result; } static char* alloc_shortoptions(struct arg_hdr** table) { char* result; size_t len = 2; int tabindex; char* res; /* determine the total number of option chars required */ for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { struct arg_hdr* hdr = table[tabindex]; len += 3 * (hdr->shortopts ? strlen(hdr->shortopts) : 0); } result = xmalloc(len); res = result; /* add a leading ':' so getopt return codes distinguish */ /* unrecognised option and options missing argument values */ *res++ = ':'; for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { struct arg_hdr* hdr = table[tabindex]; const char* shortopts = hdr->shortopts; while (shortopts && *shortopts) { *res++ = *shortopts++; if (hdr->flag & ARG_HASVALUE) *res++ = ':'; if (hdr->flag & ARG_HASOPTVALUE) *res++ = ':'; } } /* null terminate the string */ *res = 0; /*printf("alloc_shortoptions() returns \"%s\"\n",(result?result:"NULL"));*/ return result; } /* return index of the table terminator entry */ static int arg_endindex(struct arg_hdr** table) { int tabindex = 0; while (!(table[tabindex]->flag & ARG_TERMINATOR)) tabindex++; return tabindex; } static void arg_parse_tagged(int argc, char** argv, struct arg_hdr** table, struct arg_end* endtable) { struct longoptions* longoptions; char* shortoptions; int copt; /*printf("arg_parse_tagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/ /* allocate short and long option arrays for the given opttable[]. */ /* if the allocs fail then put an error msg in the last table entry. */ longoptions = alloc_longoptions(table); shortoptions = alloc_shortoptions(table); /*dump_longoptions(longoptions);*/ /* reset getopts internal option-index to zero, and disable error reporting */ optind = 0; opterr = 0; /* fetch and process args using getopt_long */ #ifdef ARG_LONG_ONLY while ((copt = getopt_long_only(argc, argv, shortoptions, longoptions->options, NULL)) != -1) { #else while ((copt = getopt_long(argc, argv, shortoptions, longoptions->options, NULL)) != -1) { #endif /* printf("optarg='%s'\n",optarg); printf("optind=%d\n",optind); printf("copt=%c\n",(char)copt); printf("optopt=%c (%d)\n",optopt, (int)(optopt)); */ switch (copt) { case 0: { int tabindex = longoptions->getoptval; void* parent = table[tabindex]->parent; /*printf("long option detected from argtable[%d]\n", tabindex);*/ if (optarg && optarg[0] == 0 && (table[tabindex]->flag & ARG_HASVALUE)) { /* printf(": long option %s requires an argument\n",argv[optind-1]); */ arg_register_error(endtable, endtable, ARG_EMISSARG, argv[optind - 1]); /* continue to scan the (empty) argument value to enforce argument count checking */ } if (table[tabindex]->scanfn) { int errorcode = table[tabindex]->scanfn(parent, optarg); if (errorcode != 0) arg_register_error(endtable, parent, errorcode, optarg); } } break; case '?': /* * getopt_long() found an unrecognised short option. * if it was a short option its value is in optopt * if it was a long option then optopt=0 */ switch (optopt) { case 0: /*printf("?0 unrecognised long option %s\n",argv[optind-1]);*/ arg_register_error(endtable, endtable, ARG_ELONGOPT, argv[optind - 1]); break; default: /*printf("?* unrecognised short option '%c'\n",optopt);*/ arg_register_error(endtable, endtable, optopt, NULL); break; } break; case ':': /* * getopt_long() found an option with its argument missing. */ /*printf(": option %s requires an argument\n",argv[optind-1]); */ arg_register_error(endtable, endtable, ARG_EMISSARG, argv[optind - 1]); break; default: { /* getopt_long() found a valid short option */ int tabindex = find_shortoption(table, (char)copt); /*printf("short option detected from argtable[%d]\n", tabindex);*/ if (tabindex == -1) { /* should never get here - but handle it just in case */ /*printf("unrecognised short option %d\n",copt);*/ arg_register_error(endtable, endtable, copt, NULL); } else { if (table[tabindex]->scanfn) { void* parent = table[tabindex]->parent; int errorcode = table[tabindex]->scanfn(parent, optarg); if (errorcode != 0) arg_register_error(endtable, parent, errorcode, optarg); } } break; } } } xfree(shortoptions); xfree(longoptions); } static void arg_parse_untagged(int argc, char** argv, struct arg_hdr** table, struct arg_end* endtable) { int tabindex = 0; int errorlast = 0; const char* optarglast = NULL; void* parentlast = NULL; /*printf("arg_parse_untagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/ while (!(table[tabindex]->flag & ARG_TERMINATOR)) { void* parent; int errorcode; /* if we have exhausted our argv[optind] entries then we have finished */ if (optind >= argc) { /*printf("arg_parse_untagged(): argv[] exhausted\n");*/ return; } /* skip table entries with non-null long or short options (they are not untagged entries) */ if (table[tabindex]->longopts || table[tabindex]->shortopts) { /*printf("arg_parse_untagged(): skipping argtable[%d] (tagged argument)\n",tabindex);*/ tabindex++; continue; } /* skip table entries with NULL scanfn */ if (!(table[tabindex]->scanfn)) { /*printf("arg_parse_untagged(): skipping argtable[%d] (NULL scanfn)\n",tabindex);*/ tabindex++; continue; } /* attempt to scan the current argv[optind] with the current */ /* table[tabindex] entry. If it succeeds then keep it, otherwise */ /* try again with the next table[] entry. */ parent = table[tabindex]->parent; errorcode = table[tabindex]->scanfn(parent, argv[optind]); if (errorcode == 0) { /* success, move onto next argv[optind] but stay with same table[tabindex] */ /*printf("arg_parse_untagged(): argtable[%d] successfully matched\n",tabindex);*/ optind++; /* clear the last tentative error */ errorlast = 0; } else { /* failure, try same argv[optind] with next table[tabindex] entry */ /*printf("arg_parse_untagged(): argtable[%d] failed match\n",tabindex);*/ tabindex++; /* remember this as a tentative error we may wish to reinstate later */ errorlast = errorcode; optarglast = argv[optind]; parentlast = parent; } } /* if a tentative error still remains at this point then register it as a proper error */ if (errorlast) { arg_register_error(endtable, parentlast, errorlast, optarglast); optind++; } /* only get here when not all argv[] entries were consumed */ /* register an error for each unused argv[] entry */ while (optind < argc) { /*printf("arg_parse_untagged(): argv[%d]=\"%s\" not consumed\n",optind,argv[optind]);*/ arg_register_error(endtable, endtable, ARG_ENOMATCH, argv[optind++]); } return; } static void arg_parse_check(struct arg_hdr** table, struct arg_end* endtable) { int tabindex = 0; /* printf("arg_parse_check()\n"); */ do { if (table[tabindex]->checkfn) { void* parent = table[tabindex]->parent; int errorcode = table[tabindex]->checkfn(parent); if (errorcode != 0) arg_register_error(endtable, parent, errorcode, NULL); } } while (!(table[tabindex++]->flag & ARG_TERMINATOR)); } static void arg_reset(void** argtable) { struct arg_hdr** table = (struct arg_hdr**)argtable; int tabindex = 0; /*printf("arg_reset(%p)\n",argtable);*/ do { if (table[tabindex]->resetfn) table[tabindex]->resetfn(table[tabindex]->parent); } while (!(table[tabindex++]->flag & ARG_TERMINATOR)); } int arg_parse(int argc, char** argv, void** argtable) { struct arg_hdr** table = (struct arg_hdr**)argtable; struct arg_end* endtable; int endindex; char** argvcopy = NULL; int i; /*printf("arg_parse(%d,%p,%p)\n",argc,argv,argtable);*/ /* reset any argtable data from previous invocations */ arg_reset(argtable); /* locate the first end-of-table marker within the array */ endindex = arg_endindex(table); endtable = (struct arg_end*)table[endindex]; /* Special case of argc==0. This can occur on Texas Instruments DSP. */ /* Failure to trap this case results in an unwanted NULL result from */ /* the malloc for argvcopy (next code block). */ if (argc == 0) { /* We must still perform post-parse checks despite the absence of command line arguments */ arg_parse_check(table, endtable); /* Now we are finished */ return endtable->count; } argvcopy = (char**)xmalloc(sizeof(char*) * (argc + 1)); /* Fill in the local copy of argv[]. We need a local copy because getopt rearranges argv[] which adversely affects subsequent parsing attempts. */ for (i = 0; i < argc; i++) argvcopy[i] = argv[i]; argvcopy[argc] = NULL; /* parse the command line (local copy) for tagged options */ arg_parse_tagged(argc, argvcopy, table, endtable); /* parse the command line (local copy) for untagged options */ arg_parse_untagged(argc, argvcopy, table, endtable); /* if no errors so far then perform post-parse checks otherwise dont bother */ if (endtable->count == 0) arg_parse_check(table, endtable); /* release the local copt of argv[] */ xfree(argvcopy); return endtable->count; } /* * Concatenate contents of src[] string onto *pdest[] string. * The *pdest pointer is altered to point to the end of the * target string and *pndest is decremented by the same number * of chars. * Does not append more than *pndest chars into *pdest[] * so as to prevent buffer overruns. * Its something like strncat() but more efficient for repeated * calls on the same destination string. * Example of use: * char dest[30] = "good" * size_t ndest = sizeof(dest); * char *pdest = dest; * arg_char(&pdest,"bye ",&ndest); * arg_char(&pdest,"cruel ",&ndest); * arg_char(&pdest,"world!",&ndest); * Results in: * dest[] == "goodbye cruel world!" * ndest == 10 */ static void arg_cat(char** pdest, const char* src, size_t* pndest) { char* dest = *pdest; char* end = dest + *pndest; /*locate null terminator of dest string */ while (dest < end && *dest != 0) dest++; /* concat src string to dest string */ while (dest < end && *src != 0) *dest++ = *src++; /* null terminate dest string */ *dest = 0; /* update *pdest and *pndest */ *pndest = end - dest; *pdest = dest; } static void arg_cat_option(char* dest, size_t ndest, const char* shortopts, const char* longopts, const char* datatype, int optvalue) { if (shortopts) { char option[3]; /* note: option array[] is initialized dynamically here to satisfy */ /* a deficiency in the watcom compiler wrt static array initializers. */ option[0] = '-'; option[1] = shortopts[0]; option[2] = 0; arg_cat(&dest, option, &ndest); if (datatype) { arg_cat(&dest, " ", &ndest); if (optvalue) { arg_cat(&dest, "[", &ndest); arg_cat(&dest, datatype, &ndest); arg_cat(&dest, "]", &ndest); } else arg_cat(&dest, datatype, &ndest); } } else if (longopts) { size_t ncspn; /* add "--" tag prefix */ arg_cat(&dest, "--", &ndest); /* add comma separated option tag */ ncspn = strcspn(longopts, ","); #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) strncat_s(dest, ndest, longopts, (ncspn < ndest) ? ncspn : ndest); #else strncat(dest, longopts, (ncspn < ndest) ? ncspn : ndest); #endif if (datatype) { arg_cat(&dest, "=", &ndest); if (optvalue) { arg_cat(&dest, "[", &ndest); arg_cat(&dest, datatype, &ndest); arg_cat(&dest, "]", &ndest); } else arg_cat(&dest, datatype, &ndest); } } else if (datatype) { if (optvalue) { arg_cat(&dest, "[", &ndest); arg_cat(&dest, datatype, &ndest); arg_cat(&dest, "]", &ndest); } else arg_cat(&dest, datatype, &ndest); } } static void arg_cat_optionv(char* dest, size_t ndest, const char* shortopts, const char* longopts, const char* datatype, int optvalue, const char* separator) { separator = separator ? separator : ""; if (shortopts) { const char* c = shortopts; while (*c) { /* "-a|-b|-c" */ char shortopt[3]; /* note: shortopt array[] is initialized dynamically here to satisfy */ /* a deficiency in the watcom compiler wrt static array initializers. */ shortopt[0] = '-'; shortopt[1] = *c; shortopt[2] = 0; arg_cat(&dest, shortopt, &ndest); if (*++c) arg_cat(&dest, separator, &ndest); } } /* put separator between long opts and short opts */ if (shortopts && longopts) arg_cat(&dest, separator, &ndest); if (longopts) { const char* c = longopts; while (*c) { size_t ncspn; /* add "--" tag prefix */ arg_cat(&dest, "--", &ndest); /* add comma separated option tag */ ncspn = strcspn(c, ","); #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) strncat_s(dest, ndest, c, (ncspn < ndest) ? ncspn : ndest); #else strncat(dest, c, (ncspn < ndest) ? ncspn : ndest); #endif c += ncspn; /* add given separator in place of comma */ if (*c == ',') { arg_cat(&dest, separator, &ndest); c++; } } } if (datatype) { if (longopts) arg_cat(&dest, "=", &ndest); else if (shortopts) arg_cat(&dest, " ", &ndest); if (optvalue) { arg_cat(&dest, "[", &ndest); arg_cat(&dest, datatype, &ndest); arg_cat(&dest, "]", &ndest); } else arg_cat(&dest, datatype, &ndest); } } void arg_print_option_ds(arg_dstr_t ds, const char* shortopts, const char* longopts, const char* datatype, const char* suffix) { char syntax[200] = ""; suffix = suffix ? suffix : ""; /* there is no way of passing the proper optvalue for optional argument values here, so we must ignore it */ arg_cat_optionv(syntax, sizeof(syntax) - 1, shortopts, longopts, datatype, 0, "|"); arg_dstr_cat(ds, syntax); arg_dstr_cat(ds, (char*)suffix); } /* this function should be deprecated because it doesn't consider optional argument values (ARG_HASOPTVALUE) */ void arg_print_option(FILE* fp, const char* shortopts, const char* longopts, const char* datatype, const char* suffix) { arg_dstr_t ds = arg_dstr_create(); arg_print_option_ds(ds, shortopts, longopts, datatype, suffix); fputs(arg_dstr_cstr(ds), fp); arg_dstr_destroy(ds); } /* * Print a GNU style [OPTION] string in which all short options that * do not take argument values are presented in abbreviated form, as * in: -xvfsd, or -xvf[sd], or [-xvsfd] */ static void arg_print_gnuswitch_ds(arg_dstr_t ds, struct arg_hdr** table) { int tabindex; char* format1 = " -%c"; char* format2 = " [-%c"; char* suffix = ""; /* print all mandatory switches that are without argument values */ for (tabindex = 0; table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { /* skip optional options */ if (table[tabindex]->mincount < 1) continue; /* skip non-short options */ if (table[tabindex]->shortopts == NULL) continue; /* skip options that take argument values */ if (table[tabindex]->flag & ARG_HASVALUE) continue; /* print the short option (only the first short option char, ignore multiple choices)*/ arg_dstr_catf(ds, format1, table[tabindex]->shortopts[0]); format1 = "%c"; format2 = "[%c"; } /* print all optional switches that are without argument values */ for (tabindex = 0; table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { /* skip mandatory args */ if (table[tabindex]->mincount > 0) continue; /* skip args without short options */ if (table[tabindex]->shortopts == NULL) continue; /* skip args with values */ if (table[tabindex]->flag & ARG_HASVALUE) continue; /* print first short option */ arg_dstr_catf(ds, format2, table[tabindex]->shortopts[0]); format2 = "%c"; suffix = "]"; } arg_dstr_catf(ds, "%s", suffix); } void arg_print_syntax_ds(arg_dstr_t ds, void** argtable, const char* suffix) { struct arg_hdr** table = (struct arg_hdr**)argtable; int i, tabindex; /* print GNU style [OPTION] string */ arg_print_gnuswitch_ds(ds, table); /* print remaining options in abbreviated style */ for (tabindex = 0; table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { char syntax[200] = ""; const char *shortopts, *longopts, *datatype; /* skip short options without arg values (they were printed by arg_print_gnu_switch) */ if (table[tabindex]->shortopts && !(table[tabindex]->flag & ARG_HASVALUE)) continue; shortopts = table[tabindex]->shortopts; longopts = table[tabindex]->longopts; datatype = table[tabindex]->datatype; arg_cat_option(syntax, sizeof(syntax) - 1, shortopts, longopts, datatype, table[tabindex]->flag & ARG_HASOPTVALUE); if (strlen(syntax) > 0) { /* print mandatory instances of this option */ for (i = 0; i < table[tabindex]->mincount; i++) { arg_dstr_cat(ds, " "); arg_dstr_cat(ds, syntax); } /* print optional instances enclosed in "[..]" */ switch (table[tabindex]->maxcount - table[tabindex]->mincount) { case 0: break; case 1: arg_dstr_cat(ds, " ["); arg_dstr_cat(ds, syntax); arg_dstr_cat(ds, "]"); break; case 2: arg_dstr_cat(ds, " ["); arg_dstr_cat(ds, syntax); arg_dstr_cat(ds, "]"); arg_dstr_cat(ds, " ["); arg_dstr_cat(ds, syntax); arg_dstr_cat(ds, "]"); break; default: arg_dstr_cat(ds, " ["); arg_dstr_cat(ds, syntax); arg_dstr_cat(ds, "]..."); break; } } } if (suffix) { arg_dstr_cat(ds, (char*)suffix); } } void arg_print_syntax(FILE* fp, void** argtable, const char* suffix) { arg_dstr_t ds = arg_dstr_create(); arg_print_syntax_ds(ds, argtable, suffix); fputs(arg_dstr_cstr(ds), fp); arg_dstr_destroy(ds); } void arg_print_syntaxv_ds(arg_dstr_t ds, void** argtable, const char* suffix) { struct arg_hdr** table = (struct arg_hdr**)argtable; int i, tabindex; /* print remaining options in abbreviated style */ for (tabindex = 0; table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { char syntax[200] = ""; const char *shortopts, *longopts, *datatype; shortopts = table[tabindex]->shortopts; longopts = table[tabindex]->longopts; datatype = table[tabindex]->datatype; arg_cat_optionv(syntax, sizeof(syntax) - 1, shortopts, longopts, datatype, table[tabindex]->flag & ARG_HASOPTVALUE, "|"); /* print mandatory options */ for (i = 0; i < table[tabindex]->mincount; i++) { arg_dstr_cat(ds, " "); arg_dstr_cat(ds, syntax); } /* print optional args enclosed in "[..]" */ switch (table[tabindex]->maxcount - table[tabindex]->mincount) { case 0: break; case 1: arg_dstr_cat(ds, " ["); arg_dstr_cat(ds, syntax); arg_dstr_cat(ds, "]"); break; case 2: arg_dstr_cat(ds, " ["); arg_dstr_cat(ds, syntax); arg_dstr_cat(ds, "]"); arg_dstr_cat(ds, " ["); arg_dstr_cat(ds, syntax); arg_dstr_cat(ds, "]"); break; default: arg_dstr_cat(ds, " ["); arg_dstr_cat(ds, syntax); arg_dstr_cat(ds, "]..."); break; } } if (suffix) { arg_dstr_cat(ds, (char*)suffix); } } void arg_print_syntaxv(FILE* fp, void** argtable, const char* suffix) { arg_dstr_t ds = arg_dstr_create(); arg_print_syntaxv_ds(ds, argtable, suffix); fputs(arg_dstr_cstr(ds), fp); arg_dstr_destroy(ds); } void arg_print_glossary_ds(arg_dstr_t ds, void** argtable, const char* format) { struct arg_hdr** table = (struct arg_hdr**)argtable; int tabindex; format = format ? format : " %-20s %s\n"; for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { if (table[tabindex]->glossary) { char syntax[200] = ""; const char* shortopts = table[tabindex]->shortopts; const char* longopts = table[tabindex]->longopts; const char* datatype = table[tabindex]->datatype; const char* glossary = table[tabindex]->glossary; arg_cat_optionv(syntax, sizeof(syntax) - 1, shortopts, longopts, datatype, table[tabindex]->flag & ARG_HASOPTVALUE, ", "); arg_dstr_catf(ds, format, syntax, glossary); } } } void arg_print_glossary(FILE* fp, void** argtable, const char* format) { arg_dstr_t ds = arg_dstr_create(); arg_print_glossary_ds(ds, argtable, format); fputs(arg_dstr_cstr(ds), fp); arg_dstr_destroy(ds); } /** * Print a piece of text formatted, which means in a column with a * left and a right margin. The lines are wrapped at whitspaces next * to right margin. The function does not indent the first line, but * only the following ones. * * Example: * arg_print_formatted( fp, 0, 5, "Some text that doesn't fit." ) * will result in the following output: * * Some * text * that * doesn' * t fit. * * Too long lines will be wrapped in the middle of a word. * * arg_print_formatted( fp, 2, 7, "Some text that doesn't fit." ) * will result in the following output: * * Some * text * that * doesn' * t fit. * * As you see, the first line is not indented. This enables output of * lines, which start in a line where output already happened. * * Author: Uli Fouquet */ static void arg_print_formatted_ds(arg_dstr_t ds, const unsigned lmargin, const unsigned rmargin, const char* text) { const unsigned int textlen = (unsigned int)strlen(text); unsigned int line_start = 0; unsigned int line_end = textlen; const unsigned int colwidth = (rmargin - lmargin) + 1; assert(strlen(text) < UINT_MAX); /* Someone doesn't like us... */ if (line_end < line_start) { arg_dstr_catf(ds, "%s\n", text); } while (line_end > line_start) { /* Eat leading white spaces. This is essential because while wrapping lines, there will often be a whitespace at beginning of line */ while (isspace((int)(*(text + line_start)))) { line_start++; } /* Find last whitespace, that fits into line */ if (line_end - line_start > colwidth) { line_end = line_start + colwidth; while ((line_end > line_start) && !isspace((int)(*(text + line_end)))) { line_end--; } /* Consume trailing spaces */ while ((line_end > line_start) && isspace((int)(*(text + line_end)))) { line_end--; } /* Restore the last non-space character */ line_end++; } /* Output line of text */ while (line_start < line_end) { char c = *(text + line_start); arg_dstr_catc(ds, c); line_start++; } arg_dstr_cat(ds, "\n"); /* Initialize another line */ if (line_end < textlen) { unsigned i; for (i = 0; i < lmargin; i++) { arg_dstr_cat(ds, " "); } line_end = textlen; } } /* lines of text */ } /** * Prints the glossary in strict GNU format. * Differences to arg_print_glossary() are: * - wraps lines after 80 chars * - indents lines without shortopts * - does not accept formatstrings * * Contributed by Uli Fouquet */ void arg_print_glossary_gnu_ds(arg_dstr_t ds, void** argtable) { struct arg_hdr** table = (struct arg_hdr**)argtable; int tabindex; for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { if (table[tabindex]->glossary) { char syntax[200] = ""; const char* shortopts = table[tabindex]->shortopts; const char* longopts = table[tabindex]->longopts; const char* datatype = table[tabindex]->datatype; const char* glossary = table[tabindex]->glossary; if (!shortopts && longopts) { /* Indent trailing line by 4 spaces... */ memset(syntax, ' ', 4); *(syntax + 4) = '\0'; } arg_cat_optionv(syntax, sizeof(syntax) - 1, shortopts, longopts, datatype, table[tabindex]->flag & ARG_HASOPTVALUE, ", "); /* If syntax fits not into column, print glossary in new line... */ if (strlen(syntax) > 25) { arg_dstr_catf(ds, " %-25s %s\n", syntax, ""); *syntax = '\0'; } arg_dstr_catf(ds, " %-25s ", syntax); arg_print_formatted_ds(ds, 28, 79, glossary); } } /* for each table entry */ arg_dstr_cat(ds, "\n"); } void arg_print_glossary_gnu(FILE* fp, void** argtable) { arg_dstr_t ds = arg_dstr_create(); arg_print_glossary_gnu_ds(ds, argtable); fputs(arg_dstr_cstr(ds), fp); arg_dstr_destroy(ds); } /** * Checks the argtable[] array for NULL entries and returns 1 * if any are found, zero otherwise. */ int arg_nullcheck(void** argtable) { struct arg_hdr** table = (struct arg_hdr**)argtable; int tabindex; /*printf("arg_nullcheck(%p)\n",argtable);*/ if (!table) return 1; tabindex = 0; do { /*printf("argtable[%d]=%p\n",tabindex,argtable[tabindex]);*/ if (!table[tabindex]) return 1; } while (!(table[tabindex++]->flag & ARG_TERMINATOR)); return 0; } /* * arg_free() is deprecated in favour of arg_freetable() due to a flaw in its design. * The flaw results in memory leak in the (very rare) case that an intermediate * entry in the argtable array failed its memory allocation while others following * that entry were still allocated ok. Those subsequent allocations will not be * deallocated by arg_free(). * Despite the unlikeliness of the problem occurring, and the even unlikelier event * that it has any deleterious effect, it is fixed regardless by replacing arg_free() * with the newer arg_freetable() function. * We still keep arg_free() for backwards compatibility. */ void arg_free(void** argtable) { struct arg_hdr** table = (struct arg_hdr**)argtable; int tabindex = 0; int flag; /*printf("arg_free(%p)\n",argtable);*/ do { /* if we encounter a NULL entry then somewhat incorrectly we presume we have come to the end of the array. It isnt strictly true because an intermediate entry could be NULL with other non-NULL entries to follow. The subsequent argtable entries would then not be freed as they should. */ if (table[tabindex] == NULL) break; flag = table[tabindex]->flag; xfree(table[tabindex]); table[tabindex++] = NULL; } while (!(flag & ARG_TERMINATOR)); } /* frees each non-NULL element of argtable[], where n is the size of the number of entries in the array */ void arg_freetable(void** argtable, size_t n) { struct arg_hdr** table = (struct arg_hdr**)argtable; size_t tabindex = 0; /*printf("arg_freetable(%p)\n",argtable);*/ for (tabindex = 0; tabindex < n; tabindex++) { if (table[tabindex] == NULL) continue; xfree(table[tabindex]); table[tabindex] = NULL; }; } #ifdef _WIN32 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { return TRUE; UNREFERENCED_PARAMETER(hinstDLL); UNREFERENCED_PARAMETER(fdwReason); UNREFERENCED_PARAMETER(lpvReserved); } #endif sslh-2.3.1/argtable3.h000066400000000000000000000343201515234404100145040ustar00rootroot00000000000000/******************************************************************************* * argtable3: Declares the main interfaces of the library * * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of STEWART HEITMANN nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #ifndef ARGTABLE3 #define ARGTABLE3 #include /* FILE */ #include /* struct tm */ #ifdef __cplusplus extern "C" { #endif #define ARG_REX_ICASE 1 #define ARG_DSTR_SIZE 200 #define ARG_CMD_NAME_LEN 100 #define ARG_CMD_DESCRIPTION_LEN 256 #ifndef ARG_REPLACE_GETOPT #define ARG_REPLACE_GETOPT 1 /* use the embedded getopt as the system getopt(3) */ #endif /* ARG_REPLACE_GETOPT */ /* bit masks for arg_hdr.flag */ enum { ARG_TERMINATOR = 0x1, ARG_HASVALUE = 0x2, ARG_HASOPTVALUE = 0x4 }; #if defined(_WIN32) #if defined(argtable3_EXPORTS) #define ARG_EXTERN __declspec(dllexport) #elif defined(argtable3_IMPORTS) #define ARG_EXTERN __declspec(dllimport) #else #define ARG_EXTERN #endif #else #define ARG_EXTERN #endif typedef struct _internal_arg_dstr* arg_dstr_t; typedef void* arg_cmd_itr_t; typedef void(arg_resetfn)(void* parent); typedef int(arg_scanfn)(void* parent, const char* argval); typedef int(arg_checkfn)(void* parent); typedef void(arg_errorfn)(void* parent, arg_dstr_t ds, int error, const char* argval, const char* progname); typedef void(arg_dstr_freefn)(char* buf); typedef int(arg_cmdfn)(int argc, char* argv[], arg_dstr_t res); typedef int(arg_comparefn)(const void* k1, const void* k2); /* * The arg_hdr struct defines properties that are common to all arg_xxx structs. * The argtable library requires each arg_xxx struct to have an arg_hdr * struct as its first data member. * The argtable library functions then use this data to identify the * properties of the command line option, such as its option tags, * datatype string, and glossary strings, and so on. * Moreover, the arg_hdr struct contains pointers to custom functions that * are provided by each arg_xxx struct which perform the tasks of parsing * that particular arg_xxx arguments, performing post-parse checks, and * reporting errors. * These functions are private to the individual arg_xxx source code * and are the pointer to them are initialised by that arg_xxx struct's * constructor function. The user could alter them after construction * if desired, but the original intention is for them to be set by the * constructor and left unaltered. */ typedef struct arg_hdr { char flag; /* Modifier flags: ARG_TERMINATOR, ARG_HASVALUE. */ const char* shortopts; /* String defining the short options */ const char* longopts; /* String defining the long options */ const char* datatype; /* Description of the argument data type */ const char* glossary; /* Description of the option as shown by arg_print_glossary function */ int mincount; /* Minimum number of occurences of this option accepted */ int maxcount; /* Maximum number of occurences if this option accepted */ void* parent; /* Pointer to parent arg_xxx struct */ arg_resetfn* resetfn; /* Pointer to parent arg_xxx reset function */ arg_scanfn* scanfn; /* Pointer to parent arg_xxx scan function */ arg_checkfn* checkfn; /* Pointer to parent arg_xxx check function */ arg_errorfn* errorfn; /* Pointer to parent arg_xxx error function */ void* priv; /* Pointer to private header data for use by arg_xxx functions */ } arg_hdr_t; typedef struct arg_rem { struct arg_hdr hdr; /* The mandatory argtable header struct */ } arg_rem_t; typedef struct arg_lit { struct arg_hdr hdr; /* The mandatory argtable header struct */ int count; /* Number of matching command line args */ } arg_lit_t; typedef struct arg_int { struct arg_hdr hdr; /* The mandatory argtable header struct */ int count; /* Number of matching command line args */ int* ival; /* Array of parsed argument values */ } arg_int_t; typedef struct arg_dbl { struct arg_hdr hdr; /* The mandatory argtable header struct */ int count; /* Number of matching command line args */ double* dval; /* Array of parsed argument values */ } arg_dbl_t; typedef struct arg_str { struct arg_hdr hdr; /* The mandatory argtable header struct */ int count; /* Number of matching command line args */ const char** sval; /* Array of parsed argument values */ } arg_str_t; typedef struct arg_rex { struct arg_hdr hdr; /* The mandatory argtable header struct */ int count; /* Number of matching command line args */ const char** sval; /* Array of parsed argument values */ } arg_rex_t; typedef struct arg_file { struct arg_hdr hdr; /* The mandatory argtable header struct */ int count; /* Number of matching command line args*/ const char** filename; /* Array of parsed filenames (eg: /home/foo.bar) */ const char** basename; /* Array of parsed basenames (eg: foo.bar) */ const char** extension; /* Array of parsed extensions (eg: .bar) */ } arg_file_t; typedef struct arg_date { struct arg_hdr hdr; /* The mandatory argtable header struct */ const char* format; /* strptime format string used to parse the date */ int count; /* Number of matching command line args */ struct tm* tmval; /* Array of parsed time values */ } arg_date_t; enum { ARG_ELIMIT = 1, ARG_EMALLOC, ARG_ENOMATCH, ARG_ELONGOPT, ARG_EMISSARG }; typedef struct arg_end { struct arg_hdr hdr; /* The mandatory argtable header struct */ int count; /* Number of errors encountered */ int* error; /* Array of error codes */ void** parent; /* Array of pointers to offending arg_xxx struct */ const char** argval; /* Array of pointers to offending argv[] string */ } arg_end_t; typedef struct arg_cmd_info { char name[ARG_CMD_NAME_LEN]; char description[ARG_CMD_DESCRIPTION_LEN]; arg_cmdfn* proc; } arg_cmd_info_t; /**** arg_xxx constructor functions *********************************/ ARG_EXTERN struct arg_rem* arg_rem(const char* datatype, const char* glossary); ARG_EXTERN struct arg_lit* arg_lit0(const char* shortopts, const char* longopts, const char* glossary); ARG_EXTERN struct arg_lit* arg_lit1(const char* shortopts, const char* longopts, const char* glossary); ARG_EXTERN struct arg_lit* arg_litn(const char* shortopts, const char* longopts, int mincount, int maxcount, const char* glossary); ARG_EXTERN struct arg_int* arg_int0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); ARG_EXTERN struct arg_int* arg_int1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); ARG_EXTERN struct arg_int* arg_intn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary); ARG_EXTERN struct arg_dbl* arg_dbl0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); ARG_EXTERN struct arg_dbl* arg_dbl1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); ARG_EXTERN struct arg_dbl* arg_dbln(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary); ARG_EXTERN struct arg_str* arg_str0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); ARG_EXTERN struct arg_str* arg_str1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); ARG_EXTERN struct arg_str* arg_strn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary); ARG_EXTERN struct arg_rex* arg_rex0(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int flags, const char* glossary); ARG_EXTERN struct arg_rex* arg_rex1(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int flags, const char* glossary); ARG_EXTERN struct arg_rex* arg_rexn(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int mincount, int maxcount, int flags, const char* glossary); ARG_EXTERN struct arg_file* arg_file0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); ARG_EXTERN struct arg_file* arg_file1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); ARG_EXTERN struct arg_file* arg_filen(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary); ARG_EXTERN struct arg_date* arg_date0(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary); ARG_EXTERN struct arg_date* arg_date1(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary); ARG_EXTERN struct arg_date* arg_daten(const char* shortopts, const char* longopts, const char* format, const char* datatype, int mincount, int maxcount, const char* glossary); ARG_EXTERN struct arg_end* arg_end(int maxerrors); #define ARG_DSTR_STATIC ((arg_dstr_freefn*)0) #define ARG_DSTR_VOLATILE ((arg_dstr_freefn*)1) #define ARG_DSTR_DYNAMIC ((arg_dstr_freefn*)3) /**** other functions *******************************************/ ARG_EXTERN int arg_nullcheck(void** argtable); ARG_EXTERN int arg_parse(int argc, char** argv, void** argtable); ARG_EXTERN void arg_print_option(FILE* fp, const char* shortopts, const char* longopts, const char* datatype, const char* suffix); ARG_EXTERN void arg_print_syntax(FILE* fp, void** argtable, const char* suffix); ARG_EXTERN void arg_print_syntaxv(FILE* fp, void** argtable, const char* suffix); ARG_EXTERN void arg_print_glossary(FILE* fp, void** argtable, const char* format); ARG_EXTERN void arg_print_glossary_gnu(FILE* fp, void** argtable); ARG_EXTERN void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname); ARG_EXTERN void arg_print_option_ds(arg_dstr_t ds, const char* shortopts, const char* longopts, const char* datatype, const char* suffix); ARG_EXTERN void arg_print_syntax_ds(arg_dstr_t ds, void** argtable, const char* suffix); ARG_EXTERN void arg_print_syntaxv_ds(arg_dstr_t ds, void** argtable, const char* suffix); ARG_EXTERN void arg_print_glossary_ds(arg_dstr_t ds, void** argtable, const char* format); ARG_EXTERN void arg_print_glossary_gnu_ds(arg_dstr_t ds, void** argtable); ARG_EXTERN void arg_print_errors_ds(arg_dstr_t ds, struct arg_end* end, const char* progname); ARG_EXTERN void arg_freetable(void** argtable, size_t n); ARG_EXTERN arg_dstr_t arg_dstr_create(void); ARG_EXTERN void arg_dstr_destroy(arg_dstr_t ds); ARG_EXTERN void arg_dstr_reset(arg_dstr_t ds); ARG_EXTERN void arg_dstr_free(arg_dstr_t ds); ARG_EXTERN void arg_dstr_set(arg_dstr_t ds, char* str, arg_dstr_freefn* free_proc); ARG_EXTERN void arg_dstr_cat(arg_dstr_t ds, const char* str); ARG_EXTERN void arg_dstr_catc(arg_dstr_t ds, char c); ARG_EXTERN void arg_dstr_catf(arg_dstr_t ds, const char* fmt, ...); ARG_EXTERN char* arg_dstr_cstr(arg_dstr_t ds); ARG_EXTERN void arg_cmd_init(void); ARG_EXTERN void arg_cmd_uninit(void); ARG_EXTERN void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description); ARG_EXTERN void arg_cmd_unregister(const char* name); ARG_EXTERN int arg_cmd_dispatch(const char* name, int argc, char* argv[], arg_dstr_t res); ARG_EXTERN unsigned int arg_cmd_count(void); ARG_EXTERN arg_cmd_info_t* arg_cmd_info(const char* name); ARG_EXTERN arg_cmd_itr_t arg_cmd_itr_create(void); ARG_EXTERN void arg_cmd_itr_destroy(arg_cmd_itr_t itr); ARG_EXTERN int arg_cmd_itr_advance(arg_cmd_itr_t itr); ARG_EXTERN char* arg_cmd_itr_key(arg_cmd_itr_t itr); ARG_EXTERN arg_cmd_info_t* arg_cmd_itr_value(arg_cmd_itr_t itr); ARG_EXTERN int arg_cmd_itr_search(arg_cmd_itr_t itr, void* k); ARG_EXTERN void arg_mgsort(void* data, int size, int esize, int i, int k, arg_comparefn* comparefn); ARG_EXTERN void arg_make_get_help_msg(arg_dstr_t res); ARG_EXTERN void arg_make_help_msg(arg_dstr_t ds, char* cmd_name, void** argtable); ARG_EXTERN void arg_make_syntax_err_msg(arg_dstr_t ds, void** argtable, struct arg_end* end); ARG_EXTERN int arg_make_syntax_err_help_msg(arg_dstr_t ds, char* name, int help, int nerrors, void** argtable, struct arg_end* end, int* exitcode); ARG_EXTERN void arg_set_module_name(const char* name); ARG_EXTERN void arg_set_module_version(int major, int minor, int patch, const char* tag); /**** deprecated functions, for back-compatibility only ********/ ARG_EXTERN void arg_free(void** argtable); #ifdef __cplusplus } #endif #endif sslh-2.3.1/basic.cfg000066400000000000000000000017131515234404100142310ustar00rootroot00000000000000# This is a basic configuration file that should provide # sensible values for "standard" setup. # You will find extensive examples with explanations in # example.cfg timeout: 2; user: "nobody"; pidfile: "/var/run/sslh.pid"; # Change hostname with your external address name, or the IP # of the interface that receives connections # Default is to bind all interfaces. httpd can be started # first to bind on localhost, in which case sslh will bind # only other interfaces. listen: ( { host: "0.0.0.0"; port: "443"; }, { host: "[::]"; port: "443"; } ); # Change to the protocols you want to forward to. The # defaults here are sensible for services running on # localhost protocols: ( { name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; fork: true; }, { name: "openvpn"; host: "localhost"; port: "1194"; }, { name: "tls"; host: "localhost"; port: "443"; log_level: 0; }, { name: "anyprot"; host: "localhost"; port: "443"; } ); sslh-2.3.1/collection.c000066400000000000000000000056331515234404100147730ustar00rootroot00000000000000/* collection.c: management of a collection of connections, for sslh-select # Copyright (C) 2021 Yves Rutschle # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either # version 2 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 General Public License for more # details. # # The full text for the General Public License is here: # http://www.gnu.org/licenses/gpl.html */ #include "common.h" #include "collection.h" #include "sslh-conf.h" #include "gap.h" /* Info to keep track of all connections */ struct cnx_collection { gap_array* fd2cnx; /* Array indexed by file descriptor to things in cnx[] */ int max_fd; }; /* Allocates and initialises a new collection of connections with at least * `len` elements. */ cnx_collection* collection_init(int len) { cnx_collection* collection; collection = malloc(sizeof(*collection)); CHECK_ALLOC(collection, "collection_init(collection)"); memset(collection, 0, sizeof(*collection)); collection->fd2cnx = gap_init(len); collection->max_fd = 0; return collection; } /* Caveat: might not work, as has never been used */ void collection_destroy(cnx_collection* collection) { /* Caveat 2: no code to free connections yet */ gap_destroy(collection->fd2cnx); free(collection); } int collection_max_fd(cnx_collection* collection) { return collection->max_fd; } /* Points the file descriptor to the specified connection index */ int collection_add_fd(cnx_collection* collection, struct connection* cnx, int fd) { gap_set(collection->fd2cnx, fd, cnx); if (fd > collection->max_fd) collection->max_fd = fd; return 0; } /* Allocates a connection and inits it with specified file descriptor */ struct connection* collection_alloc_cnx_from_fd(struct cnx_collection* collection, int fd) { struct connection* cnx = malloc(sizeof(*cnx)); if (!cnx) return NULL; init_cnx(cnx); cnx->type = SOCK_STREAM; cnx->q[0].fd = fd; cnx->state = ST_PROBING; cnx->probe_timeout = time(NULL) + cfg.timeout; collection_add_fd(collection, cnx, fd); return cnx; } /* Remove a connection from the collection */ int collection_remove_cnx(cnx_collection* collection, struct connection *cnx) { if (cnx->q[0].fd != -1) gap_set(collection->fd2cnx, cnx->q[0].fd, NULL); if (cnx->q[1].fd != -1) gap_set(collection->fd2cnx, cnx->q[1].fd, NULL); free(cnx); return 0; } /* Returns the connection that contains the file descriptor */ struct connection* collection_get_cnx_from_fd(struct cnx_collection* collection, int fd) { return gap_get(collection->fd2cnx, fd); } sslh-2.3.1/collection.h000066400000000000000000000011671515234404100147760ustar00rootroot00000000000000#ifndef COLLECTION_H #define COLLECTION_H typedef struct cnx_collection cnx_collection; cnx_collection* collection_init(int len); void collection_destroy(cnx_collection* collection); struct connection* collection_alloc_cnx_from_fd(cnx_collection* collection, int fd); int collection_add_fd(cnx_collection* collection, struct connection* cnx, int fd); int collection_max_fd(cnx_collection* collection); /* Remove a connection from the collection */ int collection_remove_cnx(cnx_collection* collection, struct connection *cnx); struct connection* collection_get_cnx_from_fd(struct cnx_collection* collection, int fd); #endif sslh-2.3.1/common.c000066400000000000000000001014221515234404100141210ustar00rootroot00000000000000/* Code and variables that is common to both fork and select-based * servers. * * No code here should assume whether sockets are blocking or not. **/ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "common.h" #include "probe.h" #include "log.h" #include "sslh-conf.h" #include "proxyprotocol.h" #if HAVE_LIBCAP #include #include #endif /* Make use of systemd socket activation * */ #ifdef SYSTEMD #include #endif #ifdef HAVE_LIBBSD #include #endif /* * Settings that depend on the command line or the config file */ struct sslhcfg_item cfg; struct addrinfo *addr_listen = NULL; /* what addresses do we listen to? */ #ifdef HAVE_LIBWRAP #include int allow_severity =0, deny_severity = 0; #endif typedef enum { CR_DIE, CR_WARN } CR_ACTION; /* check result and die, printing the offending address and error */ void check_res_dump(CR_ACTION act, int res, struct addrinfo *addr, char* syscall) { char buf[NI_MAXHOST]; if (res == -1) { print_message(msg_system_error, "%s:%s: %s\n", sprintaddr(buf, sizeof(buf), addr), syscall, strerror(errno)); if (act == CR_DIE) exit(1); } } int get_fd_sockets(struct listen_endpoint *sockfd[]) { int sd = 0; #ifdef SYSTEMD sd = sd_listen_fds(0); if (sd < 0) { print_message(msg_system_error, "sd_listen_fds(): %s\n", strerror(-sd)); exit(1); } if (sd > 0) { int i; *sockfd = calloc(sd, sizeof(*sockfd[0])); CHECK_ALLOC(*sockfd, "malloc"); for (i = 0; i < sd; i++) { (*sockfd)[i].socketfd = SD_LISTEN_FDS_START + i; (*sockfd)[i].type = SOCK_STREAM; } } #endif return sd; } /* Set TCP_FASTOPEN on listening socket if all client protocols support it */ int make_listen_tfo(int s) { int i, qlen = 5; /* Don't do it if not supported */ if (!TCP_FASTOPEN) return 0; /* Don't do it if any protocol does not specify it */ for (i = 0; i < cfg.protocols_len; i++) { if (! cfg.protocols[i].tfo_ok) return 0; } return setsockopt(s, SOL_SOCKET, TCP_FASTOPEN, (char*)&qlen, sizeof(qlen)); } /* Starts listening on a single address * Returns a socket filehandle, or dies with message in case of major error */ int listen_single_addr(struct addrinfo* addr, int keepalive, int udp) { struct sockaddr_storage *saddr; int sockfd, one, res; saddr = (struct sockaddr_storage*)addr->ai_addr; sockfd = socket(saddr->ss_family, udp ? SOCK_DGRAM : SOCK_STREAM, 0); check_res_dump(CR_DIE, sockfd, addr, "socket"); one = 1; res = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)); check_res_dump(CR_DIE, res, addr, "setsockopt(SO_REUSEADDR)"); res = make_listen_tfo(sockfd); check_res_dump(CR_WARN, res, addr, "setsockopt(TCP_FASTOPEN)"); if (keepalive) { res = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(one)); check_res_dump(CR_DIE, res, addr, "setsockopt(SO_KEEPALIVE)"); } if (IP_FREEBIND) { res = setsockopt(sockfd, IPPROTO_IP, IP_FREEBIND, (char*)&one, sizeof(one)); check_res_dump(CR_WARN, res, addr, "setsockopt(IP_FREEBIND)"); } if (addr->ai_addr->sa_family == AF_INET6) { res = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&one, sizeof(one)); check_res_dump(CR_WARN, res, addr, "setsockopt(IPV6_V6ONLY)"); } res = bind(sockfd, addr->ai_addr, addr->ai_addrlen); check_res_dump(CR_DIE, res, addr, "bind"); if (!udp) { res = listen (sockfd, 50); check_res_dump(CR_DIE, res, addr, "listen"); } return sockfd; } void print_inet_listen_info(int fd, const char* addr, struct sslhcfg_listen_item* cfg) { print_message(msg_config, "%d:\t%s\t[%s] [%s] [max_cnx: %d]\n", fd, addr, cfg->keepalive ? "keepalive" : "", cfg->is_udp ? "udp" : "", cfg->max_connections); } /* Start listening internet sockets for configuration entry 'index' * OUT: *sockfd[]: pointer to array of listen_endpoint object; we append new * endpoints to that array * IN: num_addr: how many entries are in sockfd[] * *cfg: configuration data for the endpoint we are adding * Return: new value of num_addr * */ static int start_listen_inet(struct listen_endpoint *sockfd[], int num_addr, struct sslhcfg_listen_item* cfg) { struct addrinfo *addr, *start_addr; char buf[NI_MAXHOST]; int res; res = resolve_split_name(&start_addr, cfg->host, cfg->port); if (res) exit(4); for (addr = start_addr; addr; addr = addr->ai_next) { num_addr++; *sockfd = realloc(*sockfd, num_addr * sizeof(*sockfd[0])); memset(&(*sockfd)[num_addr-1], 0, sizeof((*sockfd)[num_addr-1])); (*sockfd)[num_addr-1].socketfd = listen_single_addr(addr, cfg->keepalive, cfg->is_udp); (*sockfd)[num_addr-1].type = cfg->is_udp ? SOCK_DGRAM : SOCK_STREAM; (*sockfd)[num_addr-1].family = AF_INET; (*sockfd)[num_addr-1].endpoint_cfg = cfg; print_inet_listen_info((*sockfd)[num_addr-1].socketfd, sprintaddr(buf, sizeof(buf), addr), cfg); } freeaddrinfo(start_addr); return num_addr; } /* Same, but for UNIX sockets */ static int start_listen_unix(struct listen_endpoint *sockfd[], int num_addr, struct sslhcfg_listen_item* cfg) { int fd = socket(AF_UNIX, cfg->is_udp ? SOCK_DGRAM : SOCK_STREAM, 0); CHECK_RES_DIE(fd, "socket(AF_UNIX)"); int res = unlink(cfg->host); if ((res == -1) && (errno != ENOENT)) { print_message(msg_config_error, "unlink unix socket `%s':%d:%s\n", cfg->host, errno, strerror(errno)); exit(4); } struct sockaddr_un sun; sun.sun_family = AF_UNIX; strncpy(sun.sun_path, cfg->host, sizeof(sun.sun_path)-1); printf("binding [%s]\n", sun.sun_path); res = bind(fd, (struct sockaddr*)&sun, sizeof(sun)); CHECK_RES_DIE(res, "bind(AF_UNIX)"); res = listen(fd, 50); num_addr++; *sockfd = realloc(*sockfd, num_addr * sizeof(*sockfd[0])); memset(&(*sockfd)[num_addr-1], 0, sizeof((*sockfd)[num_addr-1])); (*sockfd)[num_addr-1].socketfd = fd; (*sockfd)[num_addr-1].type = cfg->is_udp ? SOCK_DGRAM : SOCK_STREAM; (*sockfd)[num_addr-1].family = AF_INET; (*sockfd)[num_addr-1].endpoint_cfg = cfg; return num_addr; } /* Starts listening sockets on specified addresses. * OUT: *sockfd[] pointer to newly-allocated array of listen_endpoint objects * Returns number of addresses bound */ int start_listen_sockets(struct listen_endpoint *sockfd[]) { int i; int num_addr = 0, sd_socks = 0; sd_socks = get_fd_sockets(sockfd); if (sd_socks > 0) { return sd_socks; } *sockfd = NULL; print_message(msg_config, "Listening to:\n"); for (i = 0; i < cfg.listen_len; i++) { if (cfg.listen[i].is_unix) { num_addr = start_listen_unix(sockfd, num_addr, &cfg.listen[i]); } else { num_addr = start_listen_inet(sockfd, num_addr, &cfg.listen[i]); } } return num_addr; } /* returns 1 if given address is on the local machine: iterate through all * network interfaces and check their addresses */ int is_same_machine(struct addrinfo* from) { struct ifaddrs *ifaddrs_p = NULL, *ifa; int match = 0; getifaddrs(&ifaddrs_p); for (ifa = ifaddrs_p; ifa != NULL; ifa = ifa->ifa_next) { if (!ifa->ifa_addr) continue; if (from->ai_addr->sa_family == ifa->ifa_addr->sa_family) { int family = ifa->ifa_addr->sa_family; if (family == AF_INET) { struct sockaddr_in *from_addr = (struct sockaddr_in*)from->ai_addr; struct sockaddr_in *ifa_addr = (struct sockaddr_in*)ifa->ifa_addr; if (from_addr->sin_addr.s_addr == ifa_addr->sin_addr.s_addr) { match = 1; break; } } else if (family == AF_INET6) { struct sockaddr_in6 *from_addr = (struct sockaddr_in6*)from->ai_addr; struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6*)ifa->ifa_addr; if (!memcmp(from_addr->sin6_addr.s6_addr, ifa_addr->sin6_addr.s6_addr, 16)) { match = 1; break; } } } } freeifaddrs(ifaddrs_p); return match; } /* Transparent proxying: bind the peer address of fd to the peer address of * fd_from */ #ifndef IP_TRANSPARENT #define IP_TRANSPARENT 19 #endif #ifndef IP_BIND_ADDRESS_NO_PORT #define IP_BIND_ADDRESS_NO_PORT 24 #endif int bind_peer(int fd, int fd_from) { struct addrinfo from; struct sockaddr_storage ss; int res, enable = 1, disable = 0; memset(&from, 0, sizeof(from)); from.ai_addr = (struct sockaddr*)&ss; from.ai_addrlen = sizeof(ss); /* getpeername can fail with ENOTCONN if connection was dropped before we * got here */ res = getpeername(fd_from, from.ai_addr, &from.ai_addrlen); CHECK_RES_RETURN(res, "getpeername", res); /* if the destination is the same machine, there's no need to do bind */ if (is_same_machine(&from)) return 0; #ifndef IP_BINDANY /* use IP_TRANSPARENT */ res = setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &enable, sizeof(enable)); CHECK_RES_DIE(res, "setsockopt IP_TRANSPARENT"); res = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); CHECK_RES_DIE(res, "setsockopt SO_REUSEADDR"); #else if (from.ai_addr->sa_family==AF_INET) { /* IPv4 */ res = setsockopt(fd, IPPROTO_IP, IP_BINDANY, &enable, sizeof(enable)); CHECK_RES_RETURN(res, "setsockopt IP_BINDANY", res); #ifdef IPV6_BINDANY } else { /* IPv6 */ res = setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, &enable, sizeof(enable)); CHECK_RES_RETURN(res, "setsockopt IPV6_BINDANY", res); #endif /* IPV6_BINDANY */ } #endif /* IP_TRANSPARENT / IP_BINDANY */ res = bind(fd, from.ai_addr, from.ai_addrlen); if (res == -1) { if (errno != EADDRINUSE) { print_message(msg_system_error, "%s:%d:%s:%d:%s\n", __FILE__, __LINE__, "bind", errno, strerror(errno)); return res; } res = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &disable, sizeof(disable)); CHECK_RES_DIE(res, "setsockopt SO_REUSEADDR"); res = setsockopt(fd, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, &enable, sizeof(enable)); CHECK_RES_RETURN(res, "setsockopt IP_BIND_ADDRESS_NO_PORT", res); ((struct sockaddr_in *)from.ai_addr)->sin_port = 0; res = bind(fd, from.ai_addr, from.ai_addrlen); CHECK_RES_RETURN(res, "bind", res); /* * There was a serious problem, when daisy-chaining programs using the same * ip transparent mechanism, as sslh uses. stunnel was mentioned in a previous * comment. This problem should now be solved through the two methods, getting * a connection established: * In the first try, SO_REUSEADDR is set to socket, which will allow the same * IP-address:port tuple, as it is used by another application. The check for * inconsistency with other connections (same 4-value-tupel) is done at the * moment, when the connection gets established. * If that fails, SO_REUSEADDR gets removed and IP_BIND_ADDRESS_NO_PORT get set. * This will search for a free port, which will not collide with current * connections. Read more in this excellent blog-post: * https://blog.cloudflare.com/how-to-stop-running-out-of-ephemeral-ports-and-start-to-love-long-lived-connections * The problem will still appear, if the another application in the daisy-chain * does not use similar mechanisms. In that case you must either pull this * application at the beginning of the chain, or get it fixed. */ } return 0; } /* Make the file descriptor non-block */ int set_nonblock(int fd) { int flags; flags = fcntl(fd, F_GETFL); CHECK_RES_RETURN(flags, "fcntl", -1); flags |= O_NONBLOCK; flags = fcntl(fd, F_SETFL, flags); CHECK_RES_RETURN(flags, "fcntl", -1); return flags; } /* Connects to INET/INET6 domain sockets and return a fd */ static int connect_inet(struct connection *cnx, int fd_from, connect_blocking blocking) { struct addrinfo *a, from; struct sockaddr_storage ss; char buf[NI_MAXHOST]; int fd, res, one; int transparent = cnx->proto->transparent || cfg.transparent; memset(&from, 0, sizeof(from)); from.ai_addr = (struct sockaddr*)&ss; from.ai_addrlen = sizeof(ss); res = getpeername(fd_from, from.ai_addr, &from.ai_addrlen); CHECK_RES_RETURN(res, "getpeername", res); if (cnx->proto->resolve_on_forward) { resolve_split_name(&(cnx->proto->saddr), cnx->proto->host, cnx->proto->port); } for (a = cnx->proto->saddr; a; a = a->ai_next) { /* When transparent, make sure both connections use * the same address family (e.g. IP4 on both sides) */ if (transparent && (a->ai_family != from.ai_addr->sa_family)) continue; print_message(msg_connections_try, "trying to connect to %s family %d len %d\n", sprintaddr(buf, sizeof(buf), a), a->ai_addr->sa_family, a->ai_addrlen); /* XXX Needs to match ai_family from fd_from when being transparent! */ fd = socket(a->ai_family, SOCK_STREAM, 0); if (fd == -1) { print_message(msg_connections_error, "forward to %s failed:socket: %s\n", cnx->proto->name, strerror(errno)); } else { one = 1; setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, &one, sizeof(one)); /* no need to check return value; if it's not supported, that's okay */ if (blocking == NON_BLOCKING) { set_nonblock(fd); } if (transparent) { res = bind_peer(fd, fd_from); if (res == -1) close(fd); CHECK_RES_RETURN(res, "bind_peer", res); } res = connect(fd, a->ai_addr, a->ai_addrlen); /* EINPROGRESS indicates it might take time. If it eventually * fails, it'll be caught as a failed read */ if ((res == -1) && (errno != EINPROGRESS)) { print_message(msg_connections_error, "forward to %s failed:connect: %s\n", cnx->proto->name, strerror(errno)); close(fd); continue; /* Try the next address */ } if (cnx->proto->keepalive) { res = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(one)); CHECK_RES_RETURN(res, "setsockopt(SO_KEEPALIVE)", res); } return fd; } } return -1; } /* Connects to AF_UNIX domain sockets */ static int connect_unix(struct connection *cnx, int fd_from, connect_blocking blocking) { struct sockaddr_storage ss; struct sockaddr_un* sun = (struct sockaddr_un*)&ss; int fd = socket(AF_UNIX, SOCK_STREAM, 0); sun->sun_family = AF_UNIX; strncpy(sun->sun_path, cnx->proto->host, sizeof(sun->sun_path)-1); int res = connect(fd, (struct sockaddr*)sun, sizeof(*sun)); CHECK_RES_RETURN(res, "connect", res); if (blocking == NON_BLOCKING) { set_nonblock(fd); } return fd; } /* * Connect to the first backend server address that works and updates the *cnx * object accordingly (in cnx->q[1].fd). Set that to -1 in case of failure. * * If transparent proxying is on, use fd_from peer address on external address * of new file descriptor. * If proxyprotocol is used, write header on new backend server connection * */ void connect_addr(struct connection *cnx, int fd_from, connect_blocking blocking) { int fd; if (cnx->proto->is_unix) { fd = connect_unix(cnx, fd_from, blocking); } else { fd = connect_inet(cnx, fd_from, blocking); } cnx->q[1].fd = fd; if (cnx->proto->proxyprotocol_is_present) { if (cnx->proto->proxyprotocol) { pp_write_header(cnx->proto->proxyprotocol, cnx); /* If pp_write_header() fails, it already logs a message and there is * nothing much we can do. The server side will probably close the * connection */ } else { /* proxyprotocol == 0 means we remove a proxyprotocol header from * the client-side, and log PP information (as it will be lost * after sslh) */ int pp_len = pp_log_connection(cnx->q[1].begin_deferred_data, cnx->q[1].deferred_data_size); if (pp_len > 0) { defer_skip(&cnx->q[1], pp_len); } } } } /* Store some data to write to the queue later */ int defer_write(struct queue *q, void* data, ssize_t data_size) { char *p; ptrdiff_t data_offset = q->deferred_data - q->begin_deferred_data; print_message(msg_fd, "writing deferred on fd %d\n", q->fd); p = realloc(q->begin_deferred_data, data_offset + q->deferred_data_size + data_size); CHECK_ALLOC(p, "realloc"); q->begin_deferred_data = p; q->deferred_data = p + data_offset; p += data_offset + q->deferred_data_size; q->deferred_data_size += (int)data_size; memcpy(p, data, data_size); return 0; } /* skip (remove) some data from the head of the queue */ void defer_skip(struct queue *q, ssize_t data_size) { q->deferred_data += data_size; q->deferred_data_size -= data_size; } /* Store some data to write *before* what's already in the queue */ int defer_write_before(struct queue *q, void* data, ssize_t data_size) { char *p; print_message(msg_fd, "writing deferred to beginning on fd %d\n", q->fd); p = malloc(q->deferred_data_size + data_size); CHECK_ALLOC(p, "malloc"); memcpy(p, data, data_size); memcpy(p + data_size, q->deferred_data, q->deferred_data_size); free(q->begin_deferred_data); q->begin_deferred_data = p; q->deferred_data = p; q->deferred_data_size += (int)data_size; return 0; } /* tries to flush some of the data for specified queue * Upon success, the number of bytes written is returned. * Upon failure, -1 returned (e.g. connexion closed) * */ int flush_deferred(struct queue *q) { ssize_t n; print_message(msg_fd, "flushing deferred data to fd %d\n", q->fd); n = write(q->fd, q->deferred_data, q->deferred_data_size); if (n == -1) return (int)n; if (n == q->deferred_data_size) { /* All has been written -- release the memory */ free(q->begin_deferred_data); q->begin_deferred_data = NULL; q->deferred_data = NULL; q->deferred_data_size = 0; } else { /* There is data left */ q->deferred_data += n; q->deferred_data_size -= (int)n; } return (int)n; } void init_cnx(struct connection *cnx) { memset(cnx, 0, sizeof(*cnx)); cnx->q[0].fd = -1; cnx->q[1].fd = -1; cnx->proto = NULL; } void dump_connection(struct connection *cnx) { print_message(msg_int_error, "type: %s\n", cnx->type == SOCK_DGRAM ? "UDP" : "TCP"); print_message(msg_int_error, "state: %d\n", cnx->state); print_message(msg_int_error, "0: fd %d, %d deferred\n", cnx->q[0].fd, cnx->q[0].deferred_data_size); hexdump(msg_int_error, cnx->q[0].deferred_data, cnx->q[0].deferred_data_size); print_message(msg_int_error, "1: fd %d, %d deferred\n", cnx->q[1].fd, cnx->q[1].deferred_data_size); hexdump(msg_int_error, cnx->q[1].deferred_data, cnx->q[1].deferred_data_size); } /* *cnx must have its proto field probed already. * If required, increment the connection count for this protocol. * Returns 1 if connection count is exceeded, 0 otherwise */ int inc_proto_connections(struct sslhcfg_protocols_item* proto) { proto->num_connections++; if (proto->max_connections_is_present) { print_message(msg_connections, "Proto %s +1: %d/%d cnx\n", proto->name, proto->num_connections, proto->max_connections); if (proto->num_connections > proto->max_connections) { print_message(msg_connections_error, "%s: too many connections, dropping\n", proto->name); return 1; } } return 0; } void dec_proto_connections(struct sslhcfg_protocols_item* proto) { if (proto) { proto->num_connections--; print_message(msg_connections, "Proto %s -1: %d/%d cnx\n", proto->name, proto->num_connections, proto->max_connections); } } /* * moves data from one fd to other * * returns number of bytes copied if success * returns 0 (FD_CNXCLOSED) if incoming socket closed * returns FD_NODATA if no data was available * returns FD_STALLED if data was read, could not be written, and has been * stored in temporary buffer. */ int fd2fd(struct queue *target_q, struct queue *from_q) { char buffer[BUFSIZ]; int target, from; ssize_t size_r, size_w; target = target_q->fd; from = from_q->fd; size_r = read(from, buffer, sizeof(buffer)); if (size_r == -1) { switch (errno) { case EAGAIN: return FD_NODATA; case ECONNRESET: case ENOTSOCK: case EPIPE: return FD_CNXCLOSED; } } CHECK_RES_RETURN(size_r, "read",FD_CNXCLOSED); if (size_r == 0) return FD_CNXCLOSED; size_w = write(target, buffer, size_r); /* process -1 when we know how to deal with it */ if (size_w == -1) { switch (errno) { case EAGAIN: /* write blocked: Defer data */ defer_write(target_q, buffer, size_r); return FD_STALLED; case ECONNRESET: case EPIPE: /* remote end closed -- drop the connection */ return FD_CNXCLOSED; } } else if (size_w < size_r) { /* incomplete write -- defer the rest of the data */ defer_write(target_q, buffer + size_w, size_r - size_w); return FD_STALLED; } CHECK_RES_RETURN(size_w, "write", FD_CNXCLOSED); return (int)size_w; } /* returns a string that prints the IP and port of the sockaddr */ char* sprintaddr(char* buf, size_t size, struct addrinfo *a) { char host[NI_MAXHOST], serv[NI_MAXSERV]; int res; memset(host, 0, sizeof(host)); memset(serv, 0, sizeof(serv)); res = getnameinfo(a->ai_addr, a->ai_addrlen, host, sizeof(host), serv, sizeof(serv), cfg.numeric ? NI_NUMERICHOST | NI_NUMERICSERV : 0 ); if (res) { print_message(msg_system_error, "sprintaddr:getnameinfo: %s\n", gai_strerror(res)); /* Name resolution failed: do it numerically instead */ res = getnameinfo(a->ai_addr, a->ai_addrlen, host, sizeof(host), serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV); /* should not fail but... */ if (res) { print_message(msg_system_error, "sprintaddr:getnameinfo(NUM): %s\n", gai_strerror(res)); strcpy(host, "?"); strcpy(serv, "?"); } } snprintf(buf, size, "%s:%s", host, serv); return buf; } /* Turns a hostname and port (or service) into a list of struct addrinfo * On success, returns 0 * On failure, returns -1 or one of getaddrinfo() codes */ int resolve_split_name(struct addrinfo **out, char* host, char* serv) { struct addrinfo hint; char *end; int res; memset(&hint, 0, sizeof(hint)); hint.ai_family = PF_UNSPEC; hint.ai_socktype = SOCK_STREAM; /* If it is a RFC-Compliant IPv6 address ("[1234::12]:443"), remove brackets * around IP address */ if (host[0] == '[') { end = strrchr(host, ']'); if (!end) { print_message(msg_config_error, "%s: no closing bracket in IPv6 address?\n", host); return -1; } host++; /* skip first bracket */ *end = 0; /* remove last bracket */ } res = getaddrinfo(host, serv, &hint, out); if (res) print_message(msg_system_error, "resolve_split_name: %s `%s:%s'\n", gai_strerror(res), host, serv); return res; } /* turns a "hostname:port" string into a list of struct addrinfo; out: list of newly allocated addrinfo (see getaddrinfo(3)); freeaddrinfo(3) when done fullname: input string -- it gets clobbered */ void resolve_name(struct addrinfo **out, char* fullname) { char *serv, *host; int res; /* Find port */ char *sep = strrchr(fullname, ':'); if (!sep) { /* No separator: parameter is just a port */ print_message(msg_config_error, "%s: names must be fully specified as hostname:port\n", fullname); exit(1); } serv = sep+1; *sep = 0; host = fullname; res = resolve_split_name(out, host, serv); if (res) { print_message(msg_config_error, "%s `%s'\n", gai_strerror(res), fullname); if (res == EAI_SERVICE) print_message(msg_config_error, "(Check you have specified all ports)\n"); exit(4); } } /* Fills a connection description; returns 0 on failure */ int get_connection_desc(struct connection_desc* desc, const struct connection *cnx) { int res; struct addrinfo addr; struct sockaddr_storage ss; addr.ai_addr = (struct sockaddr*)&ss; addr.ai_addrlen = sizeof(ss); res = getpeername(cnx->q[0].fd, addr.ai_addr, &addr.ai_addrlen); if (res == -1) return 0; /* Can happen if connection drops before we get here. In that case, don't log anything (there is no connection) */ sprintaddr(desc->peer, sizeof(desc->peer), &addr); addr.ai_addrlen = sizeof(ss); res = getsockname(cnx->q[0].fd, addr.ai_addr, &addr.ai_addrlen); if (res == -1) return 0; sprintaddr(desc->service, sizeof(desc->service), &addr); addr.ai_addrlen = sizeof(ss); res = getpeername(cnx->q[1].fd, addr.ai_addr, &addr.ai_addrlen); if (res == -1) return 0; sprintaddr(desc->target, sizeof(desc->target), &addr); addr.ai_addrlen = sizeof(ss); res = getsockname(cnx->q[1].fd, addr.ai_addr, &addr.ai_addrlen); if (res == -1) return 0; sprintaddr(desc->local, sizeof(desc->local), &addr); return 1; } void set_proctitle_shovel(struct connection_desc* desc, const struct connection *cnx) { #ifdef HAVE_LIBBSD struct connection_desc d; if (!desc) { desc = &d; get_connection_desc(desc, cnx); } setproctitle("shovel %s %s->%s => %s->%s", cnx->proto->name, desc->peer, desc->service, desc->local, desc->target); #endif } /* libwrap (tcpd): check the connection is legal. This is necessary because * the actual server will only see a connection coming from localhost and can't * apply the rules itself. * * Returns -1 if access is denied, 0 otherwise */ int check_access_rights(int in_socket, const char* service) { #ifdef HAVE_LIBWRAP union { struct sockaddr saddr; struct sockaddr_storage ss; } peer; socklen_t size = sizeof(peer); char addr_str[NI_MAXHOST], host[NI_MAXHOST]; int res; res = getpeername(in_socket, &peer.saddr, &size); CHECK_RES_RETURN(res, "getpeername", res); /* extract peer address */ res = getnameinfo(&peer.saddr, size, addr_str, sizeof(addr_str), NULL, 0, NI_NUMERICHOST); if (res) { print_message(msg_system_error, "getnameinfo(NI_NUMERICHOST):%s\n", gai_strerror(res)); strcpy(addr_str, STRING_UNKNOWN); } /* extract peer name */ strcpy(host, STRING_UNKNOWN); if (!cfg.numeric) { res = getnameinfo(&peer.saddr, size, host, sizeof(host), NULL, 0, NI_NAMEREQD); if (res) { print_message(msg_system_error, "getnameinfo(NI_NAMEREQD):%s\n", gai_strerror(res)); } } if (!hosts_ctl((char*)service, host, addr_str, STRING_UNKNOWN)) { print_message(msg_connections, "connection from %s(%s): access denied\n", host, addr_str); close(in_socket); return -1; } #endif return 0; } volatile sig_atomic_t received_sigchld; void sig_sigchld(int sig) { received_sigchld = 1; } void setup_signals(void) { int res; struct sigaction action; /* Set SIGCHLD to sig_sigchld() */ memset(&action, 0, sizeof(action)); action.sa_handler = sig_sigchld; action.sa_flags = SA_NOCLDSTOP; res = sigaction(SIGCHLD, &action, NULL); CHECK_RES_DIE(res, "sigaction"); /* Set SIGTERM to exit. For some reason if it's not set explicitly, * coverage information is lost when killing the process */ memset(&action, 0, sizeof(action)); action.sa_handler = exit; res = sigaction(SIGTERM, &action, NULL); CHECK_RES_DIE(res, "sigaction"); /* Ignore SIGPIPE . */ action.sa_handler = SIG_IGN; res = sigaction(SIGPIPE, &action, NULL); CHECK_RES_DIE(res, "sigaction"); } /* Ask OS to keep capabilities over a setuid(nonzero) */ void set_keepcaps(int val) { #if HAVE_LIBCAP int res; res = prctl(PR_SET_KEEPCAPS, val, 0, 0, 0); if (res) { perror("prctl"); exit(1); } #endif } /* Returns true if anything requires transparent proxying. */ static int use_transparent(void) { #if HAVE_LIBCAP if (cfg.transparent) return 1; for (int i = 0; i < cfg.protocols_len; i++) if (cfg.protocols[i].transparent) return 1; #endif return 0; } /* set needed capabilities for effective and permitted, clear rest * IN: cap_net_admin: set to 1 to set CAP_NET_RAW * */ void set_capabilities(int cap_net_admin) { #if HAVE_LIBCAP int res; cap_t caps; cap_value_t cap_list[10]; int ncap = 0; if (cap_net_admin) cap_list[ncap++] = CAP_NET_RAW; caps = cap_init(); #define _cap_set_flag(flag) do { \ res = cap_clear_flag(caps, flag); \ CHECK_RES_DIE(res, "cap_clear_flag(" #flag ")"); \ if (ncap > 0) { \ res = cap_set_flag(caps, flag, ncap, cap_list, CAP_SET); \ CHECK_RES_DIE(res, "cap_set_flag(" #flag ")"); \ } \ } while(0) _cap_set_flag(CAP_EFFECTIVE); _cap_set_flag(CAP_PERMITTED); #undef _cap_set_flag res = cap_set_proc(caps); CHECK_RES_DIE(res, "cap_set_proc"); res = cap_free(caps); if (res) { perror("cap_free"); exit(1); } #endif } /* We don't want to run as root -- drop privileges if required */ void drop_privileges(const char* user_name, const char* chroot_path) { int res; struct passwd *pw = NULL; if (user_name) { pw = getpwnam(user_name); if (!pw) { print_message(msg_config_error, "%s: not found\n", user_name); exit(2); } print_message(msg_config, "turning into %s\n", user_name); } if (chroot_path) { print_message(msg_config, "chrooting into %s\n", chroot_path); res = chroot(chroot_path); CHECK_RES_DIE(res, "chroot"); } if (user_name) { set_keepcaps(1); /* remove extraneous groups in case we belong to several extra groups * that may have unwanted rights. If non-root when calling setgroups(), * it fails, which is fine because... we have no unwanted rights * (see POS36-C for security context) * */ setgroups(0, NULL); res = setgid(pw->pw_gid); CHECK_RES_DIE(res, "setgid"); res = setuid(pw->pw_uid); CHECK_RES_DIE(res, "setuid"); set_capabilities(use_transparent()); set_keepcaps(0); } } #ifndef O_NOFOLLOW #define O_NOFOLLOW 0 #endif /* Writes my PID */ void write_pid_file(const char* pidfile) { int fd; char pidbuf[32]; size_t len, written = 0; ssize_t res; /* Format PID as string */ len = snprintf(pidbuf, sizeof(pidbuf), "%d\n", getpid()); if (len >= sizeof(pidbuf)) { print_message(msg_system_error, "write_pid_file: PID string too long\n"); return; } /* Open file with O_NOFOLLOW to prevent symlink attacks (Similar to CVE-2020-28935) */ fd = open(pidfile, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW ,0644); if (fd == -1) { print_message(msg_system_error, "write_pid_file: %s: %s\n", pidfile, strerror(errno)); return; } /* Write PID to file with proper error handling */ while (written < len) { res = write(fd, pidbuf + written, len - written); if (res == -1) { if (errno == EINTR || errno == EAGAIN) continue; print_message(msg_system_error, "write_pid_file: write: %s\n", strerror(errno)); break; } written += res; } /* Close file */ if (close(fd) == -1) { print_message(msg_system_error, "write_pid_file: close: %s\n", strerror(errno)); } } sslh-2.3.1/common.h000066400000000000000000000135651515234404100141400ustar00rootroot00000000000000#ifndef COMMON_H #define COMMON_H /* FD_SETSIZE is 64 on Cygwin, which is really low. Just redefining it is * enough for the macros to adapt (http://support.microsoft.com/kb/111855) */ #ifdef __CYGWIN__ #undef FD_SETSIZE #define FD_SETSIZE 4096 #endif /* Cygwin does not define some symbols * */ #ifndef SA_NOCLDWAIT #define SA_NOCLDWAIT 0 #endif #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef LIBCAP #include #include #endif #ifdef __APPLE__ #include #endif #include "config.h" #include "version.h" #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define CHECK_RES_DIE(res, str) \ if (res == -1) { \ print_message(msg_system_error, "%s:%d:", __FILE__, __LINE__); \ perror(str); \ exit(1); \ } #define CHECK_RES_RETURN(res, str, ret) \ if (res == -1) { \ print_message(msg_system_error, "%s:%d:%s:%d:%s\n", __FILE__, __LINE__, str, errno, strerror(errno)); \ return ret; \ } #define CHECK_ALLOC(a, str) \ if (!a) { \ print_message(msg_system_error, "%s:%d:", __FILE__, __LINE__); \ perror(str); \ exit(1); \ } #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #if 1 #define TRACE fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); #else #define TRACE #endif #ifndef IP_FREEBIND #define IP_FREEBIND 0 #endif #ifndef TCP_FASTOPEN #define TCP_FASTOPEN 0 #endif #ifndef TCP_FASTOPEN_CONNECT #define TCP_FASTOPEN_CONNECT 30 /* Attempt FastOpen with connect. */ #endif enum connection_state { ST_PROBING=1, /* Waiting for timeout to find where to forward */ ST_SHOVELING /* Connexion is established */ }; /* A 'queue' is composed of a file descriptor (which can be read from or * written to), and a queue for deferred write data */ struct queue { int fd; void *begin_deferred_data; void *deferred_data; int deferred_data_size; }; /* Double linked list for timeout management */ typedef struct { struct connection* head; struct connection* tail; } dl_list; struct connection { int type; /* SOCK_DGRAM | SOCK_STREAM */ struct sslhcfg_protocols_item* proto; /* Where to connect to */ /* SOCK_STREAM */ struct listen_endpoint* endpoint; /* Client-facing listen fd */ enum connection_state state; time_t probe_timeout; /* q[0]: queue for external connection (client); * q[1]: queue for internal connection (httpd or sshd); * */ struct queue q[2]; /* SOCK_DGRAM */ struct sockaddr_storage client_addr; /* Contains the remote client address */ socklen_t addrlen; int local_endpoint; /* Contains the local address */ time_t last_active; /* double linked list of timeouts */ struct connection *timeout_prev, *timeout_next; /* We need one local socket for each target server, so we know where to * forward server responses */ int target_sock; }; struct listen_endpoint { int socketfd; /* file descriptor of listening socket */ int type; /* SOCK_DGRAM | SOCK_STREAM */ int family; /* AF_INET | AF_UNIX */ int num_connections; /* How many active connections on this endpoint */ struct sslhcfg_listen_item* endpoint_cfg; /* the configuration item that corresponds to this endpoint */ }; #define FD_CNXCLOSED 0 #define FD_NODATA -1 #define FD_STALLED -2 /* String description of a connection */ #define MAX_NAMELENGTH (NI_MAXHOST + NI_MAXSERV + 1) struct connection_desc { char peer[MAX_NAMELENGTH], service[MAX_NAMELENGTH], local[MAX_NAMELENGTH], target[MAX_NAMELENGTH]; }; typedef enum { NON_BLOCKING = 0, BLOCKING = 1 } connect_blocking; /* common.c */ void init_cnx(struct connection *cnx); int set_nonblock(int fd); void connect_addr(struct connection *cnx, int fd_from, connect_blocking blocking); int fd2fd(struct queue *target, struct queue *from); char* sprintaddr(char* buf, size_t size, struct addrinfo *a); void resolve_name(struct addrinfo **out, char* fullname); int get_connection_desc(struct connection_desc* desc, const struct connection *cnx); void log_connection(struct connection_desc* desc, const struct connection *cnx); void set_proctitle_shovel(struct connection_desc* desc, const struct connection *cnx); int check_access_rights(int in_socket, const char* service); void setup_signals(void); void setup_syslog(const char* bin_name); void drop_privileges(const char* user_name, const char* chroot_path); void set_capabilities(int cap_net_admin); void write_pid_file(const char* pidfile); void dump_connection(struct connection *cnx); int inc_proto_connections(struct sslhcfg_protocols_item* cnx); void dec_proto_connections(struct sslhcfg_protocols_item* cnx); int resolve_split_name(struct addrinfo **out, char* hostname, char* port); int start_listen_sockets(struct listen_endpoint *sockfd[]); int defer_write(struct queue *q, void* data, ssize_t data_size); void defer_skip(struct queue *q, ssize_t data_size); int defer_write_before(struct queue *q, void* data, ssize_t data_size); int flush_deferred(struct queue *q); extern struct sslhcfg_item cfg; extern struct addrinfo *addr_listen; extern const char* server_type; #if defined(__APPLE__) && (MAC_OS_X_VERSION_MIN_REQUIRED < 1080) extern int hosts_ctl(); #endif /* sslh-fork.c */ void main_inetd(void); void main_loop(struct listen_endpoint *listen_sockets, int num_addr_listen); /* landlock.c */ void setup_landlock(void); /* sslh-fork.c or processes.c, depending on the model */ void setup_sigchld(void); #endif sslh-2.3.1/config.h.in000066400000000000000000000006531515234404100145140ustar00rootroot00000000000000 #ifndef CONFIG_H /* Template for config.h, filled by `configure`. */ /* Libwrap, to support host_ctl, /etc/allow and /etc/deny */ #undef HAVE_LIBWRAP /* Landlock sandboxing Linux LSM */ #undef HAVE_LANDLOCK /* Support for Proxy-protocol using libproxyprotocol */ #undef HAVE_PROXYPROTOCOL /* libcap support, to use Linux capabilities */ #undef HAVE_LIBCAP /* libbsd, to change process name */ #undef HAVE_LIBBSD #endif sslh-2.3.1/configure000077500000000000000000004047661515234404100144150ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.71. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="as_nop=: if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else \$as_nop case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else \$as_nop exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else $as_nop as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='' PACKAGE_TARNAME='' PACKAGE_VERSION='' PACKAGE_STRING='' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_STDIO_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_c_list= ac_subst_vars='LTLIBOBJS LIBOBJS OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Does the compiler advertise C89 conformance? Do not test the value of __STDC__, because some compilers set it to 0 while being otherwise adequately conformant. */ #if !defined __STDC__ # error "Compiler does not advertise C89 conformance" #endif #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not \xHH hex character constants. These do not provoke an error unfortunately, instead are silently treated as an "x". The following induces an error, until -std is added to get proper ANSI mode. Curiously \x00 != x always comes out true, for an array size at least. It is necessary to write \x00 == 0 to get something that is true only with -std. */ int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) '\''x'\'' int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' // Does the compiler advertise C99 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[0] = argv[0][0]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || dynamic_array[ni.number - 1] != 543); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' // Does the compiler advertise C11 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" ac_config_files="$ac_config_files Makefile" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 printf %s "checking whether the C compiler works... " >&6; } ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else $as_nop ac_file='' fi if test -z "$ac_file" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 printf %s "checking for C compiler default output file name... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for hosts_ctl in -lwrap" >&5 printf %s "checking for hosts_ctl in -lwrap... " >&6; } if test ${ac_cv_lib_wrap_hosts_ctl+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lwrap $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char hosts_ctl (); int main (void) { return hosts_ctl (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_wrap_hosts_ctl=yes else $as_nop ac_cv_lib_wrap_hosts_ctl=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_wrap_hosts_ctl" >&5 printf "%s\n" "$ac_cv_lib_wrap_hosts_ctl" >&6; } if test "x$ac_cv_lib_wrap_hosts_ctl" = xyes then : printf "%s\n" "#define HAVE_LIBWRAP 1" >>confdefs.h LIBS="$LIBS -lwrap" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cap_get_proc in -lcap" >&5 printf %s "checking for cap_get_proc in -lcap... " >&6; } if test ${ac_cv_lib_cap_cap_get_proc+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lcap $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char cap_get_proc (); int main (void) { return cap_get_proc (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_cap_cap_get_proc=yes else $as_nop ac_cv_lib_cap_cap_get_proc=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_cap_get_proc" >&5 printf "%s\n" "$ac_cv_lib_cap_cap_get_proc" >&6; } if test "x$ac_cv_lib_cap_cap_get_proc" = xyes then : printf "%s\n" "#define HAVE_LIBCAP 1" >>confdefs.h LIBS="$LIBS -lcap" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for setproctitle in -lbsd" >&5 printf %s "checking for setproctitle in -lbsd... " >&6; } if test ${ac_cv_lib_bsd_setproctitle+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char setproctitle (); int main (void) { return setproctitle (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_bsd_setproctitle=yes else $as_nop ac_cv_lib_bsd_setproctitle=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_setproctitle" >&5 printf "%s\n" "$ac_cv_lib_bsd_setproctitle" >&6; } if test "x$ac_cv_lib_bsd_setproctitle" = xyes then : printf "%s\n" "#define HAVE_LIBBSD 1" >>confdefs.h LIBS="$LIBS -lbsd" fi ac_header= ac_cache= for ac_item in $ac_header_c_list do if test $ac_cache; then ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then printf "%s\n" "#define $ac_item 1" >> confdefs.h fi ac_header= ac_cache= elif test $ac_header; then ac_cache=$ac_item else ac_header=$ac_item fi done if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes then : printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h fi for ac_header in linux/landlock.h do : ac_fn_c_check_header_compile "$LINENO" "linux/landlock.h" "ac_cv_header_linux_landlock_h" "$ac_includes_default" if test "x$ac_cv_header_linux_landlock_h" = xyes then : printf "%s\n" "#define HAVE_LINUX_LANDLOCK_H 1" >>confdefs.h printf "%s\n" "#define HAVE_LANDLOCK 1" >>confdefs.h fi done for ac_header in proxy_protocol.h do : ac_fn_c_check_header_compile "$LINENO" "proxy_protocol.h" "ac_cv_header_proxy_protocol_h" "$ac_includes_default" if test "x$ac_cv_header_proxy_protocol_h" = xyes then : printf "%s\n" "#define HAVE_PROXY_PROTOCOL_H 1" >>confdefs.h printf "%s\n" "#define HAVE_PROXYPROTOCOL 1" >>confdefs.h LIBS="$LIBS -lproxyprotocol" fi done LIBS="$LIBS" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to the package provider." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" Copyright (C) 2021 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi sslh-2.3.1/configure.ac000066400000000000000000000013151515234404100147530ustar00rootroot00000000000000 dnl Use autoconf to generate the `configure` script from this and Makefile.in dnl This is awkardly adapted from https://github.com/edrosten/autoconf_tutorial dnl (all mistakes mine) AC_INIT AC_CONFIG_HEADERS(config.h) AC_CONFIG_FILES([Makefile]) AC_CHECK_LIB([wrap], [hosts_ctl], [AC_DEFINE(HAVE_LIBWRAP) LIBS="$LIBS -lwrap" ], []) AC_CHECK_LIB([cap], [cap_get_proc], [AC_DEFINE(HAVE_LIBCAP) LIBS="$LIBS -lcap" ], []) AC_CHECK_LIB([bsd], [setproctitle], [AC_DEFINE(HAVE_LIBBSD) LIBS="$LIBS -lbsd" ], []) AC_CHECK_HEADERS(linux/landlock.h, AC_DEFINE(HAVE_LANDLOCK), []) AC_CHECK_HEADERS(proxy_protocol.h, [AC_DEFINE(HAVE_PROXYPROTOCOL) LIBS="$LIBS -lproxyprotocol" ], []) LIBS="$LIBS" AC_SUBST([LIBS]) AC_OUTPUT sslh-2.3.1/container-entrypoint.sh000077500000000000000000000061251515234404100172230ustar00rootroot00000000000000#!/bin/sh # SPDX-License-Identifier: GPL2-or-later # # Copyright (C) 2023 Olliver Schinagl # # A beginning user should be able to docker run image bash (or sh) without # needing to learn about --entrypoint # https://github.com/docker-library/official-images#consistency set -eu bin='sslh' # run command if it is not starting with a "-" and is an executable in PATH if [ "${#}" -le 0 ] || \ [ "${1#-}" != "${1}" ] || \ [ -d "${1}" ] || \ ! command -v "${1}" > '/dev/null' 2>&1; then entrypoint='true' fi unconfigure_iptables() { echo "Received SIG TERM/INT/KILL. Removing iptables / routing changes" set +e # Don't exit if got error set -x iptables -t raw -D PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP iptables -t mangle -D POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP iptables -t nat -D OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f iptables -t mangle -D OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f ip rule del fwmark 0x1 lookup 100 ip route del local 0.0.0.0/0 dev lo table 100 if [ $(cat /proc/sys/net/ipv6/conf/all/disable_ipv6) -eq 0 ]; then ip6tables -t raw -D PREROUTING ! -i lo -d ::1/128 -j DROP ip6tables -t mangle -D POSTROUTING ! -o lo -s ::1/128 -j DROP ip6tables -t nat -D OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f ip6tables -t mangle -D OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f ip -6 rule del fwmark 0x1 lookup 100 ip -6 route del local ::/0 dev lo table 100 fi set -e set +x } configure_iptables() { echo "Configuring iptables and routing..." set +e # Don't exit if got error set -x iptables -t raw -A PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP iptables -t mangle -A POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP iptables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f iptables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f ip rule add fwmark 0x1 lookup 100 ip route add local 0.0.0.0/0 dev lo table 100 if [ $(cat /proc/sys/net/ipv6/conf/all/disable_ipv6) -eq 0 ]; then ip6tables -t raw -A PREROUTING ! -i lo -d ::1/128 -j DROP ip6tables -t mangle -A POSTROUTING ! -o lo -s ::1/128 -j DROP ip6tables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f ip6tables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f ip -6 rule add fwmark 0x1 lookup 100 ip -6 route add local ::/0 dev lo table 100 fi set -e set +x } for _args in "${@}" ; do if [ "${_args:-}" = '--transparent' ] ; then echo '--transparent flag is set' configure_iptables trap unconfigure_iptables TERM INT KILL break fi done # Drop privileges and run as sslh user sslh_cmd="${entrypoint:+${bin}} ${@}" echo "Executing with user 'sslh': ${sslh_cmd}" exec su - sslh -c "${sslh_cmd}" & wait "${!}" exit 0 sslh-2.3.1/doc/000077500000000000000000000000001515234404100132325ustar00rootroot00000000000000sslh-2.3.1/doc/Daisy-Chaining-Transparency-Explained.md000066400000000000000000000435231515234404100227300ustar00rootroot00000000000000# Daisy-Chaining-Transparency # This documentation goes a level deeper, what happens in the operating system with IP-addresses, and why some combinations of programs are failing, when they use the same transparency method. There are situations, where you need to combine two applications, both working as ip-transparent proxies, to reach your goal. One example is, having nginx or stunnel as an proxytunnel-endpoint for tls tunneled ssh connections through https-proxies. An example for such a combination will be desribed at the end of this article. Unfortunately you will see a lot of errors popping out: **Address already in use** [This article from Cloudflare blog](https://blog.cloudflare.com/how-to-stop-running-out-of-ephemeral-ports-and-start-to-love-long-lived-connections) explains why this is happening, while it is describing the solution to another problem. However this is a close relative to our problem. Let us look to the following example: We have sslh (S) accepting connections from a client (C) and forwarding one of those connections to a man-in-the-middle (M), which finally forwards this connection to sshd. If everything works perfectly, we would like to see those connections. ![Dataflow-Of-Daisy-Chain](./detailed-ip-transparency.png) But unfortunately we are receiving in many constellations errors, when M tries to open its connection to our final target sshd, here called T. Let us look more close, why that is happening. We need for this two terminal windows on the same server. ### First example, uncooperative applications ### As the problem has nothing to do with transparency itself, but only of reuse of same IP-addresses and ports, we avoid the overhead of the additional capablities, to keep the example easy and clear. In the first terminal we are starting python3 and entering the following three lines: ``` user@host:~$ python3 Python 3.11.2 (main, May 2 2024, 11:59:08) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import socket >>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) >>> sock.bind(("192.168.255.254", 12345)) >>> ``` Now we are going to the second terminal window, and trying just the same: ``` Python 3.11.2 (main, May 2 2024, 11:59:08) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import socket >>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) >>> sock.bind(("192.168.255.254", 12345)) Traceback (most recent call last): File "", line 1, in OSError: [Errno 98] Address already in use sock.bind(("192.168.255.254", 12346)) ##this however works!! ``` Here we are getting the error, which caused many of us hours of research. The problem is caused by the fact, that the kernel does not know at the moment of the bind()-call, how we want to use the socket. If we use this as a server socket, and will do a listen()-call as next, this will not work, as for server sockets, the two-value tuple ADDRESS:PORT needs to be unique only to the process, tied to this socket. That is the reason, that there are port ranges, reserved for servers, where the administrator is responsible not to assign the same port to two applications. But as server ports are coming from a range, which will not be used for client connections, a server can be sure, that if it is started at any time in the future, no outgoing client has used its port for an outbound connection. Clients are usually using ports from a so called [ephemeral port range](https://en.wikipedia.org/wiki/Ephemeral_port). However, for clients each connection is valid, as long as one value in the four-tuples describing the connection is different. In our example above, the two values from the destination are different, so this connection could be established (in theory) without conflicts. To make that happen, you need to deploy a special socket option to this socket, to explain, that we "know the risks" and we will reuse the ip-port combination. And, as we see from the second bind() in the second example, the error message: _**Address already in use**_ really means: _**Address:Port already in use**_ ### Taking Care, part I ### Ok, now we are entering our two terminals again, pressing Ctrl-D to finish python, and start a new session like this in both terminals: ``` user@host:~$ python3 Python 3.11.2 (main, May 2 2024, 11:59:08) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import socket >>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) >>> sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) >>> sock.bind(("192.168.255.254", 12345)) >>> ``` And we will see, that the problem is solved, when both applications are taking care. ### Taking Care, part II ### Ok, now we are going back to our terminals, pressing again Ctrl-D to finish python, and start new sessions like this: In the first terminal we repeat the input from our first example, without the setsockopt() call: ``` user@host:~$ python3 Python 3.11.2 (main, May 2 2024, 11:59:08) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import socket >>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) >>> sock.bind(("192.168.255.254", 12345)) >>> ``` in the second terminal, we enter our modified cooperative example: ``` user@host:~$ python3 Python 3.11.2 (main, May 2 2024, 11:59:08) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import socket >>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) >>> sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) >>> sock.bind(("192.168.255.254", 12345)) Traceback (most recent call last): File "", line 1, in OSError: [Errno 98] Address already in use >>> ``` Oops, here is our error again. And this is the reason, why I called this method "cooperative". As the first application has bound to that IP:PORT combination, without telling, that "it knows the risk", the kernel denies us, to use this combinations, as we may break the already active application. The first application is not "cooperative" :-( Ok, but the kernel gives as some more possibilities: As we now get connections from a uncoperative application, we can no longer use the Client-IP-Port combination. We need to use a conflict free port for the client IP, to succeed. So lets get back to terminal 2 and continue after the error with the following commands: ``` user@host:~$ python3 Python 3.11.2 (main, May 2 2024, 11:59:08) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import socket >>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) >>> sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) >>> sock.bind(("192.168.255.254", 12345)) Traceback (most recent call last): File "", line 1, in OSError: [Errno 98] Address already in use >>> sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 0) >>> sock.setsockopt(socket.SOL_IP, socket.IP_BIND_ADDRESS_NO_PORT, 1) >>> sock.bind(("192.168.255.254", 0)) >>> ``` This last example makes it neccessary, that you use a recent version of the python3 socket library, as older versions, have the option _IP_BIND_ADDRESS_NO_PORT_ not yet defined. With his behaviour, we are telling the kernel, that the kernel should assign us a conflict free port address at latest possible moment, while calling connect(). From `man ip`: ``` Inform the kernel to not reserve an ephemeral port when using bind(2) with a port number of 0. The port will later be automatically chosen at connect(2) time, in a way that allows sharing a source port as long as the 4-tuple is unique. ``` Ok, now with those two actions an application is really ready for cooperative working in ip-transparent chains. If you are running in problems, with any kind of application, where you are redirecting transparent traffic to from sslh, check the following: - Are you using a recent version of sslh, having the described feature enabled - are you using the most recent version of the other application If you can confirm both checks, tell the maintainers of the other application, about possible fixes, and send them a link to this article. ## Practical Use Of Daisy-Chaining: Proxytunnel Endpoint ## One reasons, why we want to combine two programs is related to the core functionality of sslh. You wish to hide your ssh connection behind a https port. But now you would like, to reach this port via the [proxy-tunnel application](https://github.com/proxytunnel/proxytunnel), though an restrictive http(s) proxy. This is in many cases, one of the few methods, to escape from restricted private networks, like in companies, schools and universities. Unfortunately, many of those proxy-servers will check, that the protocol leaving the proxy is really tls. Therefore you need and endpoint in your system, which will terminate the tls-connection and forward the encapsulated ssh stream to the sshd. Sslh can't do tls termination, as this is not a core job of tls. One of the solutions tried here is stunnel. Stunnel can do transparency like sslh, but unfortunately belongs to the uncooperative ip-transparent programs. At the time of writing this article, you can use stunnel as the first-in-chain, and a very recent sslh as second in chain. But nginx (or openresty) is capable of this, however it prefers (at least in the tested versions), mostly the second way just selecting a new random port and not (always) preserving the original source port, what makes debugging of events much easier. ``` stream { ssl_preread on; map $ssl_preread_server_name $name { default master.yourdomain.top; t1.yourdomain.top t1.yourdomain.top; t2.yourdomain.top t2.yourdomain.top; cryptic.foo.bar location.selfsigned.cert; } ## $destination port :443 is assumed, beeing as real ## webserver. Either anothe nginx http-server or apache ## or anything other ... map $ssl_preread_server_name $dest { default 192.168.255.254:443; t1.yourdomain.top 192.168.255.254:443; t2.yourdomain.top 192.168.255.254:444; cryptic.foo.notexist 192.168.255.254:445; } ## this is the server, to handle incoming tcp streams ## and dispatching them transparent to $dest ## 192.168.255.254:1443 is the address, where ## the front facing sslh sends traffic to server { listen 192.168.255.254:1443; proxy_connect_timeout 5s; proxy_timeout 3m; proxy_bind $remote_addr transparent; proxy_pass $dest; ssl_preread on; } ## this is a basic endpoint for proxy-tunnel connections server { listen 192.168.255.254:444 ssl; ssl_protocols TLSv1.2 TLSv1.3; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_prefer_server_ciphers on; ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"; ## give facl to the nginx user, see later in article ssl_certificate /etc/letsencrypt/live/$name/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/$name/privkey.pem; ssl_dhparam /etc/nginx/dhparam-nginx.pem; ssl_session_cache shared:MySSL:10m; ssl_session_tickets off; proxy_connect_timeout 5s; proxy_timeout 3m; proxy_bind $remote_addr transparent; proxy_pass 192.168.255.254:22 ; } ## this is a fancy destination, using some tricks, to fool ## some proxies. server { listen 192.168.255.254:445 ssl; ssl_protocols TLSv1.2 TLSv1.3; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_prefer_server_ciphers on; ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"; ## this points to a directory, containg a self signed certificate ## created with CN and SAN to an not officially existing ## domain, e.g. cryptic.foo.notexists ssl_certificate /etc/nginx/$name/fullchain.pem; ssl_certificate_key /etc/nginx/$name/privkey.pem; ssl_dhparam /etc/nginx/dhparam-nginx.pem; ssl_session_cache shared:MySSL:10m; ssl_session_tickets off; ## additional trick: requiring client certificate authentication ssl_client_certificate /etc/nginx/public.cert ; ssl_verify_client on ; proxy_connect_timeout 5s; proxy_timeout 3m; proxy_bind $remote_addr transparent; proxy_pass 192.168.255.254:22; } } ``` This nginx stream server shows a combination of different possibilities, how to establish an endpoint for proxytunnel or similar programs, to hide your ssh connection. Remember: Hiding ssh tunneled in tls does not neccessarly raise the security of your connection. In theory a combination of two methods may also lower the security. In addition there are more drawbacks: Such a connection needs more cpu on both ends for doing double crypto, and the throughput through he connection drops, as the ratio payload/header increases. the single ssh-packets are smaller, than usual. So it is not recommended for doing scp or sftp through such connections. ### Nginx Configration Explained ### However, there are situations, where this is the only way, to reach your server. So we have now this nginx instance helping us out. The server stanza listening on _192.168.255.254:1443_ is the main process, accepting incoming connections forwarded from sslh. It prereads tls SNI names, to get destination information. When in the nginx-configuration a variable is used, which is set by an map action, the mapping takes place just in that moment, when the variable needs to be expanded. So we have either default values, in case there is no SNI, or values for individual SNI. The connection stream is than forwarded ip-transparent to a given destination, which is itself another nginx instance, defined in the configuration file. #### The Standard TLS-Termination #### The server stanza listening on _192.168.255.254:444_ is a very basic TLS terminating endpoint. In most cases, a proxy is happy with a destination like this. Here nginx just terminates the TLS connection and shovels the incoming packets over to sshd in ip-transparent way. The proxytunnel configuration for this target will look like: ``` host t2.yourdomain.top ProxyCommand /path/to/proxytunnel -e -p PROXY-IP:3128 -d t2.yourdomain.top:443 ServerAliveInterval 30 ``` If you have no proxytunnel on your system, you can also use openssl. In this case the configuration looks like: ``` host t2-alias ProxyCommand openssl s_client -proxy PROXY-IP:3128 -connect t2.yourdomain.top:443 ServerAliveInterval 30 ``` `ssh ts-alias` will use this configuration. One point from the above configuration needs further explanation, as we just refer to our common letsencrypt store, for certificates. ##### Excurse To File ACLs ##### We are using here our common letsencrypt certificate store, as copying certificates after renewal is a pain in the as and prone to errors. A small script makes sure, that all applications can read the certificates: ``` for i in Debian-exim dovecot mail www-data nginx ; do setfacl -Rdm u:$i:rX ./archive/ setfacl -Rdm u:$i:rX ./live/ setfacl -Rm u:$i:rX ./archive/ setfacl -Rm u:$i:rX ./live/ for file in $( find ./live ./archive -type l,f ) ; do echo -e "$i $file set" setfacl -m u:$i:r $file done done ``` This script needs only to be run, when a new application user needs access. The first two lines are making sure (watch the **d**), that the given options on those directories will be the default for newly created files below. The uppercase **X** means, that **x**-access will only be granted to directories or files, having already **x** set for others. #### The Tricky TLS Termination #### The server stanza listening on _192.168.255.254:445_ is a more tricky TLS terminating endpoint. Some proxies are trying to inspect the destination, before letting you go. Some of them you can fool, others not. One trick can be to use an phantasy domain name with a self signed certificate, no dns server will ever resolve. As you are using this name as SNI name in your proxy-tunnel connection, it will work. This can be also a way, to hide your sshd, if someone, who knows you are using sslh tries to find your sshd. As long, as this person does not get access to proxies you are using, this may help in some situations. Another trick is, requiring a client certificate for authentication. This is in each case the much better approach, as you can combine this also with official connected domain names. Without the client certificate no sshd! The client certificate does not increase the above mentioned ratio between payload and headers, as this is only used while establishing the TLS connection. It prevents however a proxy, doing a parallel sneak to your destination, to figure out what is behind. I have seen proxies letting you connect with this method, others are denying access. To access this endpoint, the proxytunnel configuration inside `~/.ssh/config` will look like: ``` host cryptic.foo.notexists ProxyCommand /path/to/proxytunnel -e -c ~/public.cert -k ~/private.pem -C ~/myOwnCA.cert -p PROXY-IP:3128 -o cryptic.foo.notexists -d t1.yourdomain.top:443 ServerAliveInterval 30 ``` `-C` gives the certfile to your certificate used for selfsigning the server certificate. You can also set `-z` for not verifying the certificate, but that is not recommended! `t1.yourdomain.top` represents a valid domain name, where the listening sslh can be reached. This name is not taken for SNI, because **-o** sets our hidden SNI name. Whenever you enter `ssh cryptic.foo.notexists` you will get connected to your server! The best recommendation however is: Avoid self-signed certs, if you are not really sure what you are doing. sslh-2.3.1/doc/FAQ.md000066400000000000000000000141341515234404100141660ustar00rootroot00000000000000Frequently Asked Questions ========================== When something doesn't work, look up here... and if it still doesn't work, report how what was suggested here went. It's also worth reading [how to ask questions](http://www.catb.org/~esr/faqs/smart-questions.html) before posting on the mailing list or opening an issue in GitHub. Getting more info ================= There are several `verbose` options that each enable a set of messages, each related to some event type. See `example.cfg` for a list of them. If something doesn't work, you'll want to run `sslh` with lots of logging, and the logging directly in the terminal (Otherwise, logs are sent to `syslog`, and usually end up in `/var/log/auth.log`). There is a general `--verbose` option that will allow you to enable all messages: ``` sslh -v 3 -f -F myconfig.cfg ``` forward to [PROBE] failed:connect: Connection refused ===================================================== Usually this means `sslh` is configured to forward a protocol somewhere, but no service is listening on the target address. Check your `sslh` configuration, check the corresponding server really is listening and running. Finally, check the server is listening where you expect it to: ``` netstat -lpt ``` I get a segmentation fault! =========================== Well, it's not yours (fault): a segfault is always a bug in the programme. Usually standard use cases are well tested, so it may be related to something unusual in your configuration, or even something wrong, but it should still never result in a segfault. Thankfully, when they are deterministic, segfaults are usually fairly easy to fix if you're willing to run a few diagnostics to help the developer. First, make sure you have debug symbols: ``` $ file sslh-select sslh-select: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=a758ac75ff11f1ace577705b4d6627e301940b59, with debug_info, not stripped ``` Note `with debug_info, not stripped` at the end. If you don't have that, your distribution stripped the binary: you will need to get the source code and compile it yourself (that way, you will also get the latest version). Install `valgrind` and run `sslh` under it: ``` valgrind --leak-check=full ./sslh-fork -v 2 -f -F yourconfig.cfg ``` Report the full output to the mailing list or github. Valgrind is very powerful and gives precise hints of what is wrong and why. For example on `sslh` issue (#273)[https://github.com/yrutschle/sslh/issues/273]: ``` sudo valgrind --leak-check=full ./sslh-fork -v 2 -f -F /etc/sslh.cfg ==20037== Memcheck, a memory error detector ==20037== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==20037== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==20037== Command: ./sslh-fork -v 2 -f -F /etc/sslh.cfg ==20037== sslh-fork v1.21b-1-g2c93a01-dirty started --20037-- WARNING: unhandled arm-linux syscall: 403 --20037-- You may be able to write your own handler. --20037-- Read the file README_MISSING_SYSCALL_OR_IOCTL. --20037-- Nevertheless we consider this a bug. Please report --20037-- it at http://valgrind.org/support/bug_reports.html. ==20040== Conditional jump or move depends on uninitialised value(s) ==20040== at 0x112A3C: parse_tls_header (tls.c:162) ==20040== by 0x111CEF: is_tls_protocol (probe.c:214) ==20040== by 0x11239F: probe_client_protocol (probe.c:366) ==20040== by 0x10A8F7: start_shoveler (sslh-fork.c:98) ==20040== by 0x10AE9B: main_loop (sslh-fork.c:200) ==20040== by 0x1114FB: main (sslh-main.c:322) ==20040== ``` Here we see that something wrong is happening at `tls.c` line 162, and it's linked to an uninitialised value. Using sslh for virtual hosting ============================== Virtual hosting refers to having several domain names behind a single IP address. All Web servers handle this, but sometimes it can be useful to do it with `sslh`. TLS virtual hosting with SNI ---------------------------- For TLS, this is done very simply using Server Name Indication, SNI for short, which is a TLS extension whereby the client indicates the name of the server it wishes to connect to. This can be a very powerful way to separate several TLS-based services hosted behind the same port: simply name each service with its own hostname. For example, we could define `mail.rutschle.net`, `im.rutschle.net`, `www.rutschle.net`, all of which point to the same IP address. `sslh` uses the `sni_hostnames` setting of the TLS probe to do this, e.g.: ``` protocols: ( { name: "tls"; host: "localhost"; port: "993"; sni_hostnames: [ "mail.rutschle.net" ]; }, { name: "tls"; host: "localhost"; port: "xmpp-client"; sni_hostnames: [ "im.rutschle.net" ]; }, { name: "tls"; host: "localhost"; port: "4443"; sni_hostnames: [ "www.rutschle.net" ]; } ); ``` HTTP virtual hosting with regex ------------------------------- If you wish to serve several Web domains over HTTP through `sslh`, you can do this simply by using regular expressions on the Host specification part of the HTTP query. The following example forwards connections to `host_A.acme` to 192.168.0.2, and connections to `host_B.acme` to 192.168.0.3. ``` protocols: ( { name: "regex"; host: "192.168.0.2"; port: "80"; regex_patterns: ["^(GET|POST|PUT|OPTIONS|DELETE|HEADER) [^ ]* HTTP/[0-9.]*[\r\n]*Host: host_A.acme"] }, { name: "regex"; host: "192.168.0.3"; port: "80"; regex_patterns: ["^(GET|POST|PUT|OPTIONS|DELETE|HEADER) [^ ]* HTTP/[0-9.]*[\r\n]*Host: host_B.acme"] } ); ``` I get an error "Too many open files" ==================================== `sslh` used up all the file descriptors it can (1024 by default in Linux), which means it cannot create new connections. On some systems, you can increase the process limit with `ulimit -n 2048` (for example). Maybe more usefully, you can limit the connection usage based on protocols or listening address, as described in the [max_connections](max_connections.md) guide. sslh-2.3.1/doc/INSTALL.md000066400000000000000000000146721515234404100146740ustar00rootroot00000000000000Pre-built binaries ================== Docker images of `master` and of the tagged versions are available directly from [Github](https://github.com/yrutschle/sslh/pkgs/container/sslh). Windows binaries for Cygwin are graciously produced by nono303 on his [repository](https://github.com/nono303/sslh). Compile and install =================== Dependencies ------------ `sslh` uses: * [libconfig](http://www.hyperrealm.com/libconfig/). For Debian this is contained in package `libconfig-dev`. You can compile with or without it using USELIBCONFIG in the Makefile. * [libwrap](http://packages.debian.org/source/unstable/tcp-wrappers). For Debian, this is contained in packages `libwrap0-dev`. Presence of libwrap is checked by the configure script. * [libsystemd](http://packages.debian.org/source/unstable/libsystemd-dev), in package `libsystemd-dev`. You can compile with or without it using USESYSTEMD in the Makefile. * [libcap](http://packages.debian.org/source/unstable/libcap-dev), in package `libcap-dev`. Presence of libcap is checked by the configure script. * [libconfig++-dev](https://packages.debian.org/bookworm/libconfig++-dev), in package `lìbconfig++-dev` * libbsd, to enable to change the process name (as shown in `ps`, so each forked process shows what protocol and what connection it is serving), which requires `libbsd` at runtime, and `libbsd-dev` at compile-time. Presence of libbsd is checked by the configure script. * libpcre2, in package `libpcre2-dev`. You can compile with or without it using ENABLE_REGEX in the Makefile. * libev-dev, in package `libev-dev`. If you build a binary specifically and do not build `sslh-ev`, you don't need this. * [libproxyprotocol](https://github.com/kosmas-valianos/libproxyprotocol.git) to support HAProxy's [ProxyProtocol](https://www.haproxy.org/download/2.3/doc/proxy-protocol.txt). As this is not part of the distribution packages, set C_INCLUDE_PATH, LD_LIBRARY_PATH, and LIBRARY_PATH to the appropriate values: ``` export C_INCLUDE_PATH=/home/user/src/libproxyprotocol/src export LD_LIBRARY_PATH=/home/user/src/libproxyprotocol/libs export LIBRARY_PATH=/home/user/src/libproxyprotocol/libs ``` For OpenSUSE, these are contained in packages libconfig9 and libconfig-dev in repository For Fedora, you'll need packages `libconfig` and `libconfig-devel`: yum install libconfig libconfig-devel If you want to rebuild `sslh-conf.c` (after a `make distclean` for example), you will also need to add [conf2struct](https://www.rutschle.net/tech/conf2struct/README.html) (v1.5) to your path. The test scripts are written in Perl, and will require `IO::Socket::INET6` (`libio-socket-inet6-perl` in Debian). Compilation ----------- First you have to run `./configure` in the _**./sslh**_ directory. After this, the Makefile is created, and you can do your configuration changes in the Makefile. After each run of ./configure, those changes are gone and the Makefile is recreated. There are a couple of configuration options at the beginning of the Makefile: * `# override undefine HAVE_LANDLOCK` if you uncomment this line, sslh will be compiled without landlock. This works with gcc versions < 12. Otherwise, if your system has linux/landlock.h in the include path, the configure script creates a _**config.h**_ file, which defines HAVE_LANDLOCK. It is not enough, to set this to 0, you must delete it, when you don't wish to have landlock in your binary. * `USELIBWRAP` compiles support for host access control (see `hosts_access(3)`), you will need `libwrap` headers and library to compile (`libwrap0-dev` in Debian). * `USELIBCONFIG` compiles support for the configuration file. You will need `libconfig` headers to compile (`libconfig8-dev` in Debian). * `USESYSTEMD` compiles support for using systemd socket activation. You will need `systemd` headers to compile (`systemd-devel` in Fedora). * `USELIBBSD` compiles support for updating the process name (as shown by `ps`). * `USELIBCAP` compiles support for libcap, which allows to inherit capabilities to daughter-processes, which run as restricted users. You need this, when you wish to make sure, that the --user= parameter can be used, without setting capabilities etc. to your binaries, to make this work. Now you can do either a plain `make` to create the binaries, or you can do an `make install` to create the binaries and install them. Generating the configuration parser ----------------------------------- The configuration file and command line parser is generated by `conf2struct`, from `sslhconf.cfg`, which generates `sslh-conf.c` and `sslh-conf.h`. The resulting files are included in the source so `sslh` can be built without `conf2struct` installed. Further, to prevent build issues, `sslh-conf.[ch]` has no dependency to `sslhconf.cfg` in the Makefile. In the event of adding configuration settings, they need to be regenerated using `make c2s`. Binaries -------- The Makefile produces three different executables: `sslh-fork`, `sslh-select` and `sslh-ev`: * `sslh-fork` forks a new process for each incoming connection. It is well-tested and very reliable, but incurs the overhead of many processes. If you are going to use `sslh` for a "small" setup (less than a dozen ssh connections and a low-traffic https server) then `sslh-fork` is probably more suited for you. * `sslh-select` uses only one thread, which monitors all connections at once. It only incurs a 16 byte overhead per connection. Also, if it stops, you'll lose all connections, which means you can't upgrade it remotely. If you are going to use `sslh` on a "medium" setup (a few hundreds of connections), or if you are on a system where forking is expensive (e.g. Windows), `sslh-select` will be better. * `sslh-ev` is similar to `sslh-select`, but uses `libev` as a backend. This allows using specific kernel APIs that allow to manage thousands of connections concurrently. Installation ------------ * In general: ```sh ./configure make cp sslh-fork /usr/local/sbin/sslh cp basic.cfg /etc/sslh.cfg vi /etc/sslh.cfg ``` * For Debian: ```sh cp scripts/etc.init.d.sslh /etc/init.d/sslh ``` * For CentOS: ```sh cp scripts/etc.rc.d.init.d.sslh.centos /etc/rc.d/init.d/sslh ``` You might need to create links in `/etc/rc.d` so that the server start automatically at boot-up, e.g. under Debian: ```sh update-rc.d sslh defaults ``` sslh-2.3.1/doc/README.MacOSX000066400000000000000000000025051515234404100152050ustar00rootroot00000000000000 sslh is available for Mac OS X via MacPorts. If you have MacPorts installed on your system you can install sslh by executing the following in the Terminal: port install sslh Also, the following is a helpful launchd configuration that covers the most common use case of sslh. Save the following into a text file, e.g. /Library/LaunchDaemons/net.rutschle.sslh.plist, then load it with launchctl or simply reboot. ----BEGIN FILE---- Disabled KeepAlive Label net.rutschle.sslh ProgramArguments /opt/local/sbin/sslh -f -v -u nobody -p 0.0.0.0:443 --ssh localhost:22 --tls localhost:443 QueueDirectories RunAtLoad StandardErrorPath /Library/Logs/sslh.log StandardOutPath /Library/Logs/sslh.log WatchPaths ----END FILE---- sslh-2.3.1/doc/README.Windows.md000066400000000000000000000044611515234404100161470ustar00rootroot00000000000000It is possible to run `sslh` on Windows. The `fork` model should be avoided as it is very inefficient on Windows, but `sslh-select` and `sslh-ev` both work with good performance (prefer the latter, however). The following script downloads the latest cygwin, the latest version of sslh, and then compiles and copies the binaries with dependancies to an output folder. It may be needed to correct it from time to time, but it works. I use it in a virtual machine. Just retrieve WGET.EXE from https://eternallybored.org/misc/wget/ or git binaries. Copy the 3 files GO.cmd wget.exe compile.sh to C root folder, then execute **GO.cmd** with administrative rights. with **GO.cmd** @ECHO OFF CD /D "%~dp0" NET SESSION >NUL 2>&1 IF %ERRORLEVEL% NEQ 0 ( ECHO Permission denied. This script must be run as an Administrator. ECHO: GOTO FIN ) ELSE ( ECHO Running as Administrator. TIMEOUT /T 2 >NUL wget --no-check-certificate https://www.cygwin.com/setup-x86_64.exe IF NOT EXIST setup-x86_64.exe GOTO FIN MKDIR C:\Z setup-x86_64.exe -l C:\Z -s ftp://ftp.funet.fi/pub/mirrors/sourceware.org/pub/cygwin/ -q -P make -P git -P gcc-g++ -P autoconf -P automake -P libtool -P libpcre-devel -P libpcre2-devel -P bison -P libev-devel MKDIR C:\cygwin64\home\user COPY COMPILE.SH C:\cygwin64\home\user START C:\cygwin64\bin\mintty.exe /bin/bash --login -i ~/compile.sh START EXPLORER C:\zzSORTIE ) :FIN PAUSE EXIT and **compile.sh** # SAVE FILE TO UNIX FORMAT # COPY IT IN C cygwin64 home user git clone https://github.com/hyperrealm/libconfig.git cd libconfig autoreconf -fi ./configure make make install cd .. cp /usr/local/lib/libconfig.* /usr/lib git clone https://github.com/yrutschle/sslh.git cd sslh make cd .. mkdir /cygdrive/c/zzSORTIE cp ./sslh/sslh*.exe /cygdrive/c/zzSORTIE cp /usr/local/bin/cygconfig-11.dll /cygdrive/c/zzSORTIE cp /cygdrive/c/cygwin64/bin/cygwin1.dll /cygdrive/c/zzSORTIE cp /cygdrive/c/cygwin64/bin/cygpcreposix-0.dll /cygdrive/c/zzSORTIE cp /cygdrive/c/cygwin64/bin/cygpcre-1.dll /cygdrive/c/zzSORTIE cp /cygdrive/c/cygwin64/bin/cygev-4.dll /cygdrive/c/zzSORTIE cp /cygdrive/c/cygwin64/bin/cygpcre2-8-0.dll /cygdrive/c/zzSORTIE This method was contributed by lerenardo on [github](https://github.com/yrutschle/sslh/issues/196#issuecomment-1692805639). sslh-2.3.1/doc/config.md000066400000000000000000000161471515234404100150320ustar00rootroot00000000000000Configuration ============= If you use the scripts provided, sslh will get its configuration from /etc/sslh.cfg. Please refer to example.cfg for an overview of all the settings. A good scheme is to use the external name of the machine in `listen`, and bind `httpd` to `localhost:443` (instead of all binding to all interfaces): that way, HTTPS connections coming from inside your network don't need to go through `sslh`, and `sslh` is only there as a frontal for connections coming from the internet. Note that 'external name' in this context refers to the actual IP address of the machine as seen from your network, i.e. that that is not `127.0.0.1` in the output of `ifconfig(8)`. Libwrap support --------------- Sslh can optionally perform `libwrap` checks for the sshd service: because the connection to `sshd` will be coming locally from `sslh`, `sshd` cannot determine the IP of the client. OpenVPN support --------------- OpenVPN clients connecting to OpenVPN running with `-port-share` reportedly take more than one second between the time the TCP connection is established and the time they send the first data packet. This results in `sslh` with default settings timing out and assuming an SSH connection. To support OpenVPN connections reliably, it is necessary to increase `sslh`'s timeout to 5 seconds. Instead of using OpenVPN's port sharing, it is more reliable to use `sslh`'s `--openvpn` option to get `sslh` to do the port sharing. Using proxytunnel with sslh --------------------------- If you are connecting through a proxy that checks that the outgoing connection really is SSL and rejects SSH, you can encapsulate all your traffic in SSL using `proxytunnel` (this should work with `corkscrew` as well). On the server side you receive the traffic with `stunnel` to decapsulate SSL, then pipe through `sslh` to switch HTTP on one side and SSL on the other. In that case, you end up with something like this: ssh -> proxytunnel -e ----[ssh/ssl]---> stunnel ---[ssh]---> sslh --> sshd Web browser -------------[http/ssl]---> stunnel ---[http]--> sslh --> httpd Configuration goes like this on the server side, using `stunnel3`: stunnel -f -p mycert.pem -d thelonious:443 -l /usr/local/sbin/sslh -- \ sslh -i --http localhost:80 --ssh localhost:22 * stunnel options: * `-f` for foreground/debugging * `-p` for specifying the key and certificate * `-d` for specifying which interface and port we're listening to for incoming connections * `-l` summons `sslh` in inetd mode. * sslh options: * `-i` for inetd mode * `--http` to forward HTTP connections to port 80, and SSH connections to port 22. Capabilities support -------------------- On Linux (only?), you can compile sslh with `USELIBCAP=1` set in the Makefile to make use of POSIX capabilities; this will save the required capabilities needed for transparent proxying for unprivileged processes. Alternatively, you may use filesystem capabilities instead of starting sslh as root and asking it to drop privileges. You will need `CAP_NET_BIND_SERVICE` for listening on port 443 and `CAP_NET_RAW` for transparent proxying (see `capabilities(7)`). You can use the `setcap(8)` utility to give these capabilities to the executable: sudo setcap cap_net_bind_service,cap_net_raw+pe sslh-select Then you can run sslh-select as an unprivileged user, e.g.: sslh-select -p myname:443 --ssh localhost:22 --tls localhost:443 Transparent proxy support ------------------------- Transparent proxying is described in its own [document](tproxy.md). It might be easier to configure `sslh` to use Proxyprotocol if the backend server supports it. Systemd Socket Activation ------------------------- If compiled with `USESYSTEMD` then it is possible to activate the service on demand and avoid running any code as root. In this mode any listen configuration options are ignored and the sockets are passed by systemd to the service. Example socket unit: [Unit] Before=sslh.service [Socket] ListenStream=1.2.3.4:443 ListenStream=5.6.7.8:444 ListenStream=9.10.11.12:445 FreeBind=true [Install] WantedBy=sockets.target Example service unit: [Unit] PartOf=sslh.socket [Service] ExecStart=/usr/sbin/sslh -v -f --ssh 127.0.0.1:22 --tls 127.0.0.1:443 KillMode=process CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_NET_RAW PrivateTmp=true PrivateDevices=true ProtectSystem=full ProtectHome=true User=sslh With this setup only the socket needs to be enabled. The sslh service will be started on demand and does not need to run as root to bind the sockets as systemd has already bound and passed them over. If the sslh service is started on its own without the sockets being passed by systemd then it will look to use those defined on the command line or config file as usual. Any number of ListenStreams can be defined in the socket file and systemd will pass them all over to sslh to use as usual. To avoid inconsistency between starting via socket and starting directly via the service Requires=sslh.socket can be added to the service unit to mandate the use of the socket configuration. Rather than overwriting the entire socket file drop in values can be placed in /etc/systemd/system/sslh.socket.d/.conf with additional ListenStream values that will be merged. In addition to the above with manual .socket file configuration there is an optional systemd generator which can be compiled - systemd-sslh-generator This parses the /etc/sslh.cfg (or /etc/sslh/sslh.cfg file if that exists instead) configuration file and dynamically generates a socket file to use. This will also merge with any sslh.socket.d drop in configuration but will be overridden by a /etc/systemd/system/sslh.socket file. To use the generator place it in /usr/lib/systemd/system-generators and then call systemctl daemon-reload after any changes to /etc/sslh.cfg to generate the new dynamic socket unit. Fail2ban -------- If using transparent proxying, just use the standard ssh rules. If you can't or don't want to use transparent proxying, you can set `fail2ban` rules to block repeated ssh connections from an IP address (obviously this depends on the site, there might be legitimate reasons you would get many connections to ssh from the same IP address...) See example files in scripts/fail2ban. UDP --- `sslh` can perform demultiplexing on UDP packets as well. This does not work with `sslh-fork` (it is not possible to support UDP with a forking model). Specify a listening address and target protocols with `is_udp: true`. `sslh` will wait for incoming UDP packets, run the probes in the usual fashion, and forward packets to the appropriate target. `sslh` will then remember the association between remote host to target server for 60 seconds by default, which can be overridden with `udp_timeout`. This allows to process both single-datagram protocols such as DNS, and connection-based protocols such as QUIC. An example for supporting QUIC is shown in `example.cfg`. Limiting file descriptor consumption ------------------------------------ There are various mechanisms to limit the number of concurrent connections, which allows to limit the usage of file descriptor. This is described in a separate [guide](max_connections.md). sslh-2.3.1/doc/detailed-ip-transparency.png000066400000000000000000000723761515234404100206470ustar00rootroot00000000000000‰PNG  IHDRØ€s pHYsÊ&ó?tEXtSoftwarewww.inkscape.org›î< IDATxœìÝw`M÷ÿÇñgöND$F�!Ó–Ú#Tm¢%Æ·U´”j«¥Úª¯mi•ªúÚ5ªjÏR£2#„Ù‘�ûû#?·n3E®›ÈûñOšs?çÜ÷¹Ò¼rÎù -…B¡@!„J[Ó!„/" X!„B $`…B5�€B!Ô@V!„P X!„B $`…B5�€B!Ô@V!„P X!„B $`…B5�€B!Ô@V!„P X!„B $`…B5�€B!Ô@V!„P X!„B $`…B5�€B!Ô@V!„P X!„B $`…B5�€B!Ô@V!„P X!„B $`…B5Э¨�:uŠQ£FUÔá„Bµ166&$$D­ïQaûèÑ#¢££éׯÖÖÖuX!„¢B]¸p�+W®¨ý}*,`ó÷÷§M›6}X!„¢B̘1ƒÅ‹«ý}ä¬B¡°B!„HÀ !„j +„B¨�¬B¡°B!„HÀ !„j +„B¨�¬B¡°B!„HÀ !„j +„B¨�¬B¡°B!„HÀ !„j +„B¨�¬B¡°B!„HÀ !„j +„B¨�¬B¡°B!„HÀ !„j +„B¨�¬B¡°B!„HÀ !„j +„B¨�¬B¡°B!„HÀ !„j +„B¨�¬B¡°B!„HÀ !„j +„B¨�¬B¡°B!„HÀ !„j +„B¨�¬B¡ºš.@!4åèÑ#¬[÷qqw033Òt9å’••C^ž]»ödܸ‰˜››kº$ñÿ$`…ÕNzz:ãÆ�¤^½<æÌiG½z/kº¤g’��˾}a Ð�™3Ò­›·¦KHÀ !ª™ÜÜ\üü2eJSºvuÒt9B__—þý›âããÂðá3Ð×_@‡�4]Vµ'Ï`…ÕÊ�?~Oß¾õ^˜p}’±±>ë׿ÎÌ™���­érª= X!Dµ²k×fÞxÃKÓe¨�™™!¾¾®üöÛM—RíIÀ !ª�ÈÈH<ׯ?dÚ´dgç©´ÉË˧G�ïÐÑÑfÙ²áÔªeÆÚµgðö^DdäÔ¬iÀñãQ ¶’fÍê±zõh¢£ãyûí�88Xóá‡> Ü’ÜÜ<>þø>^^�0 ™ò}¬­MŸõ£DVQ-ýñG{ö\æüùOhÑ¢ ==ë2p`ó§>V§NŽÊÿ¾t)†iÓ ·Yµê4‘‘q\»ö%ff†|ñE_þüó k֜ჺ+Ûúø¸òÙg}h×®1GŽDpâÄeÀ>®qîÜýxzÚáëÛê©kê'+„¨–Ž‹ÄÍÍV®ÏãýŒ�õ˜:u»Êöøø4""TW¾qq©£ò}ݺ5ˆŠŠS{�¢bIÀ !ª¼„„Ξ=KNNíÚµ£V­ÒŸAæææ+Ÿi>ùù ¬¬LiÕª�ÊöV­àêj[â¾/úúµ/* X!D•¥P(øä“Oøæ›oÐ××'77]]]Ö¬Yƒ¯¯o‰û¶iÓ�Ÿþ‹7Ò°¡U©ïeh¨Gbbù{ízy5䯿®2bÄKë—û8O²´4~¦š„zÉT‰BˆJ+&&†3fгgOzõêÅòåËÉÏÿg�ÓuëÖ1þ|-ZDrr2qqqtîÜ™Q£FqóæÍŽ ¯½Ö W×:ôí»”#G"ˆ�Oãüùøú®`߾˅Ú7mZ�'®|‡RUfx*‹±c;bl¬Ï AË Œ!##‡¨¨8fÎü�ä䌧:Öc�;;ñË/ç¹t)†G�²‰ŒŒ#..¥\ÇOV¡1™™™„……qýúõB¯…††âééɶmÛðôôÄ‚ &0yòde›_~ù…V­Zñî»ï¢««K�5Xµj¹¹¹,]º´Ä÷Ö××åÈ‘÷éÜÙ‰qã6P»öGôïÿ#îîvtëÖ¤Pû·Þê@·nMxé¥y4l8ƒ¥K�y\]7¶FGGõ׫™™!'ON¥N úõ[†™Ù{¼úêdgç¢Pü3�EÆV˜š¨ìkiiŒ�]�Bï5uªݺ5ÁÛ{SèÛw)AA·Káááj:;!J'+„(VNN¡¡¡ìܹ“Õ«WsàÀ•NFEÉÏÏçàÁƒÊ^¼—/«vzðà‰‰‰xzzªlýõ×166f×®]ØØØ�ššZèømÚ´!88˜¬¬,œ��‰ˆˆ(tëààPjG'!ÔIžÁ !TìÝ»—uëÖFDD999*¯wëÖ�ýû÷£¯_ôP“®]»ròäIlmm±¶¶.°ÚÚEÿ]off†——gΜ aÆDEEjçêêJNN·nÝÂËË‹¯¿þšàà`Z´h¡lchX0SRrrrÙO\ˆ &W°BTs&L Y³æ²½rå [¶l¡M›6¬Y³†ÀÀ@ÒÒÒHIIaÚ´i;vŒ 6�‘‘Á¹sç Rî¿bÅ >|Hll,o½õV¡€µ²²ÂØØ˜Û· ÷vmÑ¢ÁÁÁ@ÁmÞ   •¶uëLŒC§N�ÐÑÑaëÖ­*m¨Y³fy?!ž™¬Õœ®®.—/_æÑ£‚ ÷ÊíѣǧY³f˜˜˜`ffÆœ9s°¶¶f÷îÝ\¼x‘—^z‰… *�çâ⢠6âââˆ��W¾®¥¥…ƒƒC‘ÏG�œœHMMåáÇ´mÛ–„„.^¼XdÝ …‚:uêЯ_?~úé'¢££•Û¿ûî; èܹs|BB”�¬UœB¡`çÎ�Œ5 :vìÈŒ3¸råJ™ö÷ðð ??Ÿ°°0ÜÝÝ�ÂÏN¡ ŒkÖ¬©|6êááÁСCéÚµk±Ç.êX^^^º:}ÜcøáÇôêÕ }}}V­Z¥ÒæñÕ²£cÁûß~û-†††´lÙ’AƒѬY3Ö¯_Ï÷ß��MÙWÄ¢¢IÀ Q…=xð€Î�;3dÈnß¾M“&MprrâǤiÓ¦ìÛ·¯Ôcü;ëÔ©Sä³S€]»vE«V«·XXX°eËÞz«èñ¡...Ê+ä'uêÔ‰»wï*Ÿ·>öø*ÚÌÌ kkkÞ~ûmV¬XÁ�?þH||<»víböìÙ¼òÊ+ØÛÛÏjƒ‚‚øøã�±±±Á××—��Æ�Wê¹ ¡NÒÉIˆ*J¡PàëëKdd$§N�¢mÛ¶Ê×bccñööfäÈ‘\¿~33³b�ãî––JzxxÌùóç &44”'NpñâEœ��yÿý÷ËT£��NNN…vÀ€XXX0oÞ<~ûí7´µµÉËËcóæÍ888P§NÁj2 , >>ž‰'2aÂôõõ}:¯¾ú*FFFe®ÓÝÝ�ÐÐÐBï¹páBÆ�G·nÝhÛ¶-ÇŽ#00�;v('}000`ãÆ�,^¼˜øøxêÕ«Wâ ê�™™Ã˜1ëÙ¶í"]º8‘——�¿ÿ.>ú¨ŸÞ§Ìǹ~=žùópåÊ} õ¨_߀”;}úNѸ±ÍÿÏ/|�š5MX½z4:8Tü µ‘€¢Šúý÷ß©Q£ƒ *òõÖ­[Óºuë2ëñë“ßìܹ“~ýú;´¦¬Ç>|øp¡ícÇŽ¥N�:¬]»–‹/Ò®];V­ZUhêC(¸BÕÔóÔ©S·süx$ÁÁ3iÒ¤6W¯> 66驎Ӯ]c ®²}|¾ÃÅ¥6K–¼^dÛQ£Ú*\ÏÎÎe̘õ¼ñÆZ¢¢f?ÙˆçMVˆ**::šºu뢣£S¦ö)))„„„pùòe._¾Lhh(óæÍÃËË öíÛGbb"–––ÊŽNÉÉÉ¥†krr2óçÏÇÜÜœéÓ§zÝÃÃÌÌLîß¿_h�Ö¾}ûÒ·oß2žñówï^ +Vœdùr?e¸8:Úàèø|___—#^bÆ¿IIÉÄÜÜ𹼯xv°B<ƒììl¶oßÎéÓ§ÉÍÍ¥]»v 6 ==õ/ä­P(”�‚Êâ‡~`ÆŒ˜™™áî§'ÆÆÆÀ?W¬¡¡¡tìØ±ØÞ¿EÑÓÓcÁ‚888°ýû÷'--­ÌT&Ç�G‘››Ïk¯µÒh·n%`l¬_aëÈŠçCVˆ2¸ví7nÜàå—ÿYÑ$==�—_~™   ¼½½ÉÎÎfÅŠüúë¯Êq¢%IJJbëÖ­åîíÚ°aCNœ8Arr2E¶Y»v-³fÍ" €1cÆ0|øp6lX¨Ý“�Ú±cGjÔ¨Qè¹lqŒ��Ù¶m�7.òu]ݪûkæÎ�DjÕ2S>-Îôé;‰ŽŽ/´ÝˆŸñÔï{÷n2.Ü";;—àà;Ìœù;'vEWW~T%U÷'_ˆçhذaddd¢Ü¶zõjBBBPÞR]°`Ó¦MãÂ… Ê¡,E9xð o½õ,õ½ 7nÜ 44”Ë—/ΪU«èÔ©ÿûßÿTæýý·àà`bcc±°°(vjC(˜~PGG§PG§²,ô ~ééé�––UêRvƒµ %¥ð¢éúúåû»uë GOO‡zõ,ùæ›!øùy•ëXBs$`Eµ7kÖ,´´´øâ‹/Š|ýðá⥥ENNŽòöï‘#GèÚµ«2\^yå¦M›FLLL‘›––ÆG}Ä®]»øé§Ÿ =¼wïžòiíÚµ6l¯¾úªr<«½½=îî¤0hÐ Þ{ï=.\ÈÀ� ])æææ²cÇÚµkWb¸ѲeK•ùá‡н2®.\\ê�žžÅ�iÔȺØv^^ +ô}ß{Ï[ÙÉIT]r¿ATkÑÑÑÌ�;—C‡ÛfÞ¼yL�:•ììl"##•Û›4iB�=TÚþþûïXZZÒ©S§BÇ9qâÍš5#11‘��•p½{÷.666ÊÅÂçÎ�«\æÍßߟӧO“œœÌ�7سg–––˜™™1wî\Ο?ÏèÑ£UVžILLdذaܺu‹™3g–é³8wîœÊøR¬­‹•ê sg'jÕ2ãë¯ ÿ|dgçj "Q•Ȭ¨òrrrˆˆˆ ..CCC¼¼¼J½b{láÂ…888ZämÀóçÏsíÚ5~ÿýw.\Hhh¨òyå¼yó”íþøã–.]Êþýûy÷ÝwU®&322˜1c6l`É’%¼öÚk…ê¨]»6³fÍÂÍÍ OOO•Þ¶íÛ·/¶þ &Çœ9sسgmÚ´!''‡³gÏ¢§§Çš5kðññ)Ógñ"ÈÍ…[·„†* ûçëË/k3þÓw²24Ôã›o†0jÔLM øàƒîé³jÕ)–/?ApðÌ2ßÎÈÈáîÝäÿÿïl’“3”Ïm4¨)ÏW_@°¢Ê‰‹‹cåÊ•Ê!'QQQ*Kª9::ràÀ�b;Ý øâ‹/ðõõeóæÍDGGcjjÊë¯¿Ž¯¯/VVVå:fe—› W¯ÒÈHOΫaeZüÿ<å2bÄKêñÉ';Y°à nn¶,[6ü©ž±ž9Í�!?)¿ »Ë<Ó ô§Aƒ‚ÌÌ 12’ÞÂ/ XQé>|˜O>ù„5kÖàîîNvv6þþþ¸ºº2`À<==qwwÇÄÄ„£G�òî»ï2uêTvìØ@jj*7nÜ(´À÷âÅ‹>|8;v zÐ>€üù矬]»(¹Ó�ŸŸ~~~Lž<™fÍšñí·ß²`Áú÷ïÏŽ;pww§cÇŽx{{óòË/Ó¢E‹gšÀáIÌ™3§BŽU™wE¦ ã‰>E5j€ƒƒ¯½¦�»»nnZ¸»kѸqÅL/8dHK† iI\\ ZZZÔªõô³Iy{7!!áÛRÛ;öAyJ•�¬¨ôtuu  ((wwwêÕ«‡……žžžÌ�;W¥­ƒƒ§N�bË–-dffbhhˆ³³3©©©¤¤¤(-))‰Ÿþ™€€jÔ¨Aýúõ¹|ù2¯¾úªòX ,`ܸqÊ^<<ýôSFŽYêp�?ÿôðð ''‡€€ttt áÂ… ìÚµ‹¸¸8V¬XQì Bk×®ÅÈȈ€€V¯^Mhh(AAA$''+k:t(Ÿþ9îîîxxxШQ#òóó155¥yóæÊÕkÖ­[GŸ>}hÛ¶-–––$''S¿~}öï߯|¶û"{Ö mÔH‹æo¢J“€juâÄ ’’’øøã�Un�òÝwßñÇ�›[úxBwwwŽ9BZZ¦¦¦ÊÛÆ:tÀÄÄWWWå-Ø–-[{¬´´4bbbøöÛoñôô¤sçÎôîÝ›éÓ§séÒ%ÜÜÜ€‚Ù�ž¤££ƒ«««JÐ;88(×M}ôè5kÖ¤E‹%ÎúSååÁÍ›¤B< X¡V††+DGGzÍÝÝ]e¤’xxx P( S®þàëëËW_}E£F�ÊÜ#wüøñLœ8QeMÓÇcUÃÃÕ[”ùóçZFOO¯Ä±ªUMlì?!zá‚©å%+ÔªS§N4lØ�I“&±k×.š5k†••–––ØÚÚÒ¾}{•±šIIIÊ¥ÔBBBðððàí·ßVéèäåå…�� µjÕ"++ ‡Ò¡Þ½{7gΜá‹/¾(rÁn###ÜÝ݉�/K—.¥Y³fÄÇÇ€‰‰ ›7o¦K—.¥ÇÀÀà9T«>¤•ÃË/wçôéãøûïgöìžhk¿8lPÐmÞÿ›7¾[$ž? X¡vúúúüñÇlß¾��ššŠ››cÆŒ¡_¿~XXXhºÄ %AZùÍœ9‡Õ«¦G�Ÿ:Ôƒöíí©]Û ]ݧ_3VÓ’“3ˆŠŠcûö’“ Ùºuo©3£‰çCV<ÚÚÚøúúâëë«éR*LY‚ÔÜœœ$H+£7Þ‹¯ï0öîÝÃúõ§IJº¦é’ÊE_ß{{GÞ{o|‰“¤ˆçOVˆRH�¾¸LMM:ô5†}MÓ¥ˆ�¬ÿO‚TQ‘$`EµST�)HKû§�©âYIÀŠÖÓéÀ�¤BˆŠ%+ª< R!DeT¶õ½Ô(6-óeæ\OºNÿßûóuÀ׬ ]G»ÍíHÏJÇ|™9wxóÀ›|ú×§ì‰ÞƒógÒ³Òiô¿F¼q�©'¦2þðxÎÜ9ƒõrkÒ³Òiµ©¿„ÿÂWÅ�?†ù0óeæÜK½G�=X¸”Ÿ‚Â{›7Ò`¾Ìœ°ø0^ßó:_žý’_#¥Ù†f¤g¥SgENÆœdâщL9>…#·ŽÐ`eÒ³Òq[çÆ®«»ð?åϨý£Š Â|™9ÉÉtÚÚ‰U!«X|a1}~ëCLJŒœë3œëÕé8ú6£?=ÏK°v ÁÄ4“ºusðñÉeÊ”<ÖmÌ$&ñ¦-�0sv&Foûq à&½6ަÿóè;c'›ê¶Ä»GíÛò×íÊy®ÕéßUÎUε<皯È×t|•JK¡P(*â@‡¢G�œ;w®ÔyaŸ4ø�Áh+´™ßn>×R®a¡o�ž¶÷Òïánåι¸sxZ{r7ý.úÚú˜é›q=å:Í­›séÁ%-IÌJ$�äiº QV‡öðÑ$  §Þù³úXYçK� !ÔêjòU.>¼ÈÇš.¥DØF�x”ñ¨ô†B£²³´˜û¹k~6¦¸‡ “Çýs›_‚T¡.=ôd¤ûHM—Q*�ìÚðµXëYã`á éRD1ΟÕg›5¸Wr26k‘ÃÓÓptÎ¥^¹-!„P� Q8s�“COjº”i<`èú·okº Q‚Ø;Ú<¸_úe§¶Ž‚®Ý³žCEBˆêl`£�Œt“+ØR�:0 [#[&yNª�ãåääq9‚k‘×HJLâQšÜ~. ]=]ÌÌͨg_·¦nXÙX)_{µ&>¯Äqì�÷pì�ÉI…÷J¤Æœ„ÕÀʼnJ�bNû9š.¥Dÿ�øi›OIy”R!Ǻ|é2G÷%+3 <\=Ð××/}GA~~>ÉÉÉ„†qòÈI<[xâÓÇC#CtuAWWÁ«ý3yµ&¹¹pîŒ>‡örh¿17 ÖÐ44ÔðI!ª  Ð@Óe”Jã{*öº ]ìLìžé8G÷å쉳tëÖ�îÝ»cddTAV?ááálß¾�5?®aØð°T]]WÚwʦ}§l>› ᡺œ?«OÛÙªXQ�XZSøòÏ� ñþœùŠ|žu®‹s§Îqî¯s¼ùæ›ôíÛWÂõ¹ººòÁ`jbÊÖu[ÉÎ.98]Ýs5æÎ.¹Ï©B!Duvîþ9~úAÓe”JãÛ¥^Ü­Ü˽JR Ç£ÿþxxxT`eÕ›±±1cÞCFzgŽŸÑt9B¡4¸ñ`6õÚ¤é2J¥ñ€�}n6Û®m+÷þgNœÁÚÊš:T`UÀÌÌŒ^½zqîÔ¹R¯b…âyÙµ‰¾¿WþÙÿ4°zn(wb…BATX^^^hËìjѪU+òùDGEkº!„ {ýî|Õá+M—Q*�§Òäã“Y¾ª\ûffd’’œB£F�*¸*ñ˜��vvvÄÝ�Ót)BÀõ”ë�9ªé2J¥ñ^Ä~.~<Ê,ßXÕô´‚•ÌÍÍ+²$ñ/æÊÏZ!4M�‚¼üÊ?[œÆ6&5òÀÉÂé©÷ÍË+ø€åö°ziëh“ŸWù7BTŽޏX»hºŒRi<™®'_'î‘Ü~BQ6nàÃjºŒRiü v´Ûh¤>Ðt¢ܼ~“õ«×|)˜ÜÜ\5nDÏ>=éÞ³»ÜeBT?g?¦¶™ªé2J¥ñßz�MdeØJM—!žÑî�»éÙ©';¶ì aã†4oÙœÛ1·?j<~ƒüˆ¯é…/ˆ�Ñ;up”¦Ë(•Ư`×÷\Ïݤ»š.C<ƒÀ‹�Ly{ :wàÇÕ?bbj¢|íÜ™s¼1ì &Ž™È–ß·”z¬G�all¬Îr…U\K›–xÖöÔt¥ÒøìÏÿ—íÑÛ5]†xsfÎÁ²¦%ËV-S W¯v^Lú`gO�årðåR�õŧ_й…²[ÌÍÎüu†„‡ j©]Qõ$e'q#ù†¦Ë(•Ư`;Ûu&;Gf ªªn\¿Áù³ç?i<¦f¦E¶ñyŇý{ösûÖm<š–<�edx$µj×BG§`…žÝ;w3ÿËùØÔ²¡‰k\Ü\èìÝ™�: «§ña!Äs–�‘À•Ô+š.£Tÿí¤¥¥…Zš.C”SÀßxûxÛÆÁÉ�ßüVê± QQtïÙ]¹-2"~Z÷aD…GqôàQVþ¸�¦¬Ù²›Z6Ï~"Bˆ*ë¶ÝvÓt¥ÒxÀ¿sœ:5hjÕTÓ¥ˆr¸s€Ú¶µ+äXéié8»:+·E†GâÔĉN];Ñ©k'åöƒû2~Ôx¾[øs–mÑåÜÜ\tu5þ#/„xFÛ¢·q0æ '‡žÔt)%Òø3Ø™^3â0DÓeˆgdX«­G„EÐĵ Pˆ×®\S ÜÇz¼Òƒ­[pþìù2;1!/w/ì9ðÌu !4ËÏÉ�=ý÷hºŒRiüÏùûGPϸ6¯üƒ†Ea 5àÚ•kØÚÙÙfÓÚMÔ­_—.Þ]X¶xW"¯(Ÿ¥:»8cWÏ(¸ ÐÄ¥ `¯_»NvV¶2pÿ-5%“‚NUéiéܺq GgGôôõ %80˜Ä„D6®ÝÈÃø‡4°oPè8 ؾy;wcïbWÏŽWú¼BÝúuËý™!ÔëðíÃ&²Ì{™¦K)‘Ư`èöo¹½¥é2D9uêÖ CCCÖ­\WäëW£®ò釟òç‘?0·0'áakW®eôk£i׬�ò6sdxÁóÖúöõ•ß?þzôàQe»üü|¶nÜJTD]»wàÌ_gèÕ¥sfýs»øJäVþ¸’o¾ú†Û·n£«§‹ƒ“ƒJ}·oݦg§ž,Z°ˆˆ°Öü¼†n/uc÷ÎÝ÷! !*T#óF¼\ÿeM—Q*�_Án߀‘–ýõÓt)¢jZÕdÒÔI,œ³�/>ý‚�ü?RŽc�¹øQã037cü¤ñŒxc#Þ@Jr ‘á‘Ê+بð(œ]œÑÒ*èôö8`O;ÉÖ�[�‚Õ}tttxôè.n.Œy{ ¦f¦øôò¡MÛ6ÊÚø`€ï²³²™ò΢"¢Ð7ÐW©ÖôYäääpàÄêÛ×'//�‰c&2mÊ4¼{x+¯�ì=À×ÿýšè«ÑÔ¶­MÏÞ=ù`ú˜™›©åsBO -´µ4~}X*�l³PùE%˜8e"ùyù,ùv [6lÁ³¹' …‚ ç.`bjÂÏë¦v�Â� Ì-Ì•�˜›“ËÕ+W4t�òõÈðH¬¬­8rVÆW"¯�œ”Œ•�¯öU€m;´¥m‡¶EÖ§o Ï½»÷ Ýj޽˱Cǘþ ‹wþ>ý7ïüçÚwjÏôYÓ‰½Ë¢ù‹¸táÛ÷nW) &48”šÖ5iÛ¾-5,žíÃBr-å—^b ã@M—R"�¬½¹}¹—«•ƒ––“§Nf¨ßPî=Hdx$999ôêÓ‹�¾±¬iYê1¢¯E““�£‚‘a‘8»tpzÆO^¡–Õãá?]_ý쩳äççÓw`_•í5,k�ø0€ù_Χ~ƒú¬Ú´JylkgË¿1œ>yšN];¡P(˜þþt6¯ßŒµ�5YYYädçðż/x}äëO]³¢x>õ|ðsóÓt¥ÒxÀ®�X�µ¾5ŽŽš.幺}û6ü³ÈAýúõ±¶¶.Ô.$$„ºuëR³fÍçY^¹Ô±­Ã¨1å›ôñíàÇ›‘‘Á­›·”ÏXŸEìíXRSR ]Á^ ¸„¹…y¡ç²Y™Y˜˜™p7ö.Ï_äcÿ�Un/·ëØ€ˆÐ:uíÄŽ­;ؼ~33¾˜Á؉cÉÍÉe¶ÿl>ýðSZ´nQlG-!ÄÓÛxe£ Ó)‹%]—0ÆuŒ¦ËxîÖ®]ËÈ‘#9r$]»ve×®]E¶ëÛ·/¼øCK hÞ²9.nk<^‰¼B~~¾ò öY(ÃÛM5䢯FÓĵ‰ò™ïc·nÞ ^ýz\<…B�wÕ‰4tt n ?ž…ìËÿ‡{Swƽ;---ôôõ˜þÙt´´µØÿÇþg>!Ä?5Ćž4]F©4°£ŒbIÈM—ñÜ͘1ƒË—/sùòeììì4]ŽÆõx¥»íÂÚ¦à*ÞÚÚš�ü?*ö¹ê“.œ»À’o–(ƒôß"Ã#122*4Dçö­ÛÔkP¯Pû°ËaèêéÒÈ¡!A!àè¬z‡%!¾`näZµkñ0þ!¡Á¡ ¢ú<ÈÄÄ îݽWê9!Êîƒ ¬¸¼BÓe”Jã·ˆý½üIJOÒt•Ú¿¯°ª»zv¼ûþ»ej{ìð1–|³„zõëy+62¢`6¨¯I›••…®Náÿþ>ý7îîrëÆ-6nXh¨kW¯P¿A}.\ uÛÖ…Ž•——‡��A™ÎãYäæäòë/¿ââæ‚g3O™£Y¼ÐjÔ ‘y#M—Q*�_Áž¸s‚ðÄpM—QfiiiÌž=›îݻӢE †ÊÞ½{Q(*ívíÚÅ€hÑ¢>>>|óÍ7¤¦¦–ë=õõõÙ±cÝ»w§]»vÌš5‹ìlY á±AC1oÑ<^êðR‘¯G„E(o=?ɶ®-·cn«l»s‡sgÎ)ŸýÞ�»OM«ÂÏ¿CCÐÑÑÁ£©W"¯ ¥¥Uè=ÒRÓHJLz.“V\�¾Îô÷§3 çΨýý„Фš5q¨áPzC “?sŸÒ{ï½ÇÍ›7ùꫯ000 00�ï¿ÿžV­ZQ»vÁP”#GŽ0vìX–/_Ž››7oÞdóæÍüþûïøù=}Ï·Ÿ~ú‰Úµk3uêTbbb˜1cÖÖÖLž<¹¢O¯Hééèè+Jo¨!�ÓØ±q±¯·y©èÞÇ}öeöŒÙìÚ¶‹~ƒû‘–šÆ´)Ó000Àï?ÿNzzzäääÚ÷ÐþC4qk‚©™)·cnS»NmŒŒŒTÚ<¾eíàX¾_©)©|øî‡|õíWXY[•Øöñ4“ºzº„†„{ký‹O¿àÁýôЇ^}z•«®]nn.i)idddhº”*KWWS3SŒŒ�Jo\8wšnõ+÷„ÿØÎu;W©[Ä!!!¼üòË´iSð »iÓ¦Œ¥ÚsöòåËXYYÑ«W/Œ��qqq¡gÏžå~ÏfÍš±`Áå÷—.]âøñãÏ-`�ñäÀþæÌþ,§&¹8»ä*¿ººçbe�ÿ\ê(¯/|YäöÑo�æJäÞ{û=>ùðrrrÐÑÖaÑ�‹”ãvÝ›º³iÍ&’“”ÃwB‚B¸p‰i3§Aøï , `¥!---Z´nÁ¡ý‡˜=c6.®ÓCº¸»Ðú¥ÖÅN/ “jØÕµ£GÇÌY8‡Wú¾RlÛÈðHtõt騥#a!aE¶9{ê,«W¬F¡Pààä ûÿ 7®Ý ârW#®’’œ¢é’^zzzØ;Øãìꌫ§+†FÏ>g9À Æƒ˜Øbb…K�4°sÎÍÁÖÈ–Iž“4]J™øûû3~üxùOdª]½<œœópvÍÁÉ9�&n98:åajV¹ƒWGG‡¯¾ýŠÉS'x!�ÜÜ\Úvh«²üÝÞú[6lÁo�£ÇŽ&;+›ï¿þžºõë*‡$Õ´ªIRbùùù*Ïyßñ;nžnXÖ´¤±Cc|‡ùÉþ=ûY¾d9_.ø’ᣇóZ¿×¨]§6MÜšÐÄ¥ ®î®Ô­_}}>ÿêsz¾Ú“©“¦²Ï~fÏ›]ääQáQ4vhLó–Í‹\Ð //�Ï?ùœ póúÍ2 ÚÿÇ~Ö®\˼Eó°odOnn.™™Å®û[ݺ~‹cû�{;–† Ò­k7êÖ­‹¹¹9fffÕ²ÿCEÈÌÌ$))‰ÄÄDÂÂÂ8¶ÿÇ£C·´nÛZÙ ¿¼6EmâXì1 ªÜ#,4°ëz®ãvâíÒVýúõ£k×®8p€£G�2fÌôõõÙ¸q£2mlløë¯¿8}ú4‡bùòåL˜0>øàƒg®áyÿOïät'—»ôRpU—“­Åõh®Dê¡«üúן&ä=1+W­Úù*W»NMrqóÈÅÄ´r¯­�m±W’õÔcס],ž¿˜_. //�VmZñÙÜÏ01-˜Eª›O7V¯X͆Õ”¡ûë/¿r9ø2óÍ ÖÄ�<õŸ;9Ù9äæå’››K‹Ö-ˆ �dãš�܉¹ƒGSöûg¥�vÛqàÄfûϦGÇÌÿn~¡I3"Ã#ñlî‰{Sw~XôÙYÙ*WÕ×läúµëL|"ß|õM™6ðb §OžÆÜ€àKÁ ì5�z :“5q-øƒÀ«½vu«VOx…BÁÙg9vàNNNL�:[Ûâï&ˆ§cdd„¥¥%�5¢eË–dggó×_qøða"B"kºr{jJ*>,ÔÞÔÌ”ß-àèÁ£|4é#º÷êŽÿlLLMxôè·nÞbȰ!¸{¸“›“KTdM=€‚Õ‚¾ùêÞžü6iiiаqÃRÏ;2<’Úuj+gâzüLÙÛÇ›¤Ä$Ž<ÊŠ¥+ÈËÍ£‹w/_\¦Y»4M¡P°{ÛnÂCÂ1b-[¶ÔtI/<}}}¼½½iÞ¼9ÿûßÿX½t5#ÆŽÀÒª|?/×’¯qóÑMšÛ4¯àJ+–Æv¤ËÈ*3UâíÛ·?~<ï½÷ݺuCOO�””>|ˆ»»»²ÝøñãqqqaôèÑÔ¬Y“¼¼½ *�™¹Y‰ ´iÛ†�ü?ª?9Ù9|ýÃ×ÿLÊáêLÝúu©aYƒ°�0eÀ~=÷kLÍLyç½w?z<ŽMUæO.Ndx¤êÔ•á‘hkkóÉçŸ(tHOKgÇÖÌöŸÍÄ1Ù´sSq‡«4N9IxH8Þ™@£F•¨Ç‹¤fÍšLž<™?¯à×õ¿òŸwþSdÿ…RiQhäFe¤ñ€½™rò¨S%ÚÙÙ1zôhfÏžÍðáÃ144$//___fΜ©l÷Þ{ï1þ|æÍ›§ì…Ú´iSvìØQä/¶Ï?ÿœ×_�Úµk£§§Ç¼yó?¾`õ ôõU�ŒŒ ]WfÕ%xÝ›ºãÞÔ½ô†O!33“€¿8}â4§Ož&ìržÍ=?i<}ô O3éêîJhH(—ƒ/³yýf–þo)†††D…G•iòŽÔ”TboÇÒ»oo嶈°êÛ×W†+€‰© #ßIð¥`¶mÞFnNn™Æà* –|³gççÚÙêfôMþ:ú#GŽ”pÕÞøÏ|»è[öÿ¾Ÿ~¾O¿’šƒ¹M¬+ÿô£Ø[©·0ÒROW­­ÍСC:t(™™™ddd`iYø‡››k×®%??Ÿ¤¤$ÌÌÌT:Aý›‹‹ ���¤¤¤`ll¬2©APPP¡ö“'O~n=ˆÕ©ºoyD„Eðù'Ÿx!'ÚwnÏ”�§Ð¦]å B�E…Gall¬œ©Ê£©A—‚P(|6ý3ÚvhË+}_!%9…Ø;±Ê ºÄ…shâÚ7•¡@QQ( œ]�U¶µjÓªÈz�Œ� ®(þ¿{@^^^±WÉ …‚Sg°qÍF>˜þA‰›››[h’�òR(Ùw„æÍ›ê8(ž/SSS†úeÅŠxuð¢Ž]�§Úÿ`ÌAŽÅãà ƒjª°bh<`ý\üˆO�×tOÍÐÐCÃ’»œkkk?Õ$ýæææÏZÖ A‚²³³ùÏØÿðÒê—J}®¡2S•›§¿¬ÿ…�¿î$ðB ûþÜüs¥ûxBŒÈ°H–|³„„‡Ó>ZY[±èÇEtñîR¨müƒxÆ?ÄÄÌ„øñÊ)-¡àïÁ½iÞ²9ººº¤¦¤ÒÚµ5=z÷`ÉϪӠ* ü?ò'ìrÁP¢’:[%¯ø0`È€RŸw‡‡„ãìì\îár¢âµk׎�›6êõ^šÑ;8sÿ [zoQcuÏN㻡×î&ÝÕt¢ SKðzæ`bRù;Q( >›û™Ê0#GgG Ð××çýiï+·G†Gbna^hH’µ�5»t¤c—ŽÊma4°o ì”÷8œ·ü¾…ÜÜ\"Ã#‰Šˆ"5%•ö�Úã;ÜWòÎ.Μ;OnN®J�³¦Í"$0„ Û7°w÷^ ±oh_èœñìGÏÞ=‰¾­r•{ïî=^ëûÆÆÆôìÓ“Ä„D¦M™Æî�»Y¹ae‰·¥¯E]£÷+½‹|]h†››Zhq#úF±l¥µMkšÖ.Û š¤ñ€ýòÜ—XèX0Ìi˜¦K/˜ê¼ZZZÊÎN�éêêòÛ�ßÈWä+ǰBÁ3Tgç2�£ŽŠˆR™^22<=}=Z{µVÎUšÇ��? ¾pþ¿ìüS3S¢"¢pjâT(““>h8Þݽé?¸?‹,V Ø?¬@¡PðÛÁß”3kuìÒ‘Ic'qòØÉb×Îx”Á£ôG4hРÈ×…f`ccC|\üSlBV÷³îã]ß»ôƤñ€íZ·«L\/ž«ê¼nžn…¶-_³œÄÄÄR÷}pÿ T‚-*< G'ǧ^¥G¡Pðù'ŸsöÔY6ïÚ¬œ…*2,²ÐóפÄ$üùѾc{>òÿˆ}»÷¡£££²T ³‹3ÓfMS†+@‹V–îÆ',-% �~•‘……i©iOµORVÑ)Ñjª¨âh<`óù(¨<¿˜Dõõ¢¯eMË2Ms3=}=e* ¢"¢èþJ÷§~Ïë×®³æç5tïÕ��¿îTöXŽ �¤Sמ­&'%ã7È�­[àÿ¥?Pp›Ú¾¡½ÊØñ×G¾^è=¶nÚŠ¶¶6-Zß3øñÄýO1•ƒ‰‰ÉS/¬ÐºVkºÚwUOAHã{2ö$:4³j¦éR„(RqÁ›�¥Å�ëU?xÿ­e›–DÄD È/¨/-5�Ž];Ò®C»R÷MMIåÂù ¸{ºcSËS3S>òÿˆˆÐ6¯ßLôµhå³Ù�Ûv’––ÆÓ?`ä�‘88;ðå‚/•·°£"¢Š½mxüÈq~üîG¹{—ÿ~ýß"—$|¬*LJP�=í¿ÏöèíŒ9ÈÉ¡'ÕTQÅÐxÀÎh3C:9‰*IßàÅ Þ'Çžš™›±bÝŠ2ít)ˆÑCGóúÈ×™¿x>µj×âÝ÷ßU¾ž“�ÃoÛcê»Siס …‚øñ«ŒËmâÚ„K—x¹çËädç §¯:ŽÜ¾‘=ݺwã×_~Å®®]™&Ï/?'?Þkùž¦Ë(•Ævä�‘2LG¼P^äà-MÍš5ñû�_±� ôôõÈx”�¹…9³þ;K¹=ôF(Q‘QD„FÅ…s¸{— «7°{çn‚®ñ÷é¿qjâ„•µ�7âíÉo3zìhúx÷á£É±}ïöçušBÃÝ>Ä¥‡—Xþò³��V'�ìÒnKy�ú@Óe¡vÕ!xÝ<Ý”ãa‹s%òJ¡N&¦&´hÕBÙa)48”ÞÝz³u÷V � ÑÒÒbŒßF�ÍÇ3?Vîgdd„woVý´ªâOFTZ�ÍccbSzC ÓxÀ® [‹±¶1ýõ/½±/ â‚7-U›ëÑ:*¡{%R—Ó'õK ^÷¦9Wžà}Ògs?#9)¹Ä6áÐÊ«•òvµ­�-A— Oz5ê*µj×RK­B< �l#‹F�Wz;!ªS³|<›åãÙLu)꼺ºº*óÅÒÒ’¡~CUž�{wMúÿ�üñû�zzzlß²�c‡Žñá§òˆ©:‰N‰æÒÃK r¤éRJ¤ñ€­oV¿Ê,W'Deð´Á{ê„>OvÒ¬¬Áû$ïÞx÷P�D`èð¡hii±â‡¬_µs sƽ;Ž ïMÐD™BC|êù0̵òON¤ñ€Ý±k}kœ,œ4]ŠUZu^ßa¾øóåÞÝ{dgeckg[¨‡±xñm¼²Q†é”Å÷]¿çvâmM—!Ä ëE Þ:¶O·¼™x± n<˜Ñî£5]F©4°#Œ ®Q]&yNzê}?ŸÉË“‡¸ê”—›÷T+]ˆªáE ^Q=Ü "ä•Ú IDAT%‚¹Jî±®iØY^³H~Tr�Â☘,<�œœŒ•UÉ�&Dù%&%âPÇAÓeˆçD‚WTv–†–8hUþßIØ?oÿ‰žB[cÛÒÿ‹¡‘!VÖV\½z•Æ�«¡:ñèÑ#îÆÞ¥“O§Ò‹ZqÁ›š¢Í�ëå ^�f9=[ðnÙ`Ìò%Æ –ÁÛ“Ò)fÅ:ñ±Ô·ÄÄÐDÓe”Jã«­¥�¥/ŸUÎþ}ooo•.ý¢bœ9sCì^·S3sÍïâ¦ÄÞÑfÁ—fœ8jÀw?%QÇ6¿ôE•uáÁÎÜ?#ËÕ•¦ƒ]R¥”{¯Ž^œ àðáÃôêÕ«+<àðáÃtôî(¼ˆ§ö<‚75E›Ø;ÚÊïÏžÒǧƒ5_}›BŸ™j?G¡dB‹Ê?4Kã¿5瞟‹­‘m¹:9›óÊÀWصeæææ´oß¾‚+¬žX¹r%µíjÓ¦}›Òw¢Œ*"x=›çàì’‹^#tR’µ™8¦Gd0÷Û”g¾]ÄÅűqãFå÷¶¶¶ V¶q¦ÁÁÁDDD0tèPu•WÈÆ¨�‹=ÆÁAŸÛ{–‡Æv]ÏuÏ>[[[´µ‹þ\²²²HIIÁƦbV¢ùå—_èСõêÕ«�ã•™¢ ƒle§ñ€½ž|òÀÁ¢bÆ4iiiaߨ^z½ Q \½R8àtt e›l|zeáÓ;“ÆyܸÏÆ•Ïö^çÏŸg„ ÄÅÅ¡P(ÈÏÏç�7Þà“O>ÁÄÄ„ûÿ×Þ}‡5y½}ÿ’!ldoIÑŠ[ñ§àQ·¸êªûuRmßjëjÚZëjU«"NT¬Ü{`�ÈV™Š({C ï¼FÓ¨$ž ÷纼z‘<ã~Rô›sžóœ“™‰öíÛ£´´yyyøê«¯d&$$@[[AAAÈËËÃæÍ¯ ºsçüýý €µµ5Ο?�Å‹ãСC¨ªª‚§§'BCC¥Û̘1�|>óçÏG~~>5j„;vÀËËKzüÔÔTáܹsàóùÐÒÒÂâÅ‹øAŸIHHfÏžýAǨ ''M…ý¼µÅü+@ZA²J³X—Ai€;TÏâÆçKàÛ³ Ë×ä#2:û�ecâ´"8:Õß,o'ND�=�œœŒÔÔT\¾|&&&àóùüóÏ?xøð!455±fÍ<|øPúçÕvÅÅÅ(.–íµ‹ÅÈÍÍ…ä�›Ê¹¹¹’““Ñ»wï:£®N¥žÂ7—¾ùèç­-æ-Øa.Ã𲀺q !µ·uOâcÕ!‰¡¥¥ÜщéééÈÌÌ„¹¹90sæLéû†††ª{Ò´µµ¥?×Õ¼yó0`À€››zôè�ÈlÓ¼ys¬\¹Rúó„ ЧO”––BKK ýõŠ‹‹±víZi‹ÚÛÛþþþسg�ôÞkm…„„`РAÐÒz÷=pe&† Öª¿D!óì´óÓ°%f ë2! �'AÓ/*”®Œ´´48;;£S§NX²d =z¤Ôs¾ê ~ÅÈÈ ·‘H$(**PÝÒ,((€——:vì(ýsᤤ¤Ô©®òòrìÝ»#FŒ¨Óþêàãƒ~r8“s×óìÎ;ñ4÷)ë2!佚6mŠˆˆdddàܹs8räZ¶l‰½{÷Â××Wf[555™îÞ«ªªÛLSjjµŸõŽÏçC `õêÕrï½oÐÔûœ¤<==‹U«VáÔ©S ‘y?33gΜùàÈ"·,OòŸ0;M1ï"®”T¢²ŠÖs%„¨®fÍšáâŋشi–,Y‚òòrØÛÛ#$$]»v•Û~ñâÅÐÓÓÖ-[ ‹!‰Ð­[7ÃËË k×®ÅþýûqóæM 2cÆŒ�šš4Þ˜û±ÿþ077—«ÃÌÌLúsË–-庛 Ñ¿ðxÕÓW©©©a×®]ضmΞ=‹��ØÛÛcèСppp�«½E‹øóÏ?Œ£G�¢mÛ¶�H$Òîé={ö sçΰ´¬ý hõ¥¥iKt¶ëÌìü5¥&yß�‚Z8uê|||póæÍZõËÏ¿:êâ<¤>Ê „9I�’°sóNüòË/2!Fj¯mÛ¶øöÛoѯ_¿z9^HHJ+KÑwHßï³=n;"R#pið¥:�sÞ¼yXµj•t ˜²0oÁþoëÿųÜg¬Ë „¢ÀíÛ·‘žžŽž=ÙÎ<\0³ZÎR¼!cÌïÁ~þ%Ö>X˺ Bˆ IOMÇå —ÿÞѸäã¸uë–´û™•Si§ðõ¥¯™ÖPÌ[°ëº¬Ã‹ü¬Ë „¨€´”4Ìœ<‘×#¥¯uîÒ¶o€¶6Í�ÍšžžôôôX—'}'˜éš)Þ�1æ-Øm·á\ú9ÖeB>‚k—¯áû¹ßcüˆñXÏD\LLÍLe¶{Û*/ÿñþV,]�;·îÀÆ®ºuúøÑcØÚÛJ·QWW‡ƒ³’'AKK .n.¸{[~^^mmmäåæÕé3øy{{céÒ¥o�ùsЈßBŽ�u 1oÁžM=‹ÙoHQ(%)=½{âÀÞ.—‹�Ûv"òz$zôÂê�«q9wîbß‘}004À·³¾•Îg›Ÿ—�[7nA\Q‘»Âv!êI®Ý» M ¹®ZK+K”––Ê kWp8DGECè"‡ÃALTŒ\Í–V–x–^=›[ÛmqåâäæÈ~é.,(„¾�~ý|H I$…KÕÕd);]]]LŸ>®®® ·­ëÒxªÌPÓöúò+©æ«ÎQ\ÖeòI065Fôƒh<¼ÿPúšÐEž_÷5üûúCä*‚Q##´íÐSgMEƳ Ü»s0kÊ, è9‰ Õ«¬èêé¢e›–ÐÓ׃º†:�/sNûÆÕÿÐ%ÆË®Ì¢¥¥ + ¤¥¦Aß@N'\»|M®f555TVV?Ó8xø`TŠ«[ݯ<ÏxŽÓá§Ñ¡c‡zø„>®¢¢"¸»»#;;3fÌ€©©)ÌÍÍ1a”——Ël»k×.4iÒÖÖÖ‰Dpww‡»»;fÏž 8räˆôµW‚ƒƒåÎÙ¦M K …×®ª‚‚‚0~üxXYYÁÏÏÞÞÞ¸uë–ôý3gÎÀÓÓ­ZµB[[%%%Ò%å5j$³Xº––Ö;Ï7fÌÌž=ÖÖÖèÔ©úöí+s>�‡mÛ¶!$$'OžÄ¤I“°hÑ"¸¹¹)é¨_!q!ð;äǺ …˜rÚæ³ i94:��¨ûQÿåxtéÖË×.‡�¡�ô½õ«×cÙâeذv¦M{ïqD."œ>yÙYÙhdÜB×êÁ ·#o£ª² q1qxøà!Î�>‡ôÔtLœ6VÖV5ªQä*BQaÒSÓ¥— `ü¶ô7Ü»s_x|ˆ~�ä¤dŒ™Xýž¥•%Öo]�™“g¢s«êµ< ðãòåYõ è…^½jTSCðïµSMMM‘—÷úžµ……8€òòrhjj"##ÙÙÙ°¶¶®—󙘘 >^ö –@ À²eË0xð`tïÞ'N¬Ó¹XèaßþΪÿ,ó€�rn L5M1Þm<ëRaêçÅ?ÃÜÂk6­‘k�Lš> àèì¨ð8"×ê[.ñ±ñhçÙB‘jjjXj8ª$Uز‘ƒ†½ž\«›nDÝ@ôƒhðx<]„¯'˜øŒü{Ôõ¸qã°iÓ&xyy¡C‡8~ü8¦N�Z£ALu9ß+çÎ�ƒ­­-ÒÒÒPZZ >Ÿ_/çS¶Ä¼D<)|‚f¦ÍX—ò^̳Ǻ�Eqi±â ù„âÊÅ+˜:kê[»þÔÔÔ0yÆäëU‹5.&í<ÛAGWÖ¶ÖÐ7ÐǦàM2ÁX[¶ö¶ÐÖÖF\Lºúv•¾®£«ƒÐ£¡X½|5._¸ žã&�Ø c ££#s ��Vu®áStæÌXZZbÙ²eHNNÆ”)Sàè¨øËԇضmþùç\½zƒ ÂìÙ³±~ýz¥ž³¾¨A êæñ¥ó å>ªG}åþ2¢ÊR’RPYY {‡š?z�“�ƒ¸˜8ÄÇÆ#6:\.K~Y'g'¨««Ë݇}p÷A�ÂõÆÕ8{ê,† "×bæp8ˆxœøXn?S,ùeI�ë'¯%%%!;;)))°²²B^^aggMMÍz?_ll,¾ùæ„……ÁÀÀ[·nEûöí±sçN >¼ÞÏWßôàdìĺ …˜ìÓ¢§à«5Œn òéËÉÎÁ‘°#xšþºzºèÙ»g�ºe?T•¤úYÅ’â’m/‘HàéቢÂ"@ä*BË6-šV qêÒÿ&Æ«cìÄRÅP>Ÿ�£G�ʽ>}út™Ÿ‡Ž5kÖ wïÞÒ×*++1tèÐwì›�ݼ)44T#GÊü¼lÙ2¹mºv튮]»Ê½®Š† ‡!¨uë2b°3ÎÏ€�¶ ‚šø‡õüésü½ïoädçÀ½‰;zøö€¾¾¾RºX>%¥¥¥ÈÎÎFLL vmÙG�#zê ]Å;7åø}åï CfF&Œ!pd ¦Îš uuuˆÅb̘4‘;î„––Š‹‹1¬ï0,øvüzû½óùÀŠò ¬^¾!ÛB°u÷V…µTUU!%9qÑÕÝ»ŽÎŽèÐ ŽÎŽ8~?üôÃ[÷‹Å8wê;4´hÝâ�繊pìïcxöô,­,å>½�ÈU$Ý^UV)É\ÄÇh !ž‹¸h $&p‘¯Žò²×ƒy �ª ‰ÑH œň½Ç°hä&žHIIÁǤúAò±x|WŸ_Eh/ù/ª„yÀîòÛ…ôœtÅ*�ô( ¡Á¡ …˜2iŠ\— QÌËË éé騽{7¶þ±#Æ�€a£Oãsœ>q:.œ¹€)³¦ éMqâÈ ü¶ì7T”Wàëy_#!.i)iXðßÒAFÚÚÚ6zæL›ƒôÔtØ5–‰ŠÁ¬©³`jjŠãç�Ë=îò4ý)âcã‡AÃáå‹—èݵ7JKKÁáp`ko‹¡#‡Àò—#âD|ü|äÎuúäiTVVÖhÔï«Ùš2žeÀÒÊÎBgì?¶®MêgTêÇò<ƒ#Ó��UÇÃû()y¤zúUhìP ÿ€R]Ĉĺˆak_‰Wƒg“å«tÀ®^½³gÏÆ/¿üsssäääàåË—˜9s&ÆŽ˺<•ÓÆ¬ ZX¼û ¦ª`° ®/€!×ÄÃê|Œ¼œ<Üu­ZµÂÀ�ß9$�(fmm�iÓ¦áÏMbÈ~Œž2êêÌMT�´}5 '.&I�“�—›3 3Ìœ3nMßþ�|lt,Ž>Že+—aè—ÕaÖ¹Kgädç`ÇÖú.eee wï©R\=mO‹'óºX,Æú5ë±é�M˜3oFŒ!ó{·nÕ:¬_³^ºL›¹…9Úÿ§="–,_‘«‘ÚÚÚÒ}ÆLƒÝÁ»1gÚ…ÉtÑ>¸÷ó¾ž7tï¡x‚wŸž>èáßCú³†¦Æ;»|UAm‚Ô¯÷»ƒ´¡ €¿¿??~Œ¼¼ègOž…©©) @áZx<ÆŒƒeË–áÖÕ[h×éý]ŠÊ�—€ô´txuõü¾òw,ÿq9€×ÏqÚ;ÚÃÀÐg"ÎàÆÕ8zæ¨ÌJ-¯¼ìÓ¹‹ì_Ææ-šãäÑ“�H$pm⊋·.Êì_Q^��Ûv¢Eë0·0—¾žŸˆ ©AÐäiâÈé#oùëÑÊsçÏ…ÐE‘«HfPÐàaƒßzÍ:::ؾw;F …AþƒÐ¢u XÛX#5%wnÝ�[S7lÞ±¹FÏ�r8Ì'i{«Ï=H߇ËåB xû ZDV^YR RX—¡ó€-¯,‡¸J¬xÃwÈËÉC̃Lž«óþY/²`gkG]ÃJ```=}=d½ÈªSÀnX³'��D|l¼t%uuutìÜ;wĸIãÐô‹¦oÝ÷Õ(Ö¸˜8XXZÀYä .—+·Tˆ+ÄÈËË“vïÚ;ØcWØ®w>.sõÒUL5 ýõÃȱ²�/TVVbüÈñˆº…}‡÷¡I³&2ï»7sÇÞÃ{QRR‚È둸zé*VüwâbâðE‹/àÙɽûõþ(ÏÎ~L¤D•ŒŽÀì–³Y—¡ó€>êƒÓ)).�®Žn=WE^ÑÕÕEqaݦ²ÔÐÔ@³æÍ0xØ`ˆ\EزöÀ†íÎyúªÕ�Î]:K»pßœ:ywB'ïênª¼Ü<\¿zW.\Á±¿�)œ�_UQ�’† <%·³nãÏn².彘ìú.ëñ"ÿE�÷—H$tïU‰8N�'ê7iœÌϱѱطsãßÙr}ÅÞÁ<O¦Å*rá⹋˜;c.â¢ã�—€¢¢"›ãëï¾Æ°Qï‰~;ò6¦Œ�‚©3§bö·òß~+++¼9§M„ƒ£rsre¦"<|°t¥˜304€oO_øöô}o ª‚‚”4dC,ôUùBæ»%j t9ºp `] Q²7»}¬ºº:œ„N2-V¡‹'Žœ@b|"pÁ›ƒñ<ã9¸\.líl!rA\Q÷Áx¬Ô$HuõªààHAJŽÊªJˆ+Uÿï#óÛZn”gIDAT€ KoH¼Wݾo†æ›*++‘š’ SSSèèê@ä*BøÑpTUU�ÃáHzæÜ™Ò®YEJJJÀçóñøÑcÄDÅ`Ô¸Q8|ð°t¥¸Ø8¤&§bÿ±ý°¶µ†WW/ˆÜDÒÇk"Á{¶V¤äs’\�Œ»Ùw1P8�u)ïÅ<`-u,QRZ³ ÎIæo K+KÄǼîö½|á2Âö…!.¦ºË·´´[vnA·Ý r!l_R“Saï`/ÓV°/_¼D·Ý raïá½x™ùðí¬oaÔÈ"×êõêæ‘«nMÝÀçó±}ßvå}õ€‚” ‹u r¤xCƘìÞø½0Ö4†ÐP¨xcÒà‰\E2-جYÈ|ž‰vÛá˯¾„‹›‹´¥+mñÆÆÁÞÁ�C“§)Ðïblb hñ«[Ÿöö9‘«fæf öfïmA¥�¢" RBv%î¢ÇtjbUçUHËIc]ùH„®Bœ?sùyùÐ7ÐGÀÀ |ûý÷7'¨÷ñó©¾/ëìôÖGuþMMM ‘ёҟÍ-ÌefcRµ Rß^¤„À@Ç�ã>†u 1Øa'‡Ášo�Íf°.…|o†¦¢Ië­m­¡£«#ÓbíÔ¥^<¯û¨sV(H ©?7žß@l~,–u”_vO•0Ø%í— ·(—uä#ys “¢€USSÜys`gÿz›ï~§Ôú>Ô‡©�]%è‰3B3á›À…[ûu—?6æ{:ù44 [ùå¹È§G €ÃáÔ¨›¨^aFQ�ÂŽ�¦´xª?ºŸyÀjr5¡^ż ò‘ðù|ü¼êg¸º7ŒuIk¤š< ìW«[™4D"1œ…b Rñj2šºNšB”G"‘€£V»¿(w^ÜÁõ×ÑÍ®›’ªªÌ“­­e[°.ƒ|Dƒ‡¿}¹6–(H?m:º:€ÂÂBðx<[“�)//¦Ö¦µÚ§¯c_Lö˜¬¤Šêó€]þÏrXhY`ªûTÖ¥�ÏéçIW¯z¾òÜÜ\3®†¼)//.ïž÷ûmBâBpöéYœpZIUÕæ»µûVzL‡Ô»·éCu¾NH ÒÏO‹ccŒ™3gÒ2—Œ]½zùùùèØ¥c­÷m¬ßNƪßÕÏ<`3Š2Àç¼ñíOÑádž+W®ÔzßÉ“'ã×_Å�!C”PYͼ|ÁÁ¬É†¸x®ú[äòŸÔj°¤„//lY»GŽA@-‘ÉJjj*9ŒN];IGx×ÆÙ´³¸ðôŽ÷;®„êêó€,Œ—ù/Y—AjáÊEMÌœdˆÌç¯S.>Nb1 þ¯ß( R¢JŒŒ�0$¡;Ba``///Ö%}v222°eË\hש]�Ž1T0³[ÍV¼!cÌvÆù°Ñ¶APó Ö¥4jŒ&¦‹�µ+t±æW]üûyýò25„…òQ�¯FAJTšÀU€žýzâèßG‘‘‘�~ýúѳ±ɽ{÷°{÷nØØÛÀ �ÿ-;ðø®d\Á~ÿýõ\aýb°»ýv#=7�u5vÿþ}Ì›7·oßFii)š7oŽI“&aÀ€Ò{:%%%øá‡pøðadddÀÖÖÄ´iÓdžÁãóùˆŠŠÂôéÓqïÞ=ØÚÚbÅŠèÚµ«t›—/_bîܹˆˆˆ€±±1&OžÌdð´.¦M0ÀíÈw,øú P�Õ×¼us!lwbbbàëë‹–-[RÐ*�D"ARRNœ8�ÄÄD´ýO[xûzÐ=ð¶fmÑÒ²e=V©ÌöûkßÃPÝÃ…ÃY—¢�D"ÁÀ�1xð`ìÙ³¥¥¥¸rå .]º„H·[ºt).\¸€ððpXXX &&[·nENNŽLÀ&''#(( ,€……–.]бcÇ"..ZZZ‹Åð÷÷ŸÏGXXôõõñçŸâéÓ§õº#N8cÇ6ˆÅïÿ¶ÙoP ‚þ·6v´ú Q}öŽö˜4×.\áC‡v( B�¶¶¶ÐÓÓƒŽNíï ’jb±¹¹¹ÈÎÎFtL4òróààì€qÿ3æV¾lä‹’È(Ë@'ëNõP­ò0X;”•øèÓ�¡¢¢YYY033ŸÏ‡ŽŽúôéƒ>}dxÎÈÈ€žžLLL ¥¥xxxÈ�ËåâÀ�ÐÕ­žeæ‡~@hh(?~ 777„††"11QQQ°°°¬X±ûöíSþž¡¬Œ.·º‹ø}ªªÔ`k_ùqŠ"¤ð´xðòõB¯xÿ 1 xóùyù(//g]^ƒÅår¡­£ #´jß Â&B42nToÇϯÈGz‘ê÷|2زÊ2TTU°.£F455±~ýzÌ™3+W®„¯¯/ºuë†^½z�Ï=zþüù5jìììàéé ôéÓööö2Ç366–†+˜™™rrr‘‘‘hÚ´©4\YéÝ7?®0AäuMœ>©…ˆ<$?áÊm—/ÿ! �&O®M]áÚ´a,Bñ¹ó0ñ€§�'ë2b~GìzÆu$ä&°.£ÆŒøøxlݺæææøñÇѬY3$&&J·±³³Ã¹sçpýúuôèÑgÏžEóæÍ±aÆ÷ûß7üy<Ôÿ=,—.hçYŽùKòqñÖ œºòsæ y‹ iw°…%­TBQ¾°'a1Šu 1Ø9-ç À¡á<�&‘HÀãñàåå…E‹áÖ­[ÐÕÕ•é¶•H$¡Pˆ©S§",, sçÎÅüQ«s‰D"DEE¡°°PúZyy9ÄŠúj?¡‹ÿ3«ŸÊÂ͇™Ø¶'¿oÎe]!ä30R8áýÂY—¡ó€1¿?ø�u5ŽvíÚaÿþýxöìrrrpöìY<}úTz�µ´´­ZµÂO?ý„¸¸8äææ"!!.\@‹-ju¾Aƒ�ÏçcôèѸ}û6Ο?�>}ú ¢BµºÔÍÌ«àݽ ::Ö¥B>'RN`Æ…¬ËPˆyÿㆮð"ÿë2jÄÇÇØ´iæÎ� ‰D'''üþûïðóóhiiaß¾}Xµj „¬¬,˜››ÃÏÏß~û­ôX‰D2Ççp8ððð�Þ—ÕÑÑAxx8¾ùæ 0VVVøñÇqðàA}¼ '„"4ÂJ¿v °À<`7?Ø Žú:öe]ŠBjjjð÷÷‡¿¿ÿ{·srrÂÚµk߻͈#0bÄ™×ø|>._¾,óš@ ÀÁƒe^«ËüÅ„ò©W‰QV©úOŸ0ï"‰`¥£úßD!„¨†”‚\L¿Èº …˜·`ÍtÌPRZº B! „·µ7º d]†BÌ[°¡ ¡¸–q�u„BˆÝ‰»ÑçpÅ2Ƽ»²ÓJ¤å¤±.ƒBH1Ði ƺ�e]†BÌ[°CO Ū{«X—A!¤�¸‘q«ï®f]†BÌ[°?uø 9E9¬Ë „Ò@˜j›Â�ëÆº …˜·`ÓÂq÷å]ÖeBi ô4ô`­kͺ …˜,_�‡Ö`$„R3w_ÜŶèm¬ËPˆyqk‹ÖÈ/Îg]!„�¢¯c_Lö˜Ìº …˜·`WÜ^�#Oް.ƒBH±#n|Ã|Y—¡óì_Ýÿ¢Çt!„ÔXOûžpVýUؘ·`'��„M7±.ƒBH—× z>™·`'¸O@aI¡â !„êjêÐR×b]†BÌ6.;jUjpÔwd] !„�ÀNÏ�5f]†BÌ»ˆ3K2‘WžÇº B! ÄùôóXpmë2bÞ‚ €¬‚¬:ïÏårQQQQ�‘7‰+ÄP×`þkB!R�‚@Ìj5‹u 1oÁκ0 Ûb·Õy]}]ääÐT‹Ê ‘H�““=}=Ö¥BˆÔþGû1äøÖe(ļi²§ç¤ç¤×y{D^�DYYx<šª>%''£¼¼6ö6¬K!„©öæíÑÆª ë2bÞ‚�wuvÅïªóþÎÐÐÐÀµk´¦l}»xñ"lÛR –¢R2K2•ź …˜l»ð0ñ¨óþèй"""ðâÅ‹z¬ìóƒ»wï¢s÷άK!„xZø”u 1Øbq1Ê«Ê?èm:¶�¹•9þüóO Ùz���€àà`´éØvv¬Ë!„_˜|�Q®£X—¡ó€�|‰ÄüÄ:‡ÃÁ€á k ‹•+Wâܹs())©§ ?¹¹¹8xð 6lØ€&Í› K�.¬K"„9‡žÂèS£Y—¡óANA-ƒ�‘—ñÁÇÑâka蘡¸yå&"NEàØ±c°²¶‚�¾ÔÕ™_¦J+//GVV233aØÈý†öƒ‹» ë²!ä­F GbNë9¬ËPˆyòŒ‰m5úàcq¸´ëÔ­:´Â“„'x–þ E…E�H$õPé§‹¯Å‡«­+z8ô€•­8æ„òNÇ“�ãvÖmlî¾™u)ïÅ<`7v݈ÌüÌz=¦ºº:®\õz\B!ì¹¹ÀÆ@õdÞTÙx#N¥žb]!„�¢¢ª%bÕgÃ<`ÝŒÝ`£«úßD!„¨†”Â\yv…u 1ï"6á› ¤Tõ¿‰BQ ÞVÞ Àº …˜·`$À�Ì¬Ë „Ò@ìNÜ�€#¬ËPˆy ö·N¿!-'�u„BˆANƒ0®é8Öe(ļx"«î­b]!„�âZÆ5¬¼³’u 1oÁ.õ\ŠœBZnŽBH͘i›�«Îe]†BÌ[°'ŸœÄ�—wX—A!¤�ÐÕÐ……Žë2b°ÚÚàqhWB!5sÿÅ}dz.C!æ]Ä-Í[¢ ¸€u„BˆÇLò˜Äº …˜·`]_„«Ï¯âÛëßâhòQœI;ƒé—¦ƒËáÂ÷ˆ/2K3±ìÎ2ìL؉^þƒÑgFƒ§ÎCÿ“ýŸ�õ×ã�¨?�˜Ÿˆ¾'ú‚§Îسcù"»vã¿·ÿ‹—e/á{Äjjj˜ueN¥ŸÂñ”ã˜{m.Ê%åð=â‹üŠ|,Œ\ˆý�öãJÆL¼0ôøñcìØ±ãÇ�‡µµu�÷³Ò±ÂÁk£¹Ys89ÀÑÀÍÍ›£‘V#t°î3345m �‘vúvhiÙ†,!„R/ÊÊÊ>JNÕ[À:88`îܹõu8B!Di455•~5‰D"QúY!„�Ï Ýƒ%„B”€–BQ XB!D (` !„% €%„B”€–BQ XB!D (` !„% €%„B”€–BQ XB!D (` !„% €%„B”€–BQ XB!D (` !„% €%„B”€–BQ XB!D (` !„% €%„B”€–BQ XB!D (` !„% €%„B”€–BQ XB!D (` !„%ø?~§ž·²é+IEND®B`‚sslh-2.3.1/doc/detailed-ip-transparency.svg000066400000000000000000001653251515234404100206570ustar00rootroot00000000000000 Viewer does not support full SVG 1.1 Families Prerouting Hook clientC-IP Prerouting Hook sslh Prerouting Hook sshd Prerouting Hook stunnel/nginx C-IP:1000-->M-IP:443 T-IP:22<--C-IP:1000 S-IP:443<--C-IP:1000 sslh-2.3.1/doc/max_connections.md000066400000000000000000000052361515234404100167510ustar00rootroot00000000000000Limiting the number of connections ---------------------------------- As a network-facing service, `sslh` can be attacked by very simple denial-of-service attacks by creating a lot of concurrent connections. Protecting against such attacks is complicated from the server side. This attack will cause `sslh` to create a large number of file handles, which can cause exgagerated resource consumption. In particular, when `sslh` runs into its file descriptor limit (as defined with `ulimit -n`), bad things happen: It becomes impossible to accept() new sockets efficiently (refer to libev's documentation, ["The special problem of accept()ing when you can't"](http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_special_problem_of_accept_ing_wh)). Currently, when `sslh-ev` or `sslh-select` reaches its limit of file descriptors, it just stops accepting new connections altogether for a few seconds, hoping for the situation to get better soon. It is better to configure `sslh` to limit connections so the `ulimit` is never reached. Keep in mind that limiting the number of connections means that in case of an attack, the server resources are protected, but this might be at the expense of serving legitimate connections. In particular, in some cases this might mean SSH is no longer available. There are several mechanisms to limit the number of connections: - Use `ulimit` (see bash(3) or your shell's man page) to limit the number of file descriptors. (but then accepting new connections might fail for a while) Then, `sslh` provides several mechanisms to limit the number of concurrent connections, which in turns limits the number of file descriptors used. Essentially there are two ways to do this: - you can set `max_connections` per protocol, and `sslh` will drop connections after probing if the count is exceeded. This should help in keeping SSH connections available even if an attacker is stuffing other protocols. - you can set `max_connections` for each `listen` entry. So the `sslh` process for each port will limit the number of concurrent connections to that port. This is similar to the `udp_max_connections` setting, but for TCP. `sslh-select` and `sslh-ev` support both limit types. `sslh-fork` has an explicit design goal to be as simple as possible, which makes it impossible to implement limits per protocol (because protocol probing is performed after the process has forked). Limits will only work for `listen` entries. As of sslh 2.2.5, this is an experimental feature and not all use cases have been tested. If 2.2.5 does not exist yet, you must be on the Git's head, so it is even more experimtental! Do not hesitate to send feedback if you notice inconsistent behaviour. sslh-2.3.1/doc/podman.md000066400000000000000000000130511515234404100150320ustar00rootroot00000000000000Here is an example of deployment of sslh in transparent mode using ansible and podman, [submitted by Github user olegstepura](https://github.com/yrutschle/sslh/issues/448) ```yaml # ansible podman task - name: "Create sslh-co pod" containers.podman.podman_pod: name: sslh-co # read as "sslh and company" state: started ports: - "80:80" - "443:444" # ... (more ports if needed) network: - '{{ containers.config.network }}' # other services from this network can access containers in this network for example prometheus can read caddy metrics at sslh-co:2020, also caddy itself can connect to other services to act as a reverse proxy - name: "Create the sslh container" containers.podman.podman_container: name: sslh image: "yrutschle/sslh:latest" pod: sslh-co capabilities: - NET_RAW - NET_BIND_SERVICE - NET_ADMIN sysctl: net.ipv4.conf.default.route_localnet: 1 net.ipv4.conf.all.route_localnet: 1 expose: - 444 volume: # ... (make sure to mount config as you like) command: --transparent -F/etc/sslh/sslh.cfg # parameter --transparent here is needed to trigger configure_iptables in init script state: started # âš ï¸� Important: Never add a `network:` here, otherwise this setup will NOT work. # Adding a network disconnects the sslh container from the pod's shared localhost. - name: "Create the caddy container" containers.podman.podman_container: name: caddy image: "lucaslorentz/caddy-docker-proxy:alpine" # regular caddy or nginx image will also work pod: sslh-co expose: - 80 - 443 - 2020 # metrics, since caddy-docker-proxy uses :2019 internally volume: # ... (mount your configs and other stuff here) - "/var/run/podman/podman.sock:/var/run/docker.sock" state: started notify: podman restart sslh - name: "Create the SSH proxy to host container" containers.podman.podman_container: name: ssh-proxy image: "alpine/socat:latest" pod: sslh-co expose: - 222 command: TCP-LISTEN:222,fork TCP:host.containers.internal:22 state: started ``` ```ini # sslh config foreground: true; inetd: false; numeric: true; transparent: true; timeout: 5; listen: ( { host: "0.0.0.0"; port: "444"; keepalive: true; }, ); protocols: ( { name: "ssh"; service: "ssh"; host: "localhost"; port: "222"; fork: true; }, { name: "http"; host: "localhost"; port: "80"; }, { name: "tls"; host: "localhost"; port: "443"; }, ); ``` I omitted Caddy configs here since they're irrelevant, and some unrelated container configs were also dropped for clarity. In the example above, `sslh`, `caddy`, and `ssh-proxy` are **three containers inside the same Podman pod**, all sharing the same **pod-local `localhost`**. `sslh` listens on port **444** instead of **443**, because `caddy` already binds to port `443`, and reconfiguring Caddy is more complex due to its Let's Encrypt integration (Caddy itself "thinks" it’s bound to your host interface). #### Port mapping scheme All containers **share the same `localhost`** inside the pod: ``` host 443 → pod 444 (sslh) → pod 443 (caddy) ``` - **Podman** maps the host’s `443` → pod’s `444`. - **SSHL** listens on `localhost:444` inside the pod and forwards TLS traffic to `caddy` on `localhost:443`. - **Caddy** listens on `localhost:443` and reverse-proxies to other services in the private network. This ensures that **reverse-proxied services** receive the correct client IP in the `X-Forwarded-For` header. --- ### Important note âš ï¸� Do **not** set a `network:` parameter for the `sslh` container when it belongs to a Podman pod. Setting a custom network **forces Podman to detach the container from the pod’s shared network namespace** and creates a **separate `localhost`** for that container, breaking transparent routing. For example: ```yaml command: --transparent -F/etc/sslh/sslh.cfg # parameter --transparent here is needed to trigger configure_iptables in init script state: started # âš ï¸� Never add a `network:` here! # Adding a network disconnects the sslh container from the pod's shared localhost, # causing transparent routing to fail. ``` ### Key takeaways - `net.ipv4.conf.default.route_localnet` and iptables rules are applied **inside the `sslh` container only**, not on the host. - The `sslh` **init** script manages all required `iptables` and routing rules inside of the container. - **Transparent mode restrictions**: - Any service `sslh` proxies traffic to **must** be inside the same pod and bound to its **pod-local `localhost`**. - Container ports must not conflict within the pod. - Ports should be published **at the pod level**, **not per-container**. - Containers inside this pod **must not** be attached to any custom networks. - Because of transparent routing, `sslh` cannot directly proxy SSH to the host IP. A workaround is to run a lightweight **socat** container in the same pod: `TCP-LISTEN:222 → TCP:host.containers.internal:22` - Caddy’s `reverse_proxy` **to other containers** in the **custom network attached to the pod** still works properly. - `socat` can also connect to both the **host** and **other containers** inside the custom network without issues. ### Tested setup - Confirmed working on **Debian Trixie** - Using **Podman 5.4.2** - Pinned `podman` and related dependencies (`conmon`, `slirp4netns`, `aardvark-dns`, etc.) from **Debian testing**, since **stable** often ships outdated versions that can break this setup. sslh-2.3.1/doc/proxyprotocol.md000066400000000000000000000110741515234404100165220ustar00rootroot00000000000000Using Proxyprotocol with sslh ============================= HAProxy defined the [Proxy protocol](https://www.haproxy.com/documentation/haproxy-configuration-tutorials/proxying-essentials/client-ip-preservation/enable-proxy-protocol/), where a proxy adds external connection information directly inside the TCP connection, for the backend server to get. This achieves the same goal as transparent proxying, while requiring no networking knowledge and no administration rights. Instead, the protocol needs to be supported in the servers. Many do, e.g. Apache (with the `RemoteIPProxyProtocol` setting). `sslh` supports this protocol both on the client and the server side. Proxyprotocol on the server side -------------------------------- Presumably that's the most common setup, with `sslh` being the client-facing proxy in front of the backend server. Support is enabled by adding the `proxyprotocol: [1|2]` setting in the target protocol: ``` listen: ( { host: "localhost"; port: "443"; } ); protocols: ( { name: "ssh"; host: "localhost"; port: "2222"; }, { name: "tls"; host: "localhost"; port: "8080"; proxyprotocol: 2; } ); ``` Here `sslh` listens on port 443. It forwards `ssh` connections to port 2222 without touching them (which means sshd does not see the external data) (Apparently openssh does not as of september 2025 support Proxyprotocol). It forwards `tls` to port 8080, adding a proxy-protocol v2 header which allows Apache (configured with RemoteIPProxyProtocol) to log the external IP and port. ``` 203.0.113.4:443 :2222 Client -----------------> sslh -------------> sshd 198.51.100.42:2342 | logs: 127.0.0.1: | | :8080 \--pp v2-------> apache logs: 198.51.100.42:2342 ``` The `proxyprotocol` setting can be set to 1 or 2, which selects the appropriate protocol version. Version 2 being more efficient, this is what you should use unless you have good reasons to use version 1 (e.g. your backend server only supports v1, an unlikely scenario). Proxyprotocol on the client side -------------------------------- `sslh` also supports Proxy-protocol on incoming connections. These are so-called "client side", but you should not enable proxy-protocol on an Internet-facing server. Instead, this can be useful if `sslh` is located behind another proxy that adds proxy-protocol headers, e.g. HAProxy. This is enabled by adding `proxyprotocol: true` to a `listen` statement: ``` listen: ( { host: "localhost"; port: "443"; proxyprotocol: true; } ); protocols: ( { name: "ssh"; host: "localhost"; port: "2222"; proxyprotocol: 0; }, { name: "tls"; host: "localhost"; port: "8080"; } ); ``` In that case, `sslh` expects to find a proxyprotocol header on all incoming connections. It ignores the header to perform its usual protocol detection. If the target protocol specified nothing, the connection is passed untouched, i.e. the proxyprotocol header is forwarded as usual: here, Apache on 8080 will receive the proxyprotocol header. If the target protocol specifies `proxyprotocol: 0`, then `sslh` removes the proxyprotocol header, and logs an additional message with the connection information extracted from the header. Here, `sslh` logs the external information for ssh connections, removes the header, and forwards the connection to sshd. `sshd` does not support proxyprotocol, and logs a connection coming from the local IP address. ``` 203.0.113.4:443 :2222 Client ---------> HaProxy ----pp v2---------> sslh -------------> sshd 198.51.100.42:2342 | logs: 127.0.0.1: | sslh logs: 198.51.100.42:2342 to localhost:2222 | | :8080 \--pp v2-------> apache logs: 198.51.100.42:2342 sslh logs: local connection ``` `sslh` always logs the 'real' network information, here the local addresses, and only logs the proxyprotocol information when it removes the header. It is not necessary to log the proxyprotocol information when the target server will receive it (as it is then the target server's job to log the external IP address). sslh-2.3.1/doc/scenarios-for-simple-transparent-proxy.md000066400000000000000000000130331515234404100233330ustar00rootroot00000000000000# Three Scenarios for the simple transparent proxy setup # ![Simple Transparent Proxy Examples](./sslh-examples-v3.png) ## Introduction ## The first example is the configuration, which was described in the previous document. I omitted the loopback interface "lo" in those diagrams, trying not no overload the picture. The connections have two different endings, showing the direction of the opening connection (SYN flag) and the answer connection (SYN-ACK flags). This is important, as the traffic in the transparent proxy setup flows somewhat unexpected. ## Example 1 ## The first example shows the setup, which is described in the [previous document](./simple_transparent_proxy.md). You see the Client connecting to sslh (red connection). When sslh accepts this connection, the SYN-ACK packet is send back to the client, which sends the first data packet(s) together with the ACK for the SYN-ACK. So the bidirectional tcp connection is fully open. Sslh opens now the blue connection to sshd and needs for that elevation rights, as it uses the clients IP address as its own address for opening this connection. Now things are becoming complicated: Sshd send back the first packet with SYN-ACK flags (green line), addressed to the clients IP (dotted line). As already described, that would go wrong, so our routing trick makes this packet beeing deflected back to sslh, so this tcp connection is also opened. But we have here now an asymetric behaviour, that the read and write pathes of the tcp connection are going different routes. The sslh process shuffles now all the bytes coming from sshd from the green line to the red line, vice versa for the packets from the client. ## Example 2 ## In this example sshd is running on another server. No matter, if this is docker, kvm, virtualbox or another physical host, connected with an ethernet cable. Here we need no dummy interface, so we need another way, to configure our routing deflection. The principle is the same: We need to force packets coming back from sshd going to sslh and not directly back to the client. In this case its your decision, where those rules will be tied in, options are: * the startscript of sslh * the docker or kvm configuration * the configuration of the outgoing interface Its two lines you need: ``` ip rule add from SSHD_ADDRESS/32 table sslh ip route add local 0.0.0.0/0 dev lo table sslh ``` On the sshd host, we need no additional rules, as all traffic is coming back to our sslh host, because this is in this setting the default gateway. The only thing, we need to do: Assign a unique IP address only for sshd and all other services, you wish to hide behind sslh and host on this device. There are two ways, how you can add multiple ip addresses to one device. The new _**ip addr add**_ supports multiple add statements to one and the same interface name. So you can just duplicate the interface stancas in the _**/etc/network/interfaces**_ configuration. The problem with this method is, that some older managment tools, like ifconfig are unable to show the additional addresses. So when you are used to some older tools, you may configure sub-interfaces like eth0:1. However my recommendation is, migrate to new tools, get used to it, as old tools don't show you the whole configuration! ## Example 3 ## This is now the extended version of the previous example. The target host has another path back to the client, as there is a default route to another interface. Now we need **TWO** routing deflections, one on the sslh host, like in scenario 2, and one on the sshd target host. The routing setup on the target host looks like: * Add an routing table name for the deflection table in _**/etc/iproute2/rt_tables**_ * Find a location, where you will hook the two routing rules in ``` ip rule add from SSHD_ADDRESS/32 table sslh_routeback ip route add default via SERVER1_ETH1_IP dev eth0 table sslh_routeback ``` This is setting up a default route for all traffic, originating from the ip address sshd (or any other service) is using, back to the host, hosting sslh. On that host, those packets will be deflected again with the same rule from scenario 2. Be aware, that scenario 3 can look very different and the picture above shows only one of those setups. Each configuration, where packets from the target system can find their way back, without beeing forcibly routed through the sslh hosting system, belongs into this category. This are e.g. virtual machines or containers, having interfaces in the same network, like the sslh hosting system. Even, when they look in some drawings embedded in their host, as soon, as they have network interfaces, allowing a direct connection to the client, it is scenario 3! ## Modifications ## Now you can think about many modifications, but the tools will be the same, for all other thinkable scenarios. You must always make sure, that packets from foreign hosts, will find their way back to the sslh host. So if the chain consists of three or four servers, all need the deflection rules. ## Important Finding On Routing ## When I went ahead and wrote in my first drawings the warning, that the kernel in scenario 2 and 3 needs to have forwarding in place, I finally tested, that this is not true. **Both scenarios are working without kernel forwarding beeing activated!** The background: The deflecting routing table cames into the game, before the kernel has to made the decision, that packets with non local ip addresses in source and destination must be forwarded. After the routing rule deliveres the packet to sslh and sslh rewrites the source ip, the packet is treated as local, and can pass the system. sslh-2.3.1/doc/simple_transparent_proxy.md000066400000000000000000000247511515234404100207400ustar00rootroot00000000000000# Transparent Proxy Configuration Using IP Routing# This documentation is another explanation of the transparent proxy with the goal, beeing secure and minimalistic. Besides this documentation will explain, how and why this configuration works. The explanation will only describe the connection to sshd, so the target sshd can be replace with any other target service, sslh supports. ## Introduction in the data flow ## This chapter can be skipped, if you just like to configure things fast. This chapter is a little excurse to the dataflow. First point of all is something, which you will unfortunately not see in the nice routing diagrams for iptables or netfilter-tables (nft) like: [Iptables at wikipedia](https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Netfilter-packet-flow.svg/2560px-Netfilter-packet-flow.svg.png), [Netfilter Flow](https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks#Netfilter_hooks_into_Linux_networking_packet_flows). Packets from local application talking to other local applications are routed through the loopback-interface. They leave postrouting to lo and reentering from there prerouting, without passing ingress/egress. This has nothing to do with the "**route_localnet = 1**" trick, which only makes, that the the local ip range 10.0.0.0/8 gets routed! As you can read in many articles, this is nothing you should do, as you may bring your system at risk, because it allows to leak packets from outside to applications, which feel themselves secure, by using those unroutable addresses. #### A Simple Simulation #### You can prove this behaviour with a simple test: ``` # In one terminal start socat as a local echo server # this is simulating sshd socat TCP4-LISTEN:2000,bind=SERVER_IP,fork EXEC:cat # In the next terminal start another instance of socat, # simulating sslh socat TCP-LISTEN:3000,bind=SERVER_IP,fork TCP:SERVER_IP:2000 # In another terminal you can watch the traffic on lo tcpdump -i lo port 2000 # In the last terminal talk to the echo server telnet SERVER_IP 2000 ``` You will see your traffic on lo, but not on eth0, if you retry the tcpdump there. If you setup sslh as non transparent proxy, it will just work, as what we have seen. #### Going Transparent #### In case of transparent proxy however, sslh uses some tricks, to reuse the clients IP on its outgoing interface to sshd. It opens the interface in raw mode, so it either needs to be started as root and drop privileges after binding, or you will need to give some capabilities to the sslh binary (cap_net_bind_service,cap_net_raw+ep), if you will start it as restricted user. In this setup we continue, with dropping priviledges. Doing so, you can send packets to the sshd, listening on another interface, but, the answer packets from sshd will get routed back to the client. This however will not work, as the client would refuse those packets, because they don't belong to a tcp session, the client opened. In most cases those packets would even not reach the client, as source ip addresses from private address space, will be blocked by most internet routers and connection providers. So its mandatory, to use some tricks, to get those packets back to sslh. All configurations, I have seen so far, are using two components for that. They bind sshd to lo, and than they introduce some firewall rules, to mark packets, originating from the sshd port on lo, so that those packets can be routed in a next step -based on that marking- back to sslh. ##### Drawbacks From Using loopback ##### This idea has some serious drawbacks: First, you need to allow routing of the local address space, 127.0.0.0/8, with kernel configurations. Search for the string "net.ipv4.conf.default.route_localnet" and you will find lot of articles, why you should not do this. By allowing this, you need additional firewall rules, dropping martian packets, which otherwise would get routed to the internet from other applications, running on lo, not aware, that their traffic could be routed. You need further firewall rules, blocking incoming packets to loopback addresses, as otherwise some applications (especially udp) could be the goal of some bad traffic. ##### Using A Dedicated Interface ##### So this configuration makes use of a own interface, just for the services, where sslh should hide the traffic for. We use a interface of the dummy kernel module, which was designed just for this case. It is an interface, beeing there, having no cable connection or whatsever, but applications can bind to it. We assign to this interface just a /32 private address, as this interface is not part of any network. Doing so, we can avoid all the hassle with marking certain packets, coming from the single applications, sslh has to hide, as we now just route ALL traffic from this specific interface by its ip to sslh. We need one routing rule and one routing table, this covers as many targets sslh will serve on this interface, without adding additional rules for adding apache, openvpn and others. We need no firewall rules, preventing martians, as this single routing rule will deadroute all traffic from this interface, if sslh is not catching it up. We only need firewall protection for this specific ip address, when we have activated ip forwarding on that system. If the system is no router and needs no forwarding, there is no protection needed. ## Finally The Configuration ## As described, we need as a first step a dedicated interface, just for the services, sslh should hide. Its possible, to generate individual interfaces for different configurations, however, that makes things again more complex and has no advantages seen so far. ### Named Routing Table ### As we configure the needed routing rules in the interface configuration, we need to define a name for the sslh routing table first. Using named routing tables helps, understanding the routing configuration, as a name indicates, why this routing table is configured. To do so go to _**/etc/iproute2/rt_tables**_ and add a line ``` 111 sslh ``` With newer versions of iproute2 the /etc/iproute2 directory with the embedded templates got no longer installed. The cause maybe, that the example names, which were not used in any configuration, generated confusion. However, once you need those files, generate them and they will be honoured. You still can use just numbers for your routing table. But doing this, and having more than one routing table, you need a list, which numer belongs to which configuration. And seeing in the output from `ip route list table all ` the tables names instead just numbers is worth creating the file. ### Dummy Interface ### Now we configure our dedicated interface. In the file _**/etc/network/interfaces**_, we place this entry: ``` auto dummy0 iface dummy0 inet static address 192.168.255.254/32 pre-up modprobe dummy ## Attention! with kernels, not automatically creating a dummy0 ## interface after module loading the following line should be: ## pre-up modprobe dummy; if [ ! -e /sys/class/net/dummy0 ]; then ip link add dummy0 type dummy ; fi post-up ip rule add from 192.168.255.254 table sslh post-up ip route add local 0.0.0.0/0 dev dummy0 table sslh pre-down ip route del local 0.0.0.0/0 dev dummy0 table sslh pre-down ip rule del from 192.168.255.254 table sslh ``` As long, as your system has no other interfaces with private address-space, or is routing such addresses, you can continue with the given example. Otherwise you need to select a conflict free address. If you are updating a older current configuration, make sure, that you have no longer insecure localnet routing in place: ``` sysctl net.ipv4.conf.default.route_localnet sysctl net.ipv4.conf.all.route_localnet ``` should both report "0"! ### Explanation Of The Routing Rules ### The two routing rules in the dummy0 interface configuration are the key for this configuration. The first line is an routing rule entry, routing everything coming from the dummy0 ip source address to a special routing table _**sslh**_. The next line generates this table implicitly, by inserting a single rule, routing everything from that ip address to dummy0. Opposite to other firewall based configurations, we have those rules now tied to the dummy0 device, dedicated to the hidden services. When this interface comes up, the routing rules are making sure, that no martian packets can leave the system, by some processes using this IP address. When the interface goes down, we delete those rules. Also the startup script needs lo longer special treatment for the transparent mode. #### SSLH Default Configuration #### And finally you need to configute _**/etc/default/sslh**_ with the right settings for all the services, sslh should work for. ``` DAEMON_OPTS="--user sslh --listen SERVER_IP:443 --transparent \ --ssh 192.168.255.254:22 --tls 192.168.255.254:443 \ --pidfile /var/run/sslh/sslh.pid" ``` #### Systemd #### This setup is now startup agnostic. As we don't need special treatment in the startup script, the sysV based init scripts will just work, like the systemd scripts. Nothing needs to be modified, when going transparent. #### Remote Setups #### This concept can also be adapted for several setups, where the sshd (or any other target service) is running in a container, kvm-virtual machine, etc. Precondition is, that the target system is the next hop and uses the sslh-hosting system as default gateway. In addition you need to bind an additional ip-address, solely used for sshd on the corresponding interface. Than you can adapt the routing rule, routing traffic coming back from this ip to the sslh-routing-table. Its also possible, to forward to an next hop system, which has its own default gateway back, bypassing the sslh-host. In this case, you need to add a special route back to the sslh host, for all traffic with the sshd source ip address. This can be done similar to the two rules described above: ``` # first define a name for the table in /etc/iproute2/rt_tables e.g. sslh-routeback ip rule add from IPADRESS-OF-SERVIE table sslh-routeback ip route add default via IPADDRESS-OF_SSLH-HOST dev eth0 table sslh-routeback ``` The details are depending on your network settings. Als long, as the forward chain to the hidden service passes systems under your control, you can add backroutes on each system in that route. Precondition: The used ip address produces no conflict on those systems. [I added a second document](./scenarios-for-simple-transparent-proxy.md), describing three possible scenarios in detail. Those three scenarios should cover all setups related to transparent proxying. sslh-2.3.1/doc/sslh-examples-v3.png000066400000000000000000007223441515234404100170670ustar00rootroot00000000000000‰PNG  IHDRQ?µ) pHYsÊ&ó?tEXtSoftwarewww.inkscape.org›î< IDATxœìÝwxÍçÿÇñç9'{Ë"‘X-bÕÞ{…¢¨ÕAQªÕEÛouQôKµ¥õk�¶ª”¶jÖ,j«UDm5bE2NÎùý‘oO›&ˆHr‚×ãºr]ò9÷ç¾ß'$N^ç«ÕjEDDDDDDDDDä&Œö.@DDDDDDDDDî EDDDDDDDD$W&ŠˆˆˆˆˆˆˆˆH®(L‘\Q˜("""""""""¹¢0QDDDDDDDDDrEa¢ˆˆˆˆˆˆˆˆˆäŠÂDÉ…‰"""""""""’+ EDDDDDDDD$W&ŠˆˆˆˆˆˆˆˆH®(L‘\Q˜("""""""""¹¢0QDDDDDDDDDrEa¢ˆˆˆˆˆˆˆˆˆäŠÂDÉ…‰"""""""""’+ EDDDDDDDD$W&ŠˆˆˆˆˆˆˆˆH®(L‘\Q˜("""""""""¹¢0QDDDDDDDDDrEa¢ˆˆˆˆˆˆˆˆˆäŠÂDÉ…‰"""""""""’+ EDDDDDDDD$W&ŠˆˆˆˆˆˆˆˆH®(L‘\Q˜("""""""""¹¢0QDDDDDDDDDrEa¢ˆˆˆˆˆˆˆˆˆäŠÂDÉ…‰"""""""""’+ EDDDDDDDD$W&ŠˆˆˆˆˆˆˆˆH®(L‘\Q˜("""""""""¹¢0QDDDDDDDDDrEa¢ˆˆˆˆˆˆˆˆˆäŠÂDÉ…‰"""""""""’+ EDDDDDDDD$Wì]À?%%%‘––fï2òÄÛÛ£QÙ¬ˆˆˆˆˆˆˆˆÜ½ì&îÚµ‹IãÞçò…óx¹ºb°wAyt--�tàÁ=ôäPí]’ˆˆˆˆˆˆˆˆH¾2X­V«½ûÎ;Ú±•±�ö¡t€¿½ÊÈ7æŒ f¯ÝÀ¼­;ùrî\‚‚‚ì]’ˆˆˆˆˆˆˆˆH¾±[˜øÉäÉÄØËè~½ì1|�:|æ,ÏNŸÍ¢+qss³w9"""""""""ùÂ.›ü�;wŽ5‹â;=í1|�«\š§Û¶àÃ&Ø»‘|c—0ñËé_0<¢Ã�ºCâÍumX�õ«WcÇUä"""""""""ùÊ.aâö-[h^ÕCƒÁÀ}¥Krüøq{—"""""""""’/ì&ZÌfL&{ ]¨Jùãüùóö.CDDDDDDDD$_Ø%L¼W8˜Œ˜Íf{—!""""""""’/&ŠˆˆˆˆˆˆˆˆH®(L‘\Q˜("""""""""¹¢0QDDDDDDDDDrEab°¬ö.ADDDDDDDD$ß9Ø»€Ü˜8ÿGÌÛç/÷~£ÁpÝöI))Lœ¿�Žõà�J £Ä,2È`h‰Ï8× Žò¦…>¾ˆˆˆˆˆˆˆˆHA(3c®&ðÖWsh1b$�Ÿ{™ÿÌœMrjªíñøÄ$âØ{ü8#¿˜EFFÆ ûÛðû~Fù ãç}_Ð¥…¹¿lÈrÍÑêÀ.÷f]ýßéU¾½âz±&u V4cQDDDDDDDDî\v�E�£ÆàgY¾m'½š7aPÇv¬ÿ}?C&~bkóîÀG7xƒ:¶ËUŸmj×dþèQL|jPA•mùçi^ŸñU¶ëÁæú,iAº!�) hÛ†JÑ•x+á-Ngœ.ðºDDDDDDDDDò›Ý—9?>þCÊ•(ÎÚ‰cqtÈ,ç‘¶-¹š”œç>èÙ¬ñ ÛX­VÎF_ÆÇÃO7×ë¶K3›¹G�o1[}ÿ›�pÝ{ï;V†ž±=™ï;€£æ£¼�ø6ï%¾G ç qBW—®8â˜Ëg&""""""""b?v ÷�8Éæùõ£ Y‚:“ÑH1O�[êë»u¿ÒûÝñY®�ô£úöÊr-ÍlfìœïøpÁO¸»ºŸ˜ÈÃ-šòÙóÏàâäÀËÓf�a±P§rE†}üñ‰I8;:2ëÕèÕ¼ ï|=—É?üDjZ:É©©Zv²�1¸S{>qX柣U"ŠÍi›m�g�ÁšÔ5¬I]C�1ˆGÝe�ë Ê;”¿¥ç,""""""""R˜ì&nÿã0Ž4¸¿òm÷Õ­ICb}gû¼ù #sl÷Úô¯X¶m¿M›LÅÒ¥¸Oç×ÞæÝÙóóÄ£¶vsÖ¬çò•«ürÞîî ûxÏ|ô)Ý›4ÄÁdâå‡bX·ÎÌZ±š�\ÌžÏÿ^–íìô÷LC“ÕÄŸ9Ôº\‹XK,�Æ@ê9Õ#Ì–ùávÛÏ_DDDDDDDD¤ Ù5LŒOLÂßÛ “é¶ûrrpÀé³M¦ìÛAž�¾Ì‡ ²vâûT,] €@F?Ö—¡NÍ&†”ä«‘#0üïÔèaÝ:óŲD]Ž¡lñ@\��puvÂÍÅ£ÑpÙ”eMeùÚçk:ÇvÆŠ•Öέ™ã3ç¶Ÿ³ˆˆˆˆˆˆˆˆHa²k˜èíîNtüÒÍæ÷#ÌoNžÂbµ2â³/0þ/$HIKçlôe̶`ÓËÝÍ$¶°0!ùZžÆîä܉î#˜˜4‘ãæã·ñ,DDDDDDDDDìîabÝÊ1gd°ùÀ4¯Q­ÀÇsuÎÜqÜàÇñóòÊò˜Á`ÈÓ I£ÁˆÕš»¶ã¼Æ±-}‡Í‡³\?l>L²5™šŽ5oy|‘Â’}-p!ªQ>”z÷Uâõ_‘f6Û®gX,l>p0[{oww®åmv`�Ê)æéÁ�“§¨]±|–�Zò¶oa �7—ââIMO¿i[˜ë3+Vâ-ñ¶ë»Í»YžºœE)‹H³¦å©‘‚f×™‰³^y�#FÒðÙо ®ÎN|½ê.ÄÆñûô)8;þ}˜É}eƒ ôñaø”ÿ£OËf>ÅS]:ÚNa¾7gg¦š�&súR4íêÔ"-ÝÌš]{)["�—zu¿åú[Ô ÇÅɉ'>øˆ¾­š‘nÎ )%…¾­šçØ>ØÌW>_q2ã$5�™3{¹ôâ—´_ø=ýwšÒ'r÷|DDDDDDDDD “ÝÃÄûÊóûô©Lþþ'¾[÷+ƒ�fÕ«ñb¯nY‚Dw–¾?š÷çÌgÌ7ßqH®&'ç&voÒ�šå³Ï6ìÓ²J•dÆòUŒûv&£‘VµjðD‡¶¶6õî«D©¿lc‰h�¯—g–ëÞîîl˜<žqsðÞìyø{{Ó®N­>çNÎ�Hµ¦Ú>7a¢�S86ÀÃpýƒ\DDDDDDDDDìÉ`µævÇ¿üÓ¹u+–¼þba[è&þ¸˜ZݦE‹ö.EDDDDDDDDä¶ÙuÏDÉ� 2ì]‚ˆˆˆˆˆˆˆˆˆÂÄ¢.ÎÇÔ¤©4g?�FDDDDDDDD¤0)L,â,V Îg¦,d]ê:{—#""""""""÷0»À"7ægôc Û@~Nù™ S�½Ë)1IYxV }KW‘rqp#"ü{—!÷¸�'}ÏÕ„d{—!"w©  _žaï2D¤S˜xpÄ‘..]ì]†H¡INM$:ñ•ƒêØ»‘,vž\­0QìnßïÇiÔ¸®înö.EDî2±1ñDøÓÞeˆH§0QDŠ$w½ÊØ» ‘Ðli):BÂñ)æiï2Dä.uö"ÇŽž²w"RÄiÏÄ;\œ%Ž«–«ö.CDDDDDDDDîš™x‡[˜²�+Ö+<èü ¡¡ö.GDDDDDDDDîbwT˜¸~ï~æþ²žó1q„•,Áó=ºR¶xà-õñþ·ó¹’””ízËšÕiû@-¶ÿq˜…›¶Ø ôñ¡FùPZÔÇ`0ÜÞ“Ègí�ÛócÊ�ÌK™Ç“nOâgô³wI""""""""r—ºc–9?÷É4:Œ|ƒÁ@óÕ¸ÏC‡s5!Oýýqê ç/Ìñ±=ÇŽóé¢e¶Ï#ÿI—Fõ1±Óœo¤¢CEúºöå§”Ÿ8œqXa¢ˆÈ 1!‘è‹Ñ˜ÍfŠùÃ?ÐßÞ%‰ˆˆˆˆˆØù0ÑÍÙ™JÁ¥Øvð�´iYhãúyy1ô¨B¯ „˜Bä:7£›½K‘ë0§›™?{>?|û#GÁb±Ø ,H‡®üÜ Šù³c•""""""wÀž‰;´eæÏ«9~î|–ëGÎF‘ñ�_¸$gFŒwÆ_µˆÈ='ör,};õeÌkc9tà&“‰%KP<(£ÑÈ¥ —øjÚWtiú ‡²w¹"""""r�+ò3†?ô K·î éðWÙ·÷• fç‘£¼7{?¼ý:íêÔÊu_sÖ¬#)%•ß!Ãbáó¥+¨Y!”:•*æ_Ñii¬Öüë¯X°(dÉsº™Ä«‰¤¦¦Ù»”;‚“³žî8:9Ú»”;«ώ$rßA¼}¼yiôKtìÚWÒÒÒX±h%ãßOìåXž0œÅ¿.²=."""""RØîˆ0ÑÉÁ�•Þåã3{Õ/Ä\½J…Ò%ùþ­×n)HXºm—¯\ Yõª,ذÑ6Æ_abiW»ÿöŠ6™h¿êüöýV+´,¼%Ú¹µ,uiÖ4"\"pÆÙÞåˆ)V‹•ƒ{ÿà�=pþÌù,ËNåæ %J• R�JT­]“Édï’Š¤Ã‘‡Ù²~ ïM~—–í³þ_áääD—ž�)Z†þ�!êLËú™î}ºÙ£\‘;#Lpqrâ•Þ=x¥w�ÿãÔ’SSs|ÌÇÃ�°’AÌ}ãÕ›ŽÑ . êæ½X“‰- êðøìyd´j…!4ë¯bèÛ<&ž¥s—q%ö uëÖ%¢}~~~x�ïÝ;Abb"qqqDFF²eÕ~ßö;îˆq?{—Väø=“ÉH³ÖͮۮzíêÔmT—m·±mã¶›†‰‰ ‰xxæíßkjj*ÎÎùóSF†…´ÔT\Ý\oý^s&Ñ"""""EÉ&ÞÌ+ŸÏäàŸ§s|¬uíü߈a…\\ñòâÈ+¯Pi¬'N`}òIxþy † ÁЪØéthÚ8·!ØÌ>ó>Ü îv©C¤¨‰�Žåû?Pªd)†== ooo{—tÇquu% €Š+Ò¦MæÎ�Ëü/æóЀî/UÜÞå)æt3‹•«W¯Þð€•G‡³¿˜ÍÉc'ùrá—Ôið@®¾–"""""R8îš0qɘÑö.!GÛµã>gg,3yáÚ5¬ `]°Ê”ÁЧÆ¡C!$Ä.õUv¨Le‡Êv[¤¨IOKgÉœ¥”-S–Aƒiin>ððð`РA|õÕW,�»Œ~ÏôÕ~ÿp_µÌŸ¿V«•ׇ¿ÁûŸŒÅÛ'ç»Y›f4k“óìÅÏ&~Æ”¦àåíEPé .ž¿È¶�ÛØ¾i;Ï¿6œAÃÙÚÇÇŹï eC˲öçµ¼8ä%ÒÓÓptt$¨TË~\Æ�ß.¼n˜8ÿë;|Œ~ƒúÙ®]K¾Æsžcˆ­ ÄÙÅ…³§Î²hþ"Öþ¼–)_OÉž=E侃ÄÅÆñþïóÍô9¹ýò‰ˆˆˆˆˆèô�B`=CûöÙ8}ëøñd”/�¥C¬ëÖ~q"b³gë^Ìif}ôQ‰ùÈ`0зo_LìܸÓÞå)áµÂiÑ®�9[°ÍmyqÈ‹,š¿˜³§Îæª�¥?,eÊSqswãí‰o³éà&–m^ʦƒ›2|0F£�Éc?²|ÿÏ[/½…›»C†fÚ·ŸÑûñÞtíõ [7nåJü•l÷�·lØÊ7ÓçP¾RyF¾;’Y?Ìäþj÷åêk """""…Gaba01Ξ ÁY—¦ªWÇ8kÆmÛ0Λ‡¡E ;˜³³¹ûEVän`µZÙ¿c?-Z´ÀÕõÖ÷w“srr¢Më6ìÿíö.§H™øùðô㸹»‘”˜ÄŠÅ+yí¹×hW¯=M«5ã•§_eñ‚%$%&e»7--�IïMà�÷ß G¿‡0™2ÿkwqqfø¨á<>ôq¬V+ŸŒÿ$Ûý[6lÅÅÕ•…ë~dø¨á4iÙ„âAũפ>Ń1§›Y³|m¶ûV.Y@뎭q÷ÈÜ&#rßA–|¿W7W>ŸûÔ¨SÃÖ¾xPq¦|õ UªW!ör,sf|›­Ïå —ÓªC+~Xó=� îOÝFum}‹ˆˆˆˆHÑ¡0±°øûcüþ{prÊü¼re¬¿ÿŽeÂpq�"¶/[¤9’¯®}ÅÊÔ•d _üåîwùÂe ·w)w­ððpÒÓÒ9ú¼½K)Rœ��yéÍ—X»{ oŽ“6ml{'ÆDǰìÇeŒ6Š–5[1ëÓ/±Z­¶{·oÚÎÅó—,ȃ½ºäØÿàçc2Ù·{Qg¢²=þò[/Q<(ë^–&“‘ˆ‡:°rÉÊl÷¬^¶€.=:Û®-Y°€ö]ÚSºlél÷˜L ö?ÿôsŽ_‡·'¾…ƒã]³‹ˆˆˆˆÈ]I¯Ø ‘¡n]ŒãÇcyá >>~øËO`©[ãÇc4èæ�’ЦЄ;†³3=sIb;çvv®H¤`]‰»‚££#þþþö.å®åáá�§—'ñ±W(].{Øt¯óòöâáÇzñðc½øóøŸìÞ±‡5Ë×°uÃVùï;ÿå¹óŒzo¿ïÚ€«›+3¦Ì¸nßžž\‰¿Âþ=û)\ÊvÝd2Ò¼móïy°WfL™Á¶�Ûˆ‹�³œ§OžæÐ�C ~Ó¶öÕ{9溵ÄÅÆ™Ë¤®&âéõ÷‰ÓµêÕºá4"""""R4(L,d†çŸÇ°y3Öµk1vZ5,½za<ï¿büì3p·ÿ².Gƒ#��;SÖX–r¦rö.G¤À¥$§àê¦åÍÍÍÍ�Ôk)ö.ãŽBHXÝûtãâù‹¼4ôevoßÍœßÒó‘ž”¯Tž¸˜XN�8Ť÷>¼iŸÏ]Ìò¹_€?N͘ÿ—°ŠaT­Q•{°vùZzôïü=+1â¡N¶%Õ±ÿ«eÚ_Ù°æ×›×rþž^åmŸ•*qÓ{DDäî´lù�¬_¿Šÿ¼1/¯¢µbKDD²S˜XÀ C¶kÆ™3ɨ[bc¡BŒÛ¶ayå¬LÆo¿aœ?Cµjv¨6»pG-ù”{‡�ì߯’¿ C–eº÷ºwG¾KF†…¾úPñþŠ×mW<¨8“>ŸH«Z­ÈȰ°eÃVÊW*o À+Þ_‘¾úÜt¼j5³þßx㙸]~�{°bñJ[˜ø×~‰]zd]Víö¿Z:ví@ÝFuoZ‹ÿ¿Æ(pÓ{DDòbÑâùÌ™3ƒ?O§X1?Z·êÀàÁÃññ.Æå˜hžá F¾òU«ÖÈr߇�ÅÑÁ�gŸy…ÈÈß3ö5zŽ-þ^±ó߉ïP¢DIú÷+:+ŒŠŠ¸¸¾˜þ1¯¼üöMÛ®Yû3ëÖ­dÀ€g¸ß«hü$""×gŸ01‡€ín›˜Œ¯¯oö<=1Ο�õìY ¾¾àìŒñ£�°6ož¹ì¹^=Œï¿�aøðÂ/ZŠ”ÄÄDÛGRR‰‰‰X,’““�̃-2¿•]\\ððð°}xzzÚ‘¢ç—ë¸tá*—¿a˜™a[1?_._ºLÂÕÊ„”ÀÑÑ‘ž�ô¼åñM7ùùСk&Œþ€[vǵädî;H¥*•²Õ[¦\Žüq”à�à©EDî-‹…Y_~FZZ*=êG@@ñ›ß”ƒåË2nü›¼6ò=ªT©ÎÅ‹ç™õå§Ì›÷%CŸ|¿BʆòégùtêlÛ}gΞâÛogðÍ×™ûÁ&%'qèp$OO³f­1Mœ={*ÇÉ/^`Ñ¢¹ ǽ?…K—.\ºl!T&""·Ë.¯ÜCBÃ8|æ,•‚ïî=³œ>Ã*äø˜¡Z5ø×ìC·n˜jÕÂÒ»7–çŸÇ°kÆO?�û°§}éûð0zj µw)w<³ÙÌùóç9sæ QQQ\ºt‰Ë—/Cjjª­�ÑhÄÅÅgggŒÆÌ¥…ŽŽŽ¤§§�’’‚ÙlÎr�Á`ÀÇÇ "88˜Ò¥KãééY¸OTD²©]¯?/ZÁßþHïÇzcr0]·mìåXÛ²æRÁ%¨×¸Ç#6&_¿ì{^K¾Æ ^ƒHOKgòÌÉ”,]2×õùó¡YÛf¬^ºšÕKW“ríV«5ËÁ+©×¸k–¯eûæ×íoç¶�Lxs%™úõ”\×!"÷ž;6óÉ”ñ|ùågtëÖ‡ÇJ‰â¹ÿ°zírZ·ê@çΙ³«CC+P¿~¬V‹­ÍС#èÚ­9{÷î¤F�˜5ëSZ4oG¥JUlíJ• Æb±°bÅb:vìv»O«ÕÊéÓ'9ùçq<=½¨^;Û›Àf³™#Gÿ 6&šŠï'00ë–ññ±˜LxzzqòÏãœ:u‚²eC)fk“––FlÜeJ/Ibb»÷ìÀÝ݃ðjµpttÌV×… Q>ò^^ÞT¯e NÿÉbÉàĉcœ9ó'ŹÿþpÛëÓÔ´Tb.GsâÄ,V g£NÛîsuqÃÏ/sfztôERÓ²¾nµZ­9†³ññ±:‰««•*Ý�‹KÖ­i¢¢ÎT«ÕÊ®Ý;0›Ó©Z¥†–L‹ˆ»„‰}}”Ï?ý„‰ƒµÇð…âð™³øÇÕõ{°åô.fÙ²ׯÏ\öüÉ'dìØ‘¹ì¹�0kÁ–ô-ÄZbiäÔˆ¦NMµ<ô$''sìØ1Ž=ÊÑ£G9}ú4¸¹¹D`` ÁÁÁøúúR¬X1Û C—\õŸžžNrr2IIIÄÇÇCll,±±±lذ�˜˜¬V+ÅŠ£B… ¶�   ~æ"òo}öeÅ╎<ÌÈa£xû¿oáæî–­]ZZï�CF†W7WZ¶o @Ùв4hÚ€­¿neô‹£ùð‹IÙNCž1u&{wþNXÅ0‚JÝú÷ùƒ=»°zéjV.YIjJ &“‘NÝ;ekñP½ÿ1{ÛË7ÓçÐP¿lÏáã÷?!rßAmðÀ-×!"÷–„„«¶?§¦¥2ï»/ùþ‡ohß® C§L™Üíé]<0ˆ_7®áÂ…(J”È<€Ê`0`0ü�•.U†n]{3íó™öéΟ�bÙò…|77ëÉóIɉ<ûôËLû|2íÚuÆdÊû¯R'OcäkÃ8{æaå+qéây\\]ùpÒt[xèP$/¼8ˆŒŒ ŠqäÈA""âõׯؾ©ŸþwwOÒÒRX·~..®üùçq^zq4ýúÌìçð^|éIÞyk"o¿ó >ÅŠqêÔIÂÂ*òåÌmfrrcƾΦÍë¨Z¥:çÎ�àÓ©ßô÷á]{öþÆÿyžÄÄÊ•+ÏéÓ')]ª,NšŽŸŸ?‹/૯¦q-%™ÔÔ†ík»·Aƒ¦¼þÚX&|0š?þ8dþGG_dÛ–ÃÙ‚Âé3¦ðÅZ�ĤD®^½Â˜w?¤qã–¶6]»7ç£É3™íÛu!ä³û’’’ˆˆèÁçÓ?aÙ²…té’}K‡ãÇ�d™m÷GGG*”Ïü½'99‰§žîOåûª2ã‹ùxxxbµZùùçŸ(þ¿™‡))×þÂ@ÔoÊ›ÿ‡ÑhâØ±Ã Ôƒ2eÊñØ£OÚúž;o/¾ðË—nÁ`0ðÙ´I|6m"}û °ýÜ�‰‰fî¼Y|7oÞÞ>üùçqzôjÆ_WÓªe&Nz—?OgÉ¢_ñòòÆb±ðî{#7þ?|4y&�9kñÙg£S§n¼ôâhœœœÈÈ0³lÙBŠËœß³GzöèÏêÕËxëí—YºdSŽ7L˜fûó®ÝÛybPö¯çºu+ùlÚ$¦}ú uê4àó/>âåWŸæ§×Q¼øßo’}ðß·™øÁÿZ�ää$úö�`Þ¼Y¼üÒ[9Ž/""yg· Š>›1ƒ^]äÉø+tmXÏ^eä»ó1±<9åsž~éÂÂÂn~à |ÓÞ½/{Þ¸ãŒàmÿéú.zºôäŠåŠ‚ÄëHIIa÷îÝlÙ²…cÇŽáááA•*U0`*TÀÙÙÙ.u9;;S®\9Ê•+G³fͰZ­œ?žƒràÀÖ­[‡——õêÕ£Aƒ9’"’†½ò,¥Ë”bÒ»“ˆ‰Žá›ésrlÌëc_£IË&Y®— aÆ÷3yõéW9vøãߟåqOoOÞÿ&�Z4ÊS}ŽDtïÄןgî%–Óç¿<ØëA, ãGOÈñTçÐ ¡|8}¾þ9ì',"…â×�k9~üH¶ë))×HË!û§„„«7`ÍšåÄÄFóöèÿâᑹíŒÁ`Ȳtzã¦uDG_bÄ oØf!–/_‰^=åûæd ë×kL¯^¯øjÖ¬ ÿ÷ùdbb/ãï—ùæ�Åbá�w&áíí@HH!!aœ>ý'±±—YøÓ<¦}ö­mi°Ñh¤_ß'èÛ¿fL&þôî¼üÒ[¶%Ò&“CŽÁj~øþ‡9´lÑÖ$ zâY¾ÿaË–/dà€§mן{öUBC3·˜rss§nÝFœ>óg�Ô%"r¯³[˜èééÉÂeËyï­Ñ|öŸ1´ ¯BYß;v6Tµ6:Êå”TÞûx áùµ,¹LŒ¿þŠå½÷°¾û.û÷cüî; 5jÜüÞBàm´°YÔÄÇdzvíZ~ýõW¬V+ááá<óÌ3„††É º %K–¤dÉ’´nÝš+W®°k×.~ûí7V­ZE¥J•hÛ¶-UªT)’õ‹Ü ºõîF§î�X¿j=»·ïæÌ©³¤¦¤ââêBhùrÔoRŸz�ë]wOÅ*á÷óÓº…lÛ¸�]Ûw�³³•«V¦uÇ6xzeÝ{÷�0鋉xûäîgøãO  F�Ìÿwšµi~ÓçÒªC+Ö¯ÚÀ¡ÈC$'%ãåíEízµhÜ¢q¶çÐP?ZuhIXÅÛ{NDrgõše,Yòým÷c4mAØõ8;»àìtã7O=<=1òöúßÝÝW—l)ô?tŽxˆÎ±mÛFÞ3Š—^ÊÌY¿Šù fÓ¥s�,ËzÿíÁ.½˜9k*‹ÏÏöüF¿9á¦õœ>ó'ÁÁ!¶`/'ç¢NP<Ûžaa‰Š:�eoA£)ëÏUW×Ìí2ÒR³†Ã¦í}èæêNjjJæxçÎb±Xòdïë¹zõ ÅŠùqúôI*Wª’ã^‹!êÜÚ·ë’åšÑh¢\HgÏžÊrÝð¯ß#]]ݲ} DD$ØõèDÞ7žk×®±eËNŸ:EúMÞ-š ø2úéá”-[{r88`|ë-¬µkcyüq, ©eÏ9±`ÁÈ� çÕ•+WX²d [·nÅÛÛ›N�:Q§N»Í@Ì+oooZ¶lIË–-9yò$ëׯgÊ”)”*UŠnݺQµjU{—(rWrrr¢mD[ÚF´ÍÓýŽ4nÙ˜Æ-ß´m©àR” ¾þ/ÊÿV<(�v�Û庽—·]zv¦KÏëÏbüKx­pÂk�}�Eîv#ž�aϼ’m_ºsww¿­=oׯ×òÜð9>æææÎýeÀãOßòõë7á¥ßä…“””ˆ»ûßo¶+æ‡��/!!åo؇ƒƒCgÆÌ©Ô¬Qç–Æðòò&&&‹År݉ž^ÞÄÅÇb±dd9%66//Ÿ|ƒ×Û's‰ò¼o¦rå*×mçéåÍŸÏUŸ&–ŒÛªËËÓ›ØØËÙ®ÇÆÆpÿýú¿CDÄ^ì&þÅÕÕ•V­ZÙ»Œ"Ïйsæ²ç>}2—=ÿúkæ²gŸë¿«iç-çY˜²�..](m¼»Oì†Ì¥6+V¬`ÕªUxyyѧOjÔ¨qÇβý§¿–CGGG³jÕ*¦L™B¥J•xøá‡µüYDDäT¬XþìÑ\ÐŒ9„e®®ntëú0O f;øF,– &}8†îÝúØ–¿œ9{ _ÜÜò¾UOD§î̘9•]»¶Ñ¢EîßlhÞ¬ }<޹ófѯï¶ëÑÑqtrÂÇ»�µà¿¦wX´xݺfÎLMKeáOsiÑÉæ-˜¬"^ÔªU�R¥‚o©¶*÷‡Ó¾]g222¸pá<~~þ¼4âMj×ú{‚@ÅŠ÷Ѫebb/sõj­Zudä«ïdYšíàà@h¹ò„–û{æ¥Á`ÀÛ»µjÖÅÉɣш¯¯?5kÖÍò¦·£“÷ÝW� ™³}}ýéÞ­ÎÎ.œ?Err­[u¤_ß'0üc_ËzuÓ¤I+RSS¸páeÊ”ãõQc «˜å9 :vè 8wþ ÔªU�²eC³}=ŒF#~~Ô¬Q'ËëiƒÁH‡] *ÅùóQ¸»{ðÌÓ/Ñ9¢G–û��]¨]«n–}(L&ʆ„Q¾|¥Üþµ�p5‰'ÎÒ®C]{—""E˜Áz£#Ù¤è;{KŸ>X7mÂе+Æ™3¡X±|ÆjµrîÜ9N�:eûˆŽŽ&11ÑÖÆh4ââ₃ƒ&“‰ÔÔTÒÓÓIOO·µqrrÂßߟҥKS¶lYBBB(S¦L–%E]FFsæÌaÛ¶mtëÖ�F�òvBê�îòåË̘1ƒ´´4žyæJ—ο%ígb�³öÐOÔ kŸo}ÞÌ��عaz¥`Mø`¡UÊñ@“ì]ŠHXYþûL^j;ÉÞ…È=nÐcãyä±Îø»ñ(""·*êìEÖ¬ÞÆ¤�Ÿµw)"R„i™ó�®tiŒëÖý½ì¹fÍÌeÏù0KñÚµkDFF²ÿ~"##IHHÀÍÍ�àà`BCC©_¿>¾¾¾øøøàãッCÎÿœ¬V+W¯^%..ޏ¸8bcc9sæ k×®%66GGG*V¬HµjÕ¨V­þþ¹_¾RØ, ³fÍ"22’¡C‡R¾|áÍœ+jüýýyþùçùú믙4i/¾ø"¥Jåm?¹3(L¼üuÚs“&Xú÷ÇÒ¤ Æ÷ÞÃðÊ+p‹{ÁX­V:ÄæÍ›Ù»w/aaa´iÓ†J•*pËûËd.µðÆÛÛ›��b­±4¡ N'9zô(déҥ̛7�òåËÓ¨Q#j×®]ä–Eûí·ìß¿Ÿ¡C‡ÌÉÝwggg À¬Y³˜º:vÅßßš5kR³fM¬V+'Nœ`ÇŽÌ›7�yóæÑ¸qcÚ¶m‹O8±zÛ¶mlÞ¼YAâ¿888ðøã�óé§Ÿ2}út^z饻òQ˜x÷)^ãŠXÞ}÷ïeÏsçbhØ0Çæf³™õë׳jÕ*RSSiذ!�5Â7d^8håØŠŸÍ?3'}C‡àjp2g0†……F÷îÝÙ½{7¿üò 6l qãÆtèÐÁn¡b||<ß~û-mÚ´¡B… 7¿áãèèHÿþý™8q"+W®¤cÇŽö.éž2}útN�:eû|È�!gÝ>11‘ñãÇóôÓOTØ%ŠˆˆˆˆˆÈ]BaâÝÈdÊ\öܬ–~ý°4k†áõ×1¾ù&üãt´ÈÈH¾ûî;hÒ¤ M›6ÅÍíÖNÉË‹ Æ 8e‰²‰ÿæììLƒ ¨W¯{öìaõêÕlÛ¶�N�:ѪU«BŸùöóÏ?ãííMÛ¶m uÜ;‰ŸŸíÚµcÅŠ4kÖ www{—tÏðôô¤X±b¤¤¤0fÌ"""²…‰IIILš4‰ž={*L‘¦›Ï24�Ô®]›5j°qãF–-[Æ–-[xüñÇ )øBÉ a6mÚDïÞ½1þ#Œ•ì6lȺuëØ°aƒf'¢‡~€«W¯2fÌ;W#""""""w3%#w»À@Œ+V`7ëòå¤T­Êì§žâܹs 6Œ>}úz�˜&“‰æÍ›3räH˜0a+W®ÄjµøØÀd2^àcÝé©U«–íð¹¹´´4Ž=Ê�HII¹n»óçϳgÏ¢££ok<£ÑˆÕjåÈ‘#?~œŒŒŒÛêODDDDDDî- ï¼ò ;Þ{�¤«W>¾ÀjŠ��Åßß¿Àú¿Û`µZ‰‹‹³w)EZZZÏ<ó cÇŽå·ß~cÿþýìÞ½›Zµjáàð÷cÇŽÅÓÓ“#Gް}ûv¢¢¢èׯ%J”ÈÓ¸#GŽdòäÉœ9s†={öÉ·ß~›_OKDDDDDDîr ïréééL�:•½{÷òä“OR½ukÒ.Ä”-[–G}”üK¿_ÿ {ÿâíí­ß""""""’k ïRV«•/¿ü’£G�2tèPŠ/ž½MãÆ¤oÛ†¥U+ÆŽÅ1"CÍî»UÞx纭³³3ÄÓÓ“É“'“���¯µøúúr©ˆ-/Ê¢££1 +VÌÞ¥yÕ«WgÉ’%œ>}šwÞy‡‹/R·n]6ÿc¶°››&LàÔ©SüôÓOÜwß}<÷Üs >ÜŽ•‹ˆˆˆˆˆÈ½Jaâ]jÕªUìÞ½›AƒQ²dÉë¶³úù‘þã�™Ëž·lÁ±^=Œ¿üRˆ•Þ+9ŸÞìììÌ�!C0 LŸ>=ϳ¶rrß}÷qìØ1RSSó­Ï»Ydd$¡¡¡¸¸¸Ø»”"-==Ýv2³··7Ìš5‹û￟ 6ØÚ�;wÈœÉX§NF�ŨQ£ø%‡ïS777¹zõjá< ¹ç8ܼ‰„ØØXŽ9BTT‰‰‰ ¼¼¼(S¦ +VÄÃÃ#Ï}Ÿ8q‚E‹ñÐCQ®\¹›ßð¿eÏ–zõp|ôQ»vÅüê«dŒ &SžëÈoV¬|Ÿö=¾F_Z8´Àø¯,ÜÍÍ��2iÒ$–.]J—.]²ý‡7ÞÀ±~}ÌÓ§ciÝ:Oýå'Gƒ#Ý»±Ó¼“³Ö³Ù‚Ä .°ÿ~:„Á``Á‚”(Q‚’%KR»vmJ”(A`` >>>·<³/..Ž>ø€¥K—Òµk×<ÕòäI¶mÛÆï¿ÿŽÅb!$$„:uêJ‰%nzb´Õj%..ŽsçÎqìØ1öïßϪU«ð÷÷§víÚÔ¯_?Ï'ü懋/²zõjºvíª%ιT¦L^ýõ¶qrrâ‘Gá‘GÉUŸþþþŒ?>ÛuÞ}÷Ýl×ÿ}z´ˆˆˆˆˆˆÈ�(L,'NœàÓO?ÅÝÝ�^xᆳ '<<œÈÈHæÏŸÏÑ£G6l~~~7çܹs¬[·Ž¾}ûæ:|ÌÑ_Ëžë×ÿ{Ùó /�ñÖ[EbÙóðÃöíÛÙ»w/ÑÑÑøùùQ¥Jš5kFXX˜m‰òí*V¬}ûöeæÌ™„……Q­Zµ\ß{èÐ!Ö¬YÉ' ¥[·nÔ¨Qã–ÿŽ ¾¾¾øúúRµjU ó°“�;wòÛo¿±víZêÔ©CË–-ñ÷÷¿¥¾oWjj*_ý5aaa´lÙ²PÇ‘£0±€:tˆ©S§RµjUz÷î}K3âªT©ÂË/¿ÌÌ™3?~�7¦cÇŽ·*çRjj*_|ñ©©© 0 È,¹ùKBÂUÎ�;ƒ··%JüýzÑl6“œœ„§§W¶×0©i©¤§¥áááIF†™¤¤$<<<0ÿ~s=99 “É„³sÞVe$%%b4qu½þ «ÕÊ©S'HKK¥lHÎN¿¾KMMÁl6ãîžu¿õÜô+7vþ|� èF‡öòÂó7^I""r¯ÑiÎèÌ™3|öÙgÔ®]›þýûçéÐ žzê)Š/ÎG}Ä•+WrlwùòeöîÝKëÖ­ó5̱zy‘>{6æ 0lߎcýúW¯Î·þo©«•ÈÈH&MšÄŒ3ÈÈÈàÑGeäÈ‘tèÐ�’¥Jm�.Ð"""¨S§3fÌ`ß¾}9¶±X,,_¾œ &`6›yùå—4hP¾‰ÿd0¨R¥ /¼ð}ûöeÏž=Œ7Ž?þø£ÀÆHLLäóÏ?'&&†#Fàíí] ã‰ˆˆˆÜ ³ÙÌ;ï�¤Y‹ê x¢í;6 ß#�9x0óuÜÕ«ñ´ïXŸ5kÎvï°a�ññ”Ì­CvíÞAÓæÕ˜ýÍô,m^{ý9¦Lý Oµ%%%Ò²UMøÐuÛ¬^³œ�Òóá¶ô´ mÛÕaåª%¶Ç§Ï˜Âà'{g¹gý†Õ´jS›£Çå©®»Ý”©øùçŸnÚΜa&#ÃŒÙl.„ªDDî,  ȵkט6måË—§G�·ð9::2pà@œœœ˜>}ºí‘ZµjÅ‹§Òÿ³wŸQQ]_ÆŸit‘¢(ˆ €X(jì]±b‹½cî1Qó�š�i5ÖØ{�%ÆX‚¢Ø»‰Fì R¤ Ly?ð:fu4ç·–kÅ{Ï=wÏð眽ÝÜÞ&ìÜýÿ¶çÌ  07Gѹ3ò‰!+Kÿ÷Êý{÷˜3gkÖ¬¡lÙ²L™2…#Fàå奭;yAu�u™ë¸ ºPhqH$ºvíJƒ X»v-���h4íùÄÄD-Zĉ'èÖ­£F�¢Ì;\É)‘H¨Q£_|ñ¬X±‚½{÷æú=ó¶¢¢¢˜7oééé|öÙgï|kµ ‚ ﯌Œg:ï¡ ËºõË8}ú»væôɺLÝ:�´‰6++kz÷IJåótÞ/ýý÷E®\½ÌÐÁc´Ç �X»îÒÒRõÛ±c‡ðöùˆ¨¨p<¸Ÿã|БLþ|}zâäñNŸ¼É´©ßs÷î­<ç¼}û:S¦ŒãË©ßS½š�^âüÐܼÂã'ñùŽE)ª^ IDATs(Wž C—™øÙWï *A„÷‹Øæ\H¶nÝŠZ­¦wïÞ9𬼠CCCüýýùé§Ÿ ¤uëÖÚsjµš‹/Ò¦M›BÝbªññÉÞö\¹r‘š5jãää@©RÖŒ5QgÌ€þlÿu=�‡þ u«,_ñ3={ ÀÆæE‰!kkJ—.Ë–­kC£Ñ0{öl/^LåÊ•;vl±Y¥çééÉ„ HJJbáÂ…yn“/¨;wî0wî\Ž9BÏž=9r¤H$ ùR¢ä´òtQ‡!‚ #††F|=}1±ÑLœ<‚f-|Ñ›M›W­·ûT«æÍÑà@‚ƒó\ in^‚ý‡³|ÅϨÕjþ¹öW®^Âà�q)))øÎú ËHMMy«¸RR’9}æ 4§Q£æþ¡sþú�ˆŽŽ¢WOÿÍ—‘™Á„ Cqwó`äˆÏÞ(¦gÏÒ9ºŸ|:”{¡wÈÌÌ`É’ÙL™:Nç>þƒ>æ§¹3IMMæòåstíÞ’½{wè¼¶3'³eë¦LObbÇ�Ñ«O;""´ã6mYͶíëГë×ÿáat“?ÍÊU‹tâZ¹j!þƒ?&:: µZÍÜy3ùlâp�1�ÇÓ§Ÿ3fN&::’””¾ž1Ig úáÃû9rô OóàA(gÏ�ÐþIOÏ^mš”” s|ñ’Ù9r0dzºü×yºtmΑ£ÉÌÌ`åêEtëî«ó½{âdk×.eÂgÃØà7RSSX¼d& Í1Ÿ ÂûF¬LÔ3�FÃÎ�;ñöö¦R¥Jù_ðšêׯϹsçØ»w/þþÙo.®\¹‚““%J”Ðûýò¢4µ�Ov·ç�?F5bÊo¿…7¨ ù2¥RÉüÁñãÇiР~~~®7)AÂG²�Þ:†‚²±±¡Y³f¬Y³† ЩS§b×€ÄÆÆ†1cư|ùr-ZĘ1c^û{%<<œ?ÿü“7nP£F F��••U!E,|häÈ9 <À·ßâfå†3Š:$A„ÿ¬£Gÿ$ì¥-µR©33s�cÀÜÇýÚÇÓäœÞš›Ð¦M'íß�RÞÑ™²e055åë“ »G…ÿ_áŠT*Åѱ?35¦=‘ë7®âY½FޝODäΟ?•ë¥5kÔ¡|yg,üž;·o°ó×ÃØÙe—éQ*•ÄÄ>ÔŽ_±âg?‰cûÖ?µß3Û¶¯ã›Yÿ£nÝFX[ÛjÇÞ¼¦ {‘Ëå¨Õ*ü:6bÿ�ßtž[pp K—lÄÁÁ €reùí·­ <€ N³rÕ"Ö¯û ×J•è×w(�º4åĉ#4lØ €¯gLD­R³{çÌͳßçŽû9))ÉÚ{}ÿ]v’²óÇÍèàו¾}†äx®®Ìþa©öï/×£„ì-úS§�§SÇîÚÆ,£GMbȰü8{:?ÍY¦{îü)~š³Œõ›Ьik†�ìãG1ØÚ–Îõk"‚ð>ÉD=»zõ*‘‘‘ôíÛ·Pæ—J¥´iÓ†Õ«WÓ¶m[ììì¸ÿ~¾�… ƒÆË‹¬S§��“½íùüy²Ö­CãäôÆsfdd°zõj"##ñ÷÷'«-߯ýû÷Y¿~=�5¢cÇŽENžÌÍÍ5j .dÙ²eŒ3&ß…jµšëׯ̽{÷puueÒ¤I8;;¿£¨…Éd£ÉT}Z•à�ƒ9—pŽùÌÚⱂWá¿äpÐöíßUÔaäëþý;Ü¿‡5k—bccG£†Íiܸ% ê7Ñ馜¾œöú°iËj~š;“•+òÓœeT©â©gllÂàAcøqöWdeeñÃ÷‹sÌ¥T*‘H$Œ>�ÿ}1†^=ý‘¼”¸‹‰}È“\êñ½œ˜ <´—&M|°´´ÂÛ«&��{µ‰6µJ�D"E&Ë#ÙÍ[׉‹ÄšÕ;:¬'‡ï§e‹[…ÓÓR‰Œ|�뵕+¿x¯½oÿn¡M$ÈårÊ•}ÑDð�}»ù¸K/�äs·®}Y°àŽ?ÌÇ]zk�÷é=¹<û×M©T†««GŽU§M›¶Ò&*»WeÍÚ%Ú¿ïù};îîUP*•\¿ñ�ö¸›«W®^¤aÃf$%%ròÔQ~øn±6‘`bbЉ‰iÞî ýõ×>ŒÔÙ~n``@¯ž™öå'dd<Ó&Í]\\µ‰Dxñ¼cbŠd¢ ï5‘LÔ³   ¼¼¼°±±)´{T©R;;;Ž=J÷îÝyøð!M›6ÍÿÂB 17'kíZd¾¾ÈÇŽEѰ!ÊåËQ·ióÚs%''³|ùrÒÒÒ7n¶¶¶ù_ôþRýE9i9l$úùÚÄÅűråJ<==éСƒ^æ,LFFF°`ÁÖ¬YC@@@®õ͹/9åiŽíÄ©©)¨T*�cÏž¥“™™@hè]ŽŸʵaœ©©^^5ñ𨎻[•×J$þ[ùòÎ|ñù7Œø„Ï¿ÃçÿÍÞßOèŒéúq~Y6—ž=¾²~cƒúMqv®Ä¦Í«tjä: ¦¼<}šÄÙ³'¸xñ,Û¶¯²ŸGbR‚6™hWÚ•JÉÇ‘:ɶÜ( æÏ]I•*žôë;”ù?Ï¢Q£æÚÕ—®®¸ºz¼rެ¬,’’qp(ÿÊq Oâ±³Õm.(•Ê(emÃãÇq¯¼Ö@a�ãû ·×òï1OždoIþæ›ÏsŒ}žÐ|’ðµZ�ïsÒ—„„ÇÈdrJ•Òý�Âή J¥’§O“°±ÉýCûç»­ò{‚ Å�H&êQLL ·oßfôèÑ…~¯úõë³oß>êÕ«GVVö…Ø¥ T½{£®R%{Ûs·nÙÛžgÍ‚—¶·ä%==�¥K³·Œ; ‹œÛjÞÆ3Í3N(O DIKyKªÉÞnÅ£R©dýúõ”)S†ž={»­Íy)Q¢C‡eÞ¼y:tˆV­Z‘••EXXׯ_çÚµkÄÇÇS¦LZ´hAíÚµ±´´,ê°…ÄhÃÑÌŽŸM’YÏxÆ*Í*þ`/#AÉÇÈD_A„Bgll‚Kz¿µ~cý†ÚD¢‘‘1žž5¨S»!µk7 ²{U½¾Ï*Y²ú0rT?RSSt’†˜˜˜åØÞœ›‘Ã?eÒç£tV�ÔÑà?)eeÃöm/êŽÇÄ>¤{�VÜ»wWªWóÆÜ¼{~ßÎèQ“^9Ÿ‹‹«v•åÀÃÙµ{3›6­b�ÿÈǤP(°.eÃÝ»·òlðÙIÎðˆP�cψ��¦L™r¾_A•)S–,e+–mÍsŒ­�2™œ»÷náî^%ß9 ÉÌÌ|㘞'z#£Âq(÷"ùúàÁ}ŒŒŒ ôý#‚𾿹éÑÅ‹±²²z'Û@}||ÈÊÊâêÕ«Å"á£ñô$ëÔ)Ôݺ![²ƒæÍ‘„†æ{]VV«V­"++‹#Fè=‘`$1b€á¬¥ÖœU�E‰ò­æÛ»w/ ôë×™ìÍ>!/*vvvtíÚ•?ÿü“Ù³g3eÊ–.]Jhh(õêÕcêÔ©LŸ>�V­Z‹ï+áá@A«3­tŽÅj1]ó5=Õ=9Ïù"ŠLA( »vmfê—ps­ŒÿÀ,[º™ãÁÿ°léfüŽÀ£rµ·J$¦¦¦Ð@'öïß­]-©V«8rä œ\Þª{tíÚ ¨XÑ�“§Ž¼öµ��дi+J”°Ðþq­T™JÝ <”݈ÅÈÈÿ�#Ù¸i•NwáððPþ7e,ii©¹Îmjjƈ៲jÕ"âóY)ø²Î�{±aã ®_¿ª=–šš¢Ó\¥G÷ìØ¹™È¨p »^ü’¥?addD“Æ-_ë~Ñ¥s/._>Ÿck~hè]훚šáëÛžÅKfë4x‰Ç¡CûrÌéèP�Ë�ϳ!O~<«ûàî^…Å‹g£ReÿNñäI<ëÖ/£mÛήõ.‚ð>+õèï¿ÿ¦zõÂï" `llŒ««+·nÝB.—›Z33²Ö¬AÖ²%òqãPÔ«‡rñbÔ]ºäyÍŽ;xôèãÆ�ÃÜÜ<ÏqoË ú(ú�J*ò·øÖçĉøûû¿·É¶š5krýúunß¾Mÿþýqww§ |„ÿ®Ê¡•q}êÊí·uŽ_ç:þêAÔ•Ôe’d®è¿�• ‚P|ýdªÞŸ� Bq$ѼéG2‚ŽÔÔT>ýôSFŒQ(]œssâÄ <ˆT*eæÌ™9ΫÕjââ∊ŠâÑ£G$$$�˜˜Hzz:™™™(•ÙŸ¤Éår 066ÆÒÒ’’%KbkkKÙ²e±±±Éµ®^AHoÞDÞ·/’7P „ò§ŸHLK#**ŠÇ�“��@XXQQQÚÎÀÏcR(( ŒŒŒ077ÇÊÊŠ’%KRªT)01)šk�†ùóçcjjʰaÊ$}INNæûï¿Ç××—6oPã²0E<¹GÐÍßøÈ¥õ;»çµ‹×¸xìÓ§Og÷ü/úqö�hꨙYý4h�!ÃS>“|Š=Ùåä9>ø ãýZõ+ühØe5ŸùÎ-ê@„ÿ¸!~ ß?,KÞ‡°’´´T._>GBbeJÛS½z ò(ÅsçîMJYYce¥Û$,55…á¡xTÖ-•sëV––V:MK^åù0&&¦4hЬ@c_N=gjj–#Áàæözɺ¼æ(QÂ�9ÏÙÚ–¦•¯_®×ØØØaccWàãagW&ß䨣c+äzN.—çúÿ�}>ÇËÌÌÌs½ÖÔÔŒ�jÕ{eLNjÄR²d©mË._>ïòU …o¯Zyž·¶¶ÅÚZ·¡¤T*Íóë/‚ð>ÉD=‰ŒŒ¤téÒït»ñóûeddpøða.]ºDLL –––¸¹¹Ñ½{w°¶¶~íz3�†øøx"""¸}û6Ç�ç÷ßÇÎÎŽš5kR³fÍ<·ø†……qéÒ%BBBHHHÀªNZ9;Soóf¾úã².„%乌Œ "##‰ˆˆ <<œƒ²sçNJ—.MÕªUùè£�Þ¨“öõŽ)�ÑAÑKIî¯K£ÑD�:uô’¼,êÕ«Gpp0GŽ¡cÇŽEŽð!‘H/ù„ ÍL1c¥tCÔCñW EAAA„bN$õ$**êµVíéCLL (•JN�:…··7}ûö¥lÙ²o=·D"ÁÆÆ|||xøð!/^äÔ©S>>o\Û° ìííéС~~~\¿~�   fÏž�­­-‰‰‰P³fMüýý±³Ë¹­BíæFæ±cÈ'MB¶z5Ò7ÈZ¿�Ë›' ¤R)NNN899Ѷm[î߿ϹsçØµkû÷ï§iÓ¦Ô­[7Ϻ8ÏU–VÆVaË>å>LȽã™3gðôô¤dÉ’ooqT»vm8À… hÔ¨QQ‡SdÌK˜‘‘‘Arr²Øò]H´Ï×2»{æpI35Ùõ^³Š+"Š‚ ‚ ‚ ÅšH&êIbb"…zµZMPP‡ÂÆÆ†€€ÜÜÜ õž¹‘H$T©R…*UªpûömvíÚ…J¥¢~ýúøúú¾:©ilŒráB4uë"?>»ÛóÂ…¨ßpÛóËœ��qvv¦C‡;vŒƒD»víøè£�^¹Ý»”¤ýýs=—””ÄÝ»wßû¦+¹100 zõêœ;wî?�L´+k‡¡‘!×®]£nݺE„FƒôÖ-$g΀‘ª^½Š&ŽBrýúu�€½cv£•”`C´ç«ˆ„¢ ‚ ‚ B±W¸KÙþCRSS µÃp\\ , ((ˆŽ;òé§ŸI"ñe®®®Lš4‰.]ºÌÏ?ÿL\\\¾×©z÷&ëäIprBáï�|ÈHKÓ[\¦¦¦´mÛ–¯¾úŠÚµk³cÇ~þùg"""Þh¾Ë—/cnnþÎ:u¿kµjÕâÞ½{<~ü¸¨C)2R™wOw‚‚‚´]Å ]f&’sç�ÏŸ�¢{w QÔ¨�|ôhäC† ¹ÿÝÄñh4>D¥*•00|±RØM¢ûÿ±ç Å,²ðWâ÷Þu¨‚ ‚ ‚ Â+ˆd¢(•JÔju¾[ißÔ­[·˜7o2™Œ‰'R¿~ýBßÒü:¤R)õêÕcÒ¤I( æÍ›ÇÍ›7ó½NíêJæ±c¨FŽD¶e І ‘ܸ¡×ØŒŒŒh×®“'OÆÔÔ”ùóçsðàAÔjõkÍs9ô2•=*«ç®OÎÎΘ˜˜pCÏÏÿ}óQãZ¤¦¥²û·Ý…zÉÙ³(Ú´ÁÐÞƒfÍ�M™‚tß>$OžhÇhÊ•CãàP¨q¼Kû÷ï'>>žºÍëä;öå„â}>œ¤ª ‚ ‚ ÂûîÃÌŒ¼c*•  PMçÎ�cùòåøøø0räHJ•*¥÷{è‹••#GޤF�¬X±‚³gÏæ‘‘ÊÙ³Q®Z…42E“&ȶo×{lÖÖÖ :”ž={Ì’%KHLL,еO•O9dyˆPïPR4)z�­8�H$¸¸¸( ü!313¡M÷6œ=s–_ýµÐV(*¦MCzü8¤§ç9Fï°;|aQ«ÕüþûïѪ‹/%,Kèº*x°T²” 2DBQAA¡ÉD=xÞ1øuW»åçܹslÛ¶ ???ºvíŠL&Óëü…A*•òñÇãççÇöíÛ –PT={’yò$T¨€¼¶=?W«V-&L˜À³gϘ7oQQQù^ó$ò ¥BK¡´U²)s*Tz�«8¨X±"wîÜ)ê0Šœ£‹ûu௿ÿâ»ï¾ãäÉ“N<”º]»W01Aåï¯×{¾kOŸ>åÌ™3|ÿý÷œ:}Šö½Úáâñzõ½$ž,“,ãÏDBQAA¡˜ Xô@&“!•JÉÌÌÔۜ׮]cÛ¶mtèÐ�&MšèmÞw¥I“&H$¶oߎ©©i�:]k*U"38ù´iÈ–,Arù2Ê�Ñxxè56[[[Æ�ÏæÍ›Y¸p!ýû÷Çã÷ˆ��¥BB•D²&Å?©û&ìííILL$--­Pë¾]é;¦/�_`ÿ�ýìܹ¹BŽB®Ÿ•‚ �›Þ·nåzþtÅŠìœ=[/÷ÊË“'¶?ïVLLRõ:w–2 e–C#Cܪ»Ñ±qLÍMßh./‰'ËXF€&@Û”Åg½Æ+‚ ‚ ‚ œH&ꉹ¹9ÉÉÉz™+66–�7Ò¸qã÷2‘ø\ãÆ�IJJbÓ¦M|òÉ'ØÙÙåÑÿo{Vת…|Ì š6E9¾Þ»ÚÊårúöíËîÝ»Y½z5ƒ¦råʹŽ���ÅÖÖ{‰}vèeccÀ£G�prr*Ú`ŠScµiDƒV ‰‹~DrR ÏÒòÞ–üºžT´GýéT¤™Yº'$RG  žCY½Ý+7§Ž•#2ª¿ÿñŸuûrúÛÂodb„Y 3lËØ"•½ýx‘PAAA(>D2QO,--IJJzëyÔj56l |ùòøùùé!²¢Õ¾}{¢¢¢X¿~=&L(ðVmu÷îdÕ®�¢ÿì®¶AA(þLßluSnžoÉV(¬Y³†aÆQ±bÅãž�J¥z£¹4ŽŽd¢œ0ÙÖ­ÙÛž¯]Ó[¬fffôíÛ—K—.qãÆ íq…BAVVVž×=ŽL…˜ øøã.u×[OüÔOˆ™;Mýc5?¯Ž¦Ïà$~ÛV‚€^eIN*¾�Ë_N(FQÔ! ‚ ‚ ‚ ü'ˆ,zbllŒ““7nÜȳ+ð«Ü¾}›´´4¼½½ !º¼íÞ½ÍK{­¬¬rí"}öìY ñöö&22’={ö�ššJµjÕhÕª•N�Ç¿þú‹ÄÄD®\¹À±cÇ([¶,!!!,^¼˜ZµjQ·n]�ùÕj5ÁÁÁ\¸p�FC­ZµhÚ´©níH…ÕÌ™œ“H¨³b�“:e [mmyðà666téÒEÛ0åÌ™3ãååEDD¿ÿþ;©©©T¯^__ßu)+V¬ˆ§§'3gÎÄÝÝ ž~åXº)вÊ¢-W^/–³ŒašªýY+]ƒE– ‚ ‚ ÂM$õÈÛۛÇÓ¹sg$¯¹U1$$,,, )ºÜ�;µZ­ý{JJ ÞÞÞ¹nGž?>FFFøùù1räHÊ–-Ë£G�HHH`àÀ�,þW-ÃaÆñðáC”Êì$Äœ9s�ËådddpúôiÚµk§“LŒˆˆ wïÞüóÏ?x{{£P(øñÇñööfçÎ�9jH¶[¶ŒeS¦Ðrͬ¦MÃZ&cA™2Üyôˆ5jh“‰óçÏÇÄÄ„¶mÛ2zôh�˜ ÄÂ… uæ=vì_}õOŸ>åþýûH¥R®^½J“&MèØ±£öë:wî\m"V£Ñ°gÏ<¨�ÇÂÂâ½L&¦§§ëm‹û�å†_±ýbYö¥‰Z¿ˆL·œ�‹«~C±/—Ť‘¥éÝΑÅëRÕ«xÖÒô’x±Œ_Ð  EAAÈGZZ*s~šAíÚ håû~½W}ô(†Ÿ|O§ŽÝ©UëõËBíØ¹‰´´Tú÷VÑ ‚ ü·ˆmÎzT£F ž>}ÊíÛ·_ûÚððp*T¨PQ½ZDDQQQÚ?/¯|ÙŸþÉüùó9uê—/_&44”:°~ýzÄÞÞ¾@פ§§£T*ßùç7Q¢D ÌÌÌtŽ•.]€Ç�ç{½……*•ŠôôtLM³W:�>}‰DBPPPŽíÕ÷ïßçÙ³gDGGãää¤s®K—.´hÑuÛ¶d�=‹bà@ä“&!=yå/¿¼V̧N�¢dÉ’Ìž=€ÐÐP¦OŸŽ»»;iiioÔ\ÇTbJƒ>+ƒQ¡BBñí��¥¥%&&&EÊ{É 4û~£0 }@üÔOx O“µÿ�––ʺu¿°eËjüÚw%`Øx�Q~6nZÉÒ_æbldŒy FE0tè8† ­³fíR~Y6û2ey’ð ‹’Ìùq)®®$&&Ðί>Û¶àó/Æ R©ˆ��¦\9GÖ®Þ…¹y ¦=‘úõsûö N�F¥R’’’Â�?,¡q£Úû]ºt–é_OD"•biiŽ»·9ò3úô¤£V«X°ðG6oYE©R6Èå ž<ŽçóÉ3ðóë @ÇN�ÉÌÊ$%%…[·BøuÇ‹�4«VþJ¥Šî\»ö7Ÿ|úâ÷’´´TúôÌ'ã§è<§¸¸X¾œþ)W®\¢L™²„‡‡ÒºU¦MýA›LÛþëîß¿CõêÞ,[>cc>Œdè�±Œñi�¾‰„¾ý:0yÒ×´iÝ‘G�b˜ýÓ× :ŽJݹrõ2ãÆâxð?9r�Ù?}­½6%%™Ï'Í {÷þÚcAGþdæ7“Q)U è¡}¯ïêêÁÊåÛ´c Y¸è~Û³ …Ü€¸øGL�ò-�;õÔŽ >vˆ™ßLF¡ÈNt¦§§2å‹oñmÙ€øø8Úû5`Û–¸¹UÑ^7cÆ$ìíø|ò éFÔÃÒÒR‘J¥ þS;öûïQ¯nã=/A„âH$ A×®]ùþûï¹zõ*Õ«WÏwüóŽÂIƽožw~¾Ýàùöf™ìŧ¡NNNdeeñý÷ß¿ýVo¹Õ”)hêÕC>h³NŸ¦d©R Ñ@>Mqœœœˆ‰‰aÆ Úcß|ó uêÔáÎ�;Ú¦.ÿfh˜ýōßЊóªD�Fý{÷èܹsQ‡òÞyŸ­¼™\ÃôÙ�pqÍä‡/mè×±K7>Ä®Lñëôì-ñæ–2\3‚�jÖI×RŽrE– ‚𞯠û·ÌÌLvîÚÌï{¥•¯Ÿä»"n÷o[™ÿó·|;k�6ÊÍ[!Ú1îeùŠŸY±l Õ«×@©TòõÌIŒçÏžÝÁ:+Èf|ó9ó~Z�““ qq±|Ü­¿ïý•>½_ìHX¼d“>›Î—Ó~@£Ñð¿/ưxÉm21&&ŠqŸ fÌèIôè>€›7C4¤+5kÔÖ&¨–,ý‰]»7³dÑjÖÌ®kr…ää§Ú{>t €®Ý[â×¾+úäx5jÔáxð?Ú¿Œè�cŒF£á³IÃ100äП055#<<”¡=Y¼d¶NâñpÐ~,--9°ÿ,††lݶ–9?Í OïÁXXXæ˜ûe‰„jÕ¼ ¹B›Ö¹xñ §O£j/*Ut'$ä U«z!‘HðóëªMœ´÷k�c¾–-ÚÒ²E[®]û›¾ý;°oï)J”È}ÇסÃû9|‡þ¼€T*cÎO3X°ðm2ñö�|61€I¿¦{·~lÛ¾Ž/¦Œ¥B…ŠTªèžïë{nËæýŒÝ''&~öU�¯A(îDÍÄBàääD“&MرcOŸ>Íwüóm¥©©©…Ú;W®\ö/ð!!ÙoØÒÒÒt¶ÒvíÚ™LƬY³r�ãßõ JÝ´)Y'Or×Ò’ÿÅÅ¡èÕ Ibâ+¯éÑ£wïÞeÛ¶Ÿ^zxxpóæMÜÜÜ É‘ð533ÃÒÒRûú^— Iš¤7ºVŸBCCIKK£råÊEÊ{ãCi´òºú MdβhÂîЫ­7¯åÜžTøH|øE²”§dÍÚ¥¬Y»” Wä9׺u¿0wÞ7Ìüæsîß¿“ë˜S§ƒ™:m<'�`ÓæU¹ŽIMM!`DoퟌŒgȤyoÃÍÊÊâ�}»èѳµÎÖÑܬY»”®÷Õ&+èü}õš%tìÐ�êÕk —Ë™<ñks48Pg¾Ï'ÏÀÉ)»·��Þ^µ ½«3¦m›NtèÐ ‰D‚T*¥eËv<»§=¿aãJœ+TÒ&!»–a½º�µ�:223Ø´y5ÆŽÓ&ªTñ¤N�†¯|Íoâæ­®\¹Ä§ŸLÓn£vt¬À ÿ‘ìØ¹ ¥ò҇噸Ùtíeß–íQ*•DD„ø~Õ«ùr€Ë�§q“–ü}%»aaHȪVñÒÓ+ÓU·NC ®ÝÂîëÛž„„ÇÚºœ;vn¢bE7m" G÷¸VªÌÎ�› %&A„÷‘X™XH>þøcîܹÃúõë Щ§ñ2 IHHx‡¾øøø0kÖ,¤R)R©”ˆˆV¬XÁرcpsscÆŒL™2…ÈÈHúö틽½=ááálß¾�êÕ«3cƌ׾·¦lY¦Ö­K³³gµoŠ:uÈZ·MíÚ¹Ž0` €S§NáëëK||<û÷ïgÕªUTªT‰;wîè4‰èׯK–,ÁÅÅ…úõë“™™ÉåË—™0aB¾[×�«ŽsUy•6Š6¸J]_9¶0]¼xggç\W_ 9É“°ú)&'Î’Ô» ±?LCóŠãšÖR(]&ŠÑÊпS9~ZMÃfiEV>Ÿ[žÅ EAþë~ÿc{÷î`xÀ'Tv¯šcÌÇ‘ü¼à; »F]¿¾¹—îÙ½gaÿŸ$kÖ¬5ÎÎ9Ë¥+W®dÀ€y®TsrrâÆ�ï8œ-Z”ç¹ï¾û.×ãNNNœ:MYÖJ×RŽ·lø$‚ š'3år9;tgè�1ÚOA}:aC‡v§k÷–´o÷1¦¦f\¸x†Ø˜‡lÙ¼¹\Θѓè?°u¡•¯�Űcç&F�šHùòÎú~i´hÞ†“'�0À¿3�;÷©¼3QQ<¸‡Õ«vh¥_Mû�€á½èݧ¾¾í‘H¤œ8„™Y -X«3gÇÝùbêXÌÍKàèX�‡#hÒÄ—jU½ “©©_Nû‘Ïÿ7šˆˆ0*Vtã䩣ܹ}ƒ_–N­ÀjU½9thd7�ññþˆeËæÓ°a³7šÏÚÚ–úõš0íË tïÖ™LFDă×j|Ò¦uG‚ƒé?°3]?îÀ¯;6R¿^ÚµÍ~ÿ/“ÉiÚÄ—ŸæÎäÁƒP233ùëïóÔðɽ”R¿n Ú�Yß~�»{Uââb©ZÕ‹õ›¾ÑëA(dÓ§OŸ^ÔA|èÌĮ̀W¯qqqìÙ³‡;wî —Ë)Y²¤öSF ._¾LVVnnï~«ë»Djj*íÚµ{åÖ•B%•¢iÔMýúHwïF¾|9¨Õh4ȳÛó™3gppp |ùòHÍš5ó­‡ø>8}ú4×®]cèСÚm5ÅÁÓôBãoRÖªèv¥ Ûi?`ýÃBžÕô$jûJ²Eêßd2hÙ.$¶®µàüIcš¶JÃØ¤x%í%öÔÀ‡�ìä æ Í$Í)A‰¢KxÏ܉ý‹z.­Š: á?î÷ßNáé冑qñùÙ­o¶¶¥100ÄÍÕƒY3¦}û�13{ýÿg›˜˜Ò©c,-­ˆŒ '&&ŠZµêòÅßb 0ÀÀÀ�Î�z�FíÛ×155cܸÏiÝêÅN‰D‚©©9>Þµu>€U(Ttq§|ù Ù—+psõ \¹¥n¤RYv³ïZÚ¹š6ñÅÍ­ Ñ#¹{÷VVÖŒþ)NÚ묬JÑ©SO ÂÃCIHxLËí;f’—Vnº¸¸RµªwïÝ"2"ìÿW6úäºÂÔÀÀ7WíÊÌ眜\hÙ¢‘Qá„=¸OõªÞLÿjeʼxß#—Ëq(ç¤í8�ýz²ëaúÔ¨ýZÛ¡­­m)]Úž–-ÚbiY;,,,iÑ¢-eòHR­šOžÛÛ[4oƒZ­æÖ­RR’qu­Œ«ke¤R)r¹çJ:«A¥R %ññþƒì-Úao_Ž;wo’–žFÏ1|‚Î3oÔ°9‰”ððP¬­m˜† œ9s;v,�5¢R¥J¸»»Ó¦MŒŒŒ8tèPQ‡©w���ñÑGÅç.�� Y{ö š9i` Šºu‘œ9“c\zzºöh©TJ×®]ùçŸ )Ôø4 UemæZ¨è}þÝ»wcffF«Vb…Mn BÃqhß“Ó牟ú 1sgˆDbtí“Ä/’ðXFŸö\:[üVðÖ�ÔàÉR’Hb z ‘DuH‚ ‚ ‚ ï ‘L,"FFFxxxвeK:wîL§N�hÙ²%½{÷æÄ‰„†~8EzÃÃÃ9qâ�:uÒµ.6$”&�µo¨T´n�lÖ,øWǵgÏžélivrr¢~ýúlݺ•¤¤¤B ­¤¤$½ z#CÆ Õ ½Î}ùòe.]ºDŸ>}òì2þ_frì Ž­{ ˆyDÔšÿÙŽÍoª^“46ü‰‘±†!Ý˲wñ[9óï„¢¿Ú_$AAA H$‹¼¼¼Ø²e éééEÎ[KOOgãÆ�xxxàååUÔáäIݰ!YgÏ¢nÚù·ß¢èÐÉ£G¤¦¦¢T*sl;ïСlܸµºðêÂÙKìh0�ŽŠŽz›óÑ£Güú믴iÓwww½Íû¡°Üð+åúŽ@eiÁƒ}›þó›ß”kå ¶ìÇÅ-“I#K³xΫ;‡…’,•.!‘D‘PAAA( ‘L,†úõëÀúõë 5QUØÔj56l@£ÑЫW¯¢'_kk²vïFùã�HOžDÑ  {÷"‘H°··×«P(èß¿?‘‘‘lß¾�Â,=j,1Æý¬ìJIIaåÊ•”/_???½Ìù¡�(UØNù»‰_óÌ»û6‹ŽÍoɶ´Šõ¿EÒ¨y*KæXñå[”YEÔ|)5©ÉRé#Óþa IDATH EAAA„ÉÄbÈÔÔ”‘#GƦM›ÞË„¢Z­fóæÍÜ¿ŸAƒét½+Ö$T£F‘ùÇ Ñà|8 …øïÿet ¶=†a²v+1=;ñì�u¤ÏÞŒGÈ==}K7†Ð£4l3bDokb_*ÕV5©É*ÅÊÌ„b�H( ‚ ‚ ‚ ¼‘(–VHY[[3vìX/^ÌÖ­[éÑ£G‘©m—––ÆöíÛñõõeøðáXYY©;¤\“ë×'õï¿ iÙ’ÆgÏݰ!G�âiJ !!!„‡‡“žžŽ±±1ŽŽŽœ:u •JE»ví�¤‚Yyå§òÃ7Í—6šmЕÞÞä">>žÕ«W“��ÀäÉ“‹Nr·h=~ŠuŸ/Ñ~@Ä´¯D}Ä| TÊL›Žƒc*?Ï4§ïç6¬ØŒ•MšºCËôOBq¸jýUØ X��èò,‚ ‚ ‚��XšTˆ•.]šqãÆáïïÏòåˉ��UwHïËŠ+¸ÿ>ǧdÉ’êé½%+ÆÂÆ�Ù]¯7nPÌìïß§nݺ 6Œü‘yóæ1a†ιsçØ¾};ééé_´Í#ùS6¦ {ã¸ÈÈH–,YBjj*“&MÂØØ¸@â+ D£•‚ÕgH4‹V‡ðô±&=ÚØsç–¶ºCÊ¢&5Y"-!ŠHú‹Š‚ ‚ ‚ ¯%’‰…\©R¥˜:u*iiiÌŸ?___u‡ôFwïÞeáÂ…$%%1nܸ"�HðõõER(øìÄ 4½½Ñ77§å’%´¼x‘*+bföª¡D•*U;v,¾¾¾,]º”¨¨¨|�¯®².Ý4»¡!i -½>)sûöm-Z„��“&MÂÄÄ$ßã**D£õhÞ.Žu‘žý:Ør渾ºCÊ¢žäÊRi™H( ‚ "&&šE¿ÌÁ×÷†ºCy­#Göqüć•ó¹rÅ›ïfOfôØþü4w:�ù£R¥³xÉO™ËW,È£ˆóNrJ2K–Îå⥠êE¡ÐÉÄ"ÀÌ̌ɓ'S£F Ö®]˶mÛxùò¥ºÃÊËöíÛY³f +VdìØ±YmE•——U«VEWW©vm”W® µj…üÝw¨š7‡��,ãË”)ôiÓP(,\¸Ÿ|mÌ`¯°g�Ö Œ$£,Ç“““Ù³gëÖ­£^½zŒ?}ý•´QÑhEýªÔHbûágXX¥1º¿Û×½û¢ôï„âÕ@‘PAríè_xüäá;Ç]ºìŦͫñؽ¥¢Ê=Ï3Ç9þÔ{_ù²#¾ì�™Yqڷ댥¥5ii©YÆ|8ÎÎÎj‰%¯=}ú”‡Òµk×WÍÌP<ˆ¼d ªÉ“I¯RÅæÍH-[þkˆ“&Mbÿþýlß¾�‹/òÅ_`aa‘o±J¼ªÑ(Ë2ׯ_gÿþýH’Ĉ#¨R¥J¾Í]Ô(£c°2½sÓ³ÏçMGþOs¡`Ø:¤²õP cX2gj ž<ÔbÊìp K_ z’+KYÆhyTY¯X'j( ‚ 9¶yËú÷N©’Žoפq æÏ[Iµêµ (²‚µgßš7oǨ/'g;7vÌTNž:‚—÷™‚‹iïvjÖ¨K… o�\©b5~Y¸gg—ŠL¡èÉÄ"¦|ùòÌœ9OOOþüóO<==quu¥~ýú˜šL÷Ù¨¨(Ο?�——´nÝšúõë£T®­âøñã”-[6ûVmIB;E½z¨ºuCÕº5ÒäÉ(~øþÿø•J%�:uÂÍÍ�íÛ·3oÞ<\\\hÕª¶¶¶ù¯,Ëܹs‡cÇŽHãÆ�iôY#,u-óe¾¢H4Z)|ŒŒÓY½3˜é_Y°åwcBC4˜·ì9:º…£ƒ}FBq)£åÑ –‡°� XH%Ô– ‚ðâ ~†¹¹ÆFYË¿¨T*066ÅÐðÃVÍ¿Œ‰ÎÑ8 š7oûÎq¡ÏƒIMIÁÆÆ…"ûkîää$‚ƒ±´´FW÷ÃíEGG‘”œ„¥…5Š·¼ËŠJVaiaýÆ1ÏCƒ©]ÛíƒâùÇ‹‘Ä'Äccm÷Ö†‡¡¡A$&&âàPêµÏUì˘Í'IMš´|똄„xÂÂB±µuxk³Ì¤¤D‚‚žaaaE±b9š_¡0ÉÄ"H©TÒ¬Y34h€——'NœÀÓÓ“Ò¥KS£F \\\02ÊÛmƒ111ܹs=z„™™íÚµ£víÚhiiåé\êv÷î]|}}™4iÒÇHµj¡¼v ÕàÁÈóæ¡úûoÛ¶�õ«SŒ;–[·nqäÈ-Z„³³35kÖ¤R¥Jhkxó‰ÈÈH|||¸rå QQQÔ©S‡Áƒ£a®ÁÚ„µ”K*Gk�Öhòi¯¾Ó;ã�õÐñHé*‚Ö/õ --™¹ËB±/•ÊŠ¦ Ñ`ù¦`L‹L#£w©'Õc)K%�f€4€õòz‘PA(BdY¦Z Žÿu™�»6±eë臘¦¢¥¥ÅYÏ[hþ‡Âþ»X¸è{$IA\\,•*UåûÙ¿`gëÀ±ã‡˜1s{ÝËrÿFM*óõäÙ´nÝ�èè(Ú´s#!!€ISFÀ”WcÏzÞÂÐЈ½ûvðÝì¬+õ¦LþŽÝd9VÇÕ™õkwóÛê_¹|Å›ÄÄJ—.Ão+·Q¼ø«ßE›6¯fíºe8Ø—æÞý;$''P­j-Ö¯û#ÇÏUtt3gMä칓â`_]]]¬¬²¾~ù²s~ü†ø¸X444A’ønæ|êÔ©Ÿ9¦U뺄>àêµK¬úíš6iÅ¢…«sdl7ž=çk(VÌ€„„&OœIëÖ2ÇȲ̦ͫY·~ÉÉIhhh §§Ï´o¢aƒf4jR…˜˜ø\½È‚…³3¯÷ØuŒ2Nåðò>ÃÈ/ûd™@ÿ™«(ÿñòe ?͛αc‡044"!>Žž=2zÔ”Ììšß—øW׆ü4w:ÉÉI 'Π{·þ¹zA ‘L,´´´2V 5j„¿¿?ÞÞÞº}Þqç�—ñfJ|ó©Ö–mZ&ê#B’_NŒÄÚ6•Y“JУ�«¶SÊ)EÝ¡ Åe"¡(‚P¤}?çk´µµÙíq[{¢¢"2‰¼<ùáÇoøyÞJ7jN||ßN˨Ñýؽëxæ¸w166Åëü]ܸ0kÆü×®:ìØ¡;;tÏüü³�ÞxÏ)_Éĉ3Yüë:ÂÂBéÓïs¶n[›™Üº~ý ËW,`Çö#”*éÈã'é? #Û¶ÆÆÆ.§O³fO&$$ˆ?yaeeÃÍ›>LþzT–dâ£GþŒ;€É“fÑ©c #;eê(öí=�¹Úóè‘¿è?°uë4`ø°¯rË?"##>²7Ý»õcÈàÑ(J¼½Ï2~âP*T¨‚½})ÖoXÉïk—òݬ…4kÚ €sçO‘œœœy¯3§3ê$vü¢)_têIï^ƒ³ÍWϵׯ>Íü|ȰîÙÆ|7{2aa¡üuäoŠ/ÁÍ›>Œ;�bÅ 4ðËÌq§N%--�ûÎ`hhÄÊU‹øuñO´o×}ýbïõœ‚ "™ø�$ gggœ��éÓ§�=âîÝ»øûûsåÊ‘$ CCCLLLÐÓÓCKK+sEaJJ )))ÄÇÇABB²,£££ƒ�� •+W¦sçΔ*Uê­[> >>žN�:åì‚¶=»¹¡êÞUÛ¶H£G£X°þó³lÙ²”-[–äädnÞ¼ÉÝ»w¹páÀÈȈâÅ‹£££ƒ¶¶6ZZZ$%%‘””D||<ááá$%%¡P(°··§bÅŠtïÞ''§l‰]%JZj·Ä^i�×ÊÑœ’ÒÒ1Ÿù3&k·’X»Áë“V¼`Jï§c÷—XÙ¤2n�=ÛÚ²d}µê%ª;,@$AŠ:•,ó󼕙¯™LM‹gž[¹jíÚ~AãFÍÐ×/ÆŒéóhѪ6gÏ� YÓÖ¯½gA1|<�ºP¢„%�ºãÿàÕêÈÛ¾×qttάÍXª¤#66ö\¾â…�M·ÏóàÁ=<=�±nín¬¬2jW®\ƒ*•«g·ò·E¸Õkœ™Høü³®lÞ²†‹ÏÓ²Eû÷~¬¯³ióoXYZ3lè¸Ìc®® ©Y³.§N¥¿¤¤¤°vÝ2Ms÷6™ãþyÞòÚýûw8yê[6È\!Z¹r ôÎÆM«ÐDæßLææÌùþ—Ìï»/:õdõšÅP¶l…|‰O¡ ˆdâGF¡Pàää„“SÆê+Y–‰ˆˆ 44”/^ðâÅ bccIOOÏ|§NOOJ–,IPP¾¾¾ôïß—�rõá›\¿~�óçÏ3bÄ rWËDªYåÕ«¨† ÉX©xñ"Š;à¿5Éh¦S«V-jÕª@tt4¡¡¡<þœ¨¨(âããIII!55===LLLÐ××§D‰XXX`ii™ã¦;å5Êçêq|,D£•¢«nƒD¶ dD/†t³áû_Âhß¹pt¯ EA„¢«G÷þo|]ûøÑƒ,+!#Ùhmmǃ÷ÔšLÔÑÕÍò¹��!‰�ü3?wr,Ë“' ÂÊʆ�� ž<¢ŒS¹\ÍóøÉC +T}븇ïF»öõ³�ˆ '4$(WsæÄÇ÷ xœm¾ÑQX[e¬¼ $>>ŽÚµêåùü¯óèñ”J Ê—¯˜åxÅ Uyñ"’¨‘73@GG7Ë÷���! ‰ « B~ÉÄ�œ$I˜››cnnž£ñ²,³lÙ2öïß�ƒƒÅŠ}ËƒÙ¹s'­Zµzÿîdž†(vîDnÖ Õ˜1¤×ª•±í¹M›·^fllŒ±±1åÊåîEŸðz¢ÑJÑçT6…m‡Ÿòe_k¦Ž¶àéMFNˆ¤0¼·‘QCq £å1"¡(‚P„¼í r]ââb³Oˆ�COOÿÿ×+P©r^ÏW¡P #ç>Ð\ª[·..•éÙ»ÎÎåyøð>C†Œ~g§âÿ244B¥R‘ššòÖz躺z¸»·eà€‘ÙÎý·¡M^ÐÕÕ¥ZõÚ|=ev¶sÿ42ÑÑÉH¸ÆÇÇåèž …Y~ÿ¯�ŽŽ.ééi$%%eÙª‡$Ièêè¾åjA„�ÃǽgUÈ5I’8p ššš¬ZµŠ¤¤$u‡”ïÂÃÃYµjÎÎÎ|öÙg|?ièP^^`lŒª];TcÇBjjDšwÂUáø¥ù©;Œ<§wÆûVÝÐ #hý‘H,ÂÌ-ÒÙ¸7ˆÆ-âY±À”iã,HM-ÙDÀMrc©´„P9” ๦î�A„àæÖ„cÇ¡R©2�]ºìEdTDfSSS3RRR Ísù²×Xffæ„æoàÀù §‘e™#‡½˜öíOüyÈ‹þýFäú>NŽeÑÐÐà칓™ÇÒÒÒx’e\}·&\ºxcSlmì³|¼o—b£Ì²KÿåæÖ„›7}ÐÔÐÌ6ß?ÉK +œœÊ²cׯlI˜×tÕ63-NHÈûmªV­‰¾^1Žþu Ëñ#GöQ©RuQ Q„O‚X™(d£¯¯Ïرc™?>kÖ¬aèСyÒy¸0ŠŒŒdÕªUX[[3tèÐ<« )U¯ŽÒÇÕ°aÛž½½QìÜ ¥JåÉý?Ô™”3ÜK»Gm­Ú4ÕjŠ¥ºCú`¢ÑÊÇGWOÅâu!Ì›aÎÖµF„i²xmFêïôì&¹eY¡¸A^O ±BQ¡H7f*=zµeô˜þ´jõ9‘‘a¬]·œÞ½ã\&£dL—ʘšš1õ›Ñ´k÷AAϸuë*vv%_{Ï–-Ú³aÓoèêêQ¢„%�hݺ%JXæiìJ =ògËÖµØÚÚãw÷6”.]‡Ò9¾�™YqzöÈœ9S ÄÈȘÇ÷Žƒý«ûôë;ŒsçOѧßçtïÖ +ž<~ÀÉSGY³f'ÚZ¹ÿ›¡|¹Š+VŒY³'ѤqK?ögÐÀ/Q*5hßî Nž:B¿�èÝkvv% ~Æá?÷òë/k3·Oÿv.#¿ìÃð‘½hÙ¢=’$qöÜIXµbk–ùZ¶üŒ gciiƒ½]IBBƒ¨U³NNes¯±‘ “'ÏâÇŸ¦LéRNœ=ŠóNóÛÊm¹~ü‚ E‘rÖ¬Y³Ô„PøèèèP¥J<==ñññ¡bÅŠ9®ÓWT<{öŒ+V`nnΨQ£ò>aª­�Ô¹3RéÒÈë×#¯Yƒää„äâ’·ó¼'¥1r 7RoPJY #…‘ºCÊâeâ Gøacúî„ ”–N‰éó(>o)I5«´ëwRím J¡ (РY<†F*<6qê/}ºg|®nö’=©ˆ‡ìÁIéÍqG_ÒWwXB>ó~�zŽ-Õ†ð‰;°ïUª–EG÷ã|³7¯ED„Qϵ&&f¯=¯««G‡Ï»ú<˜‹Ï“�Ï�!céѽæ MêÕkÌ£Gþܾ}++¾ùæ$I�s™òÙ’„5ª×F[[‡‹—/à{çZZÚTªX•bÅ ³ÍI¥ŠÕ²u_Žˆ£Nm·Ì&�±•×ÔÄŒ*UjdÄ¥©É©SGQjhpóæUnß¹�—×Vþ¶m-mªV­™ãç©nݘ˜˜ríÚe‚‚ž2 ÿH\]bblJÙ²¯_55µh×î 4”J®ß¸Âµë—ÑÒÒbÐÀQXZXe»gttÎÎ.oMljkkS§v}nÜðáÆ Š3 j•šhii¡P(hÕ²=F†ÆÜò½Î•ËÞ¤«Tôî9'ÇWÉ?KKkÚ´î@TT$×o\áá£ûÔ¬áÊÄ 3ÐPf]?ãR¾%Ì-¸|Å‹›7¯¢R©¨T±êk¿?bb^àèèLéRe²/W¶µkÕãÚ�+\¿~[{~œ³˜R¥^½vMLˆÇÀÀˆêÕkg“eˆŠŠ žk#ŒŒŒßñQ�Ø—ñ¼¥MA NÆZYø¾¦Ï¢rÒoµ[½uœh´òi9yDŸÉ#-)f ³|S0«Ž2 çåóŒ‘Çb%Y±žub…âGMæÏë˜Øb‘º>qƒûÍ£O¿ö›¼ß¶Ráã1hpzõDÓ&Y_3-\ô=wîÞbíš]jŠL(ª‚Ÿsâøß,Z2JÝ¡‚Pˆ‰š‰Â[2aÂìííùõ×_9wîÜ,V·´´4öïßÏÚµkiРÆ Ë÷D"€T­J¤=2¶=»¹Á£Gù>ï»ÆDbNi=~Š]»Þèy]"bÚW„.š-‰¹f­ãÙ¸7Y†þ�l8u´p¬¬/Õg‰´˜9„ $LÔPA Hjj*W¯^"9ùÕl>W/rüÄŸ´o÷…#A>f"™(¼“¶¶6#GޤC‡8p€µk×�½˜qaį¿þÊåË—1b]ºtykg¿KXÌy,¤�¬—Å–gA!•,éÈòe›€ŒzŠ¢“° ‚P wH(tìíí™6m§OŸæÀ�üý÷߸»»S£F ”ÊÂÕ899™ .púôi4552dÕ«WWwX\\Px{£1yõjT>>ÝžÕ/å—ÄÈ1ìHÜAC­†ÔתŸmLpp0gÎxò”ÔÔ”<�!61š€¨ûÜ1È<¦P©h{ì,y˱� KcÌ7S(éX2o‚ Üæ5ÆÌ›a޳K2+·ca•¦î�8Ç9ƨÆbƒ5ë¤÷O(Þ¼z“U QÑÅŒÆ�06ÖÍãH FzºL@À ¾‡±¹£¿žD1ƒ¢øG¯hÀ"¢‹ ùE4`!'D2Qø`111?~<³9KåÊ•©S§¥K—.°š„iiiøùùqñâEîܹƒ��îîî4jÔ¨Ð&³¸{U·nÈ·n!õéƒâ·ß@WýI‰Œ¯¡¿¿?Æõ`éÒ¶T¨P€�[„“Þ~9ø‡¡øás¤)-óôöOŸF1pð.�›DåUòôÞBÁ9z ߌ¶ÄØ4�›ƒ)W1YÝ!}pBñô_'8¶wë×vÃÔ´p4›É gÏ=àÛ'™»b &¦…£æeΉd¢P8ˆd¢ ùE$AÈ ‘LòLrr2>>>xyyñàÁôõõ)W®...”)S†bÅòvJTT÷îÝÃÏÏ�{÷šJ¥J•pss£R¥J(E¬¿Pb"ªqã�W¯Fª^=cÛ³Sᨘ’’BëÖ Ù´©#66Æ6¯|ü.ª®k ]…bë@¤ö•óež—/“hÛ~ó׬ÂÐÈ0_æòßõ˺ŒêgEJŠÄÂÕ!4hš î�²$×+ÖcŽyŽ® xÀ’938°o šš…«„D^¸y3ˆÉßx²híJu‡’K"™("™(B~ÉDArB$…|Á­[·¸uë÷ïß'55SSSìíí±³³ÃÌÌ LLL00xó aY–yùò%QQQ¼xñ‚ððpž={F@@qqqèééáââBÅŠ©X±â[ïUTdn{V(PüöR�ê‰ß~[ŽŽÎ5úõ«E²œ† ]I3_ç”WŸC5jØ™ 80)ŸWCž8y�½¾äËÉ_åëmÎå“ÙþçS˦0y¤%˘©5žF4d¾ô3Ïx&Š‚ ‚ ‚ "™(EQÉ’(ΜɺíùÖ-uG…ƒÒ”N:Õˆ•“ðL¹ÿúAÂIw›�ìyÅÜŽ(~ïS ›…O[ Ët6í ¤a³xV,0eÆø¤¥ª¯V¦»äÎBi�H( ‚ ‚ ‚Pdˆd¢ UÚÚÛž÷î…çÏ3¶=/^¬î¨(¯aÉ@Ýz´Ñ®˜í\ai´"|ÚôôU,ÝB�þÑü±Íˆ½­‰}©T[<ÿM(Fkƨ-AAA„wË�¡ˆ“:t@Y­ªîÝQ�‡äãƒbÅ (VLm1™*ô³“WŸC5jØ™ 802ÇõË—ŸÅôémèÙ³v^‡Y ’“ˆ+š«Í”JÌK˜£¡ùñýªP*e¦Í ÇÁ1•ŸgšÓ÷sVl ÆÊ&M-ñ¸Kî,`>åIÌ-3—ž·ª¼qìÇá´h±˜3g&`kkR€Q ‚ ‚ ‚ ˆd¢ |Pœ=‹jútäŸ&ýÒ%;w"UysB¢À¤©P�÷Ȩ�èæˆbÏð,õOŸ¾ÇæÍY·®ïk/�‰I$9ùÝ ž»wC™0a7W®`n^Œ±c›2thƒ<{¹uîÔyV-YNTTæÖ&H õm¥}_©Éi„FR©Z%¾š2ûRöê)Ïõ�¥U_�² G{Vl Â¥Rr�Ç+ÇÊsŒ0â™î3¶5�gmÐxÍ‚ÔÔt=Š -MUàqæVHH ß|³oïG˜šê3bD#úô©£î°AAAø"™( MMsç"»º¢8Uݺ(æÎE;V}1EÅ£êºù¤Ò 7./q%R@K\Pþ?IòäI$÷î=ÿ°i¢âiÚt�:Uã—_ºàëÌÀ�›ÐÐP2p`½¼x$¹²äç_¹y÷ _mèŒ]Y‹Ÿ?/ɲ̕cw3t$“¾ù·&õÕRžkÞ.ŽViŒêgM¿¶,XJ£æÓÔÈ—;xÈ’‘H"%¥’4æNIÏ4ªíJ$II©4mú åË[²vm_=ŠàË/·“’’Æ AnêOAA„÷$’‰‚ð‘‘>ÿåµk¨zôÈØö|îŠßcã�CöãeÓ_Ð ŠÆÓ½Ä€®HRÁ­ ܹy'Á1˜sxX�Λ_$I¢VKÊÕ.É·­ÁÂÚ§²Nê+ÏU©‘ÄöÃÏÞËšÑý­˜:'œò§va2ÉxâÉ&y3×åëh¢ISšÒEêL]©.7žßàaòÞ,ל=ëÏ•+8;[Pö? êÈÈxN�òã³Ïª ­ýê×úñãw±³3¡\9Kââ’9}úuê”bË–‹T«f‡››#6x£¯¯MÏžµ�$‰Ó§ïQ¾¼§Nù“ÈàÁõñö~Ä•+ôêU CüüByú4Š-\²=¶={®Ñ �æælÚô7qqÉìÚ5 nnŽ$$¤0cÆ ¨‡¢®ÖAAA4`„�“½}F·ç™3‘÷î%½Näë× lú¤C·xéòRp4;»ÖàH%kš6ý…ÐÍ1|¦S™$9•«—Ÿááq•Û·ƒ‰ŽNàÄ ¿Ì�‡óÜÏÇç)­[/åÙ³ܸHÓ¦¿°ÿ�Ìó/>¦cǪY®éܹ:Q„„\3‹ˆ°ìûƒÑ+»ä:‘˜–’Æá5çßxþñí`ÿ~žÈàè ó½˜è1eKo~˜1[-ó[‡T¶ ¤zíDæL-ÁOÓÌQåáNâÇV(fÍB±oDD ª[·@º=˫ϡø|Ñ ­ËSé½c0‹uaïÞáL˜°‡3†é7dâ—ÍÙµk�;W§lYKví’ùѵk�,÷ôñ àÌ™ ,[Ö�ƒ¿äóÏ«°~½WæùààlmM ŠÆÅeË–ybaa€––��—|Û¹u]§6EC3÷��“SùeÄ6 £Vá¿E‡Å2²Î\ÖO?ÀˆÚs {•'ñæ–�“9ö•ŠsýrÁ%¦ š‘q:«wÓî‹X¶ünÌWC¬HJ|ÿ_•©¤ò1XB{U{ÖËëq‘\X¤XÈqé8㥯°àÍ[á7o¾ˆ‡ÇU¼½§°cÇ`þüs3f´}¯X’“Ó:´ûö�ÀØXss<<†Ò¼yyÎ�{�9ÎÄD�C‡¾dÀWÎ�{ÀÑ£cøþûÏðòzDzº +Ú¶­Ä’%§³ÜÍšóôí[==-‚‚¢±·7%::�F�²|¹'FFºëøâ½ƒ ‚ ‚ ê'’‰‚ð‘“Ú·Gyý:RÍš¨Æ�CÕ©DçC‚-M…jÌNTöâ£�Ø2¼!¾rƪBŸ§ê¢RÉܾ„‚Ü­Ú0 &&z™ŸW¯n—%‘��‚ŽŽ&ññÉ«Ìøßzáuà&?õ]Ïï7¦�ÝÿŸ»Ž£›0¬ú�y}Î9U±e“ÿqµÍ_P$ ¾œ‰µm*³&• G;Vm ¦”Ó›“Ó*T\”/â!ïæÇIGE\˜(M¤­Ô�÷ø•KÆe>ä¡ä‹zõ©ZÕ–µk/0~¼;[·^¢V­’”/ÿ*ÑieeDxx¦ÍÃÌLY– �ÃÚº`k¸ ‚ ‚ ‚�wD2Q>ÿßö,ׯ�ªwoT�£˜7i̘ŒÌÉûzNzûåà†bnG¤)-1?v‡#1~¼û;/×ÖÖ 99• U4›þ¦ž–# ´œ²ÕŽ{gçx{?È¬×æåõ==-ìì &™Iq£÷¾þy@.®¥é:¡9öå,9½ã2±Qñ¨T2šZ?®‹ë‘ŸŒ*]…BYð‹Ë%…„”û]ÜEVÇî/±²IeÜ +z¶µeÉújÕKÌ2&‚öËûÙ!ï$˜` (F'é zI=)Ç%íìL~G�L-­Œ/Hò¶Ç˲üAs¿Ë”)-3f'ãÆ5cýz/&Nl‘弓S ||(Q€ëן‘ž®¢T)³|�MAA„ü#¶9 Â'FrwGyå R­Z¯¶=¿x¿úeòñ»¤×ú ‚¢QìŽ4¥%Æ5`Þ¼¿¸wïyæX•JÆÏ/4Û=Ê–µÄÏï9©aé”Ö0ç\Ê%ÝÊU}ûÖåàÁ›\¾ü€¤¤TæÌ9B·n5³t·ÍO ‰hëi¾÷õz:ĄǢJÏXq™–šN\L"JM%ñ1‰hþÿqÈ*™´”tµ$_Éß$UaS·A"[RÌ@fH7î6àª|•ñª 4S¹³HþŒ™%Íä´â4³¤™œHhÞ¼<W3·õ˲Ìöí—³Œ±³3A’$¼¼f[ºô4¾¾!<ÿÛ´iS}}m~þù/ž={A§NY› õèQ‹£GïdnoV©d~øá­[WÀÔT?_cAA!ÿˆ•‰‚ð)²µEqútömÏ®®9¾…¼úªQ;ÀÎÅ�‘H^Õtûæ›ÖÇP¥Ê÷Ô«çˆ��67nR·nivìœå>Ÿ}V™jÕì¨[uuë–â™Å nêÒ~qåÇR§N)¦MkC“&¿Ð �÷ï?ÇÐP—Ÿî”ã{ä…Üvpþ7ËRf˜Y3µí2j·ªÀßÞæÅóXÎx\åÜžkH ‰´Ôt.ñÅÆÉ<£r©l Û?eøp}¦^<ÈÏ�–evm´i#µ¦/})/•ÏóyGŽlÄ�7©Zu�9ãçJÆe²|¯™›УG-úöÝÀÆ�Gõêötî\=Ïãù7I’˜<¹ýúm`òä–hie}IQ£†=_Ý’¦M¡uë V÷Îrlú¿VrºÔ-…¶ž–%E½¹‚O<ʲƒ�øÉ~h¡Ešð…Ü…3›Ú³õwc&×OdñÚ ŒÒó-¥RA‹.´há’y¬I“²YÆ(íÚUÊrìßÿôô´pwµrÒÕõUÂþßIþš52ÿíà`ŠƒCÆÏcc½,×ÿcöìÃtìX531ù:5jØS£†ýÏ ‚ ‚ ‚P´ˆdâ{¸}û6Ó§Oçðá䦦f9g``@ïÞ½™={6Å‹¿ù�«OÑ AƒØ»w/S§NeÒ¤I>¿,Ë4oÞSSSvíÚUàój(ŽAõý÷Èsæ¼Úö\¯Þ«1¯i´R�Ó_ �X+Þ¿ÉIQçðš•�BÞ{Ä#öÉûñ�=xÉKì°c¼ô¥N˜’‘w›Ž�C*?Ï4§W{[Vn ÂÆ.íwþ8ÄÅ%3cÆnÝ æþýçxyMVwH‚ ‚ ‚  ‘LÌ¥½{÷Ò£G’““‘$‰Ê•+cccÃË—/¹wï¬\¹’ÇãééI©R¥Ôr¡Ï‹/HLL|÷à|püøqNž<ˆ¢÷´6”°3!<ðÅmŒ?¨ÆãÇ&…Nsy7Þ²7 Ô‘êÐEêŒ;ÍQ¾¦_YŸ!ÑXÛ¦2y¤%=ÛÚ³|S0«&©!ú‚•˜˜‚±±]ºT§{÷ZŠmË‚ ‚ ‚ð)ÉÄ\ ¢_¿~$''Ó²eK–/_Ž££cæy•JÅÎ�;2dOŸ>¥_¿~œ={V�.•*U"22’Ò¥K¿{p»téýúõ+ðy‹"©I”>>¨z÷Fþî;TG�2ãÒ](e–­ÑJAê¦S“½I×9•⇣†9fŠ�¯ìüA›8²Î‹bÆz˜êe9×~XÃ\'=wùðóÀMÔp/‡¯×#>Ñ�v&Ìí·�Ncšâöy•¼ ¿H �øƒ=ì‘÷ð‚˜cÎ iÝ¥nXóîïõf­ãÙ°'ˆ/ûZÓ¿“ ?¯¥i«øˆ\}ÌÍ ˜1£­ºÃAAAMD216nÜHll,FFFxxx``�µé„B¡ G�¤§§Ó§OÎ�;ǵkרV­šš".\¾ýö[¾ýöÛ›oÑ¢E„„„púôi||| lÞ�‚•ŠcÇ�çÌAõý÷ø™Pùâ×P¼˜ÚB2PèÐ[¯Áªè�2‘ú$’£ë½ù~߈ý�5¯_¿NëÖ­177§J•*¸¸¸`jjʀϞpttÄÔÔ”çÏŸ³k×.œœœ(]º45kÖ¤téÒ”.]šƒ¾v.¾øâ °··§fÍš”/_sss:tèÀýû÷³Œ?r䦦¦|ñÅìÞ½gggJ•*Åܹs�Œ,¦¦¦ÌŸ??Û|ÑÑÑL˜0KKKœœœ¨Y³&NNNXYY1eÊbbbÞø|¿ÉöíÛÙµkWæÇĉs}¤5HSˆÚzù­TEkJ/ž¿Ì“ûéè�”�Bjrö„ú³{Ï1³6Γy ;*¼eoÆ«&à.7g‘ü f˜2Kš‰§äÉ,iæ'ÿah”Îï;ƒèÒ'�ÍFŒìkM|œø5+‚ ‚ ÂÇE¬LÌ777¶lÙÂãÇ�éÛ·/¿þúëWvèÐáµÇŸßŽBá/'³/é͵ËSBñæUÃ…™–Ž&S6ôcÁàÍ|·g8šöýª­§E×Ò¬ž²‡‘¿tÉ<ÍÎÇé6±ù‡†\¨EÅ^y/»d D}:I�èAwÊJeóm^¥†Ì¬ùa8:§0o†9}>·eå–`,¬Ä*iAAA>bÉD.ôïß?3é¶mÛ6lllpwwgÁ‚\¸p�¤¤·wñ”e™Þ½{@™2e¸yó&—/_æÐ¡Cܾ}› ¥¥Å… X¼xqæu< wïÞ$''3sæL?~ÌÁƒ9wî7nÜ jÕª<}ú”¼vÞiÓ¦1zôh‚ƒƒ9vì'NœàÞ½{”-[–ôôt–-[–eüÔ©S‰ŽŽÆÕÕ•ÀÀ@Μ9þ}û¸rå žžžhkkÈñãdzÍΘ1c(Y²$«W¯ÆÏÏ� ¼õ9éÕ«÷ïß§D‰œ9s†7npðàAnݺʼn'(^¼8wîÜ¡oß¾o}~õ‹�M"88•ª`·vF¨â QŰ!Á›ÛiÁ:w^IŠOfýôøœð£ƒÙ>7Ÿåcãw‡r}ϱ˻snÏ5¸|Çó€HV|åÁÀг±q2§Íàúùð(ÔÏ—;Ì’¿£¹*c¢6Ú|-}�§â4³¤™ùšHü·>C¢Yð[OhÑ£�~·µ d^AAA„ü&V&悎ާN�â‡~`ÕªUDGGsòäINž<™y¾Aƒ´iÓ†Þ½{S¼xñ,ןZhÑ„&t‘:ã*¹ª-®VŸÅaaÄèþVôí`ËÂÕ!4hšðÁ÷íÙs-/>@OO‹êÕí=º 5k:d—–¦béÒÓ:t %]»Ö`àÀzYþOæÄâŧX²äT¶ã%Jàí=€ÔÔtÊ•›™yNGG3úõ«K·n5sûAAA(ÄD21—Š+ÆO?ýÄ7ß|ÃÑ£G9uêgÏžÅÏÏ�¤¤$Ž?ÎñãÇ™6m?üðcǎͼvß¾}4iÒ„J•²7E˜4i-Z´@C#ãK“––Æž={>|øk¯qpp }ûölÛ¶�={ödK&vïÞýµ<:99üj%—,Ë\¿~;;»l×DGGóøqƱÿÝÆü�ü1G‰D ó±Õ¯_?["ñîîîÔ®]›K—.±gÏ‘L,dSi×n9;VåȑѨT*NŸ¾ÏŠgèׯ.ÆÆzlß~™!C¶°hQgÊ–µ`ñâS4n¼ˆk×¾EOOë³¼âì\‚+W¾`„Ý$%¥²|y,¬ Ð×ÌX—ÌçŸWaÑ¢.ÄÅ%ãçÊ7ßìãܹe\¾<5�Ÿ…§¡©¤Q—y~ßbÆzô›Ù.Ïï[ørÙƒCò!IÄAr`¼ô�¤N˜P8õT«�ȶÃÏÞˆ/ûZóítëýA÷ ‰¡^=GÆ�kÆÓ§Q=êK½z?³eË@ºv}õ=4tèÎ�ógÖ¬ö¤¤¤1uê>ž<‰äûï?ËÕ|]ºT§~ýŒßõëÏgÚ´6´jUÍmÅ—e™G�"ظ±?nnŽ„…Åâíýˆþý7òüùKÆŒiúA�YAA„ÂC$ß“��]ºt¡K—ŒZd111xzzòǰgÏâãã7néééŒ?€7n5ßÄÜÜ5¦ë IDATw÷W«“å¸Ùl¦fÍšœ?ž'N¤{­§§'9rØ>m5"âÆ__ßÛ¶»uþÖÇPEŠäÂÍÍ̘1+øì³ö¸¹¥]îüùpΜ M5ÝÑd2Ò¡C%6n<ž©0ñnÄZq28`6;�œ|×t|Ð,þzg�\æ­o»Ú»›�±ža¿²Ðº�"ð5øÒÛЛ.†Îä!óSÀï·œ^ÉLŸ‘÷^÷cöôœ\ 6ññ¤`œ�Óá�Yo¾ÙˆÑ£—óLJiß¾"ëÖ£J•Â)A"@ýú�äÉãɦM'hÛ¶B–Ü÷Nräp!66ñÎ EDDDDä¡¡0ÑFäùçŸ`íÚµxxd<ª#þüL˜0�fÍšqíÚ5öïßOµjÕRvgŽŽŽ¶ù¾ÿæ,XpÇ .³Áá%$$аaCvîÜI®\¹:t(uêÔ!00�‚ b2™hÚ´i†aâ�BÁÿru½1öN“¨¨(àÞŸO²ž——+sæ¼@¯^³X°`7}úÔ¦ÿú(ðÏ4Ó‹#pvvÄÏÏ“~ØÆôé›X¼¸… ù°mÛél­ÏŠ•…q»¹Ǫ/�èGÑ¢ƨÄ둱ß}Ž'ë›a['gGÌ.ŽYrßÅýX÷Ëî,é+;%’ÈÖð‹uÛ¬Û0` š¡ íiLcx¸vh7›­Œ›|™ÂÅùf‚7Á—˜4ë2Þ>÷¾Ó³——+yòxrôh0.„pc¹‰7Þ˜OΜ®ŒÙ’Â…}8>üv]e™  æÎÝÁÓO§¿¬‡ˆˆˆˆˆ<œ&ÚÈÓÓ“]»v7‚Å5n¿¨¡Bÿ,„›rlïÞ½qpcºò„ 0™LLš4‰"EŠ`6›‰��§X±b<ùä“Yð4[´h;wîÄÅÅ…­[·¦;EúßÓ¢ÿ˘Éy{���ìÝ»7åc›‘[ç‹¿?;±Jæ´ný$§OÄ´i›øê«µ|þùj†mƈ›kõEEÅáæv#Lß´é›7ŸäêÕ(ÜÜœ¸v-ãí^-Z´—�;ÏrÕ/š À –öfîà3½EvùnØb~ûzŸ¬x�RÕhíýV†m;jJŸ±mîùžñ1 ¬ûe79s»ßs_Ù%Øz…,àgëÏ„†>¼`x�ކŽä'Ÿ½Ë»'ôŠ_Þ$>”›.OçgÊœ‹.zï£÷ÜÝÍ$$Ü&#"bñôtÁjµ2sæòåËÉÈ‘-ñôt&"âÞ7�ÉÈàÁ¿2~ü*._Žäĉ«´jU.Ók4ŠˆˆˆˆÈƒMa¢� ,H`` ÇŽc„ ,\¸ð¶íwìØÜXƒ00ðÆ¨£ °xñbþ÷¿ÿqíÚ5<==Ó\÷óÏ?3uêTªV­ŠÑhÄÙÙ™ºuë²jÕ*–,Y’a˜Ø®];-ZÄðáÃ5jÔ]?ç¡C7v¿-S¦LºAâõë×SÖ~Ì Í›7gþüùüþûï\¸p�üùó§isêÔ)þøã�”öò`ʑÅ�Ÿâ�71eÊ^}eËæ£mÛ äÍ›ƒðð’’,|óMFŒhI¾|9ùí·})k±e‡ªU óÆ qs3ãàÌUï(ª9ζûeVÍVå½I‘r72ƒÑÀäéoã�'í÷‹ÿš5j³F.»c;o7Æ,럹b³™ Û­Ûùź€?YE2JSŠ× ¯ÒÊÐ 3i§Ï?ÌÚw�Ä?_"oöÉK×–øræ%*U¿û`Ýb±rî\XÊîèyòxrèPƒ�ýû‡ãì|ãÇ}HHt¦wPÏŒ§Ÿ.K¹rùÈ�Ûƒ'žð%_¾ìûÿ-"""""ö¡01 DïÞ½Y´h}ûöe„ éNwÞ³gƒ  E‹øûûн{w†NXX}ûöå‡~ÀÑñŸi‹û÷ïgܸqôêÕ+åø›o¾ÉªU«3f 5kÖ¤Q£F©î·råJ–,Y‚ƒƒݺu»§g¼5�øäÉ“„……áíí�r.>>žÞ½{§¬[O÷‚;M�1‚sçÎѱcG~ÿýw¼¼þ™B§N�HLL¤H‘"´k×îžï)ÙËd22`@}~üq[¶œ¢mÛ *äƒÑh`ïÞóT®\(%`عó,E‹æÎ¶ZòçÏIãÆ%³­ÿ{U¹I)*7)ܘòl0Ì`c [Õk_‘–}ÓßnL—.úd~\=œïé>Y%„[3Ï:Ÿ‹\ÄwÚÚÑÅÐ…@ž°wyÙªfý~\|�WºùóbÇ||ôE0-ÚDÝU_¿þº—„„d4¸1z; ?ýôV«•B…n|�‹Käᅢ³uó¡:uŠÑäæ×´ˆˆˆˆˆ<š&fB¯^½Øºu+Ó§OgêÔ©ÌŸ?Ÿ¦M›R¬X1||| aÆ lÞ¼«ÕJ@@Ó¦MK¹ÞÛÛ›)S¦Ð­[7~þùgöîÝKûöíñððààÁƒÌ›7�„„jժŋ/¾˜r]óæÍéÓ§Ó¦Mã©§žâé§Ÿ¦fÍš888°sçN-ZDrr2C‡å‰'îíÅ÷ÓO?Í{ï½GXXUªT¡K—.øøøpîÜ9.\HPP¥J•âðáÃüöÛoäÍ›÷žLgggfÏžM³fÍØºu+Å‹§k×®,X�3gÎ0gÎBCCqwwgöìÙ)ëNʃcÞ¼�¬\y˜‰;âq3 ºx1‚'®¦l¬âééÌÓO—å“Oþ`Þ¼>� bÉ’}¬^ý¦=Ëäøò¡Ò Þ²Ûº›ÙÖ9¬f5I$QšRô1¼HKCK\p±wy÷M`©x~Z~Ž~Ýóñn¿<œ>éD­LîGtôh0ï¼³�Ž+Q¼ø� WZ´(Cÿþ?±téZµ*ÀwßmÆl6Q·î£ÒŠˆˆˆˆHöR˜˜ ƒ�©S§R½zuFŽÉ… ˜7o^švNNNôèу±cÇâãã“ê\çÎ�quuåÕW_åï¿ÿfôèÑ)çŒF#]ºtá믿ÆdJý©™2e  `ìØ±,[¶ŒeËþ™ÊèêêʰaÃ2$ýé‘™Q¶lY¾ùæÞ}÷]N�:•ª¾€€–.]Ê•+WèÙ³'[¶lÁ`0ÜóhÈ:uê°nÝ:^yåvíÚÅĉS�¯Zµ*S¦L¡B…û³û¨dNÑ¢¹Ù²å ¥F�"lÜxœ-Êн{õ”v'v¤^½O©Ys%JäaÉ’} ЀZµŠfê~Ç�_¡sçéœ9ŠÅb¥rå�˜9³'eËfnM= Vö'^àIÇ´Sìï'“‘Š�Jص†ìE4+¬ÿc¶u'8�3�hDCwÊÊÛ»<»ñ͓̿]``ß<|3Á›Ãû*S¯Ö’Û^³té~Nœ¸JPP{öœ§C‡JL�úÏîܾ¾|öYºtùŽ®]«›À‚»™;·7fsæ~ôÿðÃ6~üq;ññIŒ³‚™3·âããÆÏ?¿x‡«EDDDDäQc°Z­V{ñ0JNNfÓ¦Mlß¾�   âââðõõ¥téÒ4iÒ$ÕTÝô$%%±eË|)Íq'Z¶¼ñýÙb±²pánêÖ}?¿;¯ïyKÓ3ø|æŒL×d?V–ï›ÁÀ&ŸÙ»y̽Øóº÷|†œ^i—Û¹/óçªm|öå{—""0�L¼KÔ«W�zõ29í&“ÉDݺu©[·n¦®óðð uëÖ6µ½ÓÎÏîîîTªT)Ýsžžž®Oh0hÓ&õ®²9sæÌ°¯[Š)rÛóp£æìÚ±Ú–åî˜LF5*A£;Œ¬óôt¦{÷jéž‹ˆˆaР_3¼¶{÷jÔ®] ww³Më –/_àŽmÊ9æãº5žu Ç.iÓ5rg×¹Îrëræ1Ÿ#Ö#8âHCÒÁОê†êx0vÔ~�ü}ÈÌ_[�ÉéG�ÚK�ôÿ0S¿~ Í}V®\ˆÊ• ¥{nË–“,Y²?Ãk‡WW'J—ö§tiÿÛÞÇh4Сƒ¾¿Šˆˆˆˆ<&ŠÈÁÁÁH‘"o á‘�†Ôp*BAoŽ�²_˜w=žám¿eܯ¥97wÌ <¼\yæåÌýñ!9ÉÂÿflæÏ9;¸|&7'*7)E÷÷ŸÆÓÇ-«JOå4§ùÕú¿Xá×ðÃ�~†~t6tÂï;wð˜úû ™—:ùãèƒF­'>,ˆŒÂD‘‡•Å’ŒÑè`ï2DDDä)L‘‚‡‡3ƒ5µÛýó9äĘl´Ûý““,ì^ýwºç¼ü<Ù¿áx¦ÃÄÏúÎfí¼]4ê\…Z­ŸäZèu6ýº‡uów1e×P|òfÍãXËZ~±.`«u+FŒT3T£ƒ¡=�y ì÷q}=d¦w‡|�Vf,¸Èõ¨kœ ËþûÖ¬Yô®–‘ODD øú¦]ÊàÒ¥‹xzæÀÍ-í’7÷ÓÁƒ{yáÅöôìñ2ýû ´k-"""roô ODäg0Àõk±™º&:"†?fmã£%ýx{Z7:¼Õ˜Þµæ»Ã)úd~~üpù=×uÎzŽÏ¬ŸÓÈÒˆ·,osÜzœÞ†Þüa\ÁtÃ4šÒTAâ;üO�øÝ‚ ž(‘`ï’Dä!´fÍ Ú¶oDRRRªãaa!<ýL-Ž;l§ÊþavvÆÛ+9r¤]çû~»pñï¼û25k—¤jõbtéÖ’õþ¼«¾víÚF×îÏP¹j4ªÀ£‘¦ÝÚµðlÛ”¯X�gZÕaÅi7ÚšÿË�<Óª+æégj1óûÉX,– ï}îÜiÚ´kÈôï&ÝUí×®E2ô½×©^³8Õjòî ~DD†§iwáâ9Þzû%ª×,N¥*Eèݧ#‡g¼LFFûÉpj×-MåªEè? AARÕÓò™Ú¾]ºtñ®žSDD²žF&ŠˆÜÆ_ìÄÙj¦¬!k6ʬ+çÂX6mOÖ³}�<€ë‘q8˜Œ”ÿÏúzF#Í_¨É¢Ikïª+V"J]£Ÿ¥?Ø€+ xÏð�h„I?Vlvú„/>—�ädønA�%ãí]’ˆ<¤êÕkÂè�‡±k÷vªU­•r|óæuxyySþIû¯iúD±¬øß6{—Àøñ#)Q¢ ýú½ƒWN//ù…·Þ~‰¹³—R¼¸íKL;~„w÷ã��#©U³>W®\fÔï2ú£ÁŒ7%¥Ýþ»<ôU†MýzMزu=#FÄËË'åó5oþ,.ú‰�FO¤H‘@ÚÇ࡯âêêÊsÓn‚ÃÛû›nxi‹¡Ã^#66†_æ¯ÄÁèÀ¨ßeà;/3}ê¼”6áá¡ôz¡+Tå‡Y¿áîæÁŸ«—³oÿ.J•*—©û�Ÿ0’Ý{v0sÆB¼rzóùÄ�é7 ;¿Ì[‰££#®®n¼ÿÞØ4×Íýi ‰ øù¥¿�£ˆˆÜzÕ'"’ .Y/q‰K\¶^¦ž¡N8eé=f�ZƬ‘ËRÞohx9M›€2þt|»q¦úõ-èEžÂ>ßsžÀJS�»r>œ¢OæÏT¡–HVÆlcqÌz®¼†‡!ˆö´§›¡+Å(–©¾äF�ø|Ûü$$Àw¿Qª¬‚D¹{>>¹(ÿd%6lø3U˜¸aãŸÔ«×$Í:…›·¬cÇŽÍ$%%R®\%7jŽƒÃ?/ ‚ƒ/±yË:Ú¶é̹s§Y²tW¯S®\EÚµí’Òîô™“üñÇ.]ºHΜ^4¨ß”òå+§œ?qâ(7­IuïªUjRºtÚÍöNœ8ÊŸ«—z•ÀÀR´hþlª©ÙÛ·oÂÉl¦DñÒü²`6§N' pQ:uz³9së*11õ.ò={ôåÇÙÓØ·oW¦ÂÄÀ'J²ø×õ¸»ßØUÛÃÓ×^D¿ÝIJJÂdºñ1ýþû)4oÖšÖ­:мYköïßÍ÷³&§|¾ÚµíJëVqvv ZµÚtìÐ�5kV¤&~ðá Ka¸ËýÌŽ=Ä–­ëY¾l3yòäà£'Ò´yuöØM¹²˜ùýd|}ó0vÌWnÞ¬G÷—2}¿ˆˆ0ýú3ßM›ÏÅnlØ7|ø'4iZ…5kWдÉ3˜L&ªU«�꺽{wrôØæÎ^ŠÑ¨Ù"" }GÉ€#ÏZRÉP‘pÂS~‰ÎJÞjÌ÷GFòéê71 Œ˜ß'åíÃß^aò_C˜¾ï}räºóZW¡—"9¶ëÇv�ãøîó´}­!ã{ÿÀÑ�gSŽÞvš%“×ÓuH³;ögÅÊ®ø#Œ ŸF§à!L‹ú•œFwŠýP˜u†µŒ4ŒP�xNŸt¢W»üÄÇÃwóƒ(].ÎÞ%‰È# aÃflظ:åýÄÄD¶lÝ@Ãÿ¬GlµZöÞŒþhžž9É›7?S§}ÁÐa¯§êëbÐy¦Nû’?W/§g¯¶„„\!gN¯T#àÜC§ÎÍILL B…*8::1ìý×YºlaJ›˜Øë\¸p6åmæ÷ß°{ÏŽ4µÿúÛÏtíþ W®\ÆÏÏŸ…‹æÐ©ssBB®¤´Y·~?þ8�—ûuåâÅóx{û0sÖ”4µß�={ÿ"""Œ'ïbç­ ñ«ÕŠCª�ïÈߨW7õ4hšjª°ÉdJ ÿÍ�N€6gî Ž?°¡‘�pwËcùû ÅK¥‰¹rùR¶lyŽ9�rlíÚ?èÔ±ç=ÿtôØÜÝ=R}ŒÍNfjÖ¬ÏáÝïß’’’xø›¼ýÖûx{g¼IŸˆˆÜ™("r T¦2 p°fý”®Î,‘‡|Å|1 Ôëp÷SÑ–Mݘj”ã-¯T“æØwÃóîÌ´#¢-1ü»�E××p)9Wƒ3Í]kÑʵ.Å 0|ýw8?Ÿ}»k?ÊΜt¤WÛüÄÅÂôùA”~RA¢ˆd�† š1áÓ8}úÅRB»ªUþ©¸xÉ|¶mßÀüŸWâãs#œiÙ²­Z×eÏÞ¿¨P¾JJÛ°°«L›>‰Ÿæ,K8ݲqãŠy‚W J9örß71ÿ �Ê•­˜2 n„vÿr…±cßgл£h{sÔc�î/ѽgk¾˜4–G}–Òvßþ�|;ù'Š+@Éeywp?âãã2=:1::Љ_|ÌÙs§‰cÒßgjTbFæþ<“§Ÿn›2ÒÓb±põj0¹sû±}ÇfÞø£?œH¡BEˆŒŒ ..6Ýñúõh/ù…×¼›êøî=;˜6ýKfÍ\„««[º5,^2Ÿ3gN¦{îµWc0¸rå2¹sûðJÿnDGEñã‹ñÍ�‡ààKÄ'ÄsþÂY¼}rññØ÷X³ff³™zuÓ¿ß;)#G×®ýƒýv§{¿^Ï÷ÃÓ3W‚/á›ÛƒÁÀ£³mÛ~]´_ß<\¹y¿ÿZ¾üWœÌf5¼ó@EDäþR˜("rSbb2&GÇtÏ9�õAbªþMF^Ûæžúè<¨)m_khS[G§´Ïs,ñËb6²*vñÖD ™òÐÇ£ -]ëàat½§ÚΞr¤W»ÄÅ´yA”)Ÿ~�hr4‘””ñ‚û�«5ëGûŠ<®üýóS¢Di6l\M@@16n\MÝ:�prúgyŽåË¥H‘@vïÞžêZ?ß¼:´/U˜˜��Àˆ÷?I7H¨_ï)~œ}c¤`ÃúM©U«ùòÈtÝ[·nÀbµÐºuÇ”cNNN´mÓ‰¯¾Ÿªm©RåR‚D€bO”Àjµr5ä ùó¥^ÒãN ¹rùb±X¸t��›VS±R5ÌNæL?Ã- Îaÿþ],\ðÏQ‹Å‚ÅbÁÑÑ‘ää$¬+K2Ž7ßHLLL&Z­VF4„€€¢4oþlÊñ��+ ÜŸF}J¡BE2¬ÃÕÅ OÏÛot“˜˜ˆ£ã�¯�„øx¬X09:’˜˜ÜX—àËIŸÐû…þô{åmÂÃB>âmÆ�ɨ‘pvvÉð~·¦&'&&¤m~ÊñÐЫ”,Q¸J�FÞzcXÊZ†9sxÑï•·ygÐ+Œ1ƒÁ@�u©Q£îï Àè'b±X0�„††àëë—¦}HèUŽ;œjd­ˆˆ<8&ŠÈùûâôéÝõj¢¢âÀ`ÎÔ_¿Ïr–?­«©c¨“�•Ý»È�hb®¥¯.¹‡°Î¼‹Õ±;ˆµÆ“ßäK�6´p­Eã�×gÛ�;}#H¼idÊÜ ÊU¼ýÔf¿¼~œ<ŽÅbM5]ðQ³aÃqÊT¨`ï2D)�6gÚô/9vüAA¨U³~ªóò"9ÙÂøO&gÉýråò¥÷ ýéýBbb®3ñË1¼5ð%֯ݗfÓ—Œäó/@XXaäÌé�rüä©cäÍ›/à 1+¹ººQ½zvݦ_¾ˆ±Ÿ çóO§¥»Ãqá€bìÚ½�5ê¦üž±k÷ö4a­Åbaì'ï³ã¯-L�ò9r¤íתUêþgíÅ‹ÎáᙃêÕ꤅z'…‹rôèa®_�N™®Ë¡CûèÞ­pc„hÑ"�œ:}<ÕÆ(Nf3111X,É6~ #øÊ%.\à›¯¤råé¶iûl'ý:—sçNpéÒE~úy&mží”Ò&!!�ÁC°ÿÀnfLÿ_ßQ’'�Òä©–´móÏ1?Ÿø+W-ÃÃÓgZ×åúõè”s~ð9Ï´l—OÿŸŒùš×Þèņ�«1 \‹Šä‹Ïg¤¬mЮmNŸ>A»OQ¢D.]º€Ÿo^&Œÿ6Ó÷ü`ä§ôëß�-kã陃  óŒýø«TÓÂo¹rå2Þ^>÷ôŒ""’} Ö[?ñDDnÃb±ðu”áÑ/ßíö~„†^gì¸5œ:ká½q£1›ï~ÑõcG޳pÅ ^{çuŠ2Ã’laPóItÔ”Š�JØ|]È•:õ“SÙ›t «ÅJ%—’´t­Í±ÑçðñÍaóf-ÿ5¼Åw|;sæ]]û¸¸tÑÄómòrÕ�ɳƒ¨ZËö ñ–k‘×xÿõwxªa>ú÷«…›ÛÝ}>(Ž fðÐå”,_›n/õ²w9wÁÊò}3Øä³;7ÉF/öü„î=Ÿ!§—Gšs11× Å7wž §½Æ'ÄsêÔq"#Â)\¸HšMVââ¹z5˜|þn;2ÌbIæØ±¿¹z5˜œ^^>Qò¶»*_ÂÍÍw÷´u[,Éœ!ž}ûvaµX(_¾r†Ÿ¿ËÁAœ8q?¿¼+Zü®G &''±ÿÀbb®ód¹Jé~-À��‡ÅjMõù–ûãâ…`þ\µ�Ͼ`ïRD䦑‰"b£ÑÈ„ “ؾ}ƒ�#4ôNNFÌæ¬ÿ6’lI".)'‡¬ÙØä¿“ˆ�·àäâÁ³�:Ñë­Úw¾ÈNŒFjµz’ÿÍØbS˜’ÁªØí,J^ƒå+',çiãÖ€¿ÚbÔ‚¾¸:;ãZÇ…ŸÇýq×a¢ÜÞå Ï·½$~óã݉ž9<™8s +—þ�¶æaIŽÇÅÙ„ƒéá[¡$>!‰¸Ø$üòàÅ·Þ# X€½Kyd¹ººe<Ýbv2§l²‘Ñy[vG6(Q¢4%J”¶©6?¿¼·íë‰bÿœû÷zŠ·˜L¦Lïâ|KŽ93µQLzÜÜÜÓL%¿� S @átÏy{ç"íÞ™�Ͻ­gmv2SÕ†�C?òø¥Ý¤'³L©v ÏÈÃdy°(L‘L©V­:Õª-ºsÃ{p>ì$«ÿþ�ªE›eë}²ÛåäPÜ .¸mŸ6–žS.Þö¼+»ãÿfYÌ&6Åí! �ŽIø ‘1/¼J©ò|]j>«çîà™—ë|ížê‘Œ_º$;ðõ�AT«}wAâ-ƒ�¦­ZдU‹,ªPD/eï2DänïDä! 0QD$$[-lŽÛG2ÉÔ4—#¿Éï¶íãcùú�ù©ûHJæÂñ+Üt’áó^LsM¸å+b¶²,f#—’Cp58ÓܵϺ֧ˆc>~Èõ;¿OÚH©ïhÖ«&¯×™ÀŽ‡Ø·þ8Ï�ÊüŒr{·‚Äà _Ì ¢z�{ ED2R´˜?³w"òˆ*R$ãQÄ"" 0QD$[8Œ4t®ÌÆø=l‰ßOk‡ú˜ Ž_`µžv­¤Â¥ýé2¸ÕZü3íXâ9^_ÍÚØ�$‘L cA:»w¥±KUœ ÿ¬«×ñíÆ$%ÞØ1±è“ùùð·WX¿`7}ǵ¥Å‹µ²îa…Ы¼Ø1—.˜øbæ%ê6JÝ+‘¬0äýîö.ADDDc ED²‰—ƒ'Í]jn�º}�˜]�1¿O†ç¯[cY»“_¯¯åtRNGj9—§¥km*™K¦{�ó6ì¨Ð°8ÏüƒÈm…^u W»üœ?ãÈ3.Q¯ñu{—$"""""’m&Šˆd#Gƒ _CævXLJHâꅜݜ¸êÁ²˜�ü»ƒ8k<ùM~ôñhÃÓ®µñ4Þ~�ýŒÄÇ&GÎÜéï (¶ ¹$ž;íÈÄï.Qï)‰"""""òhS˜("ò€HJHbú°Å,�¹�؆ñÐ(8Pûæ(ÄŠæ0ØÔ_û¼ï2ãà<}R‡ŽË¾Ý@Щ^ýò¹lxŠÇÇ¿ƒÄϧ_¢~‰"""""òè3Ú»‘ÇQ”%†õq»‰³Æ§ûhäL–åÚˆu·¾€%Ü X™ç:N ˆëH%sI›ƒD€èˆX¬Vkšã…Kûsú`P–<Çã*,ÔÄ íósæ”#ŸM»Dƒ¦ EDDDDäñ ‘‰""vb‰àbÒ–$…a2Ys}'‡_=…Õ�ËÒʵ.UÌ¥1ô40ê÷i,þf=/|Ø*Kî鄌b›°P½Ûûsú¤#ŸM½DÃf EDDDDäñ¡0QDÄLþ89›x+ôs®ZÂ1Z�¸Ïraú»ïãëà�ªmå&%ùkÅ!›ú�¸Å•sáX,VN{NW’“¹|&”ï‡/¡N»ŠYû@�‰k‘¼Ü9/'�91öë`5W�("""""�…‰""v’ÏäËä܃ù$bÅæzþ8BÁ7u»“û.àWÈǦ>wÿù7“. :<†¤„$6ž˜ê¼ÙÕ‰ºí*Ðý½æYõ��¨H^ìèÏ߇̌ý*˜ÏFÙ»$‘ûNa¢ˆˆys0ÖûU~Ž^Éô†¿Ñ;øCœ}Ž&eªv�U³·ó¿ï6óÍŽ!6õ×°sv®ÀÓ¯3uÏ{)°88qõtζgy”EE:ðâsþü}ÐÌÇ_Ó¢�‚Dy<)L±3:»7¥p|^F:Nåóœsøü�9ð5äôõ`ØÜÞ”ñÏt¿f'Üsºàáåš U?>¢®9Ч“?G˜ùè‹+´l§ QDDDDD_ÚÍYDäQçóÇPÊP†A٣ŘvjµŸ-WýMøó�”õåîD]s ÏsþÞofôÄ+<Óþš½K±+…‰""�œF¾È?�žî-9èq’7c>çTâÅ»ê«H¹|8˜ômþnEGy©“?‡ö9óáçWhÕAA¢ˆˆˆˆˆˆ^eŠˆ<b£ã×k1Qq8`¤§GKF{÷#ÒM¿Ð±ü³ÉÞ%>VbcŒôïîÏ�=μ?ö ­;*H…‰""„3‡‚X¿`7.îæ”c5Ìe™–kÅLùù4r6c"foM°c•�‡Ø#¯tÍË®í.¼?ö*{DÚ»$‘†ÂD‘€§�;‰ É$'YR÷uðæsŸ·iëÖ�U±Ûy9d g“.Ù©ÊG_\¬‘Wºù³s›+ÃÆ\幞ö.IDDDDDä�¢0QDä�¯Xn+`åÛÒœs4˜àÙ‘Q^} IŽ È'¬�Ýi‡*m)AâV†�¹Jçç$Šˆˆˆˆˆü—ÂD‘ÄÐÙ/ð˧«X¿`wºçë8Wà›\ƒÉãàÇÓù,rIÖ¤û\å£).ÖH¿îþüµÅ…¡]Q�("""""’“½ ˆ»Ïç/Ï%1!™Q¦âáåšê|Û×ÒsDK ˜üø:×`¾º6�e19žxŽá^}Èë�ËN•?üââŒôïáÏŽÍ. }…./h�D‘Œ(LÉX­w½ÉÉDË—jgx¾@‰<)ÿ6y;G7Ê:ãóȹ¼2†¡9{QÕ\æî xL%$x³w^¶mtá­÷BèÚ[A¢ˆˆˆˆˆÈí(LÉžÄDÆÝõõ&Gêu¨”©kš¸T§ˆ)£"¦2$ìkÚ¸5àÏö8d÷ ÖGc…ŒÄDo¼�— «]ysX½„Û»$‘Þ£ñŠPDÄÎ|rûpåüý£Š9àÛ\èë\‘E××00t"¡–ì]——ˆƒÁ!Ûú¿_ ¼þB^ÖÿéÆCCxñU‰""""""¶P˜("’!É�¸ëñ÷ýÞ®gFxõá­]9”xŠ>WG³+þH¶ÜëÀ¦”-ÿd¶ô}¿$&xóż¬_åÆkƒCéóš‚D[)LÉ"Mš5ãÏþ²Ûý[ºÖa’Ï@œ N ›Ä¬¨eX¹‡…Ó±|òvžy¶u–öy?Ý ×þáÆ«ƒBéûF˜½Ky¨(LÉ"-Û¶båŒ�D†DÛ­†âŽ…™œk•Í%™½Œaaße¹ž%}ïúóo<œ|È_(–ôw¿%%xû¥›A⻡¼ü¦‚D‘ÌR˜("’Eœ�Í 6ˆ‘Ï~GTxŒÝêÈatgŒ÷úx´aGü!ú„Œæpâé{êóØ®sÌxçw�’EUÞ_ÉɆ¼êÇêÿ¹Ñ`(/¿¥ QDDDDDän(LÉBUjTá¥WúóVí/ø}Ú&Â._³K tvoÊŸ7H²&ózÈx~Šþ#S}X’-œ?ÌŒ¡KùâÅLœú9½rfSÅÙ'9ÙÀà~,ÿ̓ú…Óo ‚D‘»e²w""�šú�ëSªL)æ~?‡á“¿ãÒ…`’“ìV�ÕÇŠa¼�iÕeæ¯KqfÆe¸ãuÎnÎ*R€&-šóö’qrrºÕf­[#—ÿêA¯~á¼=<ÄÞ%‰ˆˆˆˆˆ<Ô&Šˆdß<¾¼1øMÞü¦½K ™d¦X¿eJã)ø<•›ÏùŒ@C ½ËÊVÉɆ¾æÇï‹äËâùžtïÁ $Šˆˆˆˆˆd%…‰""�!'œb†‰\!˜Î–.üϺÂÞeÝ“[Aâ/?æ C÷H‰""""""Ù@a¢ˆÈc¬±¡1?&þ ´d¤u‰$Ú»¬L³Zaô�ÜÌÿ!í»E2bÜ wÞ°ZDDDDDD2Ia¢ˆÈc.€Âüdü™ö†vübý…®–n\ࢽ˲™Õ  ÉÍÏßç¤]‰""""""ÙIa¢ˆˆàŒ™Q†Q|lø˜“œä9Ësl`ƒ½Ëº#«>êËOßç¤mçHFN¸‚Q?ÙDDDDDD²�^r‰ˆHŠÖ†VÌ1ÌÆÓàI?KÆXÇ�D’½ËJ—Õ óå§™9hÓé£>U�("""""’Ýô²KDDR)a(Á/†ù4¡ ³­sxÑò"Wyð63ù|t.æÎÈÁ³Ï]ãƒÏ‚$ŠˆˆˆˆˆÜzé%""i¸ãÎgÆOiÁ^öÑÖÒŽ­Ö­ö.+Åg£sñÝ×^4oÅŸiD¢ˆˆˆˆˆÈý¢—_""’¡†Ì6þˆ .ôµöåkë7X°Øµ¦Ï?ÊÅw_yѬUŸ|ŒƒƒÕ®õˆˆˆˆˆˆ}777êׯOžù„B… ¥ê¿Aƒøûû§¼Ÿ7o^¶lÙÂÒ¥K9wî=zô B… ´n݃Á�ý,""""""=…‰""väëëK·nÝnÛÆd2ѤIš4i’a›Æ�§9@@@@ªctéÒ%Õ±¶mÛf¢byœiÍD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD‘› ƒ½Kx,ÐÇYDDDDDäa¥0QDä&ggbbbì]Æ#-::7{—!""""""wIa¢ˆÈM9¼spñâE{—ñH»té9¼rØ» ¹K EDn*X˜#GŽoïRIIIIì?°ŸÂÅ Û»¹K EDn ,ó&V¯^mïRI›6m"..Ž’åKÚ»¹K EDnrtr¤V“Z¬^½šÃ‡Û»œGÊ©S§Xöû2ª7¬Ž«ÖLyh)Lù—’åKP¾Fyf̘Áúõë±X,ö.é¡fµZÙ¾};“'O¦D¹âT¨QÞÞ%‰ˆˆˆˆˆÈ=0Ù»‘M�¦µq÷tgÙ²elÙ²…ªU«R¸pa<==1õ7˜;±X,DGGsöìYþÚùÁÁÁT­W•*u+Û»4¹G EDÒQ¡Fyž(]ŒÝ[ö°qóF–-[fï’:9<(R<€&ž"‡·vpy(LÉ€»§;u›Õ¡n³:$&${=ÖÞ%=4Ì.Θ��ì]†ˆˆˆˆˆˆd1…‰""6ptrÄÑÉÑÞeˆˆˆˆˆˆˆØ•ÿ›(L›(L›(L›(L›(L›(L›(L›(L›(L›˜ì]€ˆHz®ÇGrúêA{—!"""""""ÿ¢0QD8ž.^”ô¯hï2DDÒ¨ð”½K±+ƒÕjµÚ»yðiÍD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD±‰ÂD‘ÿ³wßñ5žÿÇ_çädÇH"[(jUj�ª]TkT¿FQ´º´ÕV«»U(-­ÝÚªh©­Ô¬]"v‚ ‚È�Èο?Ò¦¿4A�äïçã‘ǃû¾îëúœÓÊ}Îç¾®ë#""""""""¹¢d¢ˆˆˆˆˆˆˆˆˆäŠ’‰"""""""""’+J&ŠˆˆˆˆˆˆˆˆH®(™("""""""""¹¢d¢ˆˆˆˆˆˆˆˆˆäŠ’‰"""""""""’+J&ŠˆˆˆˆˆˆˆˆH®(™("""""""""¹¢d¢ˆˆˆˆˆˆˆˆˆäŠ’‰"""""""""’+J&ŠˆˆˆˆˆˆˆˆH®(™("""""""""¹¢d¢ˆˆˆˆˆˆˆˆˆäŠ’‰"""""""""’+J&ŠˆˆˆˆˆˆˆˆH®(™("""""""""¹¢d¢ˆˆˆˆˆˆˆˆˆäŠ’‰"""""""""’+J&ŠˆˆˆˆˆˆˆˆH®(™("""""""""¹¢W­˜� IDATd¢ˆˆˆˆˆˆˆˆˆäŠ’‰"""""""""’+J&ŠˆˆˆˆˆˆˆˆH®(™("""""""""¹¢d¢ˆˆˆˆˆˆˆˆˆäŠ’‰"""""""""’+J&ŠˆˆˆˆˆˆˆˆH®(™("""""""""¹¢d¢ˆˆˆˆˆˆˆˆˆäŠ’‰"""""""""’+J&ŠˆˆˆˆˆˆˆˆH®˜ìÀÿ—––Fbb¢½Ã¸i&“‰B… Ù; ‘|e÷dâáÇ;ú3.œ;‡“ƒg''{‡tK®&%atr¦ûÓÿ£O¿~888Ø;$‘_Ÿ cøœE,[³{‡#""""""""’'ì’L¼té{vç·÷ßÂ`0ôðbÑæm„9yðæ;ïØ;‘[?T‡É¯¾H‹Ú5ó5v€C§Ï0rÆ,%EDDDDDDDäžg÷dbÿ/¿¦¤—'›Æ�Óß³ _~¢3q‰I·Ü§“ÉÄ�NíoØ.*.ïÂ…0\gÉ´Åj%*.Ÿ¢Er\Z›�pËqŠˆˆˆˆˆˆˆˆÜMìšL<v†M‚ùcÜ癉DG“‰bE ßT_¿lÛÁÀ¯Æg9ö~ß^ {òñ,ÇÌ cý˜EK0[,X­6žnÕ‚ñ/ÆÙÑ1ãºæbµY©[¹/LøŽ‹1±õpç‡7_åñ& =“~]Á•„D’SSñêÒ3sŒ¾mZ1þ…Á7¿ˆˆˆˆˆˆˆˆÈ�ήÉć�arp q�j·ÝWëzµÙ;yBæß;½óÉ©iÙÚ½ÿÃ\~Þ¼��cGS³B9ÎGEÓiäGŒž¿ˆûý€äÔTæmØDHx»¿ûÏB¼øÍ÷ 7‘N�ÆÁhdðcíéÙ²ó7lbÊo«Ù<þ‹Ì1 ¹ºÞöë¹Óí9xlB>E‹àx�b*¹åáêJ…’¾™?ÎNŽÙÚDDÇðåÂÅL~õjV(@ébÞ|üLo~X½>KÛÒżYøÞ[”)«+¯vëJä•+œ�ŠÀ»p!*”ô¥X‘Â8š²ŒíS´Èm¿‘;�]g&vsãò•8Ì &‡|ïàÉÓX¬V†Ož�ƒñßž‹“_ ˆg!�,ç Ã-%4�#6[ž„'""""""""rG³ë2纕+R¯J%Þ›9³Å’yÜf³±÷xH¶ö…ÝÝHLI½¥ñêW­LwwŽœ9K½*•²üÔ­\ñ–úô)Z„ËWâH3›oéz‘»…]g&üðæ«´|m͇½ÅÀmpqrbÖÚ œºp‘C3¿Ë¬° PÍ¿ Þ… 1|òtz?úÇÎ�£»ÖYÚ\�»‹ ^Âóã'MÛúõ0[,¬ß»ŸÒżyåÉ.7‹Z5198ðܸ‰<ÓîQRÒÒˆOL¢[ó&7Ý—ˆˆˆˆˆˆˆˆÈ�Ì®3jV(Ç�i©_µ “—¯fÂ’e*š×¿ŸÆöCG¸’�˜c¿­ëÕ¡š™lÇûµmź/?åbL,#¦þÀW —àâäD¯VÍ3Û)‰a“¦òåÂ%œ�¼|«o‡ˆˆˆˆˆˆˆˆÈË`³üŽ�mÅo#_/èa ÜØ¥Ë©ûDOZ¶liïPDDDDDDDDDn›Ýg&ŠˆˆˆˆˆˆˆˆÈÝAÉDÉ%óA¬1�ޥư®é^N¸œÀF�¯$ÉsÚ31Ÿœv¼D­/rÕ# Oƒ']:ÒÙ¥3m�ÛRØPØÞá‰ÜÑb#Ù²;üz¹.WGwÚÖèiï0äp6&„ýg·é^'"wŸB¥h\©�½Ã‘;˜ÉÞܫʧ—`ðÂŽ|7p±Ä27y.s“çbÂÄÃNÓɹ�]:SÍTÍÞ¡ŠÜqS¯wŽßºöED$‹¿ÎlT2QòDtÂ%b“bð÷°w(""™’Ò9~1HÉD¹.%óQÉH/>ÿ˜wüß!Ý–€3ÛÓ¶³=m;#®Ž ª©*�;ÒÁ¥M�šâˆ£�£¹3¸:ºã[´¼½ÃùlpÆÞ1ȽÄÝ¥¨îu"rG¹šCd\˜½Ã‘;œöLÌgõë1»ÈlŒÿy«pàÓÔw¬OSJK`RnWDDDDDDDDî`Ê^€§\ŸâœõoÆ¿ €‡Áƒó%ÎkïD¹«ÜUÉÄ�GޱhÓVÂ/GQ¥Li†vyŒRÞ^7ÕÇwËVr5)9ÛñF5ªÑ´fu„žbíž¿2Ϲ»:S?  W»õ=mÞpƒKãÇ“`K ÂAaSaÂ,a\²\"Ð)†[î_DDDDDDDD$¿Ý5ËœGLû�æÃÞ"*.žºU*qèôê z‰¨¸ø›êçld$§.\`ý¾ýŒœ1‹S.pêÂbâ¯f¶Ùyô£æ-$6á*—ãâøóÐQÚ½õíÞz³År˯a\áqôví ÀŸi”Äïi¿óCò\¶^¾å¾EDDDDDDDDòÛ]13qÉ–í|µp ÆŽ¦E횙LJ�¡X‘›[*üù þ,ܸ…퇎0åµ—rlWÄÝ=³-À© ©Úo˶ïäÉf�oáU€3ŠÌà¢õ";Òw0€tqéBs6¤nÀ­'*EDDDDDDDDòÛ]13ñëſҭy“,‰D€êåÊX JúâçãÍɈ ·Õ�“Á‰%žKH²%e«iªÉ n/àkô½Ý0EDDDDDDDDòÍŸLL3›Ùuô8mªk×8"¢c89š %o?áWØP˜¯ }•e&¢£Áñ¶ûÉOwü2ç+ ˜-Ê/V ã&¦¤0uÅ.DÇ0{ݫХqƒ<é¿”C©\µ 1‡�hK¤¶cí<WDDDDDDDDäVÝñÉDWW"cã tÜ”´4~ß·Ÿ¢Eød@z¶l†ƒ±`'sþeþ‹Ps(Áæ`sy Oƒg�Ž/""·ïj|q±W0 ø”ðÁÉÉÉÞ!ÝS"Â#°Ùl”.SÚÞ¡ˆˆÈ߉�ŽƒŸÅpvv¶wH""’Gîød¢›³3UüJ³ûØqz·nY`ãz.Ì¢Þ.°ñ®¥»Kwö¦íe[ú6,6 쑈ˆäF|\<³&Ïbõ²5œ9u&ó¸ƒÉ�j>@·ÞÝèúTWîøG Ìì©s8rо|ƒ!w7¼°“a<Ö¤ÍmÆws&ås„""r=‰ ‰Ì™:‡•¿¬âtèil6Fª<À½ºÒ£OLŽwü×Ð|v2ŒÍë7�Á` l…²´hÓ‚’¥KÚ;4‘\¹+~‹?ÓîQ>�³�á=ŸÄ¿¸Oæñ3—")SÜc.¿pÜ�Œ t ¤ŽSѾŠ""wƒC1´Ï D_ŽÀäh»˜7ñqñ$'%¼?˜àýÁ¬X²‚ïæLÂÍÝÍÎÛ_Ü•8&~9‘Ä„D>øòý\_·dÞl6Ý{wËÇèDDäFBŽ…ðÜÓÏs1â"�ñð¬˜�7 WILHähðQFeùÏ¿1eÁdŠ-bçˆ ^ZZ£ÞÅÒ¿`µZ³œýîhžð4o|ð&;E("’;wE2ñµî]Yþç.š¾üï÷}š€2¥ù+ä$ïΜ͢÷ߦ]`½\÷µbÇn’ÓÒØuô«•Ÿ7o šj”ÏÃêÐfsÞõJ$ŠØ‘Õb%)1«ÅrãÆ‚ÑÁˆ«»+÷çá¸+q¼Øï%¢/GS) ¯ŽFÓVÍ2g ^Œ¸ÈÜésùñûYìùsŸ¾=ŠÏ¾eç¨í+%9…‘¯¼KbBâM]—žžÎ¯‹–Q¢dqšµj–OщÜÌf3ɉɨ¬6{‡rW0:qópÇh¼w'5ÜŒä¤d^ìû"#.â_ÞŸ×F¾J‹¶-ptÌøsùÒe~š½ˆ©ã§¼?˜w‡½Ç·?~cç¨ Þ;/½Ãêek09šèÕ¿µë×&þJ<ëV¬c×¶]Ì™6sº™w?×Þ¡Šˆ\×]‘LtvtdÃØÏøjá&,]Fdìªø•föˆ×o*‘0oÃDÅÅмV ¦®X ÀÿZµÌL&ú+F“šÜvÜí×mÀ+ø8;C£F·Ý_NŽš�PÍT-_ú¹_Ùl6Ž<ÎÑÇ8æ<³‰7Ãh4PÊ¿4UkW¥Zíj÷Õ—­e‹–sùÒe\\œ™¾h>%|²œ÷-åËð÷‡ãææÆ¤1ßñÛâßxyÄKø–òµSÄö´/ˆóç"ÞÌÚåk¸t!ò¦ûظf#1Q1<÷êÍ⹋…C{q<èÏ_Ì\’*¹c2™(S¡ 5ªN…ªìŽ]­^¶†ð³çq090uÁÊ”+“å¼O ^|ã )ÌïÁÆ5 =J¥€JvЏàíܺ“ÕË2 |Nœõ-Mišyî©gzòõ¨ñLÿv:?Í^Äÿõ¦|ÅrvŠTDäÆîŠd"dì�øA¿§ù ßÓ9ž?zæI©©9ž+êáNÅRûO,x÷­ŽõXÃ@kxëÁ˜Lìª_�>óaiÜC­Z^{ C·nà–wËÙv¥íâ¼õ<•*ÑÞ¹=…�…ó¬o‘ûUü•xVý´š¨KQÔ«[�VÍZá㣢¹•žžNTTGŽaÓŠMìÿs?{uÄÓ»¨½C+Áûƒ¨õPíl‰Äÿï™çŸaÆÄ¤¤¤²kÛ.ºôèrÝ~-ë-ï¯hµZ1æQ1«ÕŠÁ`Èõž†×Šã£7?æøáã·Ë⹋1�<ñô·Õ�Èý(2"’• W‘–’ÆÃ?L§�ðòòÂdºk¾ØUjj*/^$88˜• WQº\iÚuo‡›»«½C³‹C2î}Õ²%ÿ¿^ýŸâû±ßÏŽ-;o˜L¼Sî}6› ›ÍvKýý“¤_¹t%��³$ÿñò[/±üçåD^ŒdÛÆmJ&ŠÈížù´ðüøI}04irÛcôuëË®ô]ìHÛ�Í §É"·+6*–Å3–Pܧ8ï¼ý^^^öé®äëëK�5hÛ¶-óçÏgÑÔE<ñLW|J^;¹v¯HOO ájÂuÛ¹¹»ñÊ;ÃˆŠŒ¢”_©lçm6+–¬dÑœE>p˜´´4Šûúмu ¾8?ÿ¬•‹gLœÁŽ-;é÷\_š>Ò”e‹–3{êlN�8Å«ï¾Ê–ß·0jÂ(J”,žcLŸŒø„3§ÎòT¿ž<ÚñÑÌãI‰IÌš<‹•¿¬âlØYŒ#~eýèÔ­ý†ôÅÅÕ%K?¯>ûWã¯òå÷_âææÊÔ SY¶h91Q1ì?û}õ&&*&óš˜èX~üþÇë¾gÿ_øÙóìܺ‹Í¨Š³ÈM ?β9Ë©^½:=zôÀ-tßOJ•*Eݺu¹xñ"³fýÈ¢©‹è1¨;n÷ßû™žö÷½/!›ÍvÍNŽŽŽ¼òö+D„GP®bÎ[L­_±ž?.$hïRRRñ)áC“–MøÒÀl ¶?,`Ãê�tïÓ�¶�Ú²nÅ:fLœIÈÑ^|ëEþÜô'#G�¼frnÌÇc8vè8�ºu¢K�ΙÇSRR™7}.¿-^Áé“ß3K—)M‡®xæ¹~xòÈÒÏÈWÞåÒ…K|8æCJ”,ÎŒ‰3Y:)#.°;t7Ç�œà‘v�䇃É�rËy1’Ë—.çØFDäNqÏ$7}ý¹½CÈÑ¥¨j0`û꫌qqئNÅ6u*T«†±_? Ï<%JÜRÿFŒ4tlH=Çz8¡YS"·Ãœnæ·ù+(U²C† ÑìŒÀúë9t˜¾û‘~Ïõ½æL†¾ƒûäx<55•áCÞ`ãš�õ,JQ¯¢D^ŒdÑìE¬Y¶†I³'R÷ẙׄeÇ–´ëÒŽñŸM`Ú7Ó2ÏUªR‘éßN'úr4ëV¬£Ï ÞÙÆŒŠŒbÑ쟱Ùl|4öÃÌãçÂÎ1è©Áœ ;‡Á` ¸oqRSR9zšo>ÿ†µ¿­eæâõüwæéÞ�{‰‰Š!þJ/÷™ý»÷d©ÞÙõ©®YÆ?}2즒‰Kæ-ÆjµªðŠÈMJˆO`åO«¨W¯={ö¼¥YÆ’•¯¯/ƽʄo&°rá*º |ò¾{_ªWàìé³LüjC_{þšÛO<õLÏ�›ÓÍŒö.+–¬ p‘Âõò$òb$¿,ü…µ¿­eüô¯iܲqæ5§CÃØ±e�[4fƤ™Œûd\æ¹2þ~„Ÿ ç\Ø9Vÿ²Š¡Ã‡f3ájó¦Ï'--�7>žyüÒ…H?5˜Ðã¡”(Yœô´tΜ:Ã÷c¿gͯ«™¹d&Å}ÿ}8w`ïÂN†q5.ž�Þü(3‘ù�ªÕ(\¤0T¹æû@Ïû¯8�ˆÜ]òfÞ·\—qôh �äðêèQ¬#F`)Sk×®Ø6mºå1”H¹}A»‚HMJ¥ÿþJ$æ!£ÑHŸÞ}°Ù`ßö¿ìN¾ëÑ·Gæòæ1�¡C£ŽŒùx ;¶ìÈu�‘ÏßËØOª”_)¦/šÆö£Ûظkv­¡Qó†ÄÇÅ3ìÙW‰»—íÚ¿vícú·Ó)S® ¯ŽÆws¿£zíêt|¢#k–¯ÉqÌßWmÀjµRïáz™3ýR’SÚçÎ…�£AÓ¬Ùµ†�û7°ýè6¦/šFé2¥9~ø8ï¼<2Ç>§N˜ÆþÝû lÈû_¼Ï÷s¿ÏÕë¿‹ÙÂ/ ÅÛÇ›–m[æIŸ"÷‹vP´HQºuëvß%¼ò“³³3 äRÄ%ŽÝÞw£.=ºàWÖ€Éã&Ó®A{>ïs¶mÜÆÕøëÏÔÿÇ„ÑX±d>%|˜4{"ÛΆ¿~ç÷}ëy¤Ý#$%&ñúsÃsÜc÷ø‘cL=ßR¾¼ôæ‹|7gõÔ£s·N¬Y¾6Ç17¯ßLZZU¨B@õ c…ÁKϼDèñPjׯ͊í+ظ#[oeîò9”¯XŽÓ'Ã>ä�÷�3m.nú“:�uxwôH¦.˜‚£“�û˜é‹¦Ø8çí´ŽåthÆ È‡Ü\]‘‚¦dbAppÀ8>”,™õxíÚ§LÁ¸aÆÉ“1´h‘çC§sÒr2Ïû¹×Øl6ì ¢E‹Z��iýhkî>ˆÕbµw8ùÊ«˜s–ͦqËÆ Î…�ã‡ï~äÙƒhÐ�'íÆØ�DzçÏ=9~ 9q4„ŸçüŒ³³3SN¡a³†™çüüKóýÜï©V³Ñ—£™3mn¶ë—-ZN£�X¶ùWž}éYš?ÚŒ"E‹ðøß{2í âbÄÅl×­[±€NÝ;e[øãBN…œ¢JµÊLžÿ}–¥Õ ›5dú¢i¸¸º°yýfì Ê!–e¼:r?,™IÏ~=hÔ¼a¶6·bÓúM\¾t™Ç{tɬ*"7–’œÂ± ã´o×^Íò�··7 4$hWö߇÷ºB…=˜ýë,Z¶m‰Ñh$"<‚9Óæ2äéçhTµ�·èÊ|ÉŸ›w`µfÿ~ö<³¦ÎÆÁäÀ¤9“hѦEf²»DÉL˜9ž‡<ÄÕ¸«üðÝÌl×ÿ¶xµêÕâ·­ËyîµçhÞº9^żèÜ£ ƒ�“'Nr,$ÛuëV® K÷—7/[´œÃA‡ñ+ëÇŒEÓ³,�®X‡‹gR¨H!öíÚǶ?¶eësÙ¢e |q s—Ï¡Wÿ^4nÙø†û>FEF1âÅ·±ÙlÔoTŸZõj]·½ˆˆ½)™XPJ”À¸`üóÁ­re8pÛ”)J–¼åeÎ×cÃÆŽô,L^ȯ)¿’dKÊó1DîÑ—¢IˆO víÚöåžU«V-ÒRÓˆ8wÁÞ¡ä»2åÊ0uÁ–n\Ê�aƒ©ýP-LX,VŽ:ÆÌï~à™'úÓ¹Yvoß�åÚå?/Ãf³Ñú±Ö”¯T>[ß&GC^ Àê_Wg;ïèèȨñŸâìœu9y@õªÖ¨ŠÍfcífhÄDDzwç^\\œiÛ©mæñe?/ ÿÐ9&íüËûóØ“�ý˪lçkÔ®ÁÀæøÝŽÅs—`0xòOæyß"÷²3¡g1™LT«VÍޡܳj×®MdD$I ÷ßçî%K0qÖ·,ߺœ¡Ã‡R÷áº8::bµZ 9Âì)³Ôsudˆ-Y®]±d³…&-›PýÁ²õm4yîµ!@Æ,Ãÿ>Œ3�Œÿ)nîYûù—Μå÷ßÙ‰ÉIÉlÛ¸ #ºvÈ<¾lÑ2€÷Îx�Åéþ¿Œ-6rº—¯TžWÞ~%ç7)G‚�ðTû^„¥L¹2|>qt®¯±=’,@†æÍ1~ò ַ߯P¬†wßÅ:t(–zõ0N™‚á©§òv< ôwíÏÖ´­4Ć ´ˆ\Ë•è+˜MøøÜûBì¥P¡Bxò .&¿r÷GÁŒ*Õ*S¥Ze cFÐá ÃìÚ¶‹õ+×sâh§BNñlÏA|ûã·4´@æ ¿+±W˜1qFŽý^‰¹@ØÉ0âãâ)\¤pæ¹Zõj]³Št—]8vèk–¯¥ßsý2�o\³‹ÙB›Ž­)T8cCù¤Ä$BŽfÌâ8tˆË—²/+2‹¨ü+8Û¹G;´Êóe”#.²}Ó6ê7ªOÙ 9oÞ/"9‹‹‰Ã§¸�fôæ£R¥Ja³Ùˆ‹‰»/ ±”¯Xކå…áCIMMåHÐöìØËúë9|„saçx¡Ï‹|1éóÌ$^Ðß÷¾¤Ä¤kÞû’’’¸|é2áYŠoU®Vÿòþ9^×¥göìØËÚåkyéÍ3�oÙ°…”ä·lœ¹÷¡Õj%øïûÙ‰£!׌åÂùŒ£÷Ìvî‘¶-sU�:--�)_OaúĘÓÍT¯U�I³'^ó."r'Q2±€Þz î]ضmÃØ·/��X{ôÀÚ«†U«0N™®®y6ž£Á‘Gœ¡±Scœ ÷vёۑ’œ¢åÍÀÝÝ�ä¿¿ Üo\\]¨× õÔcèð¡ìܺ“áCÞ 6&–OG|JÓÝk0�™É¹m·±mcöåSÿuñüÅ,ÉÄReJ^³ícOtdì'c ÞLDxDfé—8ÿ»Ì+&:6sæÇÜéónGK§sªR}»–Î_ŠÅ¢Â+"·"%9w7w{‡qOsuuÅh4Þ·÷ºÿrvv¦N`êÖað+ƒØ¿{?¯ ~�È‹‘Œzç3íø(NNNDGE°çÏ=ìùsÏ û½xþb–dâõî7mkèw>ãtèiN9A•¿  ¬_‘±ÄùŸ}®Æ_%==£2õÏs~¾ar¸÷•,sã{ßÁ¿òÞ«ïz<“£‰ç^Âó¯=Ÿ¥P™ˆÈ�L¿­òY¶Æ™3±Ô«±±Pµ*Æ]»°Ž�í›o°:„ñ§Ÿ2–Aç!%EnÌ€6¢ÏoƒrØ'ð^v2Œ'ÏàÝÏF^÷KAƒ¦ xó£7yû¥·‰�àTÈ)*TÂÕ-ã�R‹6-¨Xç†czóÊòwŸâמÑàUÌ‹&-›°iÝ&Ö._Gÿ¡ÏÏ®m»ðöñ¦I‹+dºþ¿¥]ýžë‡÷Æù/g—ìKÁòzv…ÅbeÉü¥õ,J«­ò´o‘û…Vªä¿û­°Í¥ —ø~Üd^ïõÌî9©X‡÷¿x�û½Ä•Ø+>p˜:�upûûÞרyC4mpÃ1Kúe}pVÜ÷Ú÷wwíЊß¯`Íò5Ty  ))©lþ}ËßçÍlûÿ—5÷zæ©lãü—Á˜}âõîó§ÎaÌG_a±Xiдã¶&""w2û$ï“llb2žžžÙOxzbüé'lgÏbðôWWŒ&`{衬˞{õÊ÷¤ÀÛèM‡2ù>–ܼÔÔT2RRRHOª  IDATOÏ|búƒÁ€««+&“ wwwÜÝÝñððÀÃÃã¾û@+bOf³9s&C¿çúeÙ´='ÕjVÍüs\lFef¿²~;tŒÊU+ßÒ~ƒ7šÕðx�.lZ·‰5Ë×Ðè3l\³sº™�·ÇÁä�ÙÎÓÛ�B$\M e›ÔoTÿ¦cqpp¸q£›°}Ó6.F\¤ïà>Ùö„{1dÞûžèÕ•ë>xÝÖÕjþ»ggÜ•Œ{_™reسc/þåýoéÞçàpý{_—]þN&®åå/³ý�m$%&Ñ¥G—, DgggJ”,Î¥ ‘4jшGÚ=rÓ±˜L×¾÷͘8ƒqŸ~�““o�z“§úõÔgu¹+Ù%™è_®¡ç#¨T:ï—?ÝI�9Ë;טah¨_þSÉÌЧϿ˞Ÿ~ÃêÕ'O†|ZziÁÂÖ´­ÄÛâ©ãX‡VέpF_Î šÕjåÒ¥K„‡‡Ndd$ÑÑÑDEE‘˜˜˜¥­««+ƒ“É”¹ß‘Íf#%%ÈH>Z,–Ìö&“ ooo¼½½)V¬¥J•ÂÏÏ???\óp9½ˆd(_±<^ÞžÄDDzxîbÞø`øuÛ‡…†eþ¹ÔßË¢nÈï+gÏŽk/ó ÚĨ·GáYÌ‹)ó'ßTŒÍÛ4§HÑ":LøÙó¬ûg™W�ÎYÚ�Fjø›Ömb×L&Ξ2›KVвmKžýù›Šåf-ž»€nZâ,"rÇ(î냟iÂÏžgñÜÅ7L&ž=�ùçR/Ulü0Kü¾�a³ÙrL°… aäË#qus㇥31æ0+ðZnò0¾¥|9sê Gƒ�²þŸ*Îÿ¹÷eÄÈo‹W°gÇÞk&Ï]Ì¢Ù‹x¸Éüþþ빊áÀÞ Æ6GGGÆÏŸ¹W²ˆÈÝÈ.ÉħúôeÚôÉ|Ñ¿·=†/'#.P¨˜Ïõ÷`Ëé�±ìù­·°}ó –}û0.Z„¡zõ<�ѹ bKÚŽ™�ñˆÓ#h•gþKMMåäÉ“„††râÄ Îœ9CZZNNNøúúR¼xqªV­Š——^^^xxxàî›[®fù¤¤¤põêU‰‹‹#66–èèh"##9xð W®dn(^¼8•*U¢J•*T®\™bÅŠå÷K¹ç9˜èÑ·“¿žÂœ©³)[ÞŸî}ºçø¥(&*†o¿œ@íúµ)Y:c)ÕcO>ÆøÏ&p`Ïü¸�^Ïd-Îe1[˜øåD<’í\n899Ñáñö,øq!Kæ-fÇæT ¨Ä5³WÏìÑ·›Ömbæw?вmKªÖ¨šåüň‹Lûv:1Q1ùžHŒ¼ɦõ›¨X‡ŠU*æëX""’{ƒ�§žéŘ�ǰtÁ/T¨\�¾Cúæ˜ì‹�‹çëQã¨P‰ÊU+Ðú±Ö|ùÁ„ aÚ7ÓüÊ ,×Y­V&~5‰Ã�ðØ“�ÝT"2�uêÖ‰ißLã·%+Ø´n¾¥|s|PÖ³oO~[¼‚…?,¤MÇÖÔùÏ–#1ѱL?•ˆðzê“릎Ÿ‚Õjeð°ÁJ$ŠÈ]Ï.ÉĦ͚1ñëqì9Bý€¼ÝðN`¶XxuÚl¾š2õÖ:pqÉXöܬÖ�±6h€qòd ÿû_Þ ¸\hã܆fNÍp1dßïJòÆ•+W8xð AAA?~³ÙL©R¥¨P¡ 4ÀÏÏ�bÅŠÝô£œ¸¸¸àâârͪÄIIIœ?ž³gÏròäI.\HJJ ¾¾¾ÔªU‹|�Š+jÉ…È-ôÊ`vnÛÅ�=øèÍ�YŠy )LLT ûvícõ¯kˆ�‹Ç£��ù0óúÂE óÖÇoñþkï3êíQìܺ“6[ãUÌ‹ ç/²xîb‚öQÔ³(ƒ^|K1véÙ…?.dæw?`N7Ó¹{§Û5´m;µeíokù_§ÞôèÓ�ÀÆ�˜M„ eî´9ÄDÅØ8�æ­›ßR,¹õëO˰˜-*¼""rê;¸nÞΟ›wðÕGcX¶hm;·Ã¿¼?ž^E‰�¹Â�=Xýë*b¢cqquáÓñŸd~Þtqqæ½/ÞãµA¯3aôöïÞOûÇÛãS¢‘/óË‚¥ìÙ±ww^|ã…[бK�ÎLûfófÌÜn¦g¿§rüì]'°ÝzwcñÜÅ è6�'Ÿ~‚ÍâââÌ©ÐÓÌ›>—ˆðjÔ®A‡ÇÛçjì„« lßü'çφ3îÓ¯¯Û¾m§6T¯•÷“IDDòŠÝ °LùáGztéÌkÛЮ~]{…‘ç¢ââ2q*ý_|‰€€€ÛêËðä“8Ô¬‰µgO¬½{cX»ã÷߃{ÞWáS"1不§sàÀvìØÁÑ£Gquu¥jÕªôêÕ‹ªU«Úm™±››•+W¦råÊ´jÕ «ÕJxx8‡æÐ¡C¬]»///6lHƒ (^¼¸]â¹[¹¸83máTÆ~2–ŸçüÌá Ã:œcÛÚõkóɸ�©P¹B–ãO>ý³™1�å÷•¿óûÊß³œ÷+ëǸiã(QòÖþ}Ö¬S“ •+p*äF£‘Çž|ìšm?Ÿ4�Bî,]ð ³§ÎaöÔ9YÎ7nÙ˜±“ÇäÉÃ�k±Z­,™¿„BE ѶSÛ|GDDn�ƒÉ�‰³'2aô7Ì›1�GC8q4$ǶÕ|€�Æ~”eïDȨºüùÄÑŒzç3¶lØÂ– [²œ/Q²c&E™r·¶×{ùJå©U¯Aû‚®ù àý/ÞÇÅÅ™?,`Á� YðãÂ,çë=\�ñ3¾Îuõå�£!˜ÓÍü¶xÅ Û—«XNÉD¹£l6û•ÕLJJâ½#8´ŸöujQ¾„Îïw·‰Œ‹cû±NEÇòñç_P?00ï:OIÉ\öLµjËžkÔÈ»þ¯c_ú>JKãëà[ ãÝ ®^½ÊÆ�Ù¼y3iiiÔ¬Y“‡zˆ€€€|ý²�W¢££Ù»w/{öì!&&†êÕ«Ó¦M›ÛNŽßŒs1'ÙpìW+¶+°1í=ÄÞÍûøðà lÌûÑ—_}I…êåy¨éCö¥@\ºÉÚßÖ¼?˜¨È(ÒÒÒðôò$à�*4{´µêÕºîõ1ѱlXõ;Ç�œ .ö Þ>ÞÔ®_›GÚ=‚““S–¶Áûƒ‰� Bå T®zãYÿG‚�p.ìnîn4}¤é ÛŸ4Wýå«‚f2¼Í8;Æ ÷Šýg·uœê¥o\¹6¯lY³•„¨†>oÏG÷¾áÇӡg{*T­pãÆ÷ èËÑ™÷¾K"IIN¡¨WQ*W­L³VM©ûpÝ뮀‰�‹gÃê 9x”+1±xz{ñ`Ýš<Ú±5..Y÷w?|”³agñ/çŸ-9™“GC8z '''Z¶myÃögN�aãš?;FJr %J– q‹F6Ìö¶mÜFbb"uêס¸oÖ‡}—.\âÀÞ7ïÕkÕÀÏ¿t®Û祫)1>÷'š¼e—ñEäî`×dâ?®^½ÊæÍ› ;uŠÄÄ{‡sÓ(á[’À‡Îׄ‹í—_°©©'LÀ0hÐ�/º ©¶T¾KúŽ[ õëÓ¹&ûMf½ã%$$°råJ¶nÝŠ»»;Í›7çᇾk �Øl6BCCùã�?8vìeË–¥k×®T­ZõÆß&%ï]÷[2Qî5J&JÞQ2ñÞu¿'åî¦d¢ˆäÆ‘*T¨�=ví%V’Áе+uëf,{<ÃÖ­ù¶ìÀÙàÌ ×AlLßÈ1ó1š;çï~Xw+‹ÅÂï¿ÿÎêÕ«quu¥[·nÔ­[“éŽøçuË Cærè‹/²nÝ:Æ�O�5èÞ½;%J”°wˆ"""""""RÀîîlÇý¨lYŒ›7c}óMlß~‹eÏŒ?ý„áÁóe8£��;“씌#wçôüÎ�?þHTT­[·¦I“&8Þ¥Kõ¯Ç××—¾}ûÒ¬Y3–-[Æ'Ÿ|Âã�?N«V­T¨EDDDDDDä>¢dâÝÈÙ9£ÚsË–X ÀúðÃ?ÿÃ+¯äÛ�®†œ—êZ,bcc‰��Ål6“œœŒÅbÁb±àè舋‹ .\oooœ��sìçn´eË~úé'*UªÄ€(Z´¨½CÊwåÊ•ãå—_fË–-,[¶Œàà`Œ{>ÍŽ‘;‹’‰w1Ãã�ãP§Ö§žÂ:l†½{3–={xäËx‘‘‘œ9s†°°0Ξ=ËåË— q Á#Æ—äŒjЙ C³ÙLZZZ–><<<ðööÆÏÏ�råÊQ¶lYüüüpppÈ—˜óƒÕjå§Ÿ~bË–-têÔ‰æÍ›ßW³ó Í›7§Zµj̘1ƒÑ£Gó /P²dI{‡&"""""""ùLÉÄ»]Ù²·nÅúî»Ø¾üòßeϵ®_!47ÒÒÒ8vìÁÁÁ‹““¥K—Æßߟʵ*“\&gWgš¹6£™[3L†ìÿK¥¦¦rõêU®\¹BLL QQQœ?ž   pvvæ� fÍšÔ¨Qƒ"EŠÜvìùÅf³1kÖ,8À Aƒ ¤É�ªxñâ 6ŒY³f1vìX†ޝ¯ª~‹ˆˆˆˆˆˆÜË”L¼˜L?ÿ[£FXû÷ÇÚ Ám-{ eûöíìÛ·�ôôt*T¨@Ó¦M À×ףјٶ¾­>ëÌë³…ÑÜ�s�gggœ��)V¬X¶s±±±„††räÈ~þùgæÌ™CÕªUiܸ1µk×¾ãöüé§ŸØ¿?ƒ¦BUèsuueàÀ�̘1ƒ¯¿þš#Fàééiï°DDDDDDD$Ÿ(™x1tîŒÃþýX{õÊXö¼e Æ3 {ùY,vîÜÉÚµk¹téåË—§k×®<øàƒ¸ºæ¼_"@Cº;v'É–„7¿TÙÓÓ“úõëS¿~}, ¡¡¡ìÞ½›Y³f1þ|š7oN«V­(T¨ÐM÷�×öîÝ˦M›”HüGGG Àĉ™1c¯½öZ–„³ˆˆˆˆˆˆˆÜ;”L¼×øûgT{þôSlŸ|‚%8ã¢Ej×α¹ÅbaÛ¶m¬]»–«W¯Ò Aˆ��ÏM ëfp»íÐ €äädvïÞͦM›Ø¸q#M›6¥]»vvK*ÆÇÇ3wî\Zµju_/m¾'''úôéøqãX¿~=mÛ¶µwH÷•éÓ§sæÌ™Ì¿<˜2eÊdi“��À_|ÁСCµ¿¥ˆˆÜu–.]ŠÙl¦G�7u]rr2Ÿ}öC† ÁÏÏ/Ÿ¢¹¿húнÈdÂøá‡ýbb°6h€m„lÍNœ8Á§Ÿ~Ê’%K¨U«ï½÷]»v½éDâõìµìå*Woú:WWWš7oÎÈ‘#yüñÇÙ¿?ï¿ÿ>üñV«5ÏâË­5kÖàîîN»ví |ì»…��mÛ¶eÍš5$%%Ù;œûRZZãÆ�#"""Û¹ÄÄDÆ�Çå˗홈ˆÈíY»v-«V­ºéëRSS7n.\ȇ¨DDDîOš™x3tê”uÙóæÍgÌ ÉÙ™ °gÏêÔ©ÃàÁƒó¥èIœ-ŽÍæÍl³l£‰Cê9ÔÃÀÍU=6™L4hЀ‡zˆ?þøƒ¥K—²}ûvúõë—mæU~IJJbË–-tïÞý®ª:m�7æ�?þ`Ë–-J¼ gŸ}ȘA;qâD;G#""""""÷2ÍL¼×•)ƒqÓ& |€mÙ2RkÖäÇçŸçäÉ“ :”>}úä[õä"†" p€¯Á—£Ö£·Õ—Éd¢uëÖŒ1>ÿüs6n܈ÍfË£h¯íСC jåA…ì{�££#uëÖeÿþýöå®a±X'$$³Ù|Ív±±±?~œ¸¸¸ÛïŸý,Ïž=›ã F‘¼–––Æ©S§8}úôu?»EFFrüøqsÐÝõ~ð÷²çýŸ}FRL ƒæÍã]''*U¬˜ïC{<é験'MOÞô¬ÄûóôdРA<öØc,Y²„ï¿ÿþº$ó±cǨ\¹2NNNù:ν¢Zµjœ9s†ääd{‡rÇ[¶ltèÐ�öíÛãïïÏ|�%©xéÒ%ÚµkG­ZµèÙ³'*Tà‰'ž $$ä–Æ¼rå ­[·¦^½zT®\™víÚé¿•�¤¥¥ÝŸ´´4{‡)"r[&MšD… xòÉ'iÖ¬UªTaòäÉYÚH£F�xòÉ')[¶,ƒ ʶ5‡««+“&M¢R¥JâïïÏêÕ«³´ùã�?¨R¥ uëÖÅßߟ1cÆäûk¹ß(™x°Z­ÌŸ?Ÿ™gÎpxæL àüÑG8>õ†+Wò}|†<)Ð’ÙŸÁ@óæÍyå•W8sæ cÇŽ%>>>Ïúÿ¯˜˜˜<ÝGò^çããƒÍf#66ÖÞ¡ÜÑÒÓÓ Y³ftìØ‘Š+2xð`Ö¬YsËãþ÷¿‹§§§¿w€ƒáA¾x(ÛÏ®��L™?ÿòþX­VF¿;šð3áöWD$Wüüü˜?> .¤lÙ²´iÓ†1cÆd{üý÷ßãååEƒ ¨Q£¯¾ú*»rxØýß{Ø?û~ÿóÙãèÑ£jŸD‘|¦;í=Êf³1wî\Ž9Â�!C(UªT¶6ÖæÍIßµ k³f˜>û Çž=1àÒÔâÆâôsꇧÁ“#–#·Ü�³³3ƒ ÂÅÅ… &äyâÏËË+Ûž=rmQQQ <==íʯ~ýú¬_¿ž“'O2lØ0Ž;Fݺu³|�òððà›o¾áܹsÌž=___ú÷ïÏ믿nÇÈ¥ xò É#M˜0sF£‘ôôtÖþ¶ÖÞa‰ˆäZÇŽÙ½{7¤wïÞ¬]»–Úµkþïƒ???æÍ›Gxx8cÇŽÅf³Ñ®];¦N�zScyzzæû^Ú"""¢dâ=kãÆ�ìÚµ‹gŸ}–2eÊ\³�ÍLJô_ÍXö¼vmƲç; ,Îâ†âüÏñt6u¾­~\\\2df³™3fäi•çjÕª¢B¹täÈÊ—/�«««½C¹£™ÍæÌ™´>>>tïÞ�… À† 2Ûý3{ÃÉɉ¦M›òñÇóÎ;ïä8;ÑÍÍ “ÉÄÕ«W æEH�©R­2¥ü2ö ?{þšíÎ…�cóï[X·b{wî%%åÚ_ª®&�9=ç*âV«5³Ìÿnû{&{bBñqñ\�Ïyv«9ÝÌþÝûY·b;¶ì úrtŽí,f ñqñ$\ý·Ÿä¤dvoßMÐ>í)r·JHHÈ,òU¶lYúöíËš5kHMMÍòàìŸ{�»»;mÛ¶eüøñôîÝ;[q•yðÁÙ¼y3)))™ÇÎ�;—¯DDDDþ?Ó�›H~ˆ��'44”sçΑ˜˜ˆÑhÄÃòeËR¹re\\\n¹ï°°0–.]J—.]¨˜›ŠÍ/{¶5mŠ©œÚµÃüæ›XÞ~ `™ˆcžhñðð ÿþ|ýõ׬^½š:d9oµZ‰��åÊ•+ÄÅÅKRRééé™?�±üÔÉÉ “É„»»;nnnØl68@``àmÇù_©©©DFFrùòå̘ÒÒÒ°X,899áää„››ÅŠ£xñâx{{ãàà�çqä…´´4þúë/Z·nmïPîx7ndàÀ� 0€Æ�ãææÆ®]»8uêmÛ¶ %%…–-[R£F žxâ J–,Idd$3fÌ S§NÙú4™L4nܘO?ý”„„.]ºÄ#�pù;A_¸HálçöíÜÇ|Éá Ãÿ¹Æ…žýzòâ/àæžõ÷l¯Os*äfNàÑ­²õy.ìu 8â ágÂiß0ëïÕ¡½‡P¶BYVý¹2ó¸ÕjeÎÔ9L�0�+±ÿn?ar4Ñ®s;Þýl$…ŠÊ<~ð¯ƒôî܇굪³híOü<çgÆ}ú5ñqñ´ëÜ–±SÇæê=‘;ËìÙ³?~<Ï=÷µjÕÂÉɉß~û WWW5j@xx8 6¤S§N´oßOOOÂÂÂX¾|9~øáM�7dÈ&OžL—.]èׯçÎ�cÉ’%*Â"""’Ç”L,`!!!¬Y³†#GŽààà@É’%)T¨PÆŒ�øxV®\‰ƒƒuëÖ¥}ûöÙªÝÝHjj*S§N¥fÍš4iÒ䦮µ6kFú®]˜ÄôÙgwìÀûì3&OžŒ¿¿?M›62f-0 [á–-Zd©-w¦È‹‘œ>™±Ÿf�ZÕ³œ[·bo<ÿ&æt3E=‹Ò´UŠzåhð1öîÜˬɳطs3ÏÀÝÃý–c09šð+ëÀ…ð,+Å}‹ãäì„o)ßÌv6›�w‡½Ë²EËq09вmKÊ”õãBÄE¶¬ßŠ%+8vè VÍÏ–àX2)¾ñQæß]UKä®5tèPêׯÏÂ… ùý÷ßqrr¢zõêlݺ5ó3®ŸŸAAAÌœ9“Y³f‘��€¿¿?Ó§OÏòp²iÓ¦˜ÍYgR{yy1`À€ÌâoEŠaûöíŒ;–yóæQ­Z5V¯^Í„ ðññ)¸.""r�Ó7È’��À¼yóøë¯¿¨^½:¤J•*پħ¦¦rèÐ!¶mÛÆÇLË–-éÚµk¶jvײråJÒÒÒ®™h¸[±b¤ÿ{÷_óÝ>~üõ9#K&Y’1„ ‘ªUÔ¬ªÔ(¥¨š?T‡*î»ãÛÞÕjKµhUkåFíR»öˆ];¢H"‘‘=ÎøüþpK›1Îɉ¸ž�Gùœ÷çý¾NÔÉ9WÞ×ûZ±Ý×_£ýè#ôMš`˜3õ¿=.N j¿'Z‰¦•®!š�{Ž¿víüñgΜA£Ñ0oÞ<Ê•+G@@5jÔ E‹øøøàææöÀÝ™SRRøúë¯Y»víw„Ý�øøx¢££9tè¹¹¹JTTTA\÷b2™¸~ý:ñññÄÆÆÍš5kðõõ%22’§žzʦMORRRX¿~=:t�çûT­Z5>ýôÓ{ŽqrrbРA 4è¾æôõõeòäÉ·]wqqaÊ”)·]ïÛ·ï}Í+lçìé³|4ò#LFAU*ñl»g Kº”Äûo}€Ñ`¤Y«gøòû/qvùëu`ç–�¼=pÇ�g¾âÿ¾üð¡ãð ðcý¾›åõÏÔnƵ+×?íKê?]¿Ð¸%ó–°rñ*Êy•cÊœÉÔ‰¨SðXì™X†÷}ƒØ3±|ýé7¼÷Ù¿ Ý{ãú Æ<žêµªóÖ¿ß䩯OÉŽ"!s‘‘‘DFFÞsLÙ²e9rä=ÇôêÕë¶k·ýl+_¾<&L(t q, IDATí?ÿùÏ}F+„Bˆû!ÉÄbpñâE¾ûî;ìíí>|8•+W¾ëX{{{"""ˆˆˆàÈ‘#,]º”3gÎðúë¯ÙÐ"%%…Í›7Ó½{÷GKæ( Æ#0EF¢í5ìž{®XËžo Pèiדõ†õ3#ÄîödbZZÑÑÑ=z”K—.áææFÍš5‰ŒŒ¤J•*¸»»[$oooºwïÎܹs©Zµ*5jÔ¸ï{cccÙ´igΜ¡bÅŠ´k׎ððpÊ”y°BZ­///¼¼¼ ))‰ýû÷³mÛ6Ö­[GÆ iÑ¢…Åž÷ýÊËËcÞ¼yT¬X‘V­ZëÚB”ƒz FQ”B× ùR’Sˆ;@ízµùzÆD´º¿vGÏ›>Ÿ¬Ì,Êû—gÂnÛé×äÙ&Œüp$ÿý–-\ÆÐw†àåc½Ý9&£‰i_ÿÀ{Ÿý»P" jHU>ÿv¯tèÅ/óaøè× •m_Š¿DPÕ æ­œ{Ç]‹B!„BÛ“d¢•�={–)S¦BÏž=h‡Eݺu©\¹23fÌà‹/¾`äÈ‘xzzÞuüÊ•+  ""¡£6mŠaï^tÞ,{Þ½ûfÙ³��Eæ¿J¯ê_Å€¡Ðõ˜˜víÚÅñãÇquu¥^½ztíÚ•ÀÀÀÛ>�[Jݺu¹pásæÌaРAEžGyíÚ5–-[ÆÉ“' æÍ7ߤR¥J�©|ùòtìØ‘çŸžÃ‡³qãFvíÚEãÆ�iß¾}±ìè1 Ìš5‹¬¬,^ýu4Řp¢´Ø»cï=¯T‘·ß{‹òþ…�¾Øºa+]{u½kò­sÏN|ýéD2Ò3ÙùûN:½ÜÉ"1ßɱ#ÇINJÆÑÉ‘VÏÝù u"êP©J%ÎÇžg×ÖÝ<Õ®ÐãCß"‰D!„B!J0I&ZQbb"S§N¥víÚôèÑã¡’,®®® 6Œü‘I“&1jÔ(\\\nwõêU:Dÿþý-šLS==1,[†vêTtgþé§1Μ‰ùÙg‹¾ÙBtŠÝÿþW�‰‰aÍš5ÄÇÇS­Z5z÷îMXXX±%°¢¢¢ÈÉÉaúôé¼úê«wÜ¡h6›Ù¼y37n¤|ùòŒ1âžµ-A«ÕR¿~}ÂÃÃ‰ŽŽfõêÕœ8q‚îÝ»[µùFNNsæÌáòåËŒ9²ÈݳBˆ;?msÕí�g¦gX(â;»SNv{¶ï)r|êõ…¾Öj5xûØ®é—B!„¢h’L´’Å‹“——GïÞ½-’ÄqttäÕW_å›o¾aÓ¦M…ºÛ™ÍföïßO›6m¬š¸R##1ìØñWÙóÎ�gÏFõõ-ú懔��ͯ¿þÊÞ½{ eôèÑI«Xs,¿ç ñ môm¨¬¹ûY”–¤ÑhèÔ©¾¾¾,[¶ŒÓ§OÓ½{w²²²˜>}:ÎÎÎŒ1ovÁvrr¢gÏž„„„°dÉΟ?O¿~ý,Rö¬ª*Û¶mcíÚµT­Z•�>ðù�Bˆû§( =^{™ý»÷w>Ž+ÉWðòñ*Ôh%ýFÚ=çHûßãή·ïl¿›¼¼üŽÕ½ìÍóZýü˜½tV‘ã�þÑ]ÚÙÅå®IU!„B!DÉ ÉD+8{ö,»wïfРAÜ5ø^|}}i×®«W¯&""‚²eË7K³²²¨]»¶ÅÖºµ\9 K—Þ^öܲ¥Å׊‰‰aþüùèõzú÷ïOhhh¡Ç«jªÒEß…�Æ�œ2�*¶dâ- 6$((ˆ ðùçŸP£F zõêußÝ·­-""‚€€~üñG¾ûî; ôHŸÏŸ?ÏÊ•+IJJ¢sçδhÑ¢Xw^ ñ¤ ÿ«ŒùR|"^>^èõz*U©Ä…s8zà( ŸixÇ{óóó9ùÇ ªU¯Zp][ÄÎò[�_DpÍ`®]¹Fù¿;–n\I¾B^nvv…_+åõD!„Bˆ’O:%X˜ªªüòË/„……Q½zu‹ÏÿÌ3ÏàááÁêÕ« ®=z”ÀÀÀâëàû¿²çüÍ›¡LôQQh?øL&‹Lo6›Y³f Ó¦M£fÍšŒ5ê¶Dâ-U4Uè§ïGK�å“™÷ãV‚×l6S¿~}^}õÕ“H¼ÅÇLJ7ÞxƒÁÀäÉ“ÉÌÌ,ú¦HJJbΜ9L™2www>øàž}öYùà/D1ñ)ïSðÚrë¼A€æmš°dþ/defÝñÞ¥ –‘‘ž‰^¯§I‹&×=½o6ôºœxùŽ÷mY·ù�ã ©YŸò>äåå±iíÆ;ŽÉÏÏçÅæ�hÛ gNœyà5„B!„¶%ÉD ;~ü8qqq´oßÞ*ók4ž{î9öîÝKJJ þù'U«V-âNËS#"0ìÙƒùÅÑMœˆþùçQ’’iμ¼|8Z­–ü‘¼¼¼"ïQU•3gÎðÃ?0~üxÒÓÓ1bC‡µi ·O"�Fƒ‹ÛÍåÔë©×{ì…³‹3—/óΠ‘d¤>qÛ¦í|õŸ¯èúJ¼|¼  ¬\€ÿÎ^xÛ}¿Ìÿ…Õ¿üz×xo¾æ¦$¥º®Õjxmèk|2z,‡ö*ô¸Ñ`ä³÷Æq#õU‚«H³!„B!CRæla›7o&,,̪ɖڵkãííÍÖ­[éÚµ+‰‰‰4oÞÜjëÝ‹êêŠaÞ¼›eÏ￳ìyÆ Ì;Óñ~eee1cÆ RSSyóÍ7)_¾ü#ÅfÂÄÓêjë¢Åògp]¿~�ü‘ÐÐP:uêdñù-ÍÉɉÁƒ3yòd~úé'xÇ�…W®\áàÁƒìß¿ŸÔÔTj׮͈#¶AÔBˆ[\\]¸~õ:§�Ÿ†î7¯ùúùòé¤O9x$;¶ì ÍSmiòlÜÜÝ8uüGö NDF|0¢Ð|�{vaɼ%œ?w�M_ qóFØ;8pdÿabN�¥ï�¾Ìù~Îc©P©" q—óú&�›„Åfý2€žýz²wÇ^¶nØJŸ_¥nd]ª× !;;›ý»�˜�ˆƒ£Ÿ|ýŸû !„B!ÄÝÉ»x JIIáôéÓ4nÜØªë(ŠB£F�سg—.]"?????«®YD@•=»¸ ïÔ Ý»ï‚ÁpßSäåå1mÚ4²³³-’H8m:ÍfãfæäÏ!AMxäùþÎh42wî\¼¼¼èÑ£ÇcSîëîîÎÀ�‰��eóæ›%Œf³™ .°f;üòK>ûì3€Y¿ÌÄ©Lá3|CÃjòù·ŸãîáÎÕ”«¬\¼ŠÅsw!ž¡#‡òƘáw�å�1à « ŠBBÜ¥B¥ÒZ­†I3¿áõw‡áìêÌáèÃ,œó_V.^EbB"aáaü´|u"êXø;$„B!„(²3Ñ‚8€‡‡UªT±úZõë×gÕªUüñÇÅw^â=¨ááöìA7t(Ú©SÑüñ†Ù³Q‹Ht�FfÏžMff&o¾ù¦ÅžK¨6�¢c£a#gÌgÐXd^€5kÖ�’’ÂÈ‘#Ñé¯FåË—§K—.,Z´ˆãÇ�“œœLnn.~~~Ô©S‡>}úôØ$H…x\u|éÚt¸¹‹û~:�ûvÿ7þÿpp(|´C�ˆ:ü¼z>ÉIÉÄžŽ%''/Oj†Õ¼ç9®í;µ§Õó­8yô$)É)¸{¸S3¬fA§è=gvܶƒ0,<ŒÅÜ,‘þÇë…N¯cÈ;CøÆ@N;É•ä+èt:ª„T% ¢ÿmq„…‡±çÌnäuG!„Bˆ’îñÊ‚”pGŽ!,,¬X’0ŽŽŽT­Z•Ó§O£ÓéJLÓÕÅåfÙs‹èÞy篲ç6mîzÏòå˹téÇ·xR4DBE»ŠhË•9'$$°}ûvzõêUÐQûqÓ ANž<ÉŸþI÷îÝ ¡\¹r¶Kˆ'Š��vvvïSÞŸò>GÝȺw|ÌÕ͵Èûo�åx':½®P'ê»Ñê´÷µ–B!„Âö$™h!YYYVm¼r'Õ«WgÆ ·íPù»ëׯ“��ÀÕ«WIMM%55•œœ ùùù¨ªŠ½½=z½GGG<<}ÐwîŒiÈŒŸ}FV~>—.]âúõë\¿~�óçÏsþüy|||˜?>yyyh4ôz=öööèt:ÜÜÜððð \¹r”-[ÿ"›²ü�£âøPÏáNTUeéÒ¥T«V�zõïÆ]»veܸqdffJ"Q!„B!„÷E’‰‹V«%00°ØÖ¬Zµ*+V¬(”L¼rå gΜáÌ™3œ;wŽœœt:åÊ•ÃÃÃ|||ptt,([3›Íäää�““ÃÕ«W9{ö,×®]Ãh4âèèH•*U !$$//¯»…sµ^=’V­B3t(¾S§ryÅ ¦5kÆ5\\\ âiÔ¨z½´Ú›;o%;óóó¹qã ¤¦¦’���¢(x{{S¡BªV­JÍš5qq¹ûΘ»1¨N˜OPG[ç¾Kë:DBB£G�~àõJÚ´iÚ5khܸ1eÊ”±uHB!„B!„(á$™h!qqqøøø<ÐŽ¹GU¾|yt:yyylÛ¶�ƒ�³³3ÁÁÁDEE€¯¯oA’î~™L&._¾LBBgÏžeýúõ,]º”€€"""ˆˆˆ¸k/11‘ýû÷sòäIRRRp‰Œ¤}åÊ4Y°€�~û�¼iÓоðÂC=çììlâââˆ��'..ŽåË—³hÑ"¨U«õë׿ïÒã?L°Ù´™?LÐV×ͽKUUeÓ¦M4hÐOOÏ‡Š¿¤iÒ¤ [·neË–-¼ð�'B!„B!„xrH2ÑBñõõ-Ö5¯^½Š½½=ÙÙÙlÚ´‰zõêѹsgùÜF­V‹¿¿?þþþ4hÐUU‰‹‹ãСClÞ¼™5kÖP¿~}š7oŽ��yyyìß¿Ÿ}ûö‘��€ŸŸáááÔ¬Y“€€EÁ4p ú>}pêÑãfÙó§ŸÂœàääDõêÕ©^ýfWS“ÉÄŸþÉÉ“'Ù·oëÖ­£Zµj4hЀºuëÞÖ4àï"t8hØlØLŒƒ÷N&;vŒ”” ð@1—d:�ŽæÍ›³qãFZ·n}Ï’ùÒNooGnn®­Ã(õr²s°+Æ_º!„ø‹�½y¹y¶£TËÏÏÇd2aï ?ë„B”^’L´�«W¯R³fÍbY+--�µkײÿ~|}}éÔ©uëÖ}à݇BQ ¤cÇŽ=z”-[¶ðÅ_ÀÕ«Wˆˆˆ [·nT¨Pá¶9Ôºu1ìÞ�nøð›Ýž÷íÃ0w.j¥J—V«¥ZµjT«V�Ž;röìYöíÛÇÂ… Y»v--[¶$22ò®—C5¡Úâ �DÛ³guêÔ)uç 6lØ�õë×sàÀš4ibëplÆÅÕ™¼¼<233qvv¶u8¥R^^¸¸É÷W!lÁÙÕ™ëׯ£ªj±4 |ÝzOìì*?ë„B”^’L´�ÔÔT‹w"þ'UUÙ¶mëÖ­ÃÍÍ�~ýúQ«V-«®y'Z­–ððpÂÃÃ9qâË—/Çh4ÒºukZµjuÏ7§ª³3†Ù³Ñ¶n�îÍ7Ñ7lˆqêTÌ�:=r\Š¢Lpp0éééüþûï¬\¹’ 6СCÂÃÃRô›½´´4bbbJÕ®Ä[ìíí cß¾}Ot2Ñ'À;{;Nœ8Aƒ l‡rþ<š={Píí1wéb³8¬áÌ™3 €%[‡"„O¤ •+°yåf.^¼H¥Gøe®¸»'Nàæá†[Y7[‡"„BX�$-$++˪ ,®_¿Î‚ ˆ��ç¹çž£iÓ¦V݉x¿BCC©Q£;vì`íÚµœ>}šW^y¥Ès M={¢†‡£ëÕ }ïÞ]ö|7®®®DEEѪU+6mÚÄÂ… Ù³g]ºt¡|ùò÷5G®šK¬K-M->L™2e ±H|%Mdd$S§N%55[‡cZ­–�°6oÞLddä=Kä-ÆdB9qÍ®]höîEÙµ %)©àáüðpÔ  ëÇQ TUeã¦�T­Q;{Ëü;Bñ`Ü<\  `ãÆ� 8ÐÖá”:yyylÛ¾�Ú‘ÅÿË~!„¢8çåÒÏd2a6›±³P"ìŸbcc™8q"ƒ�‘#GÒ¼yó‘H¼E£ÑЬY3FމÙl櫯¾âܹsEÞg®^ÃÖ­˜ºuC;u*v-[¢üù§Ec+S¦ QQQŒ5 ½^Ï„ X·nªªyïAÓAÖֲа�CçQ³fÍâI0Ù@åÊ•qttääÉ“¶ŦžjIZz«W¯²ê:ÊÁƒè;wÆÎß»† Ñ�‰æ—_ %ÕòåQýc/ƒ ͉V�ÕR6lØ@òåd¶|ÚÖ¡!Ä­qëFœ>}šÝ»wÛ:”REUU-Z„¢Qonëp„B«*�™‘bf4¬’h:xð Ó¦M#44”áÇãååeñ5,ÅËË‹aÆQ»vm¾ÿþ{8Pä=ª³3ÆY³0NŸŽrú4úF�Ð,]jñؼ½½ÀÑSÿþEγÁ¸�ê úÚõ}¸8Ì`­Í¶999œÙB<9$™h!ÎÎÎdffZd®””æÍ›GãÆ�ËDâ--[¶$--�Ÿ~ú‰·ß~Ÿ¢orvÆ8cj³fèFŒ@߸±Åº=ÿ�½½=ýúõcÉ’%Ìœ9“�|ç]S)))wŒ=KÍ"AM DS:š²Ü*¡ONN&00ÐÆÑØž³«3ϾЂfíŸárüe2Ò21 ›ÿR…r„ŒxMþísÞГz•*Þóþ8Ç82ËÜ|Íqlã@ÍŒš´~왲”õ„­[Û°gï³<Ó"žç¢Îápïòÿû¡ÕépuwÁ'À�®äœï*„¢°²^eißý9òóò¹œ�LVF&&£é‘ç5+f>¯òõÓêÓæJk DZ´©öDïögÏNN/‡ª*¸ºå3xDvv�þœþIo§ÇÕÃ__�bñù…Bˆ’L’‰âááAZZÚ#Ïc6›™?>þþþDEEY 2ÛzñÅILLäçŸæ­·Þºïs%M½{£6hp³ì¹W/L=z`œ<,XjªÑhèÞ½;öööÌœ9“ÁƒSù» ¯]»F¹rån»mŽf¿q?••Ê´Ñ·ÁUy¼w^¹ººbooÏ•+W$™ø7Z­ÿJ÷n„ò £ã÷Ñç(Z-&W´é%ð²›5¤B×öT(b޽êÞ‚ Á—è¦t{ jÕ‡_¹Â‰?2˜?Ý�5Ë+±ñ· ê=•À×SiÖ: E> !ÄÁÎÞŽŠUŠúÉsÿ¾Q'qT=J;·vÔ ´^gã«)Z6®uaý*gísÀd*üƒë•™„7*º:F!„F°Xˆ§§'W®\yäy¶oßNrr2/¿ür±wlÎÍÍeܸq,Y²Äbsj4zöìIJJÊŸÇg&ûvLC‡¢]¸»V­Pbc-Û-QQQÔ®]›3fÜñï0''‡2eÊÜv½©¦) µ ¹¨^䜹èîÕ%�¢(8::’��mëPJ5·˨Хèu\\9—K?�ú·F+×ö¾¯yv¨;ÿú3;:žÐ°\ÆMIfÓ�ó y�?cìÖÇ�ö�*1oº;9ÙòcB!ÄýÛÎvfª3i¡´ ·ÒË*k¨*ük¸ÏÖ bì/öïv¼-‘¨(ðb÷t«¬/„B<éäS¢…øùùqùòåGš#''‡uëÖÑ®]»;¶_ý•±cÇÒ¯_?rr,s~šÉdââÅ‹4oÞœõë×?x¢ÊÁãøñgÌ@9w}ãÆh/¶Hl·(ŠB�=ð÷÷gΜ9þQÊšŸŸÇÉuŠŽ¦º¦4½Ø¿k~�ÉVÈË˳u¥“ÉŒçØ¯ññ!ya5¹¸~1ya5ɉ¬KÒ”ÏPííÉjù YÏ6)rªL29‘‚¯cÔ.óh¯?Þ¾&†�¼ÆïGÏóÙädììT>ÿÀ‹æu‚÷¾—âe#»Bˆ{»Ìeþm~�%€qÊ8¬³ÅýÚ-«–¸Þ–@ü»ša¹T´Üñ$B!„ø‹$-¤bÅŠ\¾|ù‘1Û¶mÃÎÎŽ&MŠN&XC“&MhÙ²%ƒ ²X£‰äädš4i‚››lß¾ý¡æ1õè�açN B÷Úkè î ÓjµôîÝ›ŒŒ –.]Zè±üü|ôzý]ïí×¹ ,´X,¶¤×ë%™hšÌ,ü_{ƒrßÎ$#ªqKgaôö,x<#ª1�ðóÔûj¯¼G݃c¡k;Õ{t‡~öö*QÝÒY±õ"3'ñt?Ït§]ƒ †ööcÏv˼6!„(]ŒyGI6Ù|¥LÀg«­åém¢ÓË÷Þuض£eÎ2B!Äí$™h!U«VEUU.\¸ðP÷›ÍfvíÚE‹-²&___V­ZÅW_}e±9¯_¿ÜLÖ5kÖŒ]»va6›j.sµjäoÝZPö¬oÚåäI‹ÅêêêJ¯^½ˆŽŽ&&&¦àº^¯Çh4Þõ¾k×®ÝñzºšÎŸæ?-_q0 ØÙY¨‹£Àîb�Ï¿‚óÆm\9”ÄiãQnßéú Þ©¬ùQJ�ïDQ á39L�—Èš]èÙïÑ»Ð-€®­+²dž¹¹ò#D!ÄMãÕñQ�ðoåßÔäÁš‚=Œ�¿J!ªÛÝŠm;H2Q!„°©[³'''*V¬È©S§ yðî¾gÏž%++‹ððp+Dww[·nEUÕB×\]]‰ˆˆ¸mì±cǰ³³#$$„””V¯^MNNaaa4mÚåoÉ�'N�‘‘Á�8xð +V$&&†yóæQ¯^=ÂÂÂn[c÷îÝ÷„‡‡ß¾KóeÏÇ=<¨=e v-Z�õå—¬tv&>>OOO:t耻»{AÌööö“œœÌ¯¿þJNNuêÔ¡I“&…b¦N�:|öÙgÔªU gggÒÒÒnÛ­wá®]»FZZœ;wŽßÿ½àq�NGfÃLŽ™ŽQCSƒguÏRF¹ýÜÅ’&77[‡QøP“ IDATj8FƯߛh²s¸4ó2Û·|ä9UTvró¼D_|1aâ WØ«îŨÑYáe=°²��½Â룮³b‘ sðà£w½™òe9^ìžÎ+ýoàSþî w!„¥Ûu ?« h¯´§«Ò¥XÖÔjUži•Ū_\PÍ…ßÏÕª›K@ ”8 !„Ö"ÉD ª[·.[·n%**ê¶$UQŽ?NåÊ•qss³Rtwö /ܶS022’­[·Þ6öÓO?ÅÁÁ�—^z‰þýûãîîNjj*™™™ <˜‰'Œíܹ3 _�9²àÏ¿þú+íÛ·/Ôè%))‰Þ½{Mhh(:�Ž?ü�F�±hÑ"\\\ ÅÒlÒ$fŒEÛ9sp:UQ˜æáARz:!!!DFF0vìXœœœèܹ3 ÀÃã æ!C†0a„BóîÞ½›O>ù„«W¯rìØ1Ìf3gÏž¥M›6…ºküñÇ,þÛÙ�³fÍbÖ¬Y_»¹¹qáÒì{RE­BMÅú¿¥T¹¹¹+qÒ¹-X†ÏèO0yz·â'òÂ,ó÷£Æ�¬¦ÐGéÍiõ iJ½éÍDu"‡9B$õ-²Î�¸¸šè=ð¯ô¿ÁöMe˜?Ùßz0÷wžm—Eß!©„…çZm}!„%OœÇ¿ÕS…*üGù¸ØÖÝð«3£‡ù\=Ÿ jù¬[ù×{E)qB!¬KjÔ,(22’´´4b¢ãp\\AAAVˆêÞ222ÈÊÊ*ø¯iÓ¦÷¿qãFÆŽË–-[8}ú4/^¤]»v̘1ƒøøø‚qgΜ!++‹ ðûï¿“••Å’%Køä“O %�F#]ºt!..Ž]»v±gÏvìØÁîÝ»ùã�?3fÌcYvü8Õ®\áPãÆ¼¢ªœóôäÒúõ·íîܰaãÆ�cëÖ­1·mÛ–éÓ§Jxž?žÎ�;ÂÌ™3yþù牎ŽfèС¬_¿¾PòpöìÙdeeÜL´þýû˜˜˜ˆ�bdzÚgég×�šš’ŸHÌÈÈ 77OOÏ¢‹»»K£KÙÁú(½­Œ.¸Ö_éÇe;TË–:ß�FÍÛd1cqK6ÆñâËélÝP†í+ЭMV.vÅd´Î¡ûB!JŽ<òÁ;˜03QóŽÏ/$7üêÌ»C|©œÏÌ_.ñåÔd^èz³äÙÞ^幨Œb‰C!„xRI2Ñ‚<==©Y³&;wî| ûTU%)) +Ef9z½žuëÖQ³æÍ䈃ƒC‡Åd2qò>Î/  ))©ÐnÈ+VpôèQ¦L™BíÚµ ®×¬Y“7ÞxƒE‹ݱ)È’%K˜:s&¡6`X¸%9™r:`7mZ¡qööö¬[·Ž5jŠÙh4rêÔ©‚q_ý5F£‘ùóçÓ¾}{òóó9xð �:u¢bÅŠÌ�;÷Á¾YÿSN)þÎÜ#%%Gòø*ªÑŠ%T(‘xK¥u¸ýèk«Y;��Ƨ°ñÀyF¼•+)zþý†í2ó[Ònh‹=&!„Åc¬:–Sê)>P>  UŠeÍB‰Ä%—ð(kB«Uùlr2ßÌHbîÊÊûËÑB!„5I™³…µlÙ’)S¦pùòe|}}ïëžÜÜ\ CÁ9%™»»ûm¥ØåË—àêÕ«÷u¿Ñh$''‡2enž!¸sçN4 G�åĉ…ÆÇÆÆ’““CRR•*U*ôXTTÏ?ÿ<æŽ1Ô­‹þÕWÑ�…rø0Æo¾n–»ººóŽ;ðööföìÙÀÍäÚ¸qã¨]»6ùùùµãô^®«×É&›%À¢ó>¬¤¤$\]]qrr²u(�%»‹ ø÷y»˜s\9”kï y ¦*÷«¥r÷sïõ˜µ•ó2ÑÿõTzºÁo+\˜3Í�‰c=™öuYžïœAï�7¨œo³ø„BXÖu ËÔåôàe:*/ËšwJ$Þ¢Ñ@kiº"„B I&ZXhh(AAA¬]»–~ýúÝ×=ÙÙÙ�íYuÍÍ ®ÿlär'·žcvvvA2133�FÃöíÛïxO‹- Æþ�——W¡¯ÕŠÉ_·Ýûï£ýþ{”,_ž˜Ûî¼sÌÙÙÙäåå±eËàf’7..Žœœôz=µjÕ*òù=ˆíÆíĘc¨£­C3m3Û6>9wîÕªU³i �+k4Zy\ÙÙ©DuK'ª[:‡ö92†;˺²ôg74ɡ׀TšµÎ²FžU!D19ËY>Tÿ�%„‘ʻŲæ½‰B!„(^’L´‚®]»2~üxNœ8Ahhh‘ã$÷¸±·· ?ÿ掤[ÏñÖs¨T©F£‘éÓ§ì|„1Ž�¹Y3tƒ3þÜ9¾*weÆ���¤¤¤ð믿ÄúÉ'ŸÐ¤INŸ>�··÷–+üüD[][ì�ö5¥Š¦ U•ª<‡¥¨ªJlll¡&3âþX«ÑJiÞ ‡ð9$\Ô³xžKæ¹2¬�•ªx¹ï ^ꕎƒ£¹è‰„B”Ùd3ÂüzEÏdeØ[}MI$ !„%‹œ™hUªT¡iÓ¦,Y²„ÌÌ¢Ë-n••ÞÚ¡XšÜ:òÖÙ„YYY…Ji;uê„F£áË/¿´Øºæ0ìÝËy77þuå ú^½PÒÓïyO—.]8{ö,Ë–-@QBCC9uê!!!œ}úœ±÷O«V­"&&†‘#Gs„ÅÇd21qâD‚ƒƒïy6ŸÙl.ÔíÙR”„ô¯¾Š²w/æ¨(Œß�ú�ÎÔ—ŸŸ�Ñhäý÷ßgРAdee±hÑ"Þ{ï½Û:Zß’••e±¸oŽ'BA]ôè-2ï?íÙ³‡•+W2nÜ8‹ÏVüõsl>½‚§ª´³u(…ü½ÑJÒ·ŸÛ¼ÑÊkæ~¤)i,S–Ú4KÈHÓ²b± s¾÷àr¢OoÝú¤Ñ³ß ù)J•µGg1²ÍD["J�Ãq;‰½z†Pÿ’ÿ˼tÒyÉüÙäð‹ò >ÊíçH[’$…°�ŒÜ뜈ßM¿&£mŠ¢“�‰VV¹reÞ}÷]’’’?~<±±±wÆ¥K—y7[I–ššJRRuêÔ¹ç8�Fc•¤–@þúõÿýo4«W£oØeÿþ»Ž·³³ÃÉÉ ;;;²³³©W¯îîîlݺõ®÷X2îçuÏSMS�ý¦ý\6_¶Ø¼g6›ùý÷ßiÖ¬Y‰I$–Tn –Q¡K?Ðëˆ[ñ“͉¥�‹›‰Þo°~ß&NO¢B¥|¦N(˳uƒø×pbNÉîO!„°•÷ÕH$‰/”Ï%‘(„BI&>üðCªT©ÂÔ©Sùá‡øã�?0 cn•íî¿Grëq·oß>Ê–-K`` í‚Ðé0½÷†Å‹!#»¶mÑ~÷Ý=oqrr"''�FC‹-سgiiiVÕYq&JE_»¾TÐT°ÊûöíãÆ�´jÕÊ*ó— Òh¥Xéô*m_Èdþªoˆ§]TkW¸Ð©EEzu `ýjgL&)�Bˆâ2K�Åfu3C•!4RYu-I$ !„�i¡YLœœœèß¿?-Z´`ýúõÌ�;¸yF¡‹‹ ªªb0ؾ};-[¶Äѱt5"ÈÍÍe×®]´k×E±}"ÀüÜsöîEß·/ºQ£ÐìØ�qÚ4Tw÷ÛÆêtº‚Äoƒ عs'+W®¤OŸ>Å«·•vdgg³fÍÚ¶m{ײí'�&3‹òCGã¼a+QíHšô©œ�XŒBÃr7%—ï_eñzô(ÑÑÑôìÙ³äý�”ŽÑ‡©ð|Oô ‰\šù ×F…°£öIgg§Õ-�[/2oeMZd³l�+Ÿ d@·¶n(ƒ´BˆGgÆÌhu4WÕkLPÆS«­%‰D!„âñ#ÉÄ&22’Zµj±`ÁòòòlÎ#ËËËcîܹnëpîÊܼ9†�;QŸz í ùe”ÔT²³³1�¸¸¸ÿâ‹/R¦LæÍ›‡­¢¿¨‘ Jv›vsÅ|å¾ï»zõ*‹-¢M›6„††Z1ÂÇ“4Zy<„7Èaâô$ÖìºÈkCS9~ÔŽa}üèÒª"K湑›+?Þ„âa}§~Çnu#”· W¬÷þM‰B!ÄãI>m•@}úôÁ`00þ|›%ª,AUUæÏŸ�Á` gÏž¶§HªŸß_eÏk×¢oØ�ÔµkQ…òåËkggGß¾}‰‹‹cÙ²e6‰×Mq£›]7zë{ã«ñ½¯{²³³™1cþþþDEEY9ÂÇŒ4Zy,U¨d`ÄûWÙtàc>¹Bfº–�Þõ¦uD Çz’œ$G !ăثîeº:�f4ãUåU«­#‰D!„âñ%ÉÄÈÅÅ…!C†pöìYþûßÿ>– EUUY´hgÏž¥_¿~8;;Û:¤û£ÕÞ,{þõW0ê×�®'Oâ`WøL6³Ù ÜlȲ{÷nÖ­[g‹hî;‘˜——ÇôéÓQ…!C† Õj­ÙãC“™…ÿkoPîÛ™dDµ#né,ŒÞž¶K<g3½Þ`ݾó|77‘�P3¿õ íS•1°ø2Nó Ö9âC‰B!ÄãM¶l”P*T`øðáL™2UUéÞ½ûc“ü1™L,^¼˜£G�2pà@üýýmÒ37k†aï^’Ûµ£Åޤ¶kÇÁaÃHÈÎ&))‰Ë—/c0pvv¦bÅŠMsJR3“Ds"Ί3®Š+999̘1ƒ7n0jÔ¨Ç'¹[ ì.&à×{ögÿäêÈ¡\{gˆœ�øÓh y›,š·Éâôq{þû“«—¸°~µ3¡a¹¼2 ��3Ðê¿_Ò!„5™01R}—L²˜¦ù7ܬ²Ž$…BˆÇŸ$K°jÕªñÆo0uêT¦M›Fß¾})S¦Œ­Ãº§ììlfÏžMbb"¤J•*¶é¡åºº2¾ysžuu¥ãîÝD;FÖÀ�x6mJ»víð÷÷Ç××EQ8pà³gÏ&##ƒ.]º ÑØvÓ¯ŠÊã²È¢Nv¢ŒÆl2óî»ïR®\9›ÆV’8FƯߛh²s¸4ó9±”©^+��ƧðÆèk,ÿ¯+?Ïtçßoøðõ§ž¼Ô;�WúßÀÝC>Ä !Àõ+©‡ø?åCB±Î1’HB!J)s.áªV­Ê˜1cÈÊÊb„ ÄÄÄØ:¤»:{ö,&L ==�·Þzë±N$œþám©ŸXÒh剥׫´}!“kâY¼!ž¶3X³Ü…¨f�ôêÀÖ ex �¨BˆGOÔ­[—ÿþ÷¿=z”–-[Ò¸qcìíímS^^»wïfãÆ�8::Ò¿BCCm‹¥ÅÇÇsöìYF�ý×E//4¿ý†:y2æwßÅT¿>š Pš6-âííÍèÑ£Y¾|9sçÎ%88˜Î�;krõøñã,_¾ƒÁÀÀ‰ˆˆ(¶µK:Mf凎ÆyÃV2¢Ú‘4éSTÛüû¶–˸)¹¼ýÞU–Ìwççn ëãGÅ =ûÝ ë+é8:™m¦BXUyŒ0¿ƒ“”o(ƒå�Ó‘D¢BQúH2ñ1F�5زe ëÖ­cË–-4jÔˆÆ�ãæf�ƒ²ÿ)--�]»v±k×.Ìf3­[·¦iÓ¦èõúbY¿8lÚ´‰jÕªQ¹råÂ( Ê›o¢©[sÏž˜Ÿ}å½÷Ð|øáÍ΀^¯§[·n4lØ� ðÅ_P¯^=Z·n�···Õbމ‰á·ß~ãâÅ‹4hЀ—^zéž�VÌ x(”QJö9œ–"�VÄ�xûš6ò¯ IeÍ2æÏpçó¼øöËr¼Ø=�>ƒSñ¯`´u˜BaŸ©ã8ÉI>S>£*U->¿$…BˆÒI’‰�!½^OÛ¶miÖ¬;vì`óæÍlÞ¼™àà`"""¨Q£†ÅµdeeqêÔ)–,Y‚Á` €ªU«R¡Büýýñòò*hRUU¹rå —.]">>žØØXÐëõÔªU‹bóŽÅÖ`4Y¶l 4 88øÞƒ==ѬYóWÙs�:hæÏGiݺ`ˆ¢(„‡‡S¯^=Nœ8Á®]»X°`:�ŽjÕªQ­Z5ªT©‚··7:]ÑÿsrrHLLäÌ™3ÄÆÆrñâE\\\ˆŒŒä™gžÁÇÇ羞§-]í»²6o-ò7PYWWÅõ¾î}ܸ-X†ÏèO0yz·â'9QÜ“¢@ÃgrhøLÿÔ³`–;K¸²mcjÔΣ{Ÿ4:vKÇÞ^WB<¾Îs��Ô� V‚£Œ±øü’HB!J7EUå¸ùÒÄ`0Ë©S§8{ö, äçç£ÓépssÃÝÝt:]ÁÎ8ƒÁ€Ñh$==�k×®‘™™‰ÉdÂÎÎ???‚‚‚¨^½:AAA¥ª”ùNV®\Itt4ü1®®÷Ÿ\S££1wïññ(ï¿�æƒ@«½ãØììlŽ9©S§8}ú4éééh4Ê–-KÙ²eqrrÂÞÞ�FƒÁ` //�ÌÌL®\¹Bff&Š¢àïïOHHµjÕ¢zõê�Ø5cæ²ù2~¿‡ºßZ⯟cóéQ?áOþäke¢$…BñP$™XÊi4üüüðó»¿„‘ªªLš4‰5kÖP¹reœœœ¬aÉ�œœÌ‚ hÙ²%õêÕ{¸I<=Ѭ^}³ìyÔ(Lu뢙;¥mÛ{Þæåå…——µjÕz¸u­$··ÆÅÁÖ¡<i´"¬E£�æm²hÞ&‹“ÇìY<×�U‹]Y¿Ú™zOåÐ{à Z=—…V'þ…%Ó"u1+ÕU¼ª¼Jk¥uÑ7<I$ !„OŽ'gÛ™¸/Š¢Ð¿TUåÇ$//ÏÖ!Yݵk×øþûï ¢sçÎ�6Ù­nÏ;wB™2˜Ÿ{ó˜1`z¼ÞPç©y,É]Â9?pÊxÊÖáÜ7ÇèÃTx¾'ú„D.Íü†k#‡J"QXEÍÚy|4>…�Î3âý«\гcÄÀò´oÈÌo=H»qçc„ÂVΨgøRý‚0Âx[yË¢sK"Q!„x²H2QÜÆÅÅ…·ß~›ŒŒ fÍšUªŠ7nÜ`Ú´ixzzòÿþßÿC{—s”‰öða”.]P¿øsË–�˜h‘¹‹ƒ½bOW‡®Ø©v¬Í[KŽZò»Øºý¼” ]ú�^GÜŠŸ¤c³(å¼Lô=•õÑçùlr2NÎf&Žõ¤UD%>z×›s1v¶Q!ÈP3xC}{øJ3=–;[‰B!Ä“G’‰âŽ<<�H"_*_à‡åÎJ–D¢Bñd’d¢¸+ÆŒƒÉdbÒ¤I$''Û:$‹‰‰‰aÊ”)T¨P�#FXïlÈ[eÏ»v�‹ æöí1¿ù& ÖYÏÂtŠ?mÉmТÉÌÂÿµ7(÷íL2¢Ú·tV©ëØ,?á r˜8=‰µ»/òÚÐTNµcX?:4©Ä¼éîäæÈ�^!Dñ™£þÄ&uƒ•Á4QšXl^I$ !„øÿìÝgTT××€ñgf轊(RTAì‚ØP,Xb�¢kŒ%5¯%–hb¢K41¦Ù jD±÷{ÁÞ� Ò{�ò~˜8‘€R¤¨9¿µX‹™¹÷Ü=Ãwö=goá¿K|¢^ËÜÜœI“&Q¡B-ZÄÙ³gË;¤7¢T*Ù½{7K—.¥qãÆŒ5 ]ÝÒïò+iÔH½ì¹wouƒ–¶máÉ“R?niŠTD’Cù%Eu"cßé#Œ#vâ(ž.] :6 o;‡ÆO�åÐÅpf.ˆF*U1o†5­ê:2wº5Ïžˆh‚ ”®«\e±j1xð©äÓW$Aá¿M$…éëë3nÜ8:vìHpp0kÖ¬y'—=?Üt¬ IDATþœŸþ™S§N1tèPüýý‘JËðWÀÄiPÒeËP…†ª—=ïÙSvÇ/Aiª46fldYÚ2(”ùñE£á]bh¤¤÷€$¶‹`å¦Ç4ðÌdý*3|=5 gŽ¿ÅeAxgÅ“Àÿ©þLøN:Y �ö‹D¢ ‚ bZ„P(‰„Ž;R³fM˜;w.:t yóæe›�+†¬¬,öïßÏñãÇ©Zµ*Ó§OÇʪü–ÂJ†GÚ¨Ê>}P~ð’1c�.\Ú%W ½´J é¡ßƒ}™ûØ™¹“Q£Ð‘”M£ Óõ!ØL™�ÂÊœÈmkD}Dá�!•‚WË ¼Zfðð�7eózŽ4Ä­N&þŸ$ѹG ZÚ¢¸â›ÈÉÉ!.&y޼FW÷,‰°°°R[ÍÄĤ\ÿG ï%J¦¨¦«ŠcµtÖX—ȸ"‘(‚ €D¥%á…¢‘ËåüðC<==ßž8““QŽ*(‰‡Ò�ÁÉ©¼£*”¸¸8Nž<É“èÒtÓ0Í4-ÑñÓc¹}KÍ}¥ŠV{ÿÄëÈiž:Tfó`?R��Š5¾ 013§^£zT¨X¡„¢.{C”“$Ib‹$¤¼CŠ)%IƶMÆ,1'ê©Vø Lâ£�Ňô"ºrþ2,_�Rž†½½9&&¥3ã3+'C]ãR[¡Pòüy OŸ¦àéÙ’I“¦cffV*Ç öèÑ#Μ9Cbbl©Œÿ8!Œ¸´*š:”øØGÜ�qÄý8ÝïugrÅ/015yã1E"QþR2ã¹ùè47Ÿ\Þ¡‚ðÉD¡ØâããÙµkgÏžÅÊÊ êׯ�v9ϰKOOçìÙ³=z”œœ|||ðõõEOO¯\ãzÕÚµ(GޤkÖ éܹ¼Cz¥èèh¦LGròcÚµ«Š��1ºº¥?ÁY–ž�ëÜýX� #ºU nOl‡ò Ž›“£àÉ“dýFZ¦c¦NÆÎ¾r F\6D2ñý!Ï‘pxŸ!k—›qå¼>::*:tKaȨDjÔÊ*ïðÞz+ÿJ³[|7ÿ*T(�D_Y;tèsæœà§Ÿ~§víÚåÎÊÝ»w™2e,&&r¼½í¨XÑmmYy‡UhW 3Ùa “íx¸9û÷ßÃIJ2ŸM™ˆ©Yñ.þØeÄÄ‘qvÉfå&‘H„÷™H& ‚P"™(¼±¸¸88À©S§ÐÖÖ¦~ýúxxx`oo_f1(•JîÝ»Ghh(ׯ_GOO�Ö­[ãããSz�šK�êòe”~~ðà�zÙó‚ S6ˆ ëáÇ êÇ‚íiذàŸm„";™Ù›×h ‹EÑåW¸…ä«ÎH¿î\¢õïß�á“›ùlê—¸º¿[K¦E2ñýtóš¬0eÏ6cä9ê{d0`X"m;¥!“‰Ùÿ¼6Eê-¾ý¦Cy‡RâbcSéÓg#��»°±±)ïpþΜ9ÅÌ™Ÿ³|yO,Ê;œ"‹R&S?f6:-.Y}‰¥Ô€³g2qò>f-^„�mÑf俜H\ü3s‘H„÷™H& ‚P"™(”˜ôôtΟ?Ï©S§ˆˆˆÀÌÌ WWWjÕª…³³s‰wMNIIáîݻܺu‹;wî�žžN­ZµhÖ¬õêÕCKë+ š’‚rÄT6 iÜX½ì¹jÕòŽ P/ïÔÉ›U«º`o_ð‡«De:KÓ�c.5¤“^mªHÍ‹u\Õ©({.…´l¤ë† éQ¯Xã$11�.ÝX¸r9Æ&Å[:]D2ñýó\ƦuflXmJB¼Œ*Ž9ô߀dŒMŇy€„ø¾?Ž}{†½=%,JØ… ¬Zõ”%KÊ;”÷^LL ýúubÛ¶•ì9KY�£Ä'îÎf?ä˜å¼trŸCÜ¿ðOwòóÚ•…®w-‰‚ðß#’‰‚ †H& ¥âÙ³g\¿~�ëׯsÿþ}T*666ØÙÙQ¥J,--±´´ÄÜܼÀ$czz:ñññ$$$Cdd$�=">>\\\pwwÇÝÝsóâ%­Þ&ªµkQ~ú)hk#]±IïÞå«V-B:Ô³ÐûÜ”?å`Öm´$2>5hY䊪•'QŽÞÖFH·�BRˆÙ�obßþ[ì9œÉÈ cKõ8%I$ÿ²³%ìÝfÌï¿™sï/ �”tê‘ ‰8UÏ.ïðÊÕ†Õëhì–B×®uÊ;”Rյ낂£¯/:—¦I“ÆÐ½»Íš•í…¼óçÃñõý‰ðð9˜˜¿$ˤä¦äWÓ~Œ2ðÎw›E?ÃúøvíTàx"‘(ÿM"™(Ba¼cS·„w…­­-¶¶¶´oßžŒŒ >|Hxx8ááá?~œ„„”J%zzzÈd2ôôôÐÑÑA¥R‘““CFFr¹œìlõ‡e---,--±··§M›68::âààPî5Kšdà@d�¡ôóCÙ§’“'Ë}ÙóŽ› êQ¤}Ü´*QUfM’*£h‰D…å—ÛQÍß�¤‰Ò­ŸBÅ7/_�¾®Ì_°¼Ô�#E¥££¢›_2Ýü’¹ªÏ+ÍØhBÈzS<›gÐÿ“¼Û¥•äêÿwƵ øâ³.åF©óð°ãÊ•+xyy•w(ï-•JŵkçY°`H©Œ?~|0nn•:´YžÇär% éæúþúõç˜7oOŸ&áî^™ zÒ¸±#»²®ó}Ú!üô¾2‘ðñüm+0™(‰‚ ‚ ¼ŽH& ¥N__WWW\]ÿ©G§P(HLL$..Ž””233‘Ëådff```€––ººº˜ššbii‰©©é{»Œ-WW¤gÏ¢9ÕO?¡��þ>ôË.YljªCVVV‰/É„’ÒÀ3ƒž< ×&øS6­3aôÀJÔtË¢ßà$ºôNAOOYÞa–™ôô4Œ�ßÎæZ%ÉÖÖ€¨¨¨òã½�­m镹¸{7šÊ•߬3÷öíW1b=Ë–ùãåU•€€3´mû#{®�a°^Õµ¬Ya6àµc˜šê““�ñÚmD"QA„‚ˆd¢P.d2™f©³ð FFHÿøUûö(G�BÑ ÒåË‘ôéSÁ”|r"B�½Ì 'ˆ_n´òõ%Þh¥0,Ì HNLÆÚƺL�+EUÅ1‡ñÓc>.ž­MX·Üœ™“*ðÓ< zôKÁh"6¶òò³ÔýG./!“IP(DB§4%&&bfVôe䉉élÞ|‰»w£©VÍšîÝëbcóÏlú��ˤ¤drçNúúÚ,_~Bó؇6ÀÒÒPs[[[Æñã÷ؽû:¦¦ú|ô‘ŽŽÿœ'}ûín&Mj‡¿¿Çß·»p"ô=ã—’f›Í!³Ï1‘œ\—¼æºH$ ‚ ‚PoØfU„Ò&8ÙùóHìíQöí‹rà@Èxý¬‚·]´2…õ¡üžq†(e2ªSPx͇ˆx¤!#�Îü Ì‰‰¤PËÌámad¬dÀ°Dö…>ä×µO©é–ê_Ìñõpdü0[®\5ö¡0T*U‘ÿíœ?Ž«ë7ìÜy ss޹ƒ›Û7Ü»­ÙfË–ËìÙsƒèèîÝ‹æÐ¡¿4_©©Yší$ óçïgÚ´mdg+ظñ�Ï%!!€ìl9—/?¢G�ú¹bP|­$ºb KL?¢žv•⿈D¢ ‚ …'f& » V-¤çΡ7ÕŠ(oÞT/{®^½¼#+– Rc:èºq$ûÛ…ðI׋H¬Œ�›Pê�Vá}$•B«öi´jŸÆ_7tٸƔ�ÁÆìßi„[�Lü?I⃞)È´D²\JBV–ÿÕ ÚŒY³ºjî;6ˆÉ“·°eËHÖ¯ÿ€Úµ¿eÀO&Lh—ïx*• --)'NLD"‘�œœ‰�Ývì¸Ê A^<{–ŒJ¥ÂÎÎŒ Î3mÚ6>;КN÷1Ü¡ËàoVOS$AA( 13QÞúúH—/Gºf ª;wP4h€jãÆòŽªØHí6/‰®þ¡HëWAvašH$ B p©�ÅÌÑ¼Îøé±ÄÆh1m¬ m:ñëBKdå¢ ¼óN�zÀ½{Ѹ»WæÐ¡Ûš¯Ê•Í8{öa±Æ;ÖGSÚÄD�jÕ¬yò$€Œ u3:==mž?Oæ±N"_ìÄ)Ó½ÙoV[X$AA(*13QÞ1’�‘yx ìÓe¿~HöìAºt)”wh…÷w£Ã�×0*‡F+‚ð_`a¥`èg ‘ÈŸû Y³ÔœßZ°êgs|»¦0ô³ª×Ì.ï0á�“‚L&eÅŠ“ykXBÆttdÈåêú†•*©›·DG§0b\KVtš‡ÊXF^ö&Ðò\±�!‰‚ ‚ ‡H& »ÈÅih(ÊÉ“ÕÝž/]B„ÄÍ­¼#+X!­D*â±—Y”C€‚ð~ÑÖVáÛ%ß.©Ü¼¦Ç+LÙ½Õ˜Á&Ô÷Èà“Ïðn—VeJá�åèh‰B¡dùrœœ¬ Ü^OO‹¬¬â7E21Ñ£bEΜ c¿Ù-®+žl>œÃÿ¢fM›b�)‰‚ ‚ —Xæ,ï*==¤‹#]·UDJ//T��åÕk¶ÑÊcEë2BY—Jœ2­"„÷“[�LæþüœC2jbn)ª4~»ôE©C©PrfçuF Æ—ß~…g3�R;–P~$ðj™�WË "´ \mFH  ÇRË=‹>“èê—Œ®nñ—h¾M %÷îE“™™ƒ««-::¹O‡23sˆˆˆ !!]s¿¶¶,WÂçEçÝÇ�ˆˆˆÇÅ¥"––¹/|üqSzõjÀ¶mW˜7oi=%¡œH$ÜÝ+ãî^¹Àm-- éØ1ïE>CCÝ|›¶¸¸T@…Š!‰k¸+�f«ùHºyÕ…b\+Û¼Ù‘~ý¼12~Àª`™H$ ‚ ‚Pl"™(ïIÏžÈÜÝQúù¡6 ÉñãH—,ÃÒ™÷Ja±$û,Â02Ž �jc<£®/%oÜxÊíÛÏ8vìqq©_Ô<æêj‹›Û?³-´´dDG§xŽÔÔ,Ú´qÁÎÜ*2s@]»ÌÔTŸ•+ ‘H¨[׎˜˜TfÎÜIÿþšüeakÐîD^á»C£‘HßýŽR™”fÝëâÖ¬*Ó;Íå»Å‹pªæXÞa ¥È¡jSgÇðÙñl 2fí2sfNªÀÏ/�öšˆ�í»»úÀ�[ þZZêÄ`DD<¿ýÖ�~ýðË/G3f£f{ ‹ñšïÛ¶­ÅÁƒã4·õô´™0a3kמE¥R‘––͆ CéÞ½žf++#¬¬Œ°¶6.ƒg'¼�~Lû“�ÌËL3êH7½ºÅãE"±víD,¬Æaf¾¸„£Aá¿DTZ„÷‘³3Ò³g‘Œ‹jÝ:�¡º~½ÌŸ}ô.qµf"‰Œg}÷zØ[àÙd>kÖœÑlóçŸ|‰óçÉ�M%8ø’æëæÍg¹Æ»~ý mÚ,âÊ•Ç?~�æþ ˜~u;AHRfpæL={ÖÏ•4ìÝ»aa±DE%—ÙóŽ�K`ÓÆ Œ_ٯȉDy¶œÝ+N¾òñGwžstÓERâ˧!�™µ1_¬ógöŒoÊåøBÙ36Q0`X"ûÏ=ä×µO©Q+›U¿˜ãëáÈøa¶\»¤WÞ!ÙíÛQôè±”o¾éÂýû³¸re:AAŸ0|øDDÄðÙg­P©–²wïTª¥š¯—‰¿ÿ~ ¢¢¾#:z!½z5`êÔmeþ¼„÷WhÎC¦¤lÅ[§ßw)Ö/'Ú�¶vÞ1‚ ‚ E!’‰‚ð¾ÒÕUw{Þ²ž?Géé‰jqéÏDP­< m$[¥Bzl·ŒdÉ’� Á矓’¢®8v¬›6 £W¯Ô¬Y‘M›†i¾þ]�þĉ{üùçÿ0ˆÆÑÑÝ�‡A±UwãVý«ÛgRl*Ÿ6žË¢OÞàÄ>I,‘x‹ÊÞ¥"¶5M¹~¹ìÓBù“J¡Uû4VnzLðÁHº÷MæèCúuªBÿ®vìßi„BþnÌÂ�;w/­[×ÌUOµ}{Wêׯ¾}7‹<^�õ;Ö™LŠT*¡_¿ÆÜ»�\®,ɰ…ÿ¨xe}Vb.1 Ðìc´ŠqÚþïD¢¥eÁ5ˆAA "’‰‚ðž“ôè�ìòe$uë¢üüs”BjjÉH¡D9e+ÊapE«†7ç/.^ŒäâÅH,, ÉÉQä™uXǷȵDг‘釳ùÄ 9¾z®¤§gc` Cbbׯ?áÞ½h$ zzÚ¤¥e—ä³|­ó¡¡4é\ü¦7*•Š/|¢½îh>m<—ˆ[ê×êÚñ{XU6c[ìBÚõ÷dÃüò«»æ;Ôƒý{ö”Ûñ…òåêžÅÌѼð�ñÓcy©Ãøa¶tjêÀª_ÌIJ”•wˆ¯uçÎsþ ‹ñ¹¾BCÃyRŒ$½î¿.ë¡P(ÉÊÊ)©�…ÿ(%*üW©ˆç³!T’™y ‘HA¡´ˆš‰‚ð_àà€ôèQ”_|�êçŸQœ;§îö\§NÉŒÿR£U ¾ˆÝ�Ûl;û0×f..6(•o>cGGG ¹\‰•Ô[[SbbR©U«"11 133 ##‡””L*W.ú°âÈÌÈD×X ©¬x×hT**¥Š:-�¹àCNl½Ìœþ«YvéK’ãÓ°w©ˆD"¡÷ø¶Œl<—1?õ)ágP8ÕëÙ±nÚár9¶ðö°´V0ô³ Odï6c–šñÃl+–.² sÏO¤ªsÙ%ò ËÔT?¿†üø£_žÇôÿÕJö÷ï²R©BúÔ?Þ-sR÷²/ë&sŒ»ÓV·V‘÷‰DAAJ“H& ÂÅßËžU>>(‡ Aéé‰tÞ<$ãÆ¼ïë„Å¢èò+ÜŽBòõȾîŒÙÉûŒåÍ矷)DXZo<‹ÇÙ¹çΩ—ffì¾x==mªT1£± +6:ë78Vtdµ<�èÿeGªÖ©ÌÉ­WH‰OC©Pi–N[’‘š•g)tY‘ʤHdïGG_áÍéè¨èæ—L7¿d.…êóÇJ3¶š²ÞÏæôÿ$ïvi”a¤×êÒ¥³fíaîÜl*UúçBƒJ¥ÊÓ¨ÉÖÖ€bpv®P¦q ÿmG³ï23e�tk3ÙÈ·Èû‹D¢ ‚ ¥M$á?FÒ­²+WPöí‹òóÏ‘œ8�tÕ*05-òXªSPö\ iÙHCF é¡î`:th3,8@·nuqr²Ro«R§¹ýBõê¸sç9±±©XYë9õïïIÛ¶?råÊ#êիµŒÇL¹¼•&3�Pè–Mí²ôô t Šÿ'U×@‡ÔÄtTJ©…\IFj2-éÉh騗�ª”*äÙŠrî-’‰B^ <3hà™Áãm6­3%x� £V±Z}'Ò»2zúå[KpäÈ–ìÛw�yŒÙKîß�&8ø"gÏNÁÄ䟦2nn¶4jä@¿~+>¼OŸ&1sæ…>^xxK—àæÍ§¤¥e1eÊVZµªA‡n%øì„÷Áse2%¬¢’Ì”5fƒ‘R´¿õ"‘(‚ BYÉÄb’Ëå=z”sç΃¶¶6¶¶¶4mÚOOÏòï­Mjj*æææ˜›—Íl1áìí‘?ŽrölT³f¡¸~iP’zõ =„jåI”£7‚µÒc�4´×<öÕW�yô(W×ohݺ&¦¦z\ºô77[¶l™kœîÝë²p¡-õëÿ�fͪ‘’’‰��9Ë–ù:–fͪ1aB[¼½¿§MnÝ{†¼�¯ùU9�u›z…^oâß3›Š¢R5+L,�øªçR<:¸qv÷u⣒9½ó§¶_E"• T(¹pà¶N–%µ ”,;‡ÆO�eÄçñìÙjÌÚåfÌ›aͯ ,èæ—ÂàO°­,/—Ø´µeìØ1Š��Ëœ8q�[·žáì\���‘¹‰ þ}>xp?þø'GŽÜÁÐPGÍ,ÆîÝëa` “kŸ*UÌ™<Ùmí¼µ#ÝÜ*áæV©TŸŸP6ž}áí�ûƒÀìÙÝèÝ»!.D0غ)¾¾®Äk§a@îûo+‰D¬­#Y2a3Û;F-O'–_šÆÒI!ØVµ¢–‡}ì§’š�ΤUË;\A(�¡‘’Þ’øÐ?‰Ð“ú¬[aÎúUfløÝ”æ>é “@}�Œ2�K&“âç×0O×øü˜™¼r&bÿþy/::Z2o^�WÞÞmË–�`úôíÄÆª›˜5nìÈÂ…Ò²¥³f›ŒŒfÍÚÍ®]×ÑÒR¿×&Nl�–VÁõt¿LÙÎᬿøÉ¤Ǿ¿Ç ~ͳMÅŠ&ܺ5€ìl9+~ñ÷÷ÝHK€�Áúöýsó†PÄY�eeòè)\»t�: ê°aO`‘ö}òè Ÿø cÚÿ¦â?ôõ332øÄo�„¯&0~Øê7®ÇâÕ‹ˆŽŠfçæ�´lÛg—~ŽÓ?ŸŽU+¶ü^ÄgWòí9ÌÜésÙq|;ÕjT{åv±Ñ±Œ6�‹¡061"%Yý^µ­lËâÕ?âV7ÿÙЙ™øwögȨÁ ;¬XqN3•ô´tNÜPÏÆNIJá¿W�e`hÀÈÿÁÐφëxeeö”ÙlØ@7¿nŒŸþ|â7ŒQG1zâ¨rŽ®xfMž�LKÆÆ½Ê;AÞa"™XD3fÌ`öìÙT©R…®]»bkkKJJ wîÜaïÞ½\¿~�6mÚ°gÏZ·n]Îÿw­ZµŠ#F P(ÐÒÒÂÆÆ†˜˜BCC 2Ö« IDAT eýúõìß¿Ób,ï}ŸHºtQ/{î×O½ìùØ1¤«WƒY>�K^j´"éÓéïƒ@ÿÕ ÙêÕ­©^ݺÀtt´ðõÍÿê‹ÕóÜçèh‰£cÞÙyuëÚQ·î?W‰my·~¶fŒ™ºnH®ûfoÿçDµ~$°wyýl Ax›H¥àÕ2¯–<| ÃÆßMÙ¼Þ„c q«“‰ÿ'Itî‘‚–¶X>/¼½ºÍ¸qA¥sgwž»·ì¦VWzöë‘«áŠSu§<³é:vë y¾O?-ódbjJ*i©éÔtµxív×/_ç¿aÈsrðlÑCCöï:@ÐÚMÌþqÝüÔ"Â"òᢣb¨×¸V¬8uô4;‚w2øÓÁLúz")É)¯ &;+›½ÛöR§A*ÚÚpîÔ9ï=Ì’õ¿Ñ²MKþºñçO«È<Ž|Lrr2^-›Pű Á낱¶±Ö$ÏŸ¹ÀÈ�F¢¥¥…—·*¥’ïf.àà>v†&-uçN�:ÅðáùuëVžÇZµjÅŠ+¨^=o�¸åË—3mÚ4ââârÝïììL@@@ž†/ 6$>>žˆˆ,XÀo¿ý†RùÏ ™LƤI“˜;wnžc…„„0vìXž>}šç± *°lÙ2ºw﮹ïСCtëÖ�öíÛ³wï^&L˜ÀÏ?ÿŒB¡àÓO?ÅÇÇçµ X.]ºÄÈ‘#9þ|žã5iÒ„¥K—R·nÝ<�å'%%…„„€W¯�L&C©T’™ùvv;,W/–=Ϙ�jþ|˜ázn ¼'³Ùô%Ú| çŽ»¢2–Âw(Ï#âÙþÛ1¦ŧ_ãó—qALY3˜=ë3¼þÿ4÷·ëïÉñÍ—D2Qx«¸ÕÉdîÏ™ŒŸ˦uflXmÊøa¶TqÌ¡wÿ$ü$clZzK ³Ur"ñ„)b SÄ&�ýûûXÂä1$«ÊñE#€_~!¼÷ �±°$jÿ«·™¤þºÅ3F²ž‘‰ëá塺Ç�ÏÎÁõ÷¿<; �p”»Œœk8‰Ù*9ƒõ½jЬС¾èÚìæ–ÀÕ«;VÎäÉÚddä���ÎÐ¡ÍøúëÎTÆBÖ‡`naNsu¹›v�Û1{ÊlBÖ‡äJ&>¸û€þ·ˆúõY¾a†êåÞ„3 Ë€\cÆÇ%0sâLª8Ú³nÇ:,,Õçæ1ÏcØ}ÐkãY³-€+®âÿ�?¿ž¨IJågþWó¹sóSfMÑ$å9rfM™Åæõ!¬_µž�Ãÿ‰mïö}ÌùiÝüºê'Ý[÷ (`£fÿµËÖ’—ÀæƒÁ¸ÔvÔ¨ûwéÏ�]‹”L426â‹g3mì—Ìž2›ï¿ýžÆ^�©Û¨.Mš{âÞ Nžz›å))1‰Y“g¡T*óM¿ P(™úcþ®û›+Æœœ¦~6S3¶h:”ß½u—A=¿Ñëôç¾?±°´`Þ@ê4¨@ÿ®�Ëål9BGõˆÈ‡‘ è6�éã¾$h‰„éŸÏ =-�µÛ×höÍÎÎfÒ§_ph÷!‘Lá�‰dbtéÒ…•+WG‹-˜;w.íÛ·Ïuåï…J•*å;ÆÑ£G騱#™™™ØÙÙÑ«W/lll'00�£G�Ò²eK._¾Œ���f¿¯¿þšo¿ý‰DB¯^½hذ!)))qïÞ=|||8vìžžy»KN›6�õë×Ó¶m[Z¶l‰\.g÷îÝ\¼x‘yóæÑ¨Q#>üðCÍö{÷î¥wïÞ¨T*5j„¯¯/ÆÆÆ<þœ   ž>}J¿~ý ÓÌBü÷ñ~üñGlmm©XñõuÞNŸ>�¯¯/©©©XZZÒ§Oìíí '((ˆ³gÏÒ¢E :„‡‡ÇkÇÐÓÓcÓ¦M899å»Í�7ÈÉÉÈ7q+ ^öý´%ººÚœ:uŸ'ÉI´ó­EV–™L‚––ŒmÛ®àâR—|šgéI´™kÜ=Ÿ#äïE"±víDöìÙC¥Jq|ùe_š4©ŠžžŽŽ–æ=/-o�#z2”¾ƒûjêΛáÝΛƒ»ò8â1vêj{¶íE!Wð٤њD"€S5G�È�skîûsߟ¤¥¦1uöM"ÀÚÆšÑG1yô›×cLINe϶½4ôl˜k‰¨–¶SfMáÏýGØ´&(W2ѽ¾»&‘ §¯‡g3¶oÚ�J¥B"‘аICª:h‰ î6oSɆk—®i¶+,ß.¾x6÷$$p §ŽœâÜ©PŽ>ÎÏ󯯶ÃÇ� Ï ¿"�YÎ?ƒ¯gÍíœìlbžÇ¢T*©áZƒ¡£?~å¾Ï^ ",‚‘ÿ7B“H065æË9_röÄYR’’ ¿ÇÕ‹WéÙ¯‡&‘ê$ëÌ_Ó¡IG‚ÖlÊ•LìØ­ƒ&‘P¡bjծœÈ'Ez~gOœåÙ“gL™5E“H¨áZƒÞz³ê—UEïe‰ñ‰¬Ý¾§¿Ÿûíë·¹|î2SgOÕ$ì�ì>ns¾œË_7þÂÐÈ�k—®Ñͯ«&‘ ££Ãäo¾àÈþ#ÅŽIá‘L,‚®]»2|øp–/_ÎÍ›7éÚµ+FFFøøøÐ´iSš6mJ“&M4'Iÿ–™™É AƒÈÌ̤S§NlÚ´ CÃfEM›6�&MšðìÙ3æÌ™ÃâÅê“¥cÇŽ1kÖ,tuuÙ¹s'íÚµÓì3}út†ʆ 4h7oÞ̳yÆ áçç§¹ï믿¦S§Nìß¿ŸuëÖåJ&Ξ=•JÅ AƒÈ5Ö¤I“¨]»6ñññüùçŸøûûçzüîÝ»9r„®]»2þ|\\\x�ÌÌLüýýIMM¥qãÆìÝ»KËê½Ìœ9“Ž;rùòeüýý¹uëÖ+_ßtttèÝ»÷k·ùöÛopww/0Æÿ:IÓ¦d¿fYÿûH‰’D± ì’�Žn•�H )6S+£7O×@‡¬ŒläÙr´trÿ©|/‹Šï_rXx¿èè¨èæ—L7¿d.…êóÇJ3¶š²ÞÏæôÿ$þ•ÖËAÁ#Eaò˜—fª“…±$*ÓsC¢…�Ô g-|uÝ4 ê2kjhUÀ¸–(—„´¨ŒŒ¼è¥×«¼CyoÝ~Ÿ_�=e^÷ ·ƒ1uÖåÈþ#¤§¥£«§þ›ñb©éË´utÈÉÉA©T!“IhÿA{”J%·®ßâú¥êNׯróZÞ•K…efnÆÐÑ3tôÇÈsäܾq›#û�üÇffM™EÌóhÆLSìñ‹ÃÄÔ·:n¹î³°4ǽ�;ºuÈwRÆ ·¯ß qÓ¼?ߦÞ^4õV×B<ñçI<šå�TQÉ®öŽöÜú×ëê\+ï®6YYE«×v7 Pw­þ·º ë乯(ª:h‰7®Üàஃ\ ½”kÛø¿ëfÞ½}sKõʸü^·¯‡ ›ÉÄ"Z¶l]»våûï¿çÈ‘#¤¦¦²cÇvìØ€±±1íÛ·gĈ¹’~ ^:‰‘‘¹‰öööLœ8‘ &°k×.M2qîܹ¨T*¦L™’gL}}}V¬XÁÉ“'¹sç{÷îåƒrŸôÑG¹‰R©”¡C‡²ÿ~ÂÂÂ4÷+•JÂÂÂ077gôèÑyž¿­­- 4àСCÄÇç]oN»víØºuëkëJ¾°iÓ&ÂÃÃÑÑÑ!888W"ÀÆÆ†   \]]¹ÿ>[¶l¡OŸ>Žû*r¹œ±cDzyófd2™f¥ ¼ìºê:ç8GmjÓXÒ­2øS©k Ã¤Uù~Ø|<™Ö›%põ�t©ÙÈ�ß¿ÚÉ'sÿ™õ’ð<™Mߢç˜Öo² ”™ž4ðÌàQ¸6l†-§c9�®«-ÏîB»záÊh"ñÈÿ5»Ð\j@U™ítjý�(üûKËG™%Ò2›g(¼«T*¼–&Mª2bD Íýþy]]-ÍŒÃÎ�Ýùì³�ž£uRcñâ?177 Y³joùs øõ׉––™”bÞ¥�+Ø´ P7µÈ϶ mŒž8™–Œ””Tttuò½xllbœëvJŠz†«¡qÞ’%ƦÆyî+ŽÌ uÒÖÌ<ÿš¥/îÏHÏÐ$u^“ {áRè%¾ÿ�"ãêîŠSu':õèD%ûÊÜu°H1Þûë±Ñ±x4óÔ,gÖÒÖ½¾;îõÝé7¤Ý[õ`ÝŠ?5a2­²©w àV×­ØÝ�ÓRÓ06}ýÐÌŒ Ì,Ló}ÜÌÂŒØè˜\÷¥ÁÍë$'§êÙ§ÿ¦UÀˆ‚ü»¡Š\¡.õ‘‘‘ArRrîciiáÕÒ }R“Õ¿FFù_œ661F¥*ÿZÄ‚ ¼ÛD2±:wîLçÎ�‰ŠŠâðáÜ8q‚3gÎpóæMRRR !$$„^½z±fÍ ÔK4P‚öõõÅÚÚ:߱ǎË�!C4·ÓÒÒ8rD=ýåÙƒ/344¤sçÎ,]º”={öäI&¶iÓ&ßý^,QŽŽŽÖÜ'•JyöìÙ+ŸûñãǹpA]ŒøUÿ„f̘Q¨D"¨—Tƒú5}U3gggÚ·oÏž={Ø»wo±“‰>dÈ�!;v Ö®]‹��O±Æò—•%'==ssƒ‚7~‹9Kœ‰QÅp�ëH‘âIÞ+Ý%-3-‹�ßàÎ…ºYŽÏSÛ¨ç8}]È3÷ÛGLðù�óûoý(ž•S·qçBNµ+ñÁðæ%¾ ”9r¢ˆâ‘ê�yÌ#óX¥þ.Òá)ãS`¼zÛ,àD޲‡•¨¢ªJ;wÜMÌ4³ «K­Ù¾þ*›6]$,*­RÚâŠ�OÍ<ÇÍÊ’søð_89YQ«ÖëËs¼Ê€¿“•%ÏsÿÀ�Møàu�ÒmÛ®¨®¬­-ÃÆÆ/¯ªtï^mí²û€/žD"ÁÓӉɓ·0þ~ÜÝ+•Ì�OY¶Ì u"ËÜÜ€¥Kýùä“ulÙr™ÌL9'OÞgÛ¶O‹ü³]ºô8+Wªg[edtá§Ÿ† ¯KËÑXZ(`ï·ËÉ#'yþ,šÏ&�Æÿÿ<�/ž»˜�Aœ†B¡¤jU+&Oöeøð¹¶Û¹ó¿ývŒøø4<<ùê«ÎX[mæÀ�OiÙra¾�íß?–Æ�øè£UìÛ§þ}ÐÕÕÂÖÖ”Žk3aB[Í¿W1À€¶’¶Ô l^»mIÑÒÑ¢ûèW¿'«äSk« µ*²êúWlZx�מ «¯ÍdzºÒqh3´DÒB(GÉ$£IªþNò˜GªG<ã r7Z1Á„*ØÑTÕ;‰U°Ã;~ÿb _ø}ËÏ‹ksè�-Ou”dw‹¤åÿݤ¡W4_~¹�•+O2y²/vvæ\¼A—.¿²oßXZ´PׯËÉQйó/œ?Abb:³fueúôNÅz^õëW!'GÁÙ³9|ø/¾üRÝTÂÆæŸ¿s·oGqúô¾úª3r¹’'O™4)„… râÄDttÄ©ÙÛhäÈ–ôëטƒo�­­)ÞÞÎTª”;)Ó·o#7v`ß¾›hiÉX±¢?•+=qÓ®]-ªW·æøqw®\ñÇÑ1Šï¾Û„µµ—f--Ž£~ý·{Éâæõ!ÈdRz~ô!&ùÌ0ëÑ·‚ؼ>ïvÞÔmX��AlZ»‰QGåÚ6$pK®ÛuÕ`ÓÚM¸×wí¶ÅUÕ¹*¶•mÙ½e7Ÿ}1:×s¸}ý6W/\Å»�72- Eá:½'&$ñüÙsºùuË•HTÈ\9¹È1z6÷$pu ¿/ `悯ó<ž••ÅÝÛw±°4ÇÔ,ÿÙ{o£Æ^êÏ;‚wЦcîäÙÒEË8°ó�{v¦qÓFèéé¼.˜~ƒûæšyy`×âcãsÕ°,Iõþ~n Úž+Æœœ¶¬ɵí‹$î¿›¸\>w™Ä„‚k»ºÖqEWW—}Û÷æI&n bñÜÅíÛˆ³‹3†F†l ÜÂàƒr½Ç#>6^$Axc⌵YYY1lØ0† ‡~ÈŽ;X³f sçÎÅÊÊŠädõtôWÍJÌOjê?ÊÃÃà ÜþEã—Tcðßnݺń Ø·oŸæ¾Ê•+ãââ°aÃØ»wo¾]—,--Ñ××/ô±^µÖ$>.ž oäÄÁjçóp§TùRlß°sK š¶j‚L.cÏÖ=l\½1Íù)—�?tcc +¬‘&•Jé7¢/C{£cSo†ŒŒƒ£—˜2ú/är9½k–J�©™ Æ&Æœ9~ÿ³þ8åqâQà#–Ï[Aà}eù¡‡âè☮ñ*׬DñRÅØì»™×/^ÓÊ»%ήÎH$n߸ͪ…«yýò5Ã'ÿá°| ç¼ÎT«[�Ã{3yÔdÚti‹")‰Ý[v³wÛ^Zy·TmÒÓ¡gGÍXD÷6=è5¸'Vœ=~–iã¦cjfJûní¿Ës;禾g=vmÞÍø¡ã©ß´>QQѬ\°’˜õú‹¹œrabjª…«É“?9rp)€©c¦¥+[ÔÈØˆ6]Ú°|Þr ��hÚº)VÖ–øŸõgÖŸ³(\¬°j˜Ž=;2ï¯yôõîG�Aݱ¶±æâ¹‹ü9üOäZ" ·?IÒéÒ¥K/®,bûæÍ›T‚r¹œ‘#G²k×.âãã¹}û6åÊ•SÌ‚ƒƒS<÷KŸ_çÎ�;XY%ÿBì£/7_ɨ·oßR±bE‚ƒƒ)Uª>>>”-[V­æÆùóçS<ßÌ,cV|ÌÂ|ûömªý>>³Ï³6Ó@õêÕ ¦pá¬^½š"EŠdh~BÚnÞ|Á³g=ºööÊïëÖ%Uõ¢@¹ÄdèÐmL˜PŸ¾}•ëO*W΋“ÓhÖ¬9¯‘Á˜==-U¡yss¢¢âR,Í�——@"(—0×jPKc#‰/µíÚ–Ú k©jÄÙØÚ°n÷Zîݾϓ‡O04ÊFábE�ɤ”¯R³OY\†Æ†,\»�ÇA� ¼ˆŽŽ…‹Fß@Ÿ’eJ¨mIJaÿzµÝƒer«·¯æÃûD†GªNË7-Ó(-Ô´uSê6­Ç�«7y÷›6ä/ä¦VãX&“rðÂ�d7„é9¸í»µSõ¯Õ &¥+”âVÀ-bccqÉ—;û( íÑÒV®ÚhàÕ€ŠÕ*`m›zÙ}}ÆMK¿}¹ê•7¯‚Ñ7Ð'§ƒ‹L5ÍÚÆšƒ|Óè¿·¯V+�dljÂÁ ’ݘ$#ô ô™¶x}r÷Ö]´´µqÎë„•�z‚…D"¡×àž´ëÚŽW®MN;òº©¿w²Ïe¯¼×d2'Í�Dbâ§€ž±‰1/ÀÈäÓ{+Ss3�6mmmÆLõaàè<}ôC#CììØ·CYÞÌâÓØ ¼P®r9®_¹@Á¢1·4§fýjõè×íY›ì{™LÊà1ƒèܧ7¯Þ$!!GGUFâçÏ£ÿÈ~´ïÞŽëWn�”˜H¾‚ù°±µáõË7ã ‚ d”&¦“¥¥%¥K—æìÙ³øøøP¥JÕÆ*ÉÙ¹s'  *æÏ¯,\«V-Ö®]«ÚAÙÑQséÂÚµk ¢V­Zª1õêÕÃ××—åË—Sºtéd¯çåå…ŸŸsæÌ¡OŸ>_}ŸOŸ* õ:99%H|ôèW®\ùêñ¿Ô¸qc–-[ÆÉ“'9wî¥J•ÒèsâÄ Î�;§êŸ àÇ4kÖŒ¥K—¦{C!ãÌÍ øûïöx{û²iÓeºv-G�°¶þô"ëùótt䨨±fÍy|}/°ysgrå2ÇßÿÑ™gTT3gÁÉÉ'§ô—HŽ«"/Á¼á’â22‰Œ"|]ÆkLd,A7^�ß#õº¦™-g^kNnɼǯëgË.ÌLÚÚIÌŸ¯E§N2d GŽTeÝ:/Ö®u¦L™× zƒºuŸ’+þ^½ cذí$%)xöì»w_§W¯ŠxüàŸÂÏçw $éÎÓÕÕÁÎÁN£=O>òäS¯5ž\?G�ÍG¾ìûy}ÂÏ™š™ª-oN)ø©««£ªã—’”æ÷å5@¬*]Qýµ½D"¡TùO¯‡ �²©–c§‡©™)•kflƒA™\–ì¼wmÞMðëÔO®n®”©TFã™ÉdÒŸÅ×°±µI3( Êçõå3ýœ\Kžâ¼,­Õ_&w_¶½ûžn-»Q»QmÚwoO¾‚ÊÒ …‚­ë¶b�Í@Õö‘™…™Fì—×NéïêG&¦&”­œöfz¦f¦T¨Z^­-¥’‚ !‚‰0yòd*V¬H@@åË—gîܹÁ½ˆˆV¯^Í„ èÒ¥ &&ÊO¾š6mÊØ±c¹ÿ>�7fçÎ�ªŒ Ë—/géÒ¥ôîÝ[5æ�!Cظq#«W¯ÆÁÁ�#F¨ê &$$0qâDüüü022¢uëÖßt�66Ê_Ò7nÜ @-ðÎ�;4oÞœ˜å ÛÈÈÈoº(w¶.S¦ gÏž¥I“&lݺU- xêÔ)š7o@¥J•¨T©Ršc¾xñ‚;v ‘H˜1c†$þžžîT®ìÊâŧX°àÓ¦ÂǧÆÕ ,,šlÙt�H$œ:uŸ£GïðêU††º„…E·ymÛÀ¥K�‰�MàÑ£wäË—�­[»"•~[ôÀPbHmjDÐ7ÕU\>b'ÛæcÚ¡¾¸–ÈE=“þ)öm1´F¦Ô>LˆOäìÎk¦± �ð{øU³ 3S‘"99t('Ož¼d̘6¬^íF@@êםгs½zݦS§{|[Æò×�J?î\ƒÂ…3ïM·ðkú݉‚ðÿÀÌ ÃlÌš4›ïC(]¡qqqìØ°ƒó§ÏÓgXôôEYA~?"˜˜åÊ•cùòåtíÚ•Ë—/S¦LlmmqvvÆÂ‚7oÞpõêUU�­^½züõ×_ªóµµµY¿~=Õ«WçÚµkäÉ“‡Ò¥KchhÈ�7T¬tïÞ�Zµj©Î+P óçϧ[·nŒ;–ùóçS¼xqd2W¯^åùóçÈd2–/_žáš…_jÚ´)£G�&44”âÅ‹S¶lYÌÍÍyøð!XXXP£F <È‚ xÿþ=Ó¦MûêëI$þùçªT©Âƒ(S¦ EŠÁÉɉ€««+¾¾¾éóèÑ£$%%!‘H(X0íBöþþþ8;;õ=JææŒY‹Áƒ«1wîq† ÙF¾|ÙiР066Æ|øEbb ´`ĈZ8:Z°k×u²gÿ~uK”ÈE¿~•ÑÖ–“3§)¹sgn½GÒW=%Ūçãùƒ78äÏ€D*aêÁä3‹mr¥=÷ S±~Ê�TûD…Ç £¯Íä=½2>aá§ô;gf&{{3V­ªN|üJ?ÞM›6³˜3'?ýú•Äǧ(íÛ—z&Hf±±1bŠØIøŒ$ ?£úž©—u”æ­žËÒÙKÙ»m/Ëç-G"‘àèâøËÖ©AHLÌ :P¢D Æ�Ç®]»xñâ/^¼PëS´hQúõëGëÖ­5²âÜÝÝñ÷÷gĈìÚµ‹'N¨Ž9880lØ0ºvíªqÝÎ�;ãääÄèÑ£9þ<û÷ïW+Y²$S¦L¡bÅŠj瘘˜ P(�Ë“ÿ6ËårLMMU™“Ù³gçðáà 4ˆS§N©æ§««K³f͘2e AAA?~œçÏŸãï¯,à«¥¥…©©iªõ 055ÕØíÙÞÞž .0~üx|}}¹zõ*W¯^”»C·k׎ѣG«Í35Ož<ÉÐF-BæÒÖ–3hP56mºÌéÓhР0fH$®_NÑ¢9U›¢\½úä›—§ÆÎÎ$KvºL �ؤx ¤©íQ§ u”ïÈÐh$ îß0ߨè8 ”q¢z[�ûd3ÕÇ¥¨=Fæ¿^†Ùÿ+‘]øu"#cY·ÎŸN�ʪe#K$ÌÍtér—Î�ïrôhvæÌqcÞ¼|(Lj�½Š‡G0U«¾ÌÂÙ ÿOD Q~mÙ ³1`ôŒ@\\2™\­–¦ ÂïH¿‚›››6m"::šëׯóìÙ3âââ055¥P¡BØÚ¦žÙàääÄÆ�‰ŠŠ"((ˆˆˆ¬­­É�;õZI•+W¦råʼ}û–'Ož�££cŠ;K¦:ž‡‡ïß¿×h/^¼8'OžäÍ›7<~ü]]]œœœT5"íííyøð!Ïž=ÃÍÍ PÖƒLn¬Ï­X±‚+V${ÌÌ̌ٳg3}út>»‰‹KàêÕ§„‡Ç0lØvêÔ)H¹r"^Ð$‰‚ð{> ‚ðÿB¿�žž%K–¤dÉ’_u¾¾¾> ÈðyXXdîrÍäXYYae•|�^[[Û4ƒ¦_C.—ãêêšéã ß���Übóæ+”)ã„DÇ�ߣ|ygÚ~–!7gŽåÊM§R¥Y¸ºZ³m[ÞÞe(_Þ%•Ñ5Ý¿ÿ†-–ðèÑ;’’+6 €U«ÚQ°`Öï†ê,ÏÉ»ÄP.ÇÝA&‘‘G+íºŠR™—?¾¾þ¢ðsÙ…?ž‡GnîÝÏ¢E§8pàqq ¸ºÚ0Š|ù>ñý:œ  ·À[Z¶¼Ilì>n߮Ϳÿ6 OŸòLž\œîÝoÓµë]¬¬Rô„„D›@®\æäÊe·QÄÄÄ«ú-𓸸ô'…”ED@|¼f{LŒ‚èdJñ&$@x¸f;À‡ ^¼ÐåÉ“B9’]Õ¦Mb¢æ‡AaaR´46“©ùÒ:)IBh¨f€!*J΢EyE QA„_Ž& ‚ðMJ—vâöí±9r‡kמ¡««E¿~U4‚„NN–ܼéÖ-Wxó&œ :Q¹rÞ _ÏÒ2C‡ÖHö˜­í§¥ðC‡Ö@WW+Ããgci6ªé•äaü rieOû@/›‹ü‡}ÓuÛ�©ûMç ßFdþ|¬­�;6õ]»–K¶=!aÛ¶90{v~||þ`„‚”-{‰ÚµOààð\Õ/W.sœ�•?ËÆ�k«6Fx¸œ„å÷1(HÙ–'�vve¹|Y3ë^ŒÒl¿y3? …- E’ƱÐPHÒl&"B‘B°�T‚m ÍÀ‡É6‰ÉÄE£¢ÄÆj¶ÇÅAr{·%%Ahhò×Néþ2Ÿ0†mÛ~ĵ>)Rä}²�ÄÙ³�2oÞq�þVV†œ;7€øøD\]ǨŽééi“+—9íÚyà)2ÔAAøŽD0Q„o¦­-§víÔ®�z¦­™™]º$ÿÆ=$$Š¡C·§xn›6%)[Öýt½I*SÆ)Í>ß“ ŽZYŸ%)d‘]øÿE.OÂËë!^^)WîÿþÛ”'jrüx©,˜MÍÿþûcvœ60€äVêéèHø¯â‰™ R*™lb"ÑÈàÈ– ´Ô>ïQvÒÕ½dÊÍjiIÈ–M³]"�”J*IH®Rо>è訷½zõŠÃ‡—Ó§O�þR)<~ü�®]×1`@UÊ—wáõë0¸Elì;fÎl¢ê;uê!–,9D`b¢EPПjcéê&¢§—ö÷ÑËË�rå”Ê•-;�Q£jS³¦ZZŸnH¡Pô–ùó›ãááHll<~~A´m»šW¯ÂèÝ»Rš×AAø"˜(ÂOA*•bjšÌ»Ôÿhkÿ>?®bñ$)’Г~z7ÇÔŽk½¡“Fÿ�Óadž�ZKgè:I‰Iýç"GÖ]àõã÷èèkS¬z~Z«��qê›Ãü¿Ù…BrNŸ®¼åÅ‹­,[–—ÐPm´µ5ÓåttÑ×× ÉåI&@25M&…04ŒG.W^ãСÛèê–¤|ùòèéIÐÕÕ쯥E*Á¶äë¶‘l°íÿуQ]¤jUëd��u�^1eŠèÒ¡ƒ; …‰äÓ ‹—bñâR¬_‘ž=×§øýM‹­­‰*Û^*•�;·9îîÉ—Âpq±R+]Ú‰'OÞãë{AAAøn~Ÿwç‚ üÒŒŒt™2¥QVOㇸw‡§ ¯øCÇgyNâ9¹å £“éohfÀ�Ó÷3LœÓkWŸ£‚ç,çBØ»NlºÄÑuX|y&–†™p7¿‘](| [ÛhÆŒ øá×}öìÙ²9QµªNggg+nß~űcwÕJtH’K»Ìb&&úDEÅeõ4¾«÷oßÓ­e7¼Ú5£i«&iŸ�†wÁï3h,W.\ÁÚÖšíÇ~ðz÷¯Ô¾Q{Š–(Jßá}¿zŒÝ[öà»t sWÏÅÆÖ†ˆð:6éH‘âEñçðLœ­ ‚ð;ÁDA„,�–=’Â8s¹®Œ\òÔ73’ʤD„$Sä,‘¡Ñì[~†I{zQ¼F~U{—¿3¬Ö<ÖŒßKŸyÍ¿jþ?;‘](BfkÓ¦$‡ߦJ•YT¬˜‡>}*Ó Aa¤ÒŸ+˜øêUë×ûS«VÆ7øû•ÄÇ'pëú¿¼}œ)ãÍ�2—SGNÒ¡GGÌÌM3eÌáέ;XÚ$¿Ybz½}ó–[×ÿ%.V€NJJâÖõ1³0ÏŒ) ‚ ¿)LAøÁÌ¥ÆÔÒ+MPüsä©oÐú6‚«üÈï‘;C׈‰F*“R¬Z>µv¹–Œz]˱}þ‰ŒNû§!² AøÑd2)ëÖu¤gÏ ÌœyOÏ¥äÉcÅš5(VÌ!Kç6lØv¦M;Lpp8wᆭnÝ‚LœØ Kçô«¹çή.ôÙ/«§"‚ ¿LAÈ$8iÙ±aê!ÖO9€B¡¬qØÀl€ªObbQa1عXá9 j†Æ·ÊiŠ¥�)A7žãTØNíØÛ¡ärK=2«‰ìBA~F¥K;Qº´AAoéÚuuêÌ'0p"Ù²é¤}òwR§NA Ê�¹y6\\¬È™óç̬S(ܽu—§�ž¢­«C¡? bj¦>×÷ï>CöÙ ãªÿUâbãÈW0vvÉŽ›””Ä‹§/ÐÑÕÁÒÚRãxðë`bcã°³×Ü-<,‚Ð!DGEðìñ3ôôõ0·ü”•ƵË×ˆŽŠ&‡½ù ¸"•~ú�Ç›—o°°²@WO—G��xöøe+—MñY$&$rãê ^¿z�¡‘Џad¬¹‹Ñ“‡O¼ˆD"Á>·=Ž.Ž)Žù(ðî<@KG›?Jü�¡‘fÕØØX.ò!„\Ž¹È“?OŠã ‚ BjD0Q! Õé\–bÕóñöy#ë/dÀ’VÄK� A®�cžÝ˜|%s#“§ {÷2”w/B�Ê$´]›é�|鿸•ªObB"»ŸbÚᯯ¯”Dv¡ ¿2GG –-kMîÜ#¹qã9¥J¥äùÞÊ•s¦zõüiwÌB�÷Òc(wnÞQµÉä2Zy·bÐè�ÈäÊ�€fŒŸÁE¿‹ôÑ—Ñ|ˆ‰Ž”›´õØ�î»kŒ-•JéѦ'Þ½çxÀqäZŸÞÞ$&&ѤjSœó:³rË �swnÚÉäQ“U_×(Y“êu«3kùL ó§ÎgÅü•ÄÇÇ«ú8º82eÁÜ )Ÿùý;ðªîżÕs9sü ›ÖlÆÒÚ’ãÇ’}7®Þ Ÿw^½x¥jÓÑÑ¡sŸNªû‹‰‰eH÷!;p …B¡êW¼T1f­˜¥„MJLdhÏaìÙºGÕfhlÈ"ß…-QTÕvtÿQ|Œ!äCˆª­h‰¢¸—tW›Ÿ\®|~Ÿ?GAAø’ø-!‚�… Mõ14Õ'w�H$*xºs*æ*ÁI(¦�¹MºÇÚ³ô4�Ý£ÑÞ­Ø$�¶5ã÷2piëoš{ZDv¡ d…âçÜèãÿɰaÛñðÈMÆETmׯ?G&“âèh‘…3ûù}xÿoÏND„G0jÊ(*V«@ÈûÍ\Ìš%k@¡`èø¡jý§Ž�†Ï_£)Y¶$a!aŒê?šÅ³—аyC²çÐ,âÙÆ“)£§pö¤ª–Wµ_ôóç]ð;†Œœìܪ֮‚SG&ÿ€Q“Gbþ_­À…3±xÖJW(Eßá}±´¶Äï¤ùüE'ÏNì8±ëìŸvÿÞ´f3×._£c�ú£P²×KLL¢wû>H¥RÖìø—|.¼zþŠ©c§1ÚÊT*C¡? ±`ê|Žî?Êà1ƒ¨Û¤.IIIìÚ¼‹Ù“æ0ê|FOù´]Û‰Ã'qÎëÌêí«qtÎÍõ+×Ü}ÓÆM矽ë¸uý_tˆ}.{f¯˜Ežüyxúè)ÓÇÏ`Õ¢UjsÔ7ÐGGGS“T¿¯‚ Âÿ7LAøO||¢êùM&—Òå¿Ý¬ój9Æé˜«Èu‹‘C®¹l+9�ûT¦z�tõÕ3üö%y"»PÈjZÚÚÄÆ& £ó{¿œyû6F¬¾3¹\NBBR²Ç zzZ4k¶œ¢EsR €-ÁÁá:t›©Scm­\žzïÞkF�ÚÀ“'ŒÃËkõë¢uë’éžÏߟcíZbc˜<ù«V�ÃÜÜ€ :}Ë­?60½vù:‚_3qö5WþžËž#;sVΦy­ü³j=í»wÀ:»r#‘¨È(ÆNC�Æu°±µ¡÷Ð^tkÙ�[·’ &Ö÷¬Ç¬‰³Ø³u�Z0qÿŽýRµNµdçfckƒ�­ Ù”¿J•/(—6¯\°’ÜιY´v‘*K¯QóFѧC_V.XÉð‰Ÿv;¾tþ›m"·sÊ5ŽÃÃÂ~LµºÕp÷Pfáó×hfOš£Ê zð©TJÓÖMÉf¨\®Ü©w'Þ¿Óx�"“ÉX´v!ffTªQ‰:�ë°}ý6‘Ée,Ÿ»œÄ„Df-Ÿ‰s^gŒ‹³híBª¯ÎûwÔÆ413ù¥6¢A~¼ßûÕ· ™")éÿ##À|о IDATìÍ›L̲î“x¯AÊ7;Ö23êè—#(áyº‰ð)Ë13…'Eñ2ñ-/ƒy‘ð–—‰o¹9ð.5’jŠìB!˹,ÈùóAT¨ð{×ýºxñ�;ÎêiüÖ¬­­yù2<Ùc‰„1cêÒ±cöì¹ÎãÇïqs³eòäFäÏÿ)°el¬GÕª®ÉŽáâ’±wÝÜlñôü@õ_}}mÕÿËå2–,i¥6‡ôHL>fúÝø�ðCO_�^ê›ÂH$š·oƨ~£9ú< ¼ê«ŽU¨VA­ïdžŸ/Ñýœ±‰1ÕëUãðÞ#DFDb�Í€„øï=B�FµÑÕÍØh—Ï_&&:¯6žË}«Ôª‚•�g�ŸUk¯^·Zª�Ä�ót+ìÆá=‡éëÝ�êuªQ¢L ìsÛ3sÙ U¿2KsâÐ šÕlŽWOJ”)A^·¼jœ,ZPHüÈÂÊ‚ÄÄ$ÂÂÂ053åfÀMòȧ $~¤§¯GíFµY»|�Z»™…&"˜(‚ ¤BAH“µµOž¼ÇÞÞ,íο¨ÈÈX’ZjEÕ³’L"ÅE+g¦ŒKÈõ7Éz†:˜X’@"Á‰x‘ü_ÐðíAÃ`^$¾%")Jí<¹DŽÜRF>‘](üjԯǂ™~ë`â£Gï�J�11K¿'===¢¢H5Ó5gNSºw¯�ì1kk#ºt)—êuüüÙµëzŠÇ}|ê ¯¯M±biî-•JÒ¼Þ—þý÷%¶9ìîÓ¯_¾&§ƒ]²¿_r;¨ú|¤£££ÊÆûÒçõ¿äÙÚ“Ý[öpdßQxÕçìI?BCBiÜ¢q†çüæU0ö¹í“=î�Ûž›×n©µårJ=�Êêâu‹˜=i6ûwàÈÞ#¸¸ºÐ´uSZth�L&¥eÇ–H¤RÖ,YÃÔ±Ó053¥Jí*ôØ]myõ—�ÄÏ)Ê¥Õ¯^¼"áäëjæÌ¥y�¦"3QAHƒ& ‚�¦îÝ2iÒH/n’ÕSùn¦Ï8I½f^Yvý¨°Zä‘âñÆ}+ÓnL]¢±hIÒþñýèÖ þê°†»÷�Ê?öÊÿZ”6AK!çMâ{QOS1”ê“]f�»v>låd—)ÿØÊ-±‘™3¦ãJ–¬Zöõ7+™ÄÎÁKG6l¸Bóæ¤}Â/&>>‘Þ½w1mÚ꬞Êÿ…–-½Y¸ðýû—O»ó/jâ¤c4ï2ð‡^S__�Ð�Ðd�}Ì4Ô7øö¬zww]Ù³m ¼ês`ç~òäσ[a· �¥«§«6¿/…|EO_O­-½Á73 3ÆÏ�Ï_>\»|� g.°oû>&�šÌë¯è£üþ´hßœí›óäá.œ¹À©£§Ùºn+çO�cûñíé~f2™C#C"Â"’=¦™‘kjn¦±Ó¶ ‚ |NAHSñâÅùçgÖ¬¹D۶Ųz:™îð‘;\¾Æä.U³lÚzZ XÒJ£ýôöŒ-²Ñ¤oeU›_Ì5“¢ˆE¹»dJÙ…çÞ]'iC¨¿ßA’ AK[Ž­Üw�|ÿ -È.³ÄNn…¾D÷»Þ« d¦ÞÃ1ºß`^¼ ¥Oï ÈÓ±óù¯àñã÷ô칃îÝGâêšüÒY!sµlÙ†¦M7P¬X åÊ9}—k”.íDéÒßgì´,\tS+�¥®ß[þÂnìÛ¾�‡j,¾pæ¾"à—ÏÖM™>~:ÏŸ>çØ�ãôÒë«Æqû/‹ï™ 4lÖPíØë—¯yøHU_1#ž?}Î��¨P­Îy�q÷pÇÝÃ�N}:Q§t]öíØÏ@Ÿ�¬_µ3Sj5¨‰}n{ìsÛãÙÆ“™g±bþ n\½Aɲé¯Á™Û%77nŽ¡±¡Ú±s§Îkô6aX¦xA„ß—& ‚�.Ӧͥ_¿n\¾¼“Q£*cii˜öI?¹ðð¦M?AÀÍÆLŸœ¥»¥ÊµdTðt×h/Û¨(CjÌ!èús •w ¯V..ÆÞ"$1Œ×‰ï©ù²7I_dš`H\X<• ‹‘CÛŠCÎ3rRG²Ë,Ø6òÖöæ4è‘òr=AøUÈä2þœ7ƒmë6Q©ÊbÜÝípq2EK+«gö5$DD$áïÿŒÄD¦N]EþüÉ/M2ŸT*åï¿7Ѿ}3Ξ}LïÞe00øöͪ²Ú«WaŒö9€BË–~£úýðë7këžíû3p,óþž‹±‰1~'ϱñïM¸p¥p±Ì© Zß«>³'ÍadŸ‘ÄÆÄR·I�¯Ç9¯3Å<бgë^ªÔ¬BÕ:Ê##"3p,ñññ4ïÐü«Æžõçl.]cöŠÙÈdÊ?¢£¢‰ŠŒÂÎÁ€C{sûæm v#g®O%OÞ¿”53¢QóFŒ8†iã¦1fêdr{·íåÒùKj}_½xÅ?+×cljŒwÏŽ_u�‚ ÂïOAH¹\ÎüùË9qâ8=zL#"â=ÚH¥™€KLJ &!mÙ÷Ë� �E&×¥~ófLéQå»]ç[ÉäRÊ5*ÊÞegTÁD;¹623®ÄÝÁAž�ìr leÊÌÂ�ÿñ*šv­Æ0:T¹ëç™8�͉^6ŠTÌËæGD0QømH$š´nFãV^<¸û€çOžû]®uõÑ1ên÷]Æpq± mÛ‚XXˆÝ›³‚¡¡![¶ìeË–�´h±Œøø ¿Ïï¢øÄX�Ë´Óîü“ˆŒŒÃÀÈ”æ:P¤xÑïr�´¸{¸ÓkH/æO�O�Òu)\¬0¡!¡\»t sKs¦.ü+Ó>Ì315¡ZÝjìÙº‡õj|ÓRÝ?çþIÇ&éש?ŠÀÊÆŠ€K¼ ~GûîíÕv�N¯9sвcKÖ­XG�5(ì^ˆøø®\¸BdD$=õ ÷�^tnÞ…R¼LqŒŒ ¼ÄÝ[w©Û¤.Ny2–ÝÚ¸E#üNø±õŸm\8ëOÁ"xùâ×/_ǽ¤;—/\Võ}óê +æ¯ÀÎÁNA„‰`¢ R±b%*V¬@dd$qqq™~�çròþ>ÜsŸ ŸL&à ۯ³QÈãÛ/ILPß5Y.‘3Á´{ŠçhÛh¡o¨KÐ�ç8ÌA‘Jy8¾ñµ½Ëþ>RcD[[[Uû/«uëß•’eJ°só.=xˆ¡¡!½†ô¢yûfªLE€òUËa�]sçks ¼{yãZ@¹äß ›>Þ½¼)ZB3@Z¡ZölÝC£ 5Ž¥¤a³mvö9Ø~|×lâÒ¹K„…„R¡jyê4®ƒG9U? KåÜòºåM×µ†OFÅjØ·c?ÏŸ>GOO—Æ-Ó¸E#r9åà�’°ûô.6ûnæî¿÷~óW7Wú í­¶Óu›.mÉýß9Ÿs/ñÞ½¼Ñûïû/•J™±t:UwTáðÞ#¼}ó–œvôщN9�‘‰V6Vx÷òÆØÔXc\AAøH¢Hm[4A„,ðô} Gïì „SͬžJºÝ»}Ÿ­VÒqÊ×-©Š‹‰çï±{ÔÚb£ãy|û%WŽÞa„oª´,‘¡1WŽÞÅ»! ^Ñ–{—Ÿ0 ÒL<êàÒáÛ´^¯�Õ¾j®>µW°dÕª¯:W~m ö][É ê3³z"Âoàê“3�”¤ ðÚ3²™|ª�øæé{Vûì£n¡Ì™¸ ‚ ‚ ‚ðEA~–9Myû"”°w‘5Ýz‰eN³t�såÈæôÚ@øûHU�­v\&—R¶aÚŒ®�9AAAþ¯ˆ`¢ ÂOÀÄÒ�ÚÝp=g{áTØŽ¨°hù^`Ï’SÌó’®q*·(NåÅQ(Ô5êÇÒ«£Ô‚“FºHe¢\® ‚ðc½ ~ÇÞíû¼HÈûXg·!_AWj5¨…®žnVOï›%&&qdßaJ”)�©™išýoÜäö�ÛÔ÷ª�ŽÎ·í>}ùüe‚éêéafnJ¡? ahløMã+ Ž8Æí›wptÎMíF™ÿ�äÝ[w¹~å:µÕÆ ›AÚ'¤ >>žOpîô9Þ¾y‡‘±vvTª^‘¼ny3qÆ‚ ÿßD0Qá'1`i+Æ{-£[±IH$ †¦ú ^Ùç"934–D"A[W‹l&zšê§}‚ ‚ |'ÇcX¯áDFDbç`‡¾�>Î\`ÝŠu,žµ„e–bŸÛ>«§ùMüÏ^`@ç�¬Ýå‹i‰´ƒ‰Çgñ¬%T­Sõ›ƒ‰{¶íeÓšMÉ“ÉeT¯S�!ã†`ecõUãϘ0ƒU WcniŽk×ïL„‡bhlHöÙ  çõ¦×ÌŸ:Ÿ†Íâ3u4ÚÚÚžßµËר¾aÞ=;’3WÆ^“ ‚ üŽD0Qá'abiÈÌã¼öŒg÷^£k ƒ[iGµš‡1ãhÿ¯>WA2Cðë`†ôЉ© kwù’'@™A¶vÙ:¦�ŸÎ�CÙ°}Ïôë$&&qî¤ÃûŒÈÐyî%Ýñîå�®næee.\»'GÕ×ÏŸ>çÀ®ƒl]·…Ë®°aÿ¬³g< x`çAŠ–(ŠïÎ5H$’L›oZŽ8FttLº‚‰O>ÁÛ³‰‰‰Lšû'uÕA®%W›âóÛ7lGGW›ÑSFgx.�ƒž°Ùw3 <ë‹`¢ "˜(‚ðÓq*l‡Sa»o'¹Í\AáG:uô4ÑQÑôÑOHÐÒÒ¢C�ö\½x•£û�ò0ð¹�reÝD¿BŸ}ñ÷ó'<4<Ãç–®XšÒKgê|l²[cçðéõƒ�ƒ%Ë–¤`Ñ‚Œî?šI£&1gÅìTFH^Dx8Ùsý¡�ÄŒš0|"a¡a,Û¸”RåK©³ÏmÏœ•³iQ»%›}7ãÝË[;Û,š© ÂïAÎAø ÄDÆ2»Çz¢Âc²z*‚ ‚�i"#”‚ikk%{¼]×¶x÷òFúE êô±ÓtnÞ…JE*S¯\}&�šLȇÕñÀ{�tòêÌ­ëÿríò5º´èJ«º­˜1~]Zt%&&VãZ‡ÿɈÏ2ãââXµp5žÕ¼¨T¤2Íkµ`Ãê�( UŸÍ¾›éѦ'›Öl¢i5OL_@¥éÜ»Fõ§Vƒšz.;6î “WgÂÃ"Tmw¤cSo*©LíÒuèÓ¡/ý.fhÜä4nшüóslÿ1Þ¿û j�Œˆdþ´4¬ØˆJE*Ó¶A;ömß§:¾~Õz:yu&**ÿ³þtòêÌÖ¶ʌ̭ÿl£}£öTù£*Uþ¨Š·g'í9¤ví®-»±zÑj�9mZ³‰N^�‰�Õü>Ý”N^� ¼ÈÓGOéäÕ™i㦧xA÷ƒð;áG¥•4‰iiiÑ©·7%Ê”äqÐcU{r÷ÑÉ«3‡÷ ))‰N^�Y1“GO¡“Wg^>©ãÖõéßiUþ¨JM�Z ï=œ§�žªŽO9™žm{‘””¤j‹��¥só. é1TmžQ‘QtnÖ™Vþ£j;ú<½Û÷¡N™ºT,\ ¯ÍX±`% ñ ,›»ŒN^�yóê�Æ}ïÜ´“N^�yñìEŠÏOákˆ`¢ ÂOàÑ­—Zs½lßV7IA~&ÅKC*•2óÏY¬_½�°Ð0µãîî ÕGUÛš¥¾tkÙ�ˆ°ê5©KþBùÙð÷FZÔnIhH(á¡áœ;uŽ g.бIG®_¾†©¹¶ö98{ü,gŽžV»Î»àwlZ³3 3âèÞª³þœ‰}îœÔ÷¬�¶¶6†M`ì ±ªóž<|‚ÿYVÌ_Á¸!ã ÃÐ0�š7»—7Þ½¼)_µB†žËÓGO9wê ñ¬_½��Cã�¨Pµ<7nб©7—Î_ÊÐØÉ)Q¶III\¿| PÛ6lÇÊù+É_(õšÔ%:*šÁ݇¨‚¥©?d>|ÐÑÓ¥Q‹FT¯W�‡‚Ðy Zôüéó›Ã<~ø„s§Î‘”˜¤q,£Îžð Z�j©ö«Y¿&Ë7-S 8~¼]==Õ}ݤç\<—ös?qè­ê´âþ�ûÔlP“’eKrìÀq¼j4ãaà#ŒLŒ8qè·oÜV�wãê üNø±wÛ^^¿ü¼èw¿“çÈ‘S¹ºd÷–=tòê̳ÇO©Z»*MZ6F‘¤`æ„™,›» WÎ�:Çþû5æç»l-Á¯ƒE&¦ ™N,sAø d3Õ'1!‘¤D2ùÏ»ŒHA2"_Á|Œš<Šf0qØD&�šLþ‚ù)Z¼åKáQ®¤Ú$„°}Ãvj7ª­j¨ß´M«yrþôyŠ—.þÕs­R« UjU¡UÝVDGǰ|Ó²TûÞ Àþ‹Z† ñ DEEiô×ÖÖFWO7}÷QªË7-c×æÝ ï=œá†Q´DQ@�Ñg$EŠaÉúŪ¿Ç�{w³º“FNbÙ†¥T«]•E3qæøYÜ »pÉïvv¼yùÿ³þÔkZPF ²àQÞ€Õ‹W“Ã>lP�ßµWª­Â¹Sçé>°;媔Ç:»5{¶î¥]·vªûxøˆÛ7n3dìàô?|A„t™‰‚ ?;+ æàØúo_Î$‚ ?“fí¼8zå(>ùP¥f^½xÅš¥¾ôh݃%j²eíUßív�˜�HŸa}Ôjô¹{¸S±ZEönÛ§¶ Ù­P~zê¡ÚlÃØÄ˜ Õ+pâðIb¢?•9´ç0®\Uu·®ÛJa÷Bj�D€^C{¡££ÃîÍ»Tm‰ ‰x÷òþn�D#c#BCBÙ½e7ññÊlEëìÖ¼p€þ#û}óøwHåýìØ¸“*5«¨‰2™”£ú“˜˜ÄÞÏ–;I&“3mñ4z î©Öž˜˜�ìÒåï)2\¹TÜÂÊB­ý™ ”Ê[ZãÏ´qÓ€´ï#.™¥òŸ;²ï¡!¡ôÔC- nç`G³vÍ8wòoß¼%¯[^ræÊ‰ß”Ï]¢l¥2ú£þg/¨ÚýNœ¥\岪ñzêÁ_ó§¨�‹–¶–ê9ËdRš´j¿7þUËÝ¿c?ZZZÔkZ/�'(‚�q"3Qá'1bmGF5XH6S}JÕ-˜ö ‚ ‚ð‹04ÊF³v^4kçÀã ÇÚsˆ¿¯aÌ ±hëèPß³÷þ½‡T*¥Gëc¼~õ†ï?¨ÕN,Q¦„F¿†^ 8¼ç0'�œ¤F½„|ÁßÏŸ�£Ê`×£ÀG˜˜šàUÝ+Ùù> |¬öµGÙ’_}ïé1âÏtmÑ•}F2~èþ(ùå<¨Q¯ÙsX~óøï‚ß`bjÂó§Ï‰�àò…ËÉÞ¿T*åÑKt“ch”�õjpïö}|—­åܿsŸÛ7o§xÎ÷dhl@hhŸo_çà”‹£ú«¾NLLbÎä9ŸÎûÆû¸ûï=&�œ„––zMÐ�¡( =ÆÂÊ‚jµ«²f™/áèèêp)¯¶ž˜Y˜³kÓN^<{ÁÃÀGôÒK5Nåš•yóê ;6îàfÀ-ïr3à&Q‘QXZÚ™»IËÆ,™µ˜=[÷ÐgXöï<@…êTKûA2“& ‚ üb£âX[í\¯kyš©žuA„¯°oû>äZrª×Uÿæàè@ç>�©P­"�+7fËÚ-Ô÷¬‡L.C*“’ÿ¿å ŸûØöy�=«ìÖýÊV*‹™…w¢F½;p€Ú�j ‘H�ɤ˜˜™¤xKkõžUv+�~™)O>\ØÏñƒÇ9wòçOŸÇï„s&Ïaè¸!´ònõMã_½ ºŽL.ÀÒÚ2ÅûwÊã”âX±±± ì2ˆã�Sؽ0Š �W}†ON«ºé›ççÙ¥ß*Áü\¹p·BùUívö9ðîå­úúÍ«7jÁÄïcÂ0ZÕk�æuå2åsÌ“?/zúzÉöù˜ZµNUV.\…ÿYÌÌ͈�‰¥x©â˜[š³púBž?}ιSçÑÖÖ¦|•rªóN_ÈÒ9˰ÉaCÉ2%([© ÝúwÕØ�ÆÆÖ†²•ʲwÛ^zíÍýÛ÷ ¼È@Ÿ�iÞ‡ Â×ÁDA„L ‘À·¼.–É¥©f#:¶Kñ˜ ‚ ü¬Ö,õåÉÃ'T©YEÄú\ž|.è諲 �ssòðI†�Š®ž®Zߘèâââ026Rí–ûeF€\KNÝÆuØä»™è¨hí>D©ò¥TBmmmrØÛ‘Ã>c§�Ñ8?<,™L½Tr×É, …‚ð°p´ut¨Y¿&5ë+w†¾{ë.ý:õç¯1S©×´FÆF_5þÃÀGø�ðÃÅÕûÜö$%%¡«§Kþ‚ù’½ÿ°Ð0´µµSodž�?xœá‡ÓºÓ§àaxh¸F_©DšlàðÍË×_u/É©\« “GMfãßiÞ¾YŠß«£Ž©}ýñ>Fü9\-Xûå&A)Éí’€vÝÚªšÅÅŃA6åf=…þ(„uv+Ξ8‹�­ Îy�1³0#›Q6tõtñ?ë�ß ?JU(¥ @ÝbÁô…T¯[�K§«ji‚r)¶L¦þïɳ�'½Úõ&àb§ŽžÂÊÆŠ²ˤë^A2JÔLAȆF†D†Fõùrm9u»”KñO¾’¹3q¶ßH!~u‚ éS¾J9BCBY½xu²Ç¯ú_%2"×®€r×a…BÁ&ßÍjý’’’èФ#íwH×ux5 &:†Ý[vsþôyêQ7®D™øŸñçq�úræÏ^P&V/J~¾ßCR’‚ +2¨ë µö¼nyñ(çAbB"‘‘_5ö³ÇÏèÛ¡/ñññôÔP.c.^ª8‡÷áÃûjý.]£TÞÒ©ÖL|þä%˪/1?vP™úyìÐÌÂŒgOž«õûðþgŽŸI×üÓ“ÁhfnJûxøà!“FN&)Is‡èÀ{�Ì›2/Ùûør©üñ�÷Á§k¬ßùù|Š—*ŽT*eÓõ¿«c�¥zñêªú—‰„*µªræøY.�¿¬Ú F[[›¢Å‹rîÔyΟ>OÕÚŸ6 zþTùÜŠ—.¦H|ô˜‡÷j<›òUÊc�ÝŠ=Ûö°çx5H6€/‚�Df¢ B&0³0ãí³�´;þââc�JÄ SA!}ÚukÇ�]™9qÎúS¿i=ìrÅ¥s—X·ò �²Ñ}@7@¹D¹t…RL7�—Ï_R®RY$R ›}·pãê ¦/™–®ë~Üle柳ÐÑÕ¡J­*jÇ»õïʡ݇hÓ -ÝúwÅÕÍ•W/_³hÆ"ŒMŒiÒªi¦?‹”ÈdRj5¬ÉÎM»˜0lÕëVGWO—ëWn°wÛ^ò̧Ú�95¾ËÖªêã%$$ð8è1~'üˆ��§÷�^jKÍûïC«º­i^«�ûtÆÉÅ‘Ç3ï¯ùØç¶§fý)^çcàwÆø™tèўĄDΟ¹À&ßMȵä<¼Äó§ÏÉ‘3å<رqóþšG™ŠexúøËæ,ÅØÔ„ð°ˆTïÇØÔ„;·î²hÆ" ãå IDATòÊO…jRìÛ½7ܹϦ5›¸sóÍÚy‘Ë)7Q‘œ;uŽ oĵ€+÷ïÜO×}Èä2‚î?T݇±©2+ôï%s÷ß»Ôm\;;š·oÎ?+ÿ!&:šõj`hlÈ‘½Gعi=õ@W÷ÓÆ)ÕêT埕ÿðêÅ+_A„o!‚‰‚ ™@[[›¤8)±Ññèè}¿¥PYí–_  ‰ÍaA„ô1Èf€ï®5Ìž4‡]›wqöøYÕ1™LJÙJe–k-A€JÕ*1aÆW¼ùú[ íóçTç†w7ä�QCríþüW-Ú¶`óúÍÌšö#«—­ìÁ×§ß|¸wDZrÉ*ÊV(Ë«C^¥÷€Þì�ÛÏcÇóÅØñ¸»»Óå™Î…3æÍ1×¼žÇŸyœø½øâÃñDÕ‹ºf˜hv33櫱LŸ4�IŸNbÐ˃ïyzyóDGzèÍë½^÷:>›ò)�ü˜•¿®´_Çàÿ£^£ú4º§kV¬eÉÂ¥Ô¿«>~~ xsþ~|ûÕTæÏú°ç_|ížïó|®kׯMPpÉIÉÔiXÇq¼^£z|4ò#ê5ªGPp�ãx±Ðb¼ñîŒ1š—Ÿz°ÿãõËz;‚ïa}‡óÝÂéŽÏ<Ò¹=_~ø%Qõ¢ˆ,yÍû+"òwl·rõ[‘[àØ…x–ÆÍ¡^×`ø7øaÊ÷¤ãÁÑ]ÊmóN§)¼úÊ ýUþGÙX¸}¯5»öÀ"®Øvô7œÛK•°]Ê?&#=ƒ}{ö‘šœJ`p %J–pìÄ›—K/qüè ¼}¼)VÜiÃ[åüÙó$œN hh1‚C‚®ÿ�Û(##“SÇOb±X(Vüš¡Þ­ræT‰ç/zCë2¦&§ròøIüý)V°×$þ0%Ë–ÄÃãÏQy'Ž� -%�Ј0üü}où5\Íjµ¿/ž„S øøùR±jÅ\#ÿÎuä'++‹c‡�a2™/ŽÙíÖ�ÙÉÌÌtô]¢T$&“}Êýq(Z¼�޶ñûâiÓ¤-oôwº¹‘‰©Øul-OÝÕÿV]‚ˆÜ�42QDäiÓ¡-Ýcç®5ð ò.èrn¹�«àfõU�(""7ÅÓË“êQÕ]nïíãMùJåncEv!…C)rÛÏã OOÇ(ÍJÑâEnj$¦_€*ä:æééá˜v{µ°ˆ°›®ïF�FÊU,G¹Š®}wnä:òãîî~ͰÿÊV(›ë˜Á`Èó÷ÆÔ Ó ¤yëü§©‹ˆÜ EDn/o/^é÷ÃÛ}Ȉù=ðöó¼þ‡þ#ýq’Ï_žÃWS't)""""r•w‡¾ÇÙÓ ,žËÿ z/o¯‚.IDîp EDn¡è&Ѥ¦¦òJÉé ÛÔÀÛÿ¿*&½À¯ßldõÌ?ûŇޅÝEDDDäßáüÙóØÏ3½ž¡ûó®íx."òw(L¹Åš=ÔŒª5ª2å«Éô~çCÒ/¥c4^áô«ÅFH‘`Z<ô ßÍì´x½ˆˆˆˆ¼÷>{· K‘ÿ1 EDnƒÐðP xý†"""""""ÿ!·gK4¹ã(L—(L—(L—(L‘Ûbyìr¢+4dÓºÍÿø¹322‰®Ð��G}|SŸ?}ò4»vìÆf³ÝÒºŽ>ƾÝûr›ýÝODWhÈþ¸ý·ô\õΠ‘4®Úä¦>›p:�];v““�s‹«ºõÎ%œc׎Ýdeet)""w$…‰"""""r[dgg“’œBNvö?r›�”ä222oêã“>ýš˜f1Xr,·´¬w‡¾Çs�{æ:–•™EJr V‹õ–žë¯2ÒÓIIN¹©ÏΜ:‹˜f1$'%ßâªn½¹3çÓ,†„S ]ŠˆÈIa¢ˆˆˆˆˆÈÿ€cF°ýØï]†ˆˆüÇ™ º¹ó%œN`ÕÒÕ$'&Fã{ïÂ×Ïש݅ó‰¬Y¾†³ gqss£j�*Ô¨S£1÷8ˆ¬¬,Ö­\Ç¡‡ðôò¢bÕŠÔ¬Sãºu¤_Jç÷Í¿c6›©]ƒÁ�ëýÔ”4þø}'§Ož`ýêõ¸{¸S¯Q½Üç^µžCûb2›©Z£ 5ëÖtêëjçÏžgßž}$ž¿@VfëV­ÃÛÇ›µs×|æT«—®"9)™ˆ’ÜÓüÜÜÜœúÛµ}[7n j�*ÔªWëº×¿/ž³gÎÒ qŽ<™Sg¨×¨GaÍŠ5¤§gP¾R9ÝÝ£ÑHFzÛ6mãø‘cl^¿ÿ4nà¸^KŽ…u«Öq`ï<½¼hи>%Ë”tœ7-5��ÛvR±jEX»b-§Nœ¢ã9˜s ç¨]‡Cñ‡Y·r-ééT¬\�†w7tº§V«•�k6²w×^ÜÜݨ۰.å*–s<—-ë·pôÐQ¶nÜÆ±#Ǩװ&³éº÷GDD\£0QDDDDDn«UKWóR·^Xr,˜Ý̤_J'8$ˆ1_�¡núŽvSÆOáÃw>"33ÿÒ/¥“��Í]÷ÞÅçS?sŠöà¥n½8vøžžX,V²³³©]‡'}H`P`žu¤¦¤ñüãϳ{ûnF�?Ïð/~_<ÏÄôp¼~®sO||}Øx`qÄñòÓ¯püÈqÜÜܰZ-X,VêF×aÌ„±‡åyî k6Ò·g_ÇëgbzP®b9æ¬øÉqlů+ùò£/ÉÎÎÆh0’��Måj•ùnátÌnöÝ2Ò3èÿb–,\j?¿ÍŠ%ÇBÓû›0fÂX<==ò}ß|ñ sgÎsŒNœ9u&?|3ƒþ#ú3¢ÿŒ££¿{[Ü˸Ésêäé\÷ãÕ}Ø~ìwÌnfŽ=A¯n/±oÏ~<==ÈÈÈÄ`0ðÜ+ÏÒ«/Ç晘|4ñC~øvkW¬¥hñ"t|¢#ßýógýLï½ygÐÛ˜Lf,V – Í[7gÌW8Î}öÌYz?ù2;¶îÀÃì¬,l6�ŸêÌÀ·_'ñ|b®Z_ïõ:ë÷®Ã/À/ßû"""7FÓœEDDDDä¶úöËoyáµØp`=›nbòì¯1™ÍôêÞ‹³gÎöÀéýᣩW}VïZͺ½kY·†æ­›óÛ²ßØ±u'`Ó^|âE’“?ý 6ÚÌ–Ã[xý­×Ù¼~ ï }?Ï’“xºãÓˆÛÏøïÇso‹{ólW©ZEb7,¦mL¬ù™Ÿ–Ï 9)™ž]ž'91‰ÑãG³ùà&Öí]Gï½Ù²a+}ží“ï=¸û�¦ÄnXLƒÆ .Lì†ÅŒÿî‹\m&}:‰á£‡±ùà&¶ÚÌ“/tg÷ÎÝ,š»ØÑfx¿á¬^ú£>Åæƒ›Øx`#ýGôgõ²ß=,ïk¿–ÌŒ ¾óŸû[mfãþ ´|øA–-^Æï›~'¢D8±óø3]ø~ÑwÄnXŒÉl"++‹ç»…‡‡}Ô\݆uôö@RSÒ˜ñíLN?Eý»êÓkÀKŽÑ}Þ>Þ´îÐ €s—CÇØù±?z‚—ú½È]÷Þ…Á`Àd2òø3]hÖªq»âœv`>ö¾><÷ʳ´é؆�k6²uÃÖ<ûõöñ&<2/o/Ìf3á‘á-^4W›®Ïu¥Õ#­pwwÇd6ñBŸ0 ÄíŠìÓ’çÏú™§^zŠÖZav3ãééA×gŸà‘.�0kÚ�7¼AŠÅb¥÷€Þ4º§&³ O/Oz¼ü,q»öbv³×ê@hx(á‘á ÍYÄÁýñÁp¢êGa0 dĘ”¯TމŸNÊu®c‡�1mþT:>Ñ‘*5ª8ŽçdçÐç�>D7‰Æd6áåíų½{8jXµd;·ídÀ›hØ4“ɈŸ¿/ýGô§výÚLüdF“‘ðÈp‚ìµ-Fxd¸Óyù{4ÍYDDDDDn«~ÐéØ}-ïÃËÛË1ò¬aÓh6�ìkìØϾÝ{™6q:€# ܼn3Í[7wêóê)±Wœ9yšnwãPüa^êû"«V¼éëØ´fƒ�ÖZ;½×¦ckæü0‡�k6U?ê¦ú¿z]F°�&³‰ÔË;0¯_½›Í†Ñ` v~¬SÛììlvlÝAã{ßàyëæzíyJpjʵw~^·jF£‘Ä ‰Nõ -Ϊ¥«HKMskÖúB ‡ä]CÃÜ5øù_®áòµ¯[µ€K/9�«H±ÂlÙ°…“ÇO:‚_¹}&ŠˆˆˆˆÈmU´X§cF£‘ÂE sêøIÀþ8}6Ó'Mgÿžý¸¹¹Y&’ˆ’Ø{Àñ¹ógÏc2›ò ¥þjñ¼X*T©@™òe˜ðÉDZ¶kIdéÈ›ºŽ ç/„—·—Ó{a%Âíõ�»pS}øû_{]¿¤Ä$>ýY¾mÎ%œ»ñóøçyü/<�ë¹�ŒÕj¥ß ý]ª'"²Dþ5^»†¤DûˆË¡}†^ó\ EDn?…‰"""""r[]È'`K<�ª5«0uÂ4F EûÇÚñÁ—P²t$ƒ�µ+×±»%ûøú²gçn ÿÀÐ¥s… vÃâ|ûñöö¾éþEDÄuZ>>.V„–íZòÖØ7s­™_?jÔ®Aåê•ðñõ¡Z­jT­QãU!¨Ñh$,"”ºÑu(\´°ýùDFÐøÞ»¨U�»hJ•Ë�]xd8íkGáË÷£LùÒt~ª3߈§·ýZÌnnD–*Aíè:æªÉÏÏ�êQÕý]a2›/F݆u›í-^”Gº§y½æÔŠŒ¢FDMî¯ýŸ�þ «Õš«í’KxäþÔ,Q‹Z‘µèöpwvlÝ‘g¿›Ön¢KëÇ©U¢&µJDÓ,†ß–ýæÔnÜ»ãh^¿ã?ü’æõ[�xþkW®¥yýŽõ'}ö5Íë· 5%ÍñÙ‹i=b4Mª5¥vÉÚT¯Á31=øý/Ó�‡öÊKÝz±o÷>žhÛÕ^‰(bšwbç¶�¹Úž8v‚Á¯ ¡aÅFÔ.Y›j¡Õ‰iÞ‰å±Ë¯{/ó²mã6º·’5‰Š¬Í}Q÷3îÝq\ºx)W»ø}ñô~òej—¬Mí’µ‰®Ð�¡}†rþìyG«ÕJóú-˜6qsgÌ¥y½æÔ.Y›¨ÈÚôy¶©É©¹îcjJ «–®¢yýL7€ö÷=¨!£r�{튵t~¨‹ýYEFñä#OqpÿAš×oÁôIÓ8{æ,Íë·à»Éß;]ã›Þ¤S‹G¯û½ÐŸ¾=û’’œBßž}©Q‹Åó°kÇnzuïMÝ2õ¨]ªÕÃkðT‡§Ùµ}?ÿø3Íë·`ç¶�9x„æõ[ÐçÙ>üòó/4¯ß‚½»ö:Îeɱ0aÜû÷·D5#jòèƒ�±lñ²\5~ùÑW´»§gN�á¥n½¨ETdmjÔŠÿ�iß"rgÐÈD¹-.¦]âø‘ã xqF£‘^ý^ÂÃÓƒi§óÖëoS­V5ªÖ¬ ؃Ǿ=û\(„ç_}žÀ� Vþ²’/ÆŽgÛ¦ßùꇯ®9RkhŸ¡üüãÚ?ÖŽ¨úQd¤g2ç‡9|:ú3ÂJ„Ñ6¦-ófÎg`ï�”.Wš~ÃûáëçËꥫy&¦F£�âaÅ}®_½žç:÷¤p‘¼<ðB ³eýzuï�_€¾~¾Ž¶‰9~ä8%ËDÝ$šù³æLt“hÊ”/@JR Ç�Çf³œYYY<ÝñvnÛÉý-ï£aÓF$œ>Ã÷“ {û'ùìÛOixwCÎ�=Ïþ=ûy¦S6�¦õ#­8s:�o¾ø†×ž{�k`v3“~)�nw'--�'zΛ1��Â!D7‰&²T$'��àü¹2ŽW.YE¯n/ÆkCûâãëÂ٠xœ<~’”¤, Ç�w¼¾Ú¹³ç9yü¤ãõÙ3g±äXx©k/âvÅѰi4aa?rœ®m»Ìó}ž'¤PGáëÏ&óR·^,Ùü+EC‹Ý$š¿¬ 3#“è&Ñ”(U°‡ÇÇ�'óòº™6›�¾Ï÷#v~,uÖ¥ës]¹˜v‰§Í¢÷“/óÆ»Cˆé@rR2Gå¹ÇzR<¬8FôçÒ¥tûw g_~Ùô Á!A.?[‘›¡0QDDDDDn+OOO&Íšè˜NÜèîF<Ý’% —RµfU2Ò3x³ÿ[2ë×™*R€Çº?Ê;ƒF2mâ4æü0‡G:·Ï³ÿ‹iYøÓBZ¶kɈ1#Ç›µz€&Õš²sëNÚÆ´%33“wßx—âaÅùnát||}hÿX;F��kwf›ÍÆÛßÁÃÃƒé ¦Q¤˜=|{¸ÓÃT¬Z‘w�Ì&^­yëæ4oÝœå±Ë©Xµ"ÃÞšï½™:a;·í¤ç«=éÕï%Çñö�ÛÓîžö ë;œEë9‚ÔÇNÐç�><õÂ“Ž¶>¾>|0âöü±‡jµª±fùN�8ŨOFѺC+G»ÂE‹0°÷@âvŹ&Úl6Þð^Þ^ü°ø{B ‡ÐîÑvxy{ñÝ×ß±sÛNªÕªÆ›¯¿Eú¥KL�?•êQÕèøDGj7ˆbð+CøôýÏôÎ@Gßq»âøqÉ,ÊV(ëx§NœbÉÂ% 9ÈqýùWªT¯’ï}´Z­¼3ðm )Äw §lÓŽiËs�{æ oÔö­Û©Z³*¿nþ…€À¾óé|üõGTªöç:™ÙYÙLüt§O�¦ntêFסÛþC$%&]ó;°šk]Â¥JàéåéØÍvýêõ$^H¤Ûs]Aâ½ú÷ÂìffñÜüwYvswã»EßÓoXß\Ç÷íÙg_ã/Ǿ†âÛþ )1‰�wp‰W<Óë™\ká�:qŠƒûÒ²]KG�xELׂ øÇs IDATßÀÈß⹋ñó÷åÙ—{ä:Æ£Ý:qâØ vlÙî8n4éüTç\m+T*ØGÒD5¨ÍŒ_fðÀC÷;ÚXr,Äï‹ì¡—«î?Hü¾xZwhí¯xᵘ0ã+Š…ãÌ©¶nØÊ=à¯x¸ÓÔ.WšÅsa³ÙÇ4n௾–ógÏ;MM¿–½»örüè :téàLf]Ÿ{Âå~ò’“�ÃÐ÷†:‚D€¶�Ú2ã—T¬ZÑq,ýR:G�nìþ,ž Àÿ zÅ$øøÑ£w2Ò3œ¦§wyæñ\¯ËW®ÀÙ„³7tn‘›¡‘‰"""""r[…†w:f4±Z-Ž? à´2€Ÿ¿/‘Ü(ßþÝÝÝ©\­¿-ÿ�µ+×±w×^öïÙ—k]B€c—Þò•Ê9õ˜kŠóÑCG¨P¥‚S[777ÊV(Ë™Sgò­ÉU‡ãS¶BÙ<7ШT½2‡âS«^-‚ ;mjb¸@Yrì÷38$OOÍ]Ķ�ÛØ»{ñûâÓ܈CP¾ry§÷‚C‚ˆn ÀÆ5í5Ws~†ƒ�JÕ*±`ö’“Á\hx¨s[£«ÕŠÍjsyèË•çZ¦B§÷J—s>v#<½<�¾/ÅÊÛG¬NšÎö-;Ø·ŸC×ø~^ÏᇠÈó~T¾|?¯<‡+þú{Êh´o\cɹñg,"r£&ŠˆˆˆˆÈme2]{·ä+ƒÕ ƼÓ#c>ǯÈHÏà©OóÇö?¸ÿÁûizº>ûÕ£ªsw�»í®ìœ_W¿òkyï€|+vFþ³¯k¿z4Ÿ+;üÆýG�N=°Zm<øðƒ´¬=¥Ê–$-5�^Ý{ßPm‹=œr»ÎÎÈWjÌï¾\ »®fºÎsuÕ•sç–f¤§»Ü�Õâ<²pÑÂNÇ–-^Fßž})T¤´z€�P¦|i¶nØÆè£o ò?åwß ~ r¿Þï)‘ÛIa¢ˆˆˆˆˆ¨’eì›j\ÙäâjÓ.rôÐQêD×É÷ó ~ZÈö-ÛúÞŽ�*À¾¹ÉÕL‰’ö 0öüGÓšæê#9)™“ÇN:F'^Ù,#nWœÓùr²s8°÷@¾k&Þˆ’¥#‰ß�¬¬,ÜÝÝs½·g§ýܥʔ¼¡>¿øpñüJ•+�ëø¼ó.O™µ�8«R³ Á…‚ù~ò÷$'%çj;eü²³ÿ\ë®Xh1ÊW*ÇüYó9~ôD®¶s~˜Ãù³ç¯{]ƒáºkÿ5oÓœÔäT&}úu®ãgN�á‡o¾'4<”µk\÷\WK:Ÿˆ—·W®iÛ6›�¹3ç]yár_•«U¦hñ"ü”Ç5Oùr ¿.ø•°a-^”šukûó/ìÞ¹;W»Ÿü™{ТMó[:¢óŠò•+P<¬8sgÌã¹ Žã—.^bòç“sµ )‚Édä@Üþ\Ç·¬ßÂÞ]{]:_âùDŠ+’+HÌÌÌdÑåu=¯¾»×ÿ´¶·?ùq®�óbÚE&Œ›ˆ§§÷4¿Û¥ÚDDþ ™("""""ÊÓË“Á£Óÿ…þø�vëDp¡Ö­ZKìü_ðóÏ=ÒpÐÈA<Ó±]Zu¡ËÓ]‹eû–Ìüv¦K°*RˆÍë61´ÏPÝÓˆf­š9µy¼ÇãÄ΋eÜ»ãˆßOt“hN'0mâ4ÒÓ3xÿ‹÷sm^ãŠZõj±iÝf^yúš·nÆù³çùeÁ¯œº<ònÕÒUT®QùºÓÇÁ¾‰Iÿýyí¹¾tnÕ…®Ï>�·�7«–¬æ—Ÿáé—žvlP3ø�Atk×�nw§ËÓ](Y&’í[vðã´Y„†‡òBßoè:\e2òîzuïEÇf1´�iƒÁhdáO )R´÷Ìu=M¸›Øù¿\h$UjTá@Ü~~˜2ƒ U*86º–Zõj±lñ2Þð&µêÖâÔ‰SÌùa.é—.°`öº÷솯Ÿ/…Šbë¦m ì=�µkÒ©[ŒS÷=x/÷·¼�¹3æröLÍZ5#-õ"3§ÎäÈÁ# 58ׯ2""Ma¢ˆˆˆˆˆÜ>¾Þ„G†;MßûnÅA!r-~�€>ý�‡Õj%¤pO¿ô4/ôyþš�Zíµ4r_~ø%ÃúÇìf¦AãL™3…i¦2kÚ�,š»˜êQÕy°m <==÷Þ'¼7ì}À¾!˸Éã˜0n…‹þ¹›t�u˜8scÞËÇ£ì£Æ"JFðöGo±jé*Nÿ¹snPpá‘á¹êzuð«|>æs6¬ÙH@P ÍZ5Ã?ПðÈp {�çááÁÄY“øä½q,˜½�…?-Äd2U/Š^ý{Q»AmG… ‡ämx…§§á‘áxy{ÐóÕžœ?{ž?-dÙâeøøñP»–|8a,O´íÊìï~¢E›”«TŽðÈpüý¯ù›·nŽ—·Ÿ¾ÿ#�ºüüBðæ:?ù˜£]¥j•˜:*¾=–ÉŸO&;;_Z=Òšÿô Á!bá‘á†8d�Á�öûxÕÆÐðP§ð64"Œ�«Ž5½¿ _ÏšÄø�¾dæ·3qswãîfwÓ½gwŒn‰ûU›Ö zg éé|?ù;,+%J•à��ß!nW«—®v´+\´pžk¾ñî¬V+³¦ýÈ÷“ pÑÂÄ<Ñ‘–íZòhËÇøêã¯x¤s{|ý|éÑ»‰’ؾe™™têƒ�¯á‘áŽMw Œÿ€ ã&0sê,†õNË­pœ; 0ÀþýùKl2™íÏ2 ‘ÛÍ`»Õ VˆˆüMÇ.ij4nõÊ´(èRDD®bcáöI¼ÖlLA"w€mGãÀ¹½T kPÐ¥ü+ådç�••…·�÷ öÒÅKxxxä /¦]Ì5%õŠÌÌLl6œvGÎKvv69Ù9ŽÀîv¹˜vOOÏ�˜ŸÔäTüü¯­V+Y™YxzyÞTÙÙÙX­Ö™‰3'\(°ožÒ«{o6ü¶�âaÅ1™MLŸ4�‰ŸNbâÌ „†‡�œ”L�Nϲkû.Š/J`p ?Nû‘©¦‘““{]C«ÕÊð~#˜5uÁ!A2óÛ™|ùÑW|:åjÕ«ØÃÉ~/ô'v~,�A�„†‡òó� øê㯨X¥â?xgEDD ަ9‹ˆˆˆˆÈm5eü¾ž5‰%[~eáÚ {( §˜;c®£ÍàW†ppÿA&ÿ4™Ø�±,Ùò+_Lÿœ£‡Ž2¬ïpG»·¾Ãï›~çóiŸ±d˯ÄnXÌäŸ&“xþ{ t´{ëõ·Ù½c7ÃGcéÖ%Ì^ú#K·.ÁÝÝ�=;÷äªoêWS™5uý‡÷cÕ«øù·ùÌ]5� � ^}¶é|3þbçÇÒõÙ'X¹c3�Áª?Vݤ!+—¬ºÍwQDDäßAa¢ˆˆˆˆˆÜVÝzv£vƒÚŽ×ík�ÙÍÌÁýñÄï‹gyìrzô~†ºÑuíßÛ˜n=»±lñ2N?É™S üüã|º<Ý™&÷5q´«]‡žÿדMë6³w×^’“’‰�·˜z�êÑáñ ‚ 3bÌpŒÆ? ²Z­Lüt ïnH×çº:Ú–*S’Á#‘p:�Øù¿ðÃ73(T¤}†ôÁìfŸäåééÁ�Qƒ  ºMwODDäßEÓœEDDDD䶪U=×k“Ù„»»;—.^`Ëú-;rœ‰ŸLÌÕöÌ©l6üþ6› ‹ÅÊÙ„³NíN?ÀÎm;IOÏÀb±Òôþ&üUÉ2%)[¡ V« €#‡Žr.áe+”uê3;+€?~ÿƒf­àäñ“´éØÚ$^áéåI£{1ÖÏ7t_DDDþ‹&ŠˆˆˆˆÈmõ×�Qþêbš=T\ו—_9ß>³²²0™Œ$œÎ»Ï„Sgòý¬ˆˆÈ�Dk&ŠˆˆˆˆH�ª\½2ƒ�µ+×8½·xÞbbšÅpüè ÊW*‡››kW8·[½l51ÍbØ»k/¥Ê”ÄÓË“Ÿg/Àf³åj·w×^î?èxíàGDÉÖ¬XëÔöø‘ãÄ4‹!v~,îîî”)_†UKV‘šœš«]Zj«–®þ;·@DDä?Ca¢ˆˆˆˆˆ¨âaÅiѦ9Ó&LçûÉ?8vOÞ½s7ï }€ðaоs;æÎ˜ËןMvLQŽßÏ;ƒF’–v‘r•ÊáíãM§n�Ø·{o|‡´Ô4ÅæõÞ�ÎÿäóO²kû.Fô“Ä ‰œ=s–¡¯ ãPüaj×·oÓýù'IKM£ïóý#/œ»@ÿ8Î!""r§Ó4g)pCßFRb2ox“w½�·�7©)i”,S’1Æ:ÚõÖ�s ç=b4cÞƒ¯Ÿ/)É)„†‡òÅôÏÓ—_ø2§Oœæ»¯¿cæÔ™øùù‘x!‘z�êQ£v .¦]tôÓµ#ÇŽå›/¦0cÊ HINÁ×ß—ÑãGS¨ˆ}=Ķ1m8rð0_}<�û¢î¿Ü.™°á4oÝœØù±ÿìM)Û_Çò‹ˆ°câY7‡zeò_ IDäŸgcáöI¼ÖlLA"w€mGãÀ¹½T kPÐ¥ÜV §ˆßOµZÕðõóÍõÞÆ5 ¢\År¹Žoݰ•�Ûv’““Cér¥ir_Lf“Sßüþ[7l%++‹ÈR‘ÜÝünÜÜÜœÚíØºƒm·‘‘‘Iåê•hØ´qì!;;‡šujäj{8þ0ëV­#9)…°ˆ0š>Ðÿ§>ÅfÝʵ¤$§Y:’{šÝÍ©“§9}â 7pl#ò_“šq�]ÇÖòÔ]ý ºùS˜("ÿ: EäßIa¢Ü:ÿ+a¢ˆü·(LWhÍDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰ÂDq‰¹  ÉËÅÌŽœ‹+è2DDDn›”Kçôg�ˆü«dæ\,èDä?@a¢ˆüëøyR®Hlät)""¹Ô‰¼» K�;Dÿ0ƒJ‚þ¬‘/³ÕÂêt"ò/g°Ùl¶‚.BDDDDDDDDDþý´f¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Da¢ˆˆˆˆˆˆˆˆˆ¸Ä\Ð8p€1ïŽ"~ï^Œ69–œ‚.馸»{`öô¤s·îÄ<ú(ƒ¡ KÉSŽ-‡ì?[°àcð)àŠDä¿Â`³Ùluò/>ù„ØŸ~äÍ.1T-YPeÜ2iééŒ_ô+«æëiÓ .è’DDDDDDþ'Y°`ÂätÜŠ•[н�ÍBˆ1$ÏÏŸ²ž"Ö@ˆ1ƒ¿S› ¶ É9€—Á‹ŠæŠyöµÆ€ùóÉ&ÛÑW°Ñù°àhŽ= 5…æîeØ2Ø�³Ãå/M-·Zyžïꑉ… …ð3ú9µÉ´e’Ž=à4ÙLy¶°asœï¿dKöj˜k`6ø i"ò/R aâû£FRÍh¡EݨúÔÿ«ÍFó7Þá×ßÖt)""""òt%Ä€üG™%Ù’#µü�þyQiÖ4ŽY�àŽ;eÌeòìksöfGPSÅT£ó”Î}9û8`9@¸1<Ï‘Zm™›1×ñú1¯Çò QæeÎãX޽®{<¹²S›Ý9»ù)ã'ÂLat÷êžgí諒ç¨ýYïg)l,ìÔæ—Ì_Ø”½ €zîõxÀý§6 Ö¾ºôn¸ÑÏ7ï�“Ó'sÂr€vžíò¬}GöVf­Äˆ‘sm<Ú8µ±aãÛôo1_ž0ÖÖ³mžÏpköVN[OPÖT6Ï)«É¶dvfïÄd0á†uÜêäYûÞœ½X±aŒÀ×èëÔ&Å–ÂEëE¼Œ^yŽZ³aã’í’#¸Íï;*ÿ]‡,‡˜ž>�Ò¦ÒtôêèøžŠˆÈÿ Ö®ZÅËÿ÷|Aœúc4(ZŒC‡QªT©‚.GDDDä?#ÕšŠÅ`Ÿè�wžSùR­©œ³�ÀÏ|§nËÞæøu·*¸ãÜW\N'-'(i.Ii“óH­ Ö ¬ÈZ€<äùPžç›�1›$[x<@„1©͖ì-Ž¾ÊšÊÒÖ³­S›L[&\üÀñúUŸWñ2x9µ[–¹Œ=9{¸×ýÞBˆ[mG‡ „Èa$™(„´Çüp IDATB<�wͼŸ¨xXŠ’B¤%ÒºF¥µ;à à¢ù¢íX�š@»É¶ë–ë¶%ýÕþvÉJ2ÿ¦ük«Âj­om÷|[R¶pËl�½UÛ©¶Ýc�7�gƒa`M¢trîd÷XcÆØbOoNÙNãN¤°�¯©SÓ4k¢ÍÑÌOš€^¥ç#·�ìžowÊnnZ¬;]vtîh7™ng�Ѻ“gqMq»ÉD°Î‚R¡B�&»kîWüéÐ¥›ürQ¹PLS ­J‹;öÛ+ªi«‘¤$á¬vÆGåcwM u \ô.8©œì>·ûç{Ãå ëß»{ÿÙóšók1âŒsºkJkK3Ò}dº1ß×ϵ_†kªèªPE—6Ùú 7•[º/T^[>Ã5^j¯tw(}�½$êÃtª´ÉX!„BaŸ$…BdŠ3 J,hѦ;›*ÔjKÐÖ¶›Ì¸a¹A¸9°&¬Ôi[Ùâ”8cVÌèÕz»»a‚5Av×bmé|Y÷2ù5i§M§mI¦¢š¢vgÿ¤�¤„I˜±Îkæ:ÌnÕÓòäå¶9e¯ê_¥Ž®ŽÝ×`aòBÀZ!7Øu°ÝØW'¯&N±¶¶öqéCaMÚkMÙ‘²€JÚJv€)¤pØhm3Õ£§•¾•Ýö×%�hK4:•£b¿‚^¯Òã£öA¥RÙÝ-ó¾ÊÚʘ0Y+I›(­)�‡Þ-Z»ÆÞëî�*Tv“©÷µwnOŠ’‚³Ú7ìÏꪬ«L9m9´ªômjÔ�UeÖÀ© hðÈ5yÕyÓÝyôAuœÒþyX>M>òi݆©Fm·ªña2ËL!„BdI& !Ä=Fň³mć)(ÜUî’l±î®™Þ §pK8Q–(ÀZã£N[�t×r—óæó˜0á¦r£’Öþ€öm)ÛHP¬»)Öwªo·-ÄBˆ)°VÙÛ½1F‰aaÒBLŠ �J“nRk~Ò|.›/Ö¤�½¶–Æ‚kB®—K/»Çš“4ÇV!7Ôu¨Ý×á¨ñ¨mNÙ˺— Ч}Mc-±ìLÙ X“#é%CÍ¡DX"РIwPýýÝ+�ô“LŠš"š"@úsíÀ:ÀÞ[å�F¥±»Á€ŸÚÏV…å¡ò°»¬m‘&LÖùi*û3ÏjéjQIW 5êt“mž*ÏǪ2k«o úG¯)¢)Â.odx¬æúæ® ÔfØŠ©GOYmÙ �•G�'Ã54hTé·Ð !„âéœ6�æ°ñ0]]ºÚ}ß,„ÈÝ$™è@ÉJ2[S¶²Þ°ž®«¥GˆgMAÁ H&*¼Tö[Æ",$‘„I1á¯ö·[ñ­DsÝ|£bÄSåI mÚÊ) ö÷‘lIFA¡¾¾¾Ý�5��rÕ|3fÊiËQF[&Íš[æ[lLÙˆ#*º8w±ûœ¤9ܱÜAA¡‹s[¢èA»Œ»ØjØ XÛë:8wH³&QIdRÂ$Ûï?qûÄnkܶ”mœ7Ý›SæÔœšNi‡Â‡[Âm-¤ù4ùÒM&2"IIB…Šêºêv“‰ñÄÛæ°%+Év�£FmMf©ÒO¢�µ%Ô[í�õèR@SÀ6Ç+½VMøon˜MºÕ‹õ�êSU[ Ý–ÎM€­‚ìQóÌúºôM÷¾ûÊkËgø³V«Ò>V•ÙãËSíIUuÕ �e¯ñaÎ*çtw;B!„ÈN‰J"WÌWX˜´�nÎÝdS"!^0’LÌf–þMù—UÉ«X‘¼‚$%‰%>K$‘˜ER”ô*û%81–Œ1*FòjòÚýV-Úm­FS’ñV{ÛmÑ3(N™N‘B ÅB]§ºvÏwÄx„HK$)¤PIW‰BêBiÖ„ZB9�r€d%?�ÍœšÙ=Ö¬ÄY$)IX°ð†Ëv«¾66sØt˜%…ÚºÚ4Õ§�SngzÒtÀš¬H¯ío¥a%7ÍÿÍ)³WAtÉt‰u†u”Ж°›LTPØbØbû}M§švß|Ü´Üä‚ùÔìÆ¤ `ÄÚ¢y‡T{òiòÙ’Ÿé é/¤.D]�õÏ-½ŠC=z[•™ Uº•O u m»JæUÙOÈ×g˜Û0àÑɽÜ>H÷¾ûêêêÚbO�‡Ê㱪̧ ÓOí—îì¿=N•™§ÊOÍ£þ«Q?rs!„B‘½ªëª°=e;±Jlºïy…¹Ós‘L»h&ó­iwï„ZegÁ{ F#S‚×Ñ´ZÊ͸Ú#«]2_bUò*‚ Ál5lµÍÓ a®÷\Ú9·{¦çKV¬_ xª<í¶èÅ(1$Z1`ÀKåe7•¨$rÕ|“bB¥R¥»‹×QÓQ•D’-ÉTÖU¶Û‚vÉt‰3æ3¤()h¨­«�fM ),IZ‚éÞ½œ{ÙM2­5¬å¢ù"Å@C§†v[:/˜.”XgY rd7öYI³ˆWâkUS!MÚäÞqÓq[‹ee]eÚèÛ¤Y“¬$³Æ°Æöû:NuìÎ);m:mk! PØM&&+ɶ¤]zIPWµ+NŠõõQ«ì·ah(�5Q]Pc7LOµ§­ÊL­Ø?@§&¶TÓ;VYmY[â/½Ø5hR%,Ó[×JߊVúVéÆÖç×Ï%ãMš;e܆YTS4Ã�.µ*-UuW™e4ï ¬Ãþ½±_‰'„B!DNW]W�òÚòò¥¯/ ‘LLHNfÚêõl=‚Él¦q•J¼ûz[tZkx—o…c4™¸Éê½ø KÔÚôCßtè(ïýþ�ÖgñWŸgiìÑqñì9ušÖµÿkc4«,ìq>ÍêÆûø­øjÂn‡¥yœ {ÿMw—î¬J^ÅåÉ–dš97£”¦TšÇ„CØ�²& © ÑÓ¥§Ý˜Æ&Œµýÿ0×av[w¦ìä¨ñ(õtõh¤o”ö¹)Ñ,K^€»Ú=Ýdâþ”ýܱܬ­zö’‰ÑJ´m£*ìŽÕP ™ÿZ4•ýJ3_µ¯-©e¯åÀWãk«ÔrU¹Ú]ÖMîo>à­²ŸØ©¬«lk‹M¯UÓCía«2ì&�Ǫ +¥)E)·´þëêÜ5Ã5å´å(§-÷È5®*× «Ú€ ç�Ý?–«&ý×û>yÃ!„B!ÄóOÞ× ñbrx21ìNM>ü�ZMïfM°( ³ÖoâØÅËüý™µ½ï�÷†°ùðQVï=�á1_­V™É¼KÃÊö“_ÏÒñK—ygŸ\š÷_2q�ói–yìætÉkÜrвû85êT³ÖœÕÎ8›�qV;§Ûòè£ö±µ >j}§&ÜÏe¥÷ýš¶Å5Åy,µ¿­ê+½ ÀZÑw“…ôfeT×U·•§ÇIåôXUfµuµí'#à«òµUÛ=Jz Òy«¼ñÖ<º‚L�:Ýd¤B!„B!Dnáðdb¿Ñ¿á忯ößF㢷&¢>îÖ‰è¸ø'>¦³“o·i™áºDƒW}ÛY±‰‰xºÚ¯¶Š²gý¤òÔO*OÁeù(Þµ¦š&66±Ö°–Ps(FŒ¼ýIÞIôué›î\¼Ò²Û†û°ôæõ=(@@öçÂݧC—îì¸=ªW!„B!Ä‹#Ú�«Ú=ò9QˆÜÊ¡ÉÄÓWCÙxèÇ|oK$èu:òû¦¿C¨=ÿìÜCÿ1¿¥ºíË>=Ñ)õެf‹…?þYů‹ÿáöÝÜ]œéݬ ?¿ý–­­úË™sQ…ºåË0dÜD®Ý¾ƒ¿·73?akg´”¿V®!.)‰È˜X|Ûw³�£OóWùmØÛx›¼iìÜØ¶Ëì%ó%66±É°‰õ†õô»Û³b¦ŸkÆyB!„B!DNeTŒÌMš‹‡Úƒ.=$¡(D.åÐdâѨÕϤ¹Yõ*ük¼í÷mÿï’ )iÖ};g¯ßÌ¢¯>§vÙ—¸tóF}˘ ¥ü_OkB0É` hëN\¹Ê†1ßáëáÁð?&3à— „ý�F­¦_«ætjP�ù›·2yÕZ¶ýö³í..éÆY\Sœ·]ßæm×·1(vw±É°‰½Æ½ÔÑe¼‹ªB!„B‘éT:êœÌ‚¤ôqéóÈ‘YBˆç“C“‰QqqøûxÛ*Ÿ†»‹ î$ñôNi‡êÝŠŠæû¹Aÿð5µË¾@ñ€ü|ûVoFLœbK&øyy²äëÿC£¶þàû¤{glÙÆ�ˆH ûû‘ÇÓƒ<žäõòD§ÕP< ¦cÖ«ô4qjb�q(„B!„B<ç*i+¡rVaRL’H"—rh2ÑÃÕ…ˆ˜XLf3Z�&ËÏwìâeLf3?-XÄ/‹–ÚnOHJæZøíTqøzz؉y½¬»Ç$$R8Ë#B!„B!žOµ‚" 94™X½tIŒ&Ξ§n¹2Y~>'�õékßow÷T÷©T9†«‘ç)™¿Š£CBˆTŽ\Û.ÉDñL܉»ÉíØÌSÊÑ¡!„MRJ§nÊödânãnŽ�ÓË¥î*÷l=·"ó$™(„È‘\�<(ä#°„9‰ÂñkÛ„ÈEÜ]|åZ'„ÈQâ’£ˆŒ ËöóæSç#F‰aNâz¹öÂCå‘í1!ŸÌLB!„B!„ÔД ³¾3Z•GG#„ȈT& !„B!„¡JhKP\[*G‡"„ÈÀs•LÁ³B!„B!Df„ZBñRyá©òtt(Bˆ{ž‹Êı‹–ñzýº©‰ÕK—̶J*Haÿ¼œ»žmçB!„B!^T)J K’–0'q±J¬£ÃBܓ㓉F“‰=§ÎЪV ‡Æ}—ëw")šÏß¡q!„B!„/'•¯;¿N ,LZˆ"[= ‘#äø6çèøxŒ&Eòùeëy“ oÛ‰Él&ôöf®ÛH•’Åyý•—³5!„B!„âE¨ ¤«sW@6h"§ÈñÉD7ggîÜ�ÉÖóÆ'%3%x-µšyòðI÷ÎôjÚ�6Ç¿dB!r˜äd1ÑwÑétxy{¡ÑjR®r#슢P°pAG‡"„âƒÁÀݨ´Z ^Þ^huò9J<¹@M £CB< ÇÿDwsv¦dÁ<{žžMgÛyý¼½Ø8æûl;ŸBˆÜ%!>�yÓç³vÅZ.ž½€ÙlÀÙYOŪéÜ«3¯u| •J¾a¿oÎÔ¹\ˆ !„ÈQΞ<Ë�^C ¿n»ÍÓË“ÄÄD’“ Øs�{²ji0ã§ÿ†³‹³£Íâbâ˜8æâbãùjô—�ý¸%ó–¢( ]zvÎÂè„BdäòÅ+ é9„Ð+¡¶Û<¼ut¨Ï…%�•É+iéÜ•�£Ãâ…ò\$]ôNü;î'~˜Ä7³çC©‚™8|h¦wyž´b5·ïÞ Rñ@~^°€þ­›Û’‰~^^T,øtA[,´Øø/>—B!O¨TééŽ'„ÈVŠ¢péô%N9ŵ‹¡˜Lòá*34 …‹¢l•²”ªPê…ª _¹xá7ÃÑëõL_<�üòÛî³¶2å‹GâáéΔñSY6Ã>Š~F�ýN‡œæÖ�[;tœ5ÿ¬ázèõLcëÆmDÜŽ`À»d—OÀb¶pêÈ)Î…œçúÕ0,Ù%53œôN)Y„Š5*R¤DaG‡ãPëWmàꥫh4j¦M¡X‰@Û}*•ŠBE ñá—âíëͯß�cýªõ\¾ðÅJs\ÐÙìÀžƒ¬\¼ €ß¦�£IË&¶ûú êÃè¯Ç0{òlæN›G�·zP¤XG…úܸk¹K˜9Œ¹IsééÜ_µ¯£Câ…ñܼóötuå§�oñÓÀ·ìÞ="ƒÑ~Õ�«^O~_ë7k~ú&ÃsujP�N ê=y°:ªW¡÷‚Ř׬AU­ªÏ>CÕ¡ètOwl!D–Š�M`í¢µÜ »E¥J•èÑ£>¾¾¾xxx8:´çBBB‘‘‘œ:uŠ ÿläðî#´îÚ OOG‡–-Ž:@å•S%Öÿ�þüý×l {¶ï¥}×vÙbŽ0rÄœ=yö©Ž±dîT*�{vzFQ ñ∸ÁšEkIˆM zõê4mÔ\]]Zާ( qqqDDDpìø1–Ï^N±ÒÅhÞ©Ù [­xüð1J—{)U"ña½ßîÍÔß§Ç®­»_¨dbðk"±zíꩉ`M¸~øÅ¬^¶šÈ;‘ìØ²ƒžý{:"ÌçJAMAz¸ô`AÒΛÎSÛ©¶£Câ…ñÜ$3Òvä79Ñî}íëÕaù·£²9"ˆòõáÒ�!”˜4 åða”®]Á×UçΨ† AU¥J¶Ç$„x´˜èX–L_‚·—7Ÿ~ú)þþ/VµØ³�'OŠ)BÕªUiÙ²%óæÍcÁä…tî׉<þy^–3 €µ5þQÜ=Üðnn‡ßÁ7¯ýÖœM«74;ˆGO’”˜Dþ‚ùiܼoy“|ùR­�þÇtölßKßÁ}x¥É+¬_µž9SçráÌy†|0„[¬c=~üý‡t¼÷ù÷\¹x…®}ºÐ¼MsÛíÉÉæÏ˜ÏÚÖréÂ%4 E‹¥M§×èѯNNN©Žóþ€ˆ‹�côŸ£q÷pcæ¤Y¬Z¼’;·#Øw~/¯w�;áwl�‰¹Ã’¹Kùš=èFØ vmÝEíúµ)øbW ‘Y7¯ÝäŸÙË)]ª4ÝÞë&_–=�¼yóR¬X1jÖ¬IXX³gÏ&hÊ":÷ïŒë 8êÃ�œ@r×>'''¾7�Ð+¡äè:vßöÍÛY8s!Ç'>>žüùx¥É+¼9ô- )˜jí‚™ ؼv ]zw¦EÛlÛ¸�™“fröÔ9¼ÛŸ=ۭלQ?}AÑâöGZýúí¯œ 9M›N¯Ñ¡[ÛíF£‘ ¿¼4˜ g/ ( E‹¥u‡VôÐ+ͼã‘ÿ üf8_ÿò5ò3{Ê–-'ìZ»Níä̽/К¾ÖÔnZ�–⥊y'’ð›·ù:ŠÿÒb�Û �àù«é1¤;NúÜýº–.[šM«7r$„3ÐýÍîé¶yýh¨ÝÛ�F#Ÿ¿ó9kW¬ÀÅÕwwB¯„2{Ê‚—3iî$*V­h{Ì…³س}-Û·äϱòǘ‰¶ûJ¾T’i¿O#*2š ÁìV;DED±hv‹’j”a7x»û ._¸ €�¯ÉÉÉœ 9Å©�S¬]±Ž© §àáõ_2âàÞƒDEDÇGƒ>bßÎ}©Z‘{ì•êü—/^ÉT2qÙ‚°X,tî%¯‘ñ±ñ/XM¥Š•èÙ³ç 5†"«*Tˆ÷ߟñãdz6h-ßzý…{]K—-X–O�0•þïôG­¶¿‰HÿaýìÞn6[øß'ß°dÞRœ]œñôô ìÚuÌZHð²`&Ìœ@­zµl�¹|á {¶ï¡^£zÌ™:—Ÿ¿üE±¶ë ,BÐß‹¸z�µ+Ö1øýAiΙŸÀÜió0 |0ê}Ûí·#Üs§CNàåí…Édâìɳœ=y–ÕËV3mÑ4òøý÷îèÁ£\¹x…øØ8ÞûâG¶nØšê\ D±X(Qªxº¯cTDÔ½óIb,3$‘(Dö“m¢²�zìXTõë§¹]9tˈ˜ ÆÒ³'ÊöíˆNqßñ}ÇIŒK¤_¿~’H|†´Z-}úôÁd4qh×aG‡“åºõéŠo^ëÌžï>ÿž�^ç÷ŸçÈþ#¶ªÅŒŒùúÖ®XG¾&Í™Èþ ûØyj«v¬¤zíêDEF3¼ßpâbâÒ<öø¡cLû'ù ägȇCømÚ8*T­@ë×[°~å»çܼv3f³…*5«Ø*ý Ãú¼Ãå —©V»«v¬dç©ì¿°�‰³ÿ _@>BŽ„ðÅö«ÿ§OœÁ¾�û¨R£2Ÿ÷9ã§ÿöXÏ?#f³…eó—áãëë­šdü!„;÷ãáîA÷îéÑ!2ÏÅÅ…~ýúq3ì&çOœwt8Ù®C÷¶Ñ¿ý0ž¶¯´ã×ïÆq`ÏA’“’ë“~™È’yKñÍãïSDzÿÂ~vœÜÁº½k©×¸q±ñ¼?à"nG¤yì…³øå¿�Ç/ßÈØ)¿P½NuÚvi Àú•ëìžsûæ J¾T’rË`6™Þo8§CNS¾ry–nZÂî3»Øw~/ÓM¥PÑBœ;}žO†Úß$eÁ¬…lݰ•ò•ÊñÉ×óû¬ 蜜øuêXmXD½ÆöÇi�;}žKç/ÖVh!„ÈÉ$™˜´ZÔ ÂÃí’Uª ž0õò娿ûU½§œÓ(„xbŠ¢plßq6lˆ»»»£ÃÉu\\\hújSŽï;Ž’ËüçõÏËìåS£Žuƒ° g/ð׸Éôj×›Ú%ëгMOþ3‘ã‡�Û}ü¥ó—X0s:�Ž) §Ð°YC[uGñRÅ™¾d¥Ë–"üæmæMŸ—æñËüC�º5Þ¹Šw>F³6Íðòö¢}·ö9pÄnûÔ†`k’±]ç¶¶ÛÍ^̹Sç¬ç]<�â÷ª)Ôj5�š7búâièõz[%æÃ–Î[Ê�‡0/x½ô|f;.ïܲƒð›á´ëÚNÿBd‚!ÉÀ©£§hÑ¢Zm®iPÊ1üýý©]«6Göut(ÙÎÓË“¿—ÿÍË�^àÊÅ+Lÿc:o¾þ&µJÕ¦[ËîŒÿq<‡÷¶U>èÖ�[Lûc:�š‰s&Ò¢m 4뵯p`aþœû'UjVánô]fþ9+ÍãW,ZA¹ŠÛYQ IDATåÞ̈ÿNËv-ñÍëKû.íP©T©uÚ°êÞµï�¹ÅÁË‚9zð `Ö²™”©P°Î5¬Û .³–ÍÄÝÃ�½;ö²{Ûž4Ç\:o)½ö"h}}÷¥IË&¶ç’žè¨h>{ç3E¡ZíjT©)ã°ž–‚B¬ëè0„ȵ$™˜] ´&5ë£GQæÎEUª”õ÷÷ïBd»ÈÛQÄÞ�¥jÕªŽ%תZµ*†d7®Ýpt(Y®XÉbü½|AëÒwp_ÊT(ƒZ­Æh4rôà1þû'=Z¿Açf]8z õ‡ÎåA+°X,4kÓŒ’/•Lsl�NÇ {­Z«ÿY“æ~µFÍOüˆ‹kê™]å*–£tÙRX,[âð¾»ÑwÙ¿ûNNN´lßò�X–0àÝþv“vÅJ£M§×Xc'–2Ê0ôÃ!v_£§±øÞÆ+]¤ÅYˆL¹zñ*µ† *8:”\«jÕª„_')áѳs£BE 2uá–m^Jÿaý(_¹<�³É̉£'˜2~*½Û÷¡}Ãìݱ7ÕcW-Y…Éh¢^£úTªV)ͱ55Ã>´ŽY»|�Ý„ä¾ÇÃ3õÂEŠ¡j-ë{»u+RW'&'%³cËÔj5m:¶±ÝþÏ‚è;¸/®ni7$ (@§{Ù»ö,ÌÇ_}üØ•¿çÏœ§{«œ=y–€‚üøû��õ8ñhë 뙑8ƒ;–;/Bdš|%™�T�£þòK,_}…* Õ×_c<sÍš¨gÍBÕ¦MÆBd‰˜È»huZÙp% yzzâæîÆÝ¨ Ìø¹@…*¨PÅú¡=.6žã‡Ž±÷6oàÚåkœ9Í›ßbÒÜI¼Ü°.€-¹˜’’Ââ9‹í7*2°V1ÆÅÄ¥šWX¹zå4›³Ü×®K{~ùß/¬[¹.ÕÌÂ-ëþÅd4ѼMs<½¬s‡9wê×._K7–¤{ík÷w±~P³×š¥;3ëI…ß¼ÍöÍÛ©V«Ú µ ¨ÏÂÝÈüüýÐétŽ%×*X° Š¢p7ò../àF,/•‰—Ê¿Xg† áÀîlÞÈ¥ó—¸xî"ow›_§üjÛŒäȽkŸ¢(é^oëuàæõ›(TÀv_©2%Ó½&´ïÒŽÃû³nåúT³ŠwlÞARbuÔ%_€õýŸÅb±]Ïn^¿™n,q1ÖŠ·£ÓV¡¾Úª mÆE"&£‰égðׯ‘’’Bé²¥øsÞŸ¶vqñt*k+sÒt’yIóèãÚ_•¯£C"W‘db6S}ñª={PBݧꊱt놥];TヒzÌ�–-!²]RR2®®i¿}Ï–››[†»çVžîÔk\�z�ëñþÈlÛ¸�ÏÞùœØ˜X¾ùäÖí]‹J¥"2"°îä¼iõ¦ �{óúÍTÉÄ‚… ¤»¶M§×÷Ã8Ž<Æ­·lX6o ]—ÿZœ£"£±X,ü5nòcÅñ°GÅò¤þYøf“Y6^â $'%ãæêæè0r5ÔjõcÏ ÌíÜÜݨóJê¼R‡w?}—½;öòñ�OˆŠˆâ›OÿG£æ�Ðê´DÞ±^ûvlÙÁŽ-;2<î­ë·R% NÿKÊíZòã?rñÜE.œ½`«úß°ÚzíkûÀx�¸Ø8RR¬;SϲÓNý0û×¾Œ¿0=sâ #G|Á™gÐhÔ¼9äMÞûì]ôz}†��'@@O—žìNÙ-´‘$™˜ÅÒ”·«Õ¨çÍÃ\­ܽ‹ªjU4‡a4eÂ,»w£ ‚âéïò%„ÈŠ‚ DŸÕÔj5ØiMÊ-®†±è^Ã{Ÿ¾›j÷â‡5lÖ�O¾ù˜/FŒ"ìj—Î_¢Déè�­$5oDµZ·Ýßßìå>ÿ|éW×úåó£^Ãzlß¼� «6ÐgPâbâØ³}>¾>¼ÒäÛZgçÿ>м9äM|óø<2½³sšÛüó?ÛJ_‹ÅºñЧ—'ÍÛ6¦Çâ…!—º,§R©ì¶áæVwÂï0gê\�x7÷ôÖu^©ÃW?Éðþ#ˆŠˆâÄÑT©Yç{×�—Ö¥Î+u2>žøøxˆ��·U %&Z[=œœœlCÔ���qww·ý’o7…È^IIILÿc:�ÞèHÑâE¹þ~ 4Àݨ».Zˆ³'ÏRºl)ú¿Ó?Ó1<*� о[;¶oÞκ•ëé3¨ÿnØŠÑh¤U‡V©ë“Ç7w7âhÔ¼5ëÖÈt,šg< x϶=\½NÏþ=S%;…B8ŽÅb±]ûZ´mNùÊå¹¾BÕ®}ÑÖk_¡¢…8¸÷ E‹}²k_ uèÚÞšL\±Žw>Æî­»IˆO ]—¶©æ":;ëñËçÇ�ð;Ôkô2�[4~‚XÒ¿öÍ™:—Ÿ¿ü�VÃÇ_}DŸA}žù8!„ÈI&*R„K7oQ< wσ8y-”ÏK¦ž ª]î%…l·õ郦F ,]»béÖ ÕÎ�Òöü‚ˆŒŒ$,,Œ°°0nß¾MDD‘‘‘ܽ{7Í7ÛÎÎζ7Z­“É@rr²-ÑøàÚ¼yó’'Oüüü páÂ(P@æ% ‘Š•(†·�7w£ï²lÁ?¼?rÄ#×_½tÍöÿ…¨Q·&›Ölæð¾#é>î䱓Œûþ7¼}¼øeò/™Š±q‹Æxxypüðqn„Ý`ã½6¯öìd Öa÷ÕkWgûæíÙ$Ýdâ¢Ù‹Ø¼‘z�êñÖÐ73Kf-ž·@Zœ…"ñÏïO@Án^¿É²Ë2L&^½tÕöÿ­×¾Zõj²º5S‘¾! fœš·iFž¼y¸qý&‹þâÀžƒxxy0hÄÛOcû®íY4{ÓŸNJJ íºØOx6iÙ„&-›°eÝz´~ƒ7ú½A­zµpvÖsæäfýù7wÂïPµVU·lòD±<®åAË1MR•(„9ЛCÞdç–]Ü{�ï>ûŽA+hѶ�%Šâ“Ç—»QÑÞw˜UKƒ¹}ë6NNN|;î[[¢‹« #ø?>ö£¿уGiÝ¡þùü¹~›¥ó—±sËNœ]œöÉ;Ocûní™>qs¦ÎÅh4ÒµW4š´IÉšukоk{V,ZAŸ}éþfw^nPW7WΟ9Ïìɳ »F™ ehÓ©Íc�;1!‘�[vpëÆ-~ýnÜ#×?N»¸x2ÅÀ–”-˜3o¸¼A~µ$…xÛ€eòÌYtëОQ�ÛѰRÚjˆçÕÝøÿ1…îýR®\¹§:–ªO45kZw{îÞÕêÕ¨'O—g­ÈJf³™��vïÞ͉'Ðjµ”)S†N�:Q¦L<<<2>HðööÆÛÛÛö÷ó~¥ä©S§Ø¿?ÁÁÁäË—�ºuëR§Nûs?…érquaúâéü4ê'V,ZÁá}‡9¼ï°Ýµå*–ã»ß¾M3x½Ç›Ý1¦ÿÃo/ &xipªûóäãש¿ÚÚÃ2«J�Ê–äÊÅ+¨ÕjÚtz-ݵcþ×|Éêe«™:a*S'LMuͺ57}œÝdÏŠ¢(,�¿ wwZµo™eçBñdt:“üÅ/ßüBÐìE„ !äHˆÝµ%_*Éÿ~ý†ÊÕ+§ºýµŽ¯‘œlàç/fcðF6oLu¿<Œùs4ÅJ>QŒ%J— |åòœ}úP¶lÙ9§P«ÕR²dIJ–,I»víçÀ�üû↓X±‚*UªÐ¼ysŠËãB<6Ow¾ÿƒßĺ•ë8qô·oÝÁl2áåëMé²¥iÔ¬!5êÖ°;  ÏÛ½iѶ‚7pæÄñôò Zíj´hÛg—Ô»'¿ÞýuªÕªFÙŠe+ÆoýÏ]ÄÝÓÃÖbm�³³žÑ“~æÍ!}Ù¼f3a×®“bH! PõÕ£núižÃÇ_}Œ!99à h”7o[…æÃÇ»pöîîn´~½5.®ò…šBäDÎ.Î|ñÓô·?kW¬#äp·o…cL1âéíEÉ—JÐàÕÔiP'Ý6åNot¤Q³†lX½‘“GO’Ÿ€»‡•kT¡e»¸{¸§Zߪ}KJ•)IÉ—ï³Ñ?Žäìɳè��)U&ý‘Z�–¯Ç|EÏþo°iõ&®^¾Š!9…|þÔmP—W^}%Ísxç“wˆ��³µn?(o>¿T]©Z«êc¯™ç§ö£§KOÔ¨ŸÛüƒަRÞÝÁ"##Ù²y3¡W¯`LIqt8™§€¯Ÿ5jÕ¢jÕ¬ûÁ¯Ìž�eèPP«­mÏÝíÏ"Ž‘˜˜ÈºuëØºu+:�Ž P·n]ÜÝÝ3~pd±X8sæ [·nåüùó”*UŠŽ;fKR14ê"›Ï,§V‰ì«@:qð·â믿ζs¾ˆF�MñòŨñJæwÂñÖ›ÁGÍut "8rm'"ÎR¾`�l;çöu;ˆ�ˆgè�ÇÛ0B<™�>úˆÖÝZQ¼Œ|+ž?qÉQœ ÝM¿úŸ::!Dæ°ÊÄåÉ“‡.]»::ŒOÕ§šZµ¬mÏ=z Z³õ_�««£C{¡Y,¶mÛFpp0�†¶mÛR«V­Y…˜jµšråÊQ®\9BCCY¿~=£G�¦jÕªtîÜ™Œ*(Uy™©ááááÌš5‹ëׯӤI6l˜áŽËϣ… 3`À.^¼ÈòåËùæ›oèܹ3¯¼òJº-šB!„Bñ<±`AMÖÍ�"·�dâóÈÙõøñ(5kb2¥n]Ôý…ê�7²=EQˆ��%&&†¤¤$, ‰‰‰èõz4 ...¸¹¹áããóÔ»ç${öìaÞ¼y)R„�?þø…¨Ô+Q¢ï¿ÿ>[¶l!((ˆcÇŽ1`À\dS !„B!Äs,ÒIPrmôm(¢)âèp„ÈÑrOfç¤êÕë¿Ýž{öDµn]–¶=GGGsõêUÛ¯;wî…ÉdJµN§Ó¡ÑhHNNN¯J…——yóæ¥P¡B-Z”ÀÀ@òçÏŸîæœHQ–-[ÆÆ�iݺ5¯¾úê U�§V«iÚ´)åÊ•cÆŒüôÓO 6 G‡&„B!„OD… “bbaÒBº¹t£¨æñ7’âE#ÉÄçÝK/¡Þ»×Ööl>xõ¢E¨*TxêC›L&Ο?OHH!!!ܾ}�FC�(\¸0%K–Ä××¼½½qrrJÓâk41�ÄÆÆMtt4‘‘‘„……±oß>’’’pss£\¹rT¬X‘ *àææöÔ±gEQ˜7oû÷ï§_¿~Tx¯óóª@�¼ÿþûÌœ9“±cÇòÑGáçççè°„B!„"Ó|Õ¾ôréÅüäù$*‰ŽGˆM’‰¹Áý¶ç† ±ôï�¥V-Ô& 0à‰wõêUvïÞÍþýûIJJ¢H‘"T¯^�—^z‰‚ fªUY§Ó¡Óépuu%þü©îS…ˆˆΟ?Ï©S§˜;w.&“‰ *P¯^=*V¬ˆF£y¢ç�U–-[ÆÞ½{8p ¥J•rt8çææÆÛo¿ÍÔ©S7nŸ~ú)^^^ŽK!„B!2ÍWíË`—ÁhU’*âQä_H.¢êØMÅŠXºvÅ2p ªíÛQÿù'rä7n¤_¿~’H|€““ `„ ̘1ƒ#F¼PmßB!„BˆÜC‰BdLþ•ä6¥JYÛž?ùÄÚö|à€µí¹bE»Ë- {÷îeíÚµDEEQ³fMzôèA�²9pkc… ¨P¡qqq8p€­[·²qãFš4iB³fÍ–TŒ‹‹cöìÙ4lØð…nmN�^¯§oß¾üúë¯lÞ¼™¦M›::¤JPPׯ_·ý¾G�¤Z“��ÀäÉ“éÝ»·´£ !„xî¬_¿“ÉÄk¯½–©Ç%''3iÒ$»×F!„B<™çg× ñøôzÔãÇ£^¶ ÂñԮ�2~|še—.]âÇdþüù”)S†‘#GÒµkW‡$æááA“&M5j­[·f÷îÝ|ùå—ìÚµ EQ²=ž 6àììœé7°/š5kÆš5kÒl¾#²V\\ÑÑÑ„‡‡3jÔ(BCCÓ¬‰��gÔ¨QܼyÓ !„OgÙ²e,^¼8Ó�KNNfÔ¨Q„……eATBˆ…A1pÝ|=ã…B¼ ¤21S½þ:šjÕ°tïŽeÄT‡¡ž4‰d­–E‹±{÷nÊ—/OŸ>}È“'�£ÃµK§ÓñÊ+¯P»vm6mÚÄüùóÙ±c}ûöͶo—“““Ùºu+;vÌÔ¼ÈQýúõÙºu+Û·o§yóæŽç…1àÞ|ÔØØXþøãG#„B!Dî²Ö°–sæstuîJ &ÐÑáápR™˜Û-ŠzûvTŸ~Š2w.É•+3møpNž<ÉÀ�éß¿ŽM$>ÈÉɉ֭[óÉ'Ÿ Óéøá‡رcG¶œûĉ(ŠBÕªU³å|Ï3½^OµjÕ8r䈣Cy®DDD†ÅbIwMRR—/_&))é©Îužå�;wˆŽŽ~ªc !„�CQn޼ɭ[·¹...Ž+W®`4íÞÿf0 Ål6§{¬Û·oc2™P«åãŽâé5vjŒ›Ê�EÉ‹ˆ°D8:!N®®/�õO?qòÿÃxý:oÏœÉ(//Ê–-ëèÈ2ÍÏÏ�ÁƒÓ¼ys,XÀÔ©SÓ}Ãù¬œ>}š’%Kâä䔥çÉ-Ê•+ÇåË—¥Õù1¬[·ŽråÊQ§Nj×®M‰%øé§Ÿ0™L¶5‘‘‘tèÐ�bÅŠÑ¢E ,H¯^½¸xñâ�3>>ž¶mÛR¼xq *D‡0 Ïê) !„©LŸ>�ÀÀ@5jDåÊ•©X±"3gÎLµæìÙ³4hЀråÊѤI ,È{ï½GdddªuÎÎÎ̘1ƒÀÀ@Ê•+GáÂ…Ù´iSª5»ví¢R¥J”*UŠ‚ Jžâ™ðR{ÑÛ¥7µuµÉ«Îëèp„p8I&¾EañâÅüyý:‡¦LA]­.#G¢ëÙUl¬£ÃË4•JÅ«¯¾Ê;ï¼ÃÙ³gùõ×_‰��ϲóEFFâïïŸeÇÏmüüüP…¨¨(G‡’£™L&Þ|óMFŒÁ… ¸~ý:kÖ¬ÁÇÇ'U;ýwß}Gbb"W¯^åܹs\½z•ÚµkãááñDç>|8Ç'66–mÛ¶±cÇ.\ø¬ž–È„%ó–R>…GþªX ¯VkʧÃ>ãTÈ)G‡,„™ríÚ5†ÎìÙ³9{ö,·nÝbòäɸ¹¹¥Z7bÄÊ–-ËÕ«W¹té!!!âîîžjÝêÕ« áôéÓ„‡‡Ó¤I>øàÛýaaatìØ‘V­ZqãÆ .\¸ðÔýâéŒùæ— ¯u• U¦e�V|÷Ùw„]“™t"çòTyÒЩ¡£Ã"G�db.g6›™6m;vì _¿~ÔêÜ™” 0ýßÿ¡^¹]ƒ¨Žwt˜O$00�#F�˜˜ÈèÑ£³,y•���æM¯Hßý×*+¼¹…J¥ââÅ‹¶¿»eË–eРAiÖEFFráÂÀº9Ñ»ï¾ûÄ î±cÇÒ´iST*5jÔ ^½z„„„<ù“YÊb±pëÆ-‚—Ó½U–-wtH¼V¯ u_z™£Ž::!D¦( jµš'N���€J¥âå—_¦k×®©Ö©T*nݺeÛ@,_¾||ðÁèõúTëªW¯Î¸qãðööÆÕÕ•·ß~›‹/’��Àï¿ÿN�øñÇqssÃÃÃ?ü0{ž¬xbf“™Ð+¡,˜µ�׿Î�ݱ1±Ô}éeê¾ô2ÑQ2F!&ÉÄ\LQþþûoN�:ÅСC)_¾¼õ­óÈ‘ƒ‚ "§Æ�ÑLœèØ`Ÿ�¯¯/ï¾û.z½žß~û�¸¸¸g~777Ÿùqs«û¯ÕÃÕ"5­VË’%Kصk���4mÚ”Ÿþ™ë×S#ÿõ×_S­Z54h@Ù²e>|8[·n}âózyy¥ú½¯¯o–ü»™s<ì'o�Hóklj팟þ Àl2ó¿O¾åFØ G‡K\l±1±˜Ì¦Œ !^XE‹eæÌ™Lž<™Â… Ó®];þøãbbbR­›4iZ­–Š+R£F >ÿüsŽ;–æx_ü½½�ÿ¾À>>ܹsç™37‹ˆˆ@¥RÙÞà‹ôÕ«W��;wròäIúöíËîÝ»©\¹2‡²­ñòòbêÔ©„††2~üxôz=ݺuãóÏ?w`ä"»øæõ¥ékM™0sòæÍ‹��ªúçb49rä�7vt(9Þ† .]ºÄ«¯¾ @RRÿÏÞ}‡5u¶ÿ&$ì­€LA\¸7îQWkGµÖªu¼uµow­ÕÚº·u�ZµÅ-.Ü[Ü¢"ˆlA‘=’ß¼P)(Ž0´ÏçºzU’sžó$JNÎ}žû¾½½½iÞ¼9}úôÁÞÞžøøx6lØ@—.]JŒ)—ËiÑ¢3fÌ 77—„„|||pvv®è—'”}ƒ‚½‘qÉæ;7®Ü`ö·¿pùÂåb7SŒLŒôÁû|4i4ººÅk�õôíÅý{÷™¿z>»u(1fäýHºµì^0~Üub"cèêÝ­Ø6ÃÞ¤¯í;³·èqµZÍë¶²lî2%ü½²[[[›^z2í»iþ]‹öÊ…+ø÷‚GC¶øƒ�[wñëÿýJÒ£$ºôê̯+~}Ñ·I„*dÕªU,[¶Œ±cÇÒ¸qc¤R){÷îE.—ãåå|oõööæÝwߥsçÎXXXpïÞ=öïßÏôéÓ_êx£G�féÒ¥ôë×�#F͆ ^ë{µPqttuÐÒÒB¥RalRò\wìà1æÍ˜Ï½;÷Š=nYÃ’Ç�äýÞ/‘â^Ϻ>jµš=§vS«v­c=p”O†�ÇÑÙ‘½§÷pìà1Æ ý¤Ø6¾õZЮs;­[Xôx^^+æ¯dãÊ ¤§ý]+ÜÈØ�Á#3vòX´dZE�ÿ¹ù/¾þôkzöïÁO bùÜå¬^²†ÌŒLÆN˸)c_âݪ tð×ógcöFNå�ÂYÏ UóZM4I+؃ äÆ�¨T*¬¬¬022B¥R‘––Æ£G�ÐÑÑ¡I“&téÒ奛,äåå±lÙ2ÜÜÜhÓæå:M©ÚµCqêòáÑM›†ôäI”Ë–¡~ƒÒUmllèÓ§Û·oÇÄÄ„¬¬,bcc‰��%>>¾(º0xkhhˆT*EOO¯(@§V«ÉÎÎ.Z9–žžŽZ­fß¾}E_„_‡J¥",,ŒÐÐPÂÂÂˆŽŽF¥R!“É033CWW]]]$ ùùùäææ’žžNZZjµj×®MíÚµqwwÇÊÊêµß7M9sæ yyy´nݺ²§RåuéÒ…½{÷²fÍ~øáòóó©]»6û÷ï/ ZW¯^ÍúõëILL¤F�Œ;–!C†”:îªU«øî»ï˜5kööö4nÜ(XÙ8bÄÌÍÍ‹mß¶mÛbÝ£…ª)éQá«ê6p/öÜÑGùtÔdòòò026¤e›VrçÖ]n^½Éòy+¸pæ"+·¬@O_ï•ç “Ë°«i@|Lùù*,kX¢­£M ›ŶýnÚ÷lÛ° ©TJ˶-±µ·%ña"§��fû¦?¹u=„�»6 «§[â8»¶í拉_E¥ZZ%¶áÍ0~üx5jÄæÍ› @&“áááÁñãDZ³+ø<±³³ãâÅ‹üöÛo,\¸�ôôtìíí™7o½zõ*Ë××¥²øjksssFŒQ” annΩS§˜5k‹-ÂÝÝ�={ö°xñb,,,*î… ¯äÚ¥kE™@îõë{nýòõüüílÔj5V´ðõB&“sõÒU"Â"˜ñÅO\¿|ƒ™‹~z­›îzúzØÕ´C­R]PÇÚÆÎ©–”jÕŠ¶ËËËcÌ౜;y:tí€yus„?àÒÙK,›»œ°»aÌ[5¯Ôù,œµ�åóVý¬%ê|¾Ñ %†øëú£%Ñ�Dá_C\AV�¬¬,¶lÙÂ… puuÅßßww÷wJ³²²¸qã'OžäÛo¿ÅÏÏ�ž={¾ðÅþþýûÉÊÊbàÀ�¯t"UÛÚ’·?Z³f!›9y‹(Ö­Cý¿»ÇUYjj*7nÜàÎ�;hii±zõjLLL°±±ÁÑÑooo,--111ÁÈÈè…ƒ‚*•Џ¸8.\È�èÚµë+ÍïáÇœ?žàà`222°µµÅÅÅ???¬¬¬077îœòòòxôèqqq„††rüøqvî܉½½=Mš4¡Y³f•šZœ””D`` �;wݯ_�‡‡¿üòËs·144d„ L˜0á…Æ´³³cåÊ•%722báÂ…%>|ø �+Tž¨ˆ(¾þôk” %öŽötèú÷*„øD>ÿ9yyy´lÛ’_–ÍÆÄôïA�AL3�+®0燹|1㿯<;œ uý6$=Jbö²ŸiÚ¢øŠí€-lÛ° 3s3殚K3￟¿}ã6GLâö�ÛÌÿi>Ó¿/¾ê(59…Y_ÏÂÉʼn ÓÇãÝÆ»Ø FAÞ<¾¾¾øúú>w›5jðå—_>wÿ�ÙÙÙ•8·988°ø�¿ÿþûœ­PYn]»Å—“ þ ´lÛWw—¢ç®_ã—ïA­VÓß¿?ÿýñó¢Nßjµš�¿mbÖ׳Øóç5kÄûþò<¼|¼8p>�Ô”TZºµà�À-˜W/~3váÌ…œ;yŽZÎŽ,X»'§¢çN�bÊÇS8¼ïÛ7ngÀ�Åö½w'Œ};öÓ´ESÆLþÏæž%:— oC©h>)ü»ˆ`bˆ��eÑ¢EH$ÆŒƒ‹‹Ë3·Õ××ÇËË‹æÍ›L@@·oßæ“O>ÁØØø¹Çyô臢oß¾¯T*L{nÕª í¹S'ò¿ùåþSåÒž322¸té×®]#22}}}ÜÝÝéׯNNN¹ -•J±³³ãÝwßeóæÍ8;;¿XúøÿÄÆÆrøða®]»†¥¥%-[¶¤yóæ%Vˆ•E[[[[[lmmiÖ¬P ¼xñ"‡fÿþýxyyѾ}ûÝË›B¡`Æ ØØØ”š~+ÂóMùxj‰@Y™Y<Œ{HØÝ0Ôj5®î.,X³¹\^´Í¦ß6’ž–�•µ%sWÎÁШøÙö]Úóé—ÿaÆ?±}ãv>þÏèb++4-?_Å’_–ðùŸ $BAíÇ™‹~bè;ÃØº~+c'�Åè©T¶˜¨Xj:ÕdÓžM‹/å‚ o‹G �øtÔä�§¥¦STØ»µ7s–/m±bþJòóU4lÒ�¯g}�–Öß7ß% CFùó <‚-kÿ`åü•¼ë? Xz±¦=yü„M«6#•J™µôçb�DŸö>Lùf*ßLþ†ß­*L¼só-|[°|ó2drq9.›I|z•³û÷ï³`ÁjÕªÅСC_ø®“D"¡iÓ¦Ô®]›•+W2kÖ,&OžüÜÔîÝ»±¶¶.ªAóºTmÛ¢8wÙÈ‘h}õ’sçP._ŽÚÌL#㿎û÷ïsúôi®_¿Žžž�5¢{÷î899½vò³4iÒ„û÷ï³zõj>þøãç6¶HII! €ëׯãêêÊØ±c©]»¶FçT£F zöìI—.]8þ÷ùšN5ùæço°w´/öxÐ�£ôÜ¿D ±Pÿþ,˜¹�Œô N=Eïw{kfÒ¥¹~‹¸˜8tõtéܳs©Û4öjLM§š<À™gJl7æÓ1"�(‚ð–ÉÊÌâÀîÏݦ±WcþûãçÅn2åææræXA³ž! )H|Úð�‡³eí$Ä'r#„úžõ57ù8t’ÜÜ\\ëºâÑ n©Ûôè׃?ÿ‘˜Èîݹ‡‹[ñÅ$Ÿ~õ©$þKd©³Ð—ˆÆ”ÿFO÷e€‚EJºº%Kü¼©Ä'X9Š��/ª×2xðàW ²˜šš2~üx–-[Æüùó™6mZ©)¤ÉÉÉ\ºt‰áÇk´9‡ÚÒÅŽhÍœ‰lÖ¬¿Óž[´ÐØ1^Æýû÷ äÞ½{ØÛÛÓ·o_š6mZl¥Nyêß¿?999¬X±‚>ø ÔU¦jµšãÇ�HµjÕ?~™�Þe]ÀZê5ª@dxdÑŸg³FÏßÞÑžê–Õyœø˜ÐÛ÷Ê5˜Xx®{œø˜ßõÌí¤ÿ;¯ß½u·X0QWO÷™AHáíò ÿ[³·ÒS·'î2÷²wÞiiiÄÅÅ‘””ÄãÇ�IJJ"%%…ÌÌL222ÈÌÌ,ªÿZ‰D‚��bhhHõêÕ©V­Õ«WÇÒÒ++«*¿HGËI^^Ë—/ÇÖÖ–÷ß/ÙYìeèêê2jÔ(æÏŸÏš5k7n\‰€á¡C‡¨V­¯;õ’´´ Òž}}‘}ðAA·çiÓÈÿüs¨ à±±±pÿþ}êׯÏÔ©S±±±©�c?M"‘0xð`¶oßβeËxç�wŠÕÊÌÌdÓ¦M„……Ñ­[7Z·n]¡ZZZøúúÒ¨Q#X´hݺu£}ûöïýèÑ#V¯^�B¡`òäÉ•ò÷!o‹Î=:=3%ëÝ¡Ög8—Ï_fáÌ…EÁ·ÌŒÌ¢&%&fÏ/m`jVÐH+=5Mƒ³.)#-€ì¬lΞ8[æöO’’‹ý,•J±´z¹Æc‚ BÕ§o ÿÌëüûÓç'ã²|Þ ®]@Fúß]’Ÿ® \S3S'>®°sÝ“ÇO^é\÷ϦeÂÛËRj‰™ÔŒ9;@P|eggFXXQQQÄÄÄ�–Vðchhˆ¹¹9ÕªUÃÚÚ}}} 100(Z�¨¥¥…¶¶6*•ŠÜÜ\ `A@VV™™™dff’––Ftt4W¯^%99•J…\.ÇÆÆ{{{œ��©]»öK7ç-o"˜XN¶oßNff&cÇŽÕHª©��ÇgÞ¼y;vŒvíÚ=§R©¸pá:tÐxÀèiªÖ­‹Òže3f ½zµ íù%kÿ½ŒÜÜ\öíÛÇ©S§pqqaòäÉØÚÚ–Ûñ^„T*åÝwßÅÚÚš�;wrçÎÞ}÷]233Y¹r%r¹œI“&UjpÍÈȈ¡C‡rîÜ9þúë/""":th‰†?¯B­VsúôiöìÙƒƒƒ£G�ÆÈȨìAx%R©”A#qùüe"Â�ô(‰jÕÐ7ø;e¦¬ §´ÿ=oðŒTèÒ<�–ñ¢ ƒš5lj°à‚ÏcfnZìg#c#‘ö%‚ð/¤§¯G¿A}YüË.�½TôøÓ纴Ôtôôõž9Fá¹îYe?JóJçºÿ5›x5aúÿM/ck¨amUìg³j•_2J¨ú}ë æÏœ?1–<¿ÿ�P5¨Õj"""¸~ý:7oÞ$&&‰D‚­­-öööxxx`ccƒµµu¹4NR©T$%%C\\±±±“���‰‰ îîî4hÐ�JO™ߨËAxx8'Nœ`äÈ‘j®îSas‹;vàé鉩iÁEXXX4lØPcÇzµ…Š�;‘Í�‹Ö·ß"÷öF±v-joo�+<<œ�7¢V«2d�=;µ¡2øúúâääĦM›˜1c... 2¤ÊtdkÑ¢¬X±‚¥K—2jÔ¨×jÎÍÎ�;‰ŠŠ¢gÏžøùùUùåׂð6hؤAÑŸ£#c¨fQ mmmj9ÅõË7há[zù ¥BIÈõj×ù»nkY¿»…Åð_FaWÊ“dÜë¹=óY™Y(•JtõŠ *Ïb‚ BÕÖ°IÁµLZjé©é™áèìˆL.C©Prãòu¬ºw,ußøØx&ÿ<×IÈÏW?ó˜¯t®s/hĘ‘‘ñÜtåô´ ÔjU‰Uâ\÷ï¢/ÑgˆÞ�Êž†P†ÈÈHΞ=Kpp0iiiÔ¨QºuëF­Zµ*ìú^*•baa�……žžeŒÔj5qqq„‡‡sçÎV¯^ €››ÞÞÞ4lذÂʾ›k…ñ_àÏ?ÿÄÃã\RŽÛ´iƒ©©){öì)zìÚµkØÛÛË�D‚òÓOQìÝ ùùhwé‚Ö�?‚J¥‘áU*`É’%8;;óùçŸW¹@b![[[z÷îM~~> 4`ĈU&�XÈÆÆ† &�™™ÉÂ… ÉÊÊzé1Ù¸q#sçÎEGG‡/¾ø‚Î�;‹@¢ T�65ŠVì¥&§=ÞÖ¯ Û7n'';§Ô}wü±ƒ´Ô4dr>í|НnY€Ä‡ ¥îwìà±—ž§{=w,¬,ÈÉÉ%(ðh©Û( :7ïŒw�–\ ¾þÒÇAÞNv5íŠþœò¿s�®ž.^>Í%7þ¶±¨¼Ç?mX¹(8·Ö[,üàaÜÃû¨ÕjŽ¾Â¹®eodr÷nß#ìnX©Û<Œ{H+÷–´tkEò“äR·¡r) Nœ8Áwß}ÇŒ3 ¥]»v|ùå—LŸ>�=zàææVé×÷…+#[·nÍG}Ä?ü€¿¿?2™Œ5kÖ0mÚ4¶lÙÂãÇ�+t^" a·nÝâþýûtïÞ½\Æ×ÒÒ¢sçΜ9s¦èKxx8®®®år¼çQùú¢8wU»vÈfÌ@Þ«’ÄÄ×S¡P°nÝ:Ž=Ê{g¿¿¥ÿò>OLL kÖ¬¡Y³f 4¨Ê×ÌÍÍ™0a*•Šß~ûí…S:ÂÃÃYµj3gÎ$!!�ñãÇ3qâD¬­­ËyÆ‚ ÄÆÆkR‘ÔÕ«£@kÉd_|�ÜÇÅš5¨[µzé±²³³Yµj‰‰‰Œ7{{ûr˜±æ¤¤¤°bÅ êԩÀª|Ê‚¡¡!£G�fÁ‚lܸ‘>ø Ô9§¤¤péÒ%.^¼Hbb"îîîL˜0ww÷*ÿámfhdÈ“ÇO¸së.½ÿ÷˜­½-ßýúŸ}òA�AtiÑ•6Û`ljÌ�›w¸pújµ�u™úíÔbãõøÛ7n'ìn=}{áÛÁm®\¼Ê­k·¹\Ž“‹á¡ál  ßà~E7²?þôcœj2ïÇyÄDŲeíEû›3bÜŒ;¢Äwòžý{ÍÊù+  '<4(\~1ã¿4õnöÌsÝôï§3ûÛŸIˆO$<4¼hEá1×ï\Ç/ßýÊî?wTl_//¾šõU±ÔmAxÚáÜÃÜQÞA©«¤¾¬~eOç­Çš5kxøð!>>>øùùUzM’H$E¥öBCCÙ±c_}õ=zô S§Nå²(H¢~Vá á¥rôèQ¾þúër_Á•™™É×_M¯^½Ø±c?ÿüs¥Ýü'IR²?Dzð ª6mP®YƒÚÊê¹ûäçç³jÕ*âââ˜0aæåØZSöîÝËÉ“'™mmí‚`¹¾>fffT«V sss¬¬¬¨Y³&5jÔx#ƒŽyyy¬Y³†7nп¼¼¼ÞÈ×ñ*¤R):tÀÃÃõë×3cÆ �—’ÁD ÉÎÎ&**ŠÎ�;WØ1ÝÜÜ8räÈs—禧§Cbb")))¤¦¦’™™‰B¡@©,(^\ŒÔ××ÇÔÔSSS,--±³³ÃÈèVˆ¦={y!:ù;ï¤=ö¹J%qqqEf„††bmmÍÖ­[‹æ¤­­�––zzzannŽ©©)ÕªUÃÆÆ™¬rþéªÕjprr¢qã7»qÀ€˜9s& …BAAA*�:xÈ<42Ö“'O¸yó&7oÞ$""‚´´4d2VVV˜™™aaa�««+zzzèèèÜ–ËQ©Täää T*ÉÎÎ&99™””nݺEPP999èêêâàà@ݺu©_¿~å–X{A999ÌŸ?Ÿ¤¤$>ùäÊÞé-T£F &NœÈÆ�™={6ãÇ�ÇÅÅE#c‹`¢†Ü»w‰DB­Zµ*옵k×fçÎ�Å †¦¤¤p÷î]îÞ½Kxx8iiiH¥RÌÌÌ033ÃÔÔ¤R)úúËô³²²P©ñUBê IDATTdddÃ�7HNNF¥RallŒ³³3uêÔ¡N�:/µ$XÝ´)�÷îE:r$ÕfÌ fófVøú’¢§‡®®.æææ˜˜˜Ð¼ystttŠæôôZnn.�?æÞ½{�XH"‘ðÞ{ï¡P(X²d _ýõ«e¡>¥jüm¿âââ*¼ëmrr2:::¨T*öîÝKÆ éÚµ+NNN¯ý!¢­­�££#ŽŽŽøøø R©ˆˆˆàÒ¥KìÙ³‡]»vѼysÚ´iCµjÕP(\¾|™óçÏ�…… 4 _¿~EjÊà`äC‡bøÞ{(ÿóò¿ý´J6xLLL¨W¯Pp×!,,Œ��Ž;Æž={pwwÇËË‹zõêitõ`HHñññ 6LccV6¹\N›6m8rä;v¬Ð`xU£­£MnnneOã­—“�ƒ\GÔ A¨ rm9y¹y•=�·šB¡ ??mq®á¨PñWÎ_8j9ÒTþwÝiµZÍ•+WØ·o±±±Ô«W�?ü�:uêThãÌÂàbûöí‰ŽŽæüùólÛ¶�={öЩS'|}}+µ6èÅ‹9{ö,cÇŽ¥zõê•6�ªH*•2pà@æÎ�ËÚµk?~ük�'‚‰òøñcÜÝÝ+äXröìYÌÍÍéÑ£Mš4)×&,R©gggœ��éÛ·/ÁÁÁ=z”Ó§OS³fM’’’ÈÎÎÆÃÃ1cÆàââR²ûZ“&(ΞE6v,²9sкxÅš5¨­­_y^r¹wwwÜÝÝéÛ·/÷îÝãìÙ³¬[·SSS:t耗——F>`OŸ>M½zõÞšU‰…ZµjÅÁƒ ¦e˲‹G¿­ Œ ÈÉÉ!++K¤|—…BAzz:ÆUº[¯ ÂÛËÈØ��'!ÿŠž•%)) Ãè\,‚ðOJµ’,U”� ¡‰¼ ÷ïßç÷ß'66–&Mšàïï�¥¥eeO{{{ìííéÖ­[ÑžƒÒ·o_š7o^áç…BÁŸþI›6m¨]»v…ûM¡­­�¿¿?¿þú+7oÞ,Z¤õ*D0QC’““˽ŸZ­æôéÓìÝ»üýýiÔ¨Q…ÿ’ÊårZ´h�——W¯^e×®]dggÓµkWÚ¶mûÜù¨��QlØPÐíùË/‘·h�råJT�:½ö¼$ ®®®¸ºº’œœLPPѳgO4hðÊcgddp÷î]FŒñÚó¬jttt¨_¿>çÏŸÿWkØ×@®-çÖ­[4kÖ¬Òæ!yøÉÙ³ «‹ªk×J›Gy¸{÷.*µ ›ÊžŠ ¿’]-;Žì "::ú_[Œ¾¼Ýºu cScL«•ïu� o'm‰6õòG΄d„ps×MΞ=K½zõ:t(Õªi¾óóëÒ××§[·n´oßž°nÝ:Nž<É Aƒ°±©¸ïý§OŸ&;;??¿ ;æ›ÈÖÖOOOvïÞýZÁÄŠ[û–ËÈÈÀÀÀ ÜÆOMMeÙ²eìܹ“:ðÙgŸáééY©w•% žžž|ñÅtêÔ‰}ûö±lÙ2RRRÊÚ‘üqãÈ;rŒ�‘÷í‹lêTP(467333úõëÇ—_~I�:uX·nË—/'11ñ•Æ .*hû6jÖ¬wïÞ-ûïî-¦¥¥…k=WŽA¥RUØq¥¡¡h­]‹ì£�Ю_mggäþþÈû÷GYaó(ojµšC‡áìæ„ŽÞ¿7�^¡2™V3ÅÆÁ†Ã‡WöTÞJ¹¹¹?q·Foç÷EA*†¶D›F‘�¸>ë:÷îÝã£�>bĈU2�ø4]]]z÷îÍÔ©S˜1cG�E­VWÈñ/\¸@³fÍD–Ù hÛ¶-< !!á•ÇÁD ÈÏÏG¥R•[m€ð믿’‘‘Á§Ÿ~JÇŽ«LqS™LFÇŽ™...ŸWU!•JqrrâîÝ»•=•JehlH§¾� bïÞ½åvM>mÒ]»�<~üÌmT£FA q+s@©ùßM*삾wï^Úõl‹™HûA¨TÖÖ´ìèÍ[ÿàìÙ³•=�·‚R©dëÖ­\¾r™nïuÍWAx%yyy,]º”cÇŽ1dÈX©ÍL^‡D"¡mÛ¶Lœ8‘øøx~þù碚²å!!!µZ�½½}¹ãm"‘H°··çáǯ<†&j@á*AM§F^½z• 6Ю];üýý˵ÁЦÈårLûöíÙ°aW®\y¡ýòGŒ /(LM‘÷ë§ñ´g(ø…iÓ¦ “'O&))‰¹sç¾PÚsLL ¹¹¹o}WBCC+{•®v]gº½Û•'N0û—Ù\¾|Yã]žó}}Ÿ¿�Žù~Xæ8•9¨8¨¡YiVnn.×®]cî¼¹â×§#u=ëVö´A ©oSZvðfûöí,^¼˜Û·o£Ðð÷®ƒ¬¬,Ο?ÏÌ™3¹rí ½ý{aSSÔá奧§ó믿É'Ÿ|‚§§g©Û%¨_=-µ2ØÙÙ1qâDtuu™9s&QQQårœ´´4är9ºººå2þÛÈÄÄäµÊœU�\Ù7˜––R©”¼¼<��yïÞ=6lØ€ŸŸ]ºtÑØ¸A"‘еkW$ 7nÄÀÀWW×2÷S7j„âÔ)dcÇ¢µd ÒË—Q¬[‡ÚÎN£ó«Q£“&Mbíڵ̛7�‘#GâììüÌí>|ˆ¾¾~¹7Ø©l666$''“““ó¯ÿ®íQK[KÎ�ç÷ß'??C#Cä2Íô%j5þµkS',¬ÔçƒëÔ!`ùò玡–¨ €R¦ä›ùß Ë¹�ó”3¶n‚§ç4¸ŠŽNÎKíÿ<Ê|%éH$j×­Íà>ƒD!zA„*¦q«ÆØ;Ùs.è<¿ýö‰CCC�—tQ«¥?Þ‘Æ�Ïalœ¦Ñ±Ÿ'['››uobkO�Äç— yyŠ<232‘ÉeÔõ¬Kó6ÍÐ7uºAxyYYYÌ�;—üü|&MšôÌëÎPU(;;h'kG3­Êkù² ;v,6l`îܹLž<; _ãËd²¢òså‘1ú6ÊËË{­k"˜¨!†††«ðäÉÖ­[GÓ¦M߸@âÓºtéBzz:ëÖ­cÒ¤IXXX”¹�ÚØÅÆ�h­X�ìóÏ‘{{£\±Bã]mutt9r$[¶laùòåŒ=ú™ÅÄÄD,--5züªÈµZMbb¢èð›Ó©¯í{¶#.2Žô´ r²²56~˜µ).Ó¾FšWr%HÂÐÔu|þßÁ}Ãrt €Ò¶ꦺ¿ÔñïÝ­Žž¾œ#GºrúLG|ÚDâ×5kÛ׿ÐÓÑÕÁÈÄkk‘ê%‚P…YX[Ðspr²sˆ�Š'#-“< ®Æ¿|Ñ–5Ë›‘𢋾±Ã?º¤±±Ërß ‚# �Ð=®í´ÓèØj@ß@cSc¬¬ßÚšÚ‚ ”¿¼¼</^L^^ãÇ�ÇÈÈè™Û:I�p”:rTy9ri5ªÀ™¾¹\ÎðáÃY¿~=óæÍcêÔ©XYYil|T*éé阘˜hlÜ·YjjêkuÛÁD 155ÕH'\µZ͆ °´´dÀ€˜YåêÓ§ñññlÞ¼™ &¼p÷éü�>Båå…|èPä�?f Ê ÖŒ�Éd <¹\ÎÊ•+7n\©5’’’¨^½ºÆŽ[U™˜˜ ­­-‚‰ÿ “Ëp¨­Ù÷C7ø¶3~E¢•¡ÒŒ¿oDdùxáìß§Ì1.¨/\Íë%0L2ì¥æÐÄŽLàòù46þfÊáýά�gól†ŒJ¡c·L´´*¦óš ‚P¹tõt©U§–ÆÆ ½­ÃÏßXpö„^Ñc½Þ3 ‰O�£,:jPC »4±«¸ã ‚ ¼(µZÍÊ•+yüøq™�D2úÊúrXyg­ggÖUUR©”Áƒ³bÅ ,XÀ_|¡±ÎË666èêêF“&â3¿,J¥’ÈÈH|||^y ±þSCªW¯Îãç4SxQ§N�"&&†�VxÇæ¼¼<æÏŸÏîÝ»56¦L&ÃßߟøøxNž<ùRûª6Dqú4ùt{îÐID„Ææ)Ù ÀÍÍ�åË——Z6++ �·*’H$èéé‘�­¹ÕwBIF;qè7$¢v®#fÓRÔO-/OåÿBãœTŸzêÏ/÷»õ´Æ^ÙÌYϾ3‘Œü$™ˆ{Ú|:Êšî­j²j‘©)bµ… ‚ðbRS´øéK úûÙ $88VlMF-´@rª~ÍqAª¶ÔÔT>>ÔªU‹êÕ«£££Cvv6>$44”ãÇ�³ÿ~:vìH÷îÝ_8³0??Ÿ�7Ò°aC¼½½ËùU=J¥’ììlœœœØ±c(•J ¨Q£5jÔÀÉÉ LLL066FKK«(%úélº¬¬,”J%iii¤¦¦H@@ãÆ�{ákÿ”‘‘App0ÁÁÁDGG£££C­ZµpuuÅ×× ÑÓÓC.—£R©ÈÉÉ!77—äädIHHàÆ�:t™LF½zõhÚ´)nnn•Þ æÂ… ÄÄÄ0jÔ¨×G5¤víÚäççóàÁƒê\üO*•Š“'OÒ¶m[t^0  i¶¶¶CC €v(Q’H"¸@.¹è ù“’H�Ažç¿?>`Ç¥§úÙÚ¿5¤Aø÷:sæ 6lÀÛÛ›Þ½{¿PZª––-[¶ÄÃÃ�72kÖ,Æ��££ã3÷ÉÌÌdïÞ½tîÜY£e².ç_&D‚R­¤•¬•ÆÆ}]�=âܹsœ?žììljÖ¬IçÎ�ñôô|¥ôð²XYYÑ·o_þøãÌÍÍKÆJñäÉvïÞ͵k×°··gèСxxx”@|†††4iÒ„&Mš�––Æ™3g8tè‡ÂÏÏ�Ö­[WØJÅÔÔTV¬XA­ZµèÒ¥Ëk�'‚‰äééÉÉ“'éÕ«×K/©½yó&ŽŽŽ˜™™•ÓìJ׳gOTªâé’Íš5ãØ±c%¶ýñÇÑÓÓcРA 6 RRRŠÚØÏœ9³hÛ®]»Sôó”)SŠþ¼gϺuëÆ¶mÛŠ{ôè|ðÇ�ÇÙÙ¹\δiÓðóócýúõ%rù[-[ÆêÏ>£ÓêÕŽI6𫑉ééáåUpGæ‡~ÀÀÀ€�2lØ0tuu‹æÑÑÑtëÖ�Þ½{m7}út¶nÝZôóêÕ«Y½zuÑÏ&&&ÄÅÅ=ï­¯’rrrD0QCŒvb=ñ òMŒ‰Ú±–œÆ%ƒç¯"„žð„ñ’ñœWŸ'U’ÊÆð�ú;‚Õ—i))¿T ‘-‚ ”ÆÀPÅ�óhÕ6“éã¬ùÇWK±2Q„*íâÅ‹¬_¿žž={Ò®]»—ÞßÄĄѣG³iÓ&,XÀ”)S°±±)uÛ£G�"—ËiÕJ³¿®ò®ä)ò8—ŽºZu1“Tl\áŸ"##9pàwîÜÁÂÂ???š7o®±rjÏÓ¼ysRRRØ´i‰OOÏR·ËÏÏçèÑ£:t >þøãWZö¢Œ��éÒ¥ íÚµãäÉ“ráÂú÷ï�“†²-Ÿ%%%…eË–a``ÀǬ‘¦èæ¬AM›6%99™ððð—Þ722’Zµj•ìž/==�ÌÌÌ¢ÿÊZMwäÈ>ÿüsöìÙCDD±±±tìØ‘¥K—[´ÝÝ»wÉÌÌdóæÍ@Á‡fff&[·nå‡~(HÌÏϧÿþ„„„pôèQ®^½ÊÅ‹9qâgÏžå‹/¾(u.»BCqyü˜ ^^ø±NNÄ;VbUåáÇùâ‹/Ø·oÄÄÄо}{–.]Z,àMïÞ½±··gùòåôë×�ëׯ3räHöìÙC@@@ѶkÖ¬!33“¨¨(  Ðúôûø&322ÈÉÉ¡zuQ¨üµ¨ÕTûe 6O%ÏÙ‘¨}›5H„‚ÎÍã%ãùXòwZDI?¾‘|ÃiNkì8e] A„ ÜeŒDª¦m§Ìb�ÛØ‰•‰‚ TM‘‘‘¬]»–N�:½R ±�L&Ãßß-ZDfff‰m Ç�§mÛ¶oÈ¡…½å½y_þ~¥£££Y±bóæÍ#??Ÿ±cÇòÙgŸÑ¦M› $êÔ©~~~lذ�”ÈÆ|òä .äÈ‘#tïÞ�O?ý´\‰OÓÑÑ¡cÇŽ|öÙgXZZ²hÑ"öïß_b‘—¦ŸLIÁ…|‚:¡Â�-›!77—•+WâîîNçÎ�_{<---†ŠD"aýúõ%ž¿rå 999åÖtE -l¤¥¯ˆ,oÙÙÙüùçŸÌ›7¥RÉ„ 3f µk×~åF(¯«K—.øûûsäÈV®\Ijj*!!!üòË/¨Õj¦N�Z¡©ÆO355eøðá <˜ãÇ�³dÉ224w¾T©T±xñbÜÜܘ2eÊkuoþ'‘æ¬a…+Þ_¸ eNN …¢ÂSœ_…™™æææÅ+\ÂýèÑ£2÷755E©T’““SÔ�éĉH$nÞ¼ÉÝ»w‹mÿþ}233‰��§f͚ŞëÑ£}ûöþ×í¹Y3dþþÈ?ø€üƒQ.XP4ç¾·¥ÍùĉXZZ}ð'$$0cÆ <<+=AxóíÚµ‹œœÞÿ}�¼tuu2dóçÏçòåËÅjö]¾|ww÷ ]¡WnÞ¼ÉÖ­[ÑÒÒbذa¥öF¨,�7ÆÊÊŠÍ›73kÖ,4hÀÅ‹iÕª½zõzáÜå©I“&888°jÕ*.\ÈèÑ£KÄ\^V\\Û¶m#>>žЦM�u+ÿ�{ËÔ¯_öïßϰaÃ^hŸÂ¶æoê‡JaÿŸK‡KS@ÌÌÌ,úszz:2™Œ“'Kv¨h×®]©ï�µuñ_*òŽGöÕWh-Y‚äÊì­¬}Á9§§§“——GPPPä�ŠŠ"++ ¹\NݺuË|}o²°°0\\\*{o¤òh´ò&] Aþ]þï3+2¿žo IDAT3¥ü0/¹üïïV•HA(K||üðÃçôÔÖÖFGG‡””” œaŨW¯uëÖåÇÄÐеZMbb"Û¶mcèС@AjøäÉ“™={6>Äßß"##Ù¶mnnnLŸ>ý¥�­vqaº�=ÏœaÈï¿#¹|åÆ�¨Ÿ05j»wïføðáŒ3†N�:¡P(8|ø0[¶lÁÖöÿٻ︪ëï�ã¯Ï½ì½§"*¸HÌñu¯2s¦fY–™9²¬o–¿Ì•–#SÓBM³\%.\¹q\8‘�Œ;¸ã÷y“/¨¨\îßO=Š{?ãvïýœÏûœãÏ•+W¨Y³f‘ý^~ùe–/_Nhh(‘‘‘¨ÕjŽ?ÎðáÃÍr™wIâââ¨V­Z©û|>ëdù |ßþ‡¿v�Óµ=És¾@gW1Û”7Q-‚Py<¨¼¹´ôz=I‰I¤§¦“—[|òéÓ¸c“ápõòU$(Óc? +++\Ü\ð¯ê��­�©Ã„gÒž={pww7ú*ÁÈÈHbcc9sæ 7nÜ0ÉÀU2ºYvC®‘sAsɃ²O|¼ÔÔTæÌ™ƒ��Æ 3ûVmiiiDGGÓªU+Ú´icêpJÅÚÚš#FðÍ7ß°jÕ*^}õUCÒ[©TÏÙ³g9{ö,Z­–Æ�—ë4ê{D2ÑHlll9r$3gÎdÕªUmê*Iþþþܼy³HƒVSðññA¥R•øœ——999Å·´´¤zõê888{N&“ñÓO?1jÔ(† †^¯ÇÚÚš‚‚ dø™|úé§Ô«W�¯¿þš^½z¡×ëqpp [·nôêÕ«Øq«U«†»»û#¿~nܘ~¯½†Å›obÕªš3°lÙ²XÌVVV¬_¿ž™3g²|ùrfÍšÞU1bÎÎÎ9r¤X2qÊ”)¤§§óÉ'ŸPPP€••¡¡¡tîÜ™ÀÀÀGÆhj�†ãÇ�Ó¥KS‡R!”× •ÊN”@ ‚ TlOSÞ|úøi~ùi©iwð¯å�‹—–Öe{Y’í” áp=5ž#—Í«ÍÝô|n]LE£„N�»ÐíÅîXZŠ”‚Pôz=‡¢eË–FŸ2ìââBݺu9tèYYYÅŠ– ‰.]PÉUXKO¾Ø%;;› àëëˈ#ÌþuK£Ñ°|ùr¼½½+\;/† œ9søý÷ß±··'!!�k×®!Iµkצoß¾4nÜØd ]I_õ™‘K—.1wî\j׮̀ =öþ×úõëIHH`ìØ±åaùÉÍÍ5Œ%ïѣǷS(¨T*œ��Ëô^º~Ë!C�ŽAûÊ+h¾ý2¹877—‚‚>ÿüsÞxã rrrX½z5ü1ŽŽŽÅ¶W*•(•Ê2�ÛØ:Äï¿ÿδiÓJL›ÂÍŒvœ_GÓšÿ1u(EÜ?h%yÖ“ZªF¶”ÍïÒZ“ÆQVîM�Þ¾Ù­FS 3¤ç¯“KסìÚrÏ®ã7þærÚêû77u(�-õŽœî­ªáã¯aõ–›¥^•¨R©ø¿ÉŸs· …�Ÿv¤jí§ì•ý‰š§~Âhç~ô´kc´ó< ežŠ˜%Ù½âŸL�B�¥ïµ.Æ’£ÌàìÍý {þñ+Ã*‚+W®0}út&Ož\ªÅ)O+..Žß~û 777ÂÃÃiÛ¶­QϧB…%Î8—éqÕj5ß~û-r¹œQ£FUˆ ¼˜˜öîÝËøñãKÝ{ÐÜìÞ½› 6àááA½zõ¨S§õêÕ3‹Ÿ¿X™hdÁÁÁ¼ÿþû|ÿý÷Ìš5‹W^y¥ÄÕj!!!ìÚµ‹ÔÔT<==Ë?Ðr R©¸sçÎ#'XÙÚÚ%»®¯V õ–-XLž\8íùèѲçôx¸—X³²²"//�F�±yófvíÚE·nÅ“H666ØØT¬r�NGll,-[¶4›D¢¹*2heý2”�ž3uH•Ž(�A¨ž¤¼¹  €Q¯¾I«Aõé8Ô¼nšŠ�½5=ßiM‹Ï1¹×|úÅT4|òòCAíÞ`ÍòH$Ô¯_Ÿ•+W’““óÈk\…BAff&™™™äää T*Ñét¨T*¬­­‘ÉdØÚÚâè舫«+®®®†ëOµ^ÍqÝqiá%ó¢Ÿe¿§Ž]§Óq÷î]222ˆ‰‰!33“Ö­[³oß>Ôj5VVVXZZbaa�½½=...¸¹¹™Åuejj*±±±ôêÕ«Â&Zµjʼn'°³³ã•W^1u8Eˆdb9¨V­ü1ÑÑÑÌ™3‡úõëIpp0r¹€ÀÀ@ÜÜÜ8rä�;w6qÄÆqøða\\\¨^½ºé‚°¶.œöܪ#G–=öÚQ£¸‹��J¥¹\NTT›6m¢M›6%®N¬hâââÈÈÈ C‡¦Å|éõ¸Ïš�Ǭù¨êÕâÖòï(ð/>Ù[(;¢ZÁ|=iyó‚oçS/ÊŸŽC˧ù½Z_zÈÕ?¸y½¹ð pãÃ_‡ðq¯Y¹i 66¦_q"•Õ…  *·óÙÚÚâëëKzzz‘9 ÷†²\ºt‰7npëÖ-233�ÂVaŽŽŽXZZI@æçç£Ñh¸{÷®a0¨››UªTÁ¦¦ g꜡žs="ä�§N§ãúõëܼy“›7orãÆ ÒÓÓÑj oä[ZZbggÇ‘#G Cd´Z-*•Š‚‚ClP¸ÇÇLJ€€ªV­J@@>>>Oö|BëÖ­ÃßߟæÍ+ÞêÿûI’DŸ>}øúë¯9yò$¡¡¡¦É@$ˉ££##GŽäâÅ‹ÄÄİhÑ",,,ðóó3 &ÑétìÞ½›¨¨(³odú¸T*{÷î¥C‡fQ¬ëÖ�‚ÐP,‡ Áb¤ãÇÑ|ó ”pŵº0qѼysþþûoÖ¯_ÏÀ�Ë;ì2¥T*ùóÏ?i×®]…¾[cLbЊiݛݣï]C ôï+�Xó³³(�A0�'�Þ¬T(ÙôûF–ÄdÄèŠ*Ðk@‚|�ù'üƒ˜-¶Ð£owS‡#•’^¯çúõëåž`ªQ£äççsþüyâââˆ��'??OOOªW¯NëÖ­©R¥ îîî899=t€«V«%;;›ŒŒ ¹uëWÿ¾JÚö4âuñÈêËP…©~èµw~~>çÎ�ãܹsœ?…B�‹‹ 4iÒÜÜÜpuu-U~âÞ*ÆÌÌL’’’¸qãG�E¡PàêêJݺu©_¿>µjÕÂÂÂx©¨›7orîÜ9F�m¹‡§U¥JÂÃÃÙ´i!!!fó=‰db9«U«µjÕ";;›‹/rëÖ-rrr�Ëå°gÏbcc+Ý0Œ;v —ˉˆxü»$Æ¢@½u+òÏ>Ãâ믑ââÐüü3ú犖¯*•J˧……}úôaþüù4kÖŒàà`S„^&6n܈……E¥] û´Ä ó"J ALïI§7ÇŸŽ§vx VâÒãašv©ËÞÅûE2QŒ$55µZ�¿¿¹ž×ÍÍ µZÍÖ­[Q«ÕѵkWj×®�››ÛcK­Wc%·ÂÍÍ 77·"«,ÓÒÒ¸páÇ�gÁ‚899ñüóÏi¸žÕëõ\¸p�Çsúôiär9µjÕ¢{÷îÔ­[gç'ïµèää„““���4jÔÈp¾äädâãã9wîÄÆÆ†ððpš5k†ŸŸßŸïA¶mÛFPP�i+"ËX»víøòË/9{ö, ˜G; ñŽn"ÎÎÎ4iÒ„&MšyÜÛÛ›åË—Ó°aÃr‘3–Û·oKß¾}Í¢Qh––h?ÿ}³f…eÏmÚ+{V(EîÄΊ+7nöâb®Îœ9Ã�xë­·Ìïwbî´r{Î&´"üK”@ ‚ ˜ÆÓLoNOMÇÍ·|ÛÃXH…­„lŸbriys÷u&5%ÕÔaB¥•œœŒL&ÃÃã\ΗŸŸÏÖ­[Ù·o¶¶¶DEEöD ;•^ÅQíQâtqô´èI€, Ø6xxxIVV‡fÏž=lß¾�-ZàììÌÞ½{ÉÈÈ víÚôïߟ u*³$IøúúâëëKÛ¶mÉÏÏçÈ‘#†ØªW¯N‡¨S§lP¥§§sæÌ^ýõ29ž¹ðôô$$$„íÛ·‹d¢P²ˆˆ>Ltt4ï¾ûn…Oô¨T*~ùåjÖ¬Y,qjNt]»Rpà–¯¾ŠÅ„ ÈöïG3oùVVh4šb Ã>}ú0kÖ,¢££1b„Ù,5.�ŒŒ V®\IÛ¶m 1u8fG Z©D ´ BùII~²òæ{tz’¬|?+YKV8Ê*ÐM_I½xßcÉÊÊÂÑÑÑ0·ÀXt:{÷îeË–-ØØØðÒK/Ѹqã§*íýSó'—u—©"UÁ’G'ÿ\\\èСQQQ9r„Í›7£P( bÔ¨Q¸ºº>q,OÃÎÎŽÖ­[ÓºuknÞ¼Ill,?üðUªT¡sçÎO�TŒ‹‹ÃÕÕ•Úµk—QÄæ£Y³füðÃdffšì÷w?Q³g††ŠR©dåÊ•†Æª‘^¯gÕªUäåå1pà@³O¸é«VE½e š?D¶a–­[“‹$IÅ–_[[[óꫯ’��À† LñãS(üøã�xyyÑ»woS‡c^ôzÜgÎÃoäxÔ5¹ñ× ‘H¬ 7S0{ÑmþÚ�áogrõ’cGøÒ%²‹¿s%;˸A*»©“ž¬¼YÁœÜ½{'''£ž#55•ï¾ûŽÍ›7Ó¶m[&MšDÓ¦MŸºG` y ^¶|™þVýñ••~¤¥¥%-Z´`òäÉ´k׎+W®°råJðSªZµ*C† aâĉxyyñÃ?°xñbÒÓÓŸø˜G�%,,ÌìsO¢V­Z8::räÈS‡ˆd¢YrrrbäÈ‘œ;w޵k×VÈ„¢^¯ç÷ßçìÙ³ 6¬âL>¶°@ûÑGüú+¤¥Q}Àº$$”ØpÖÚÚš-Z°{÷nbccMìã)((`ñâÅ0jÔ(£6½­hdù ü‡�Ácæ2ªÉª=ñþÖÖÖüç?ÿáý÷ßG©T2cÆ ÎŸ?_&±=-oooÈèÑ£ÉÊÊbúôéìܹó±ó wîÜ!55ÕЯ±²‘Éd„††ròäIS‡ˆ2g³ȨQ£øþûïÑëõôéÓç¡�̉N§cíÚµ9r„×^{�€€âýÌ�®sg $£S':oßNfçΜ|çssINN&99™üü|lllðóócÓ¦Mèõz^xáS‡^"•JÅ’%KHMMe„ F¿#W‘ˆA+•�(�A(O[Þ,‚`N4�ÑTlÛ¶�Í›7E—.]ûÚ]­Ws\wœDm"}¬ú%F(LÜ�3†uëÖ±hÑ"ºwïNëÖ­�v¾ÇÈ{ï½Ç¾}ûظq#.\`À€¥^˜téÒ%ðññ1r¤¦Ì�Œž/ ‘L4cuëÖåí·ßfþüùddd0xðàR�d7%¥Rɲe˸zõ*#FŒ¨ÐÓŽU^^|Ù¡í�¡óž=4|8Õª=zUæåË— 6«kñ²„N§ãòåËÔ¯_ߤ±ˆå7f®N�:|ðÁ¤§§3kÖ,LÒ]¹r…Ù³g“ššÊ˜1c*t" >>­$Ñ"&ùÖ­¸ØØðÒüùôNL¤EDU«V5ÜqjÞ¼9o½õdáÂ…äää˜8úB Ìœ9I’˜0aÞÞÞ¦Él8®�! Ï0�$n¬_&‰•œ(�Ax<½¼Y�$ÐêuO},M�–ÙoD³î»]O˜ &ciiIAAA™3&&†Ý»w3xðà'J$8àÀs²ç =�™H¼_DDýû÷góæÍìÚµ«\ÎYZ>>>Œ;–   æÍ›Ç™3g¹ORRR…¬Š|¶¶¶xyy‘˜˜hêPD2±"ðõõåÃ?¤F�|ÿý÷¬[·…Baê°  ëÖ­ã»ï¾£jÕªŒ;¶R,->pà!!!xxx µk‡<.©iStcÆ ëÕ þ§imƒ ˜4i999Ìœ9“øøxE^¸„óæÍÌ›7� 0aÂ\\\L�YƒVži÷J ÿØyƒŸ×'Ò²m>¿¯t¢g›j ì^…-Ðj+ïÝLA„Ò¨ åÍù:%è!]—õÀmÇœåàŸ§y¬ì´\þZ¼�M‹ö–eˆ‚ ”3[[Û2½Ž>~ü8[·neÀ€<÷ÜÓ]ODYD=UOÄ'Æ‹/¾ÈÆ�MzýZKKK Ddd$K—.åðáÃÜV£Ñ�žžŽ——W9Fh$''›: Qæ\QØÙÙñÚk¯Ñ¨Q#V¯^M\\;v$""Âdƒ44 `Ë–-XXX0xð`6lh’XÊZRR/^düøñÿ>X¥ ²ØXtS§¢ÿüs´ "[µ )"°‰¯¯/“&MbõêÕ,Z´ˆçž{Žž={–ëèö .°víZòòò2dÍ›7/·s›;Y¾ß·?Àá¯ätmOòœ/ÐÙ™wëÁxD ´ BÉž•òæOaecIó.O¸û:óSü§8¹Ù—Sd‚ ƒ‹‹ YY¾Áð8RRRXµj/¼ðB©~¨P§‰#@@UYÕ2‰¡¬DDDpûöm~þùg³[„"IÝ»wÇÑÑ‘_ý++«séééètºg¢¥———ׯ_7u"™XÑ„……Ñ A¶nÝÊŸþɶmÛhÕªØÛ—Ïœ¼¼<8Àž={P«Õ´iÓ†¨¨(“7-KÛ·o§zõêÔ¬Y³èÈ>ý}«Vè @ת²©S‘&L€z3XYY1pà@Z¶lÉŠ+øâ‹/hذ!:t0ê‹Û•+Wˆ��åܹs4kÖŒ>}úˆA+÷ƒV„¹W=j|:1ëùi¾ ³§z°àk7ºôÎaÀð,‚ë¨M¦ B¹¸WÞüÖ¸Œr-oN»•…£›=Ö¶–d§årùÄMl쬨Ӵ:r‹߯•y*®œNB’ ÆsþXÛýÛ¦B«Ñ‘r#Ï*E/„3’ïba)Çɽð³r^¶µ²€ÔÄLœ=¸}%Ͱ­›�ÖvVhÔRÿM:Èå2tÚâ%Óé·³±w²ÁÆÞškg“H¿�Mõþ¸ùÿ v7=�„“‰8ºÙaïôïÍLßOðáq¹ºº’ŸŸÿÔÃ+ôz=kÖ¬ÁßߟÎ�;?rûx]<Û4ÛPꕨ$Uyºdbnn.ׯ_/Óžy=zô !!�ß~û�×^{­ÌŽ[V¢¢¢P*•DGGckkKíÚµ‹<¯ÍسpýëèèhmÕD2±²¶¶¦[·n´mÛ–Ý»w³sçN¶lÙB�:u £nݺežØS©Tœ?ž¸¸8Ο?�­­--[¶$22;;»2=—©]¾|™'N0f̘n#µm‹üäIt¢ûà¤ýû‘-] nn†mªU«ÆÄ‰9|ø0111LŸ>�çž{ŽððpêÔ©ƒ\.êXóòò8vìGŽ!11‘��&MšTªµÏ1hE( 1Z„g�)Ë›ÿÛg!¯LìÈÍ Éüò›qt³'7+Ÿ¯w½Op£Â ïíчùæ­¸y;¡ÓéÉNËå½ùýiûJ 0±7 æd�˜Œ}ýÂd�—Ü�×ãäÅÛßö`lÔl’¯¥£ÈU!“Ëøû�†8>ùuaíërûj:oGL7<®ÈSÓúÅÆ|=¬HÜÿ7` Q}Ã8¹û"ç^¥@­!73Ÿ)kß i§†í¶,;Àü÷#¤e0×ãosóÂ\ì�[Èø#u¦q~¨‚ áççÀíÛ· |âã;vŒk×®1nܸR ûp”ñÀƒHËÈ2)eîÞ½;‡bΜ9 >ü©� —Ëéׯß|ó gΜ¡Aƒ�Þ©œuêÔ‰¼¼<–-[Ƹqãp»ïÚ[­V#IVV•¿º­­-J¥é{‹dbfooOçÎ�éС§OŸæàÁƒDGG£Óé $88˜*UªP¥J•Ç^ªœ••Ebb"‰‰‰\ºt‰k×®!“ɨ[·.ƒ ¢^½z&+¯6&�NÇüAXXuêÔyøÆ^^È6oF÷ùçè§N-,{^¹)2Ò°‰L&£yóæ4kÖŒ'N°oß>–,Yb¸›LÍš5qww7 sy˜‚‚nݺÅåË—¹té ØØØΫ¯¾J•*UžöGPé8®�Á÷Ý�Ð:;qcý2ÑQ(Q-³ÈÔåÍ«flÅÎц¥ç>Å«ª+Z�™¼ðBýÒ±Lõ'Æ.H§a-ظ`_ù‰Àú~Ôñ/õyû€ çP½�oÎz±Ø6Uk{³>c¶áë/‡ü„VSò0—?ZÏØý™¼ò5ô:=SúþÀ²)’‰wÓó˜õz4ÓþEX»ºh ´Œj>�Þ££è8$¢Äc ‚Pöqrr"11ñ‰“‰:�Ž-[¶Qêá–U¤*ô·êÿDç+‰­­m‘—…�?þ˜ììlš5kFLL õë×7˩Ƚzõ"))‰eË–ñÎ;ïr*• ++«ƼnÝ:f̘Á¾}ûÊ3\£°¶¶F¥R™: ‘L¬ ,,,hÔ¨�5B¥RqáÂÎ�;ǹsçØ¾};Z­\]]qqqÁÎÎ+++ÃêE•J…Z­&??ŸÔÔTrrrP©TÈår¼½½©Y³&QQQWªRæ’lÞ¼™ŒŒ Þ}÷ÝÒí —–=·n]Xöܦ ÒG!ûä“"%´’$~GwïÞ娱cœ?ž�7’ŸŸ�……žžž¸»»cccƒµµ5VVV(•J”J¥áw“™™‰^¯ÇËË‹:uêЮ];êׯ_)»OM¯Ç}Ö|}šÌÌLÚ¶m[äq•^ÅÝBä!eæC­[·Ž´´4|}ËîÚæòåËèõz:tèÀ—_~É¥K—¨U«V™¿¬Èår ÄÌ™3‰‰‰¡k×®@áõ¶^ÿà›`7oÞ4‹>ƒeA§Ó™E¢Wd *kkkBBB )|Óh4ܺu‹ääd233ÉÌÌ$''…Bah>Ø› IDATkmmmHêt:²³³:th¥]}ø ñññìØ±ƒ¡C‡>öJN)* ù‰èF?e º£G‘ýô¸»ÛÖÉɉ6mÚЦMôz=·oß&99™;wî�‘‘A~~>ÙÙÙhµZ¬¬¬°±±ÁÅÅ…F�áíí�ŸŸŸY5Å5GbЊPÖD ´ •™¹LonõbcC"ñ%%¤Qã9¿b�× ñçÖ¥c‡öP÷'=lì­Q)þ½ÑXßW;¶Gæ?C[p7=�ÛÏ0àÃNåª <ój×®ÍÆ�ÑëõO”�‰‹‹£^½z†ë1=zh§‹C©Wâ!yà'+þZU–,--K�H,(( 99//¯‡. ÊÌÌÄÅÅOOOjÖ¬I\\ÜC“‰¹¹¹¤¦¦âååõX³ÒÒÒP«Õøúú>ðçÿ¨˜]]]éÑ£kÖ¬!((;;;,,,(((@§Ó•Xñ—™™YêÍ�J¥ÂÆÆÆÔaˆdbegaaAµjÕJÝCO§Óñõ×_C­Zµž™dbjj*¿üò mÚ´¡Y³fOv�Êžõ_}…î£�þ-{~È]/I’ðóó3ôïžž´"›(�¡²1uysi8¸Ø’�–[ìñì´\] ûwËÿ)‰~P9òÿ’=`¨JY³¶µ¤Ëk‘,þh=+¾Ü‚2OE‡ÁÍéøªX•(å-44”U«VqåÊ•âÃ6á^à+¯¼bxLBâ¦þ&î’;Í,š%‘8}útæÌ™Sìñ5kÖТE‹"�?~œ®]»rüøq6oÞÌ'Ÿ|BZZr¹œnݺ±xñbC"jÕªUL�:…BAZZ’$áïï�V«E­V3~üxvîÜY$©xéÒ%&MšÄ¶mÛÐh4XZZÒ¹sgfÏž���O‘XæÌ™Ã† ؾ};ëÖ­ãÓO?åÒ¥KtéÒ…Õ«WpôèQºwïÎÉ“'Ù´iÿýï 1wïÞ�Å‹K*fff²nÝ:æÍ›€ƒƒAAAäææ†°\ºt‰^½zQPP@ZZ*• ÿ¢-1¦M›ÆàÁƒûwbJ"™(˜%™Lƈ#øê«¯øñÇyýõ×+}Ó¬¬,,X@ÕªUyñÅâ=s‹$!Mœˆ¬ystýû£‹Š*±ìY01hE(O¢Z„ÊÀÊ›K£eïF̾œäkéøV~$%¤rtûy&,)¼tötD&—q=þ6uC«�š˜ÉùÃ×ðò*vL?gn^4þªÆ”›™Ä,=Àš¤éh5Z¬l,�~NAJæêêJ`` Ç�ìdbbb"�¦Ø$á^–½°Âx×Ìݺu#88Øðõ©S§˜1c�¦Ø¶�†¬¬,F�Ejj*ßÿ=nnn¬X±‚¥K—É[o½@“&Møì³Ï?~<þþþŒ3†ÜÜ\Ö®]K·nÝŠ¬€¼xñ"QQQòûï¿S·n]Ο?ϸqãèÒ¥ û÷ï/’ôS*•$&&2þ|¦L™Âo¼A‹-Ðh4E¶»óÈ‘#IOO7ÄÍO?ýDdd$o¾ù¦aûÕ«W3lØ0:uêDóæÍyã�78}ú4~ø!cÆŒaÉ’%x{{¾¿ü‘£G�2wîÜ"?¯† >ñïÅTî­"55‘LŠqrrb̘1̘1ƒ¥K—2lØ0,-+燞œœ,X€““o½õV™­Ä”Z·.Zöü÷ßÈ~ùþçn�PvÄ ÁTD ´ •¹”7—FÛWšp`ÓiÞiñ]F<�^_ØG1²G(Q/‡…½Ÿïʼ÷ÖÐ"%^�1‡iU»Äcþgh ÆFÍfÖˆ_jT•ô¤,ê·¨I³Îe;ÅÔÞɽ^Ï´ÁK ¬ï‡ÜB†•µ^n4íÔkÛÊù9[ÌUdd$kÖ¬¡[·n¥ž  BEüíxÜÜܰ³³+òœ1‰õêÕ£^½z†¯¹��� Û¶m3\Ç7oÞœíÛ·³uëVC2±fÍš†„êgŸ}†ŸŸ½{÷ WõÕ¯_GGGÃ1Ç�‡ƒƒþù§!™åççǪU«hܸ1ëÖ­ãå—_.ÇíÛ·™={6±±±E¾‡’ØÛÛ³råJCÌÍš5cûöílÛ¶Í�LÌÍÍå½÷Þ£S§N¬^½šE‹qþüyFŽÉÆ�Y³f Ÿþ9þþþ899¾Ÿ;vpêÔ)Ã×YJJJ±U ¦ –J %òððàÝwß%))‰ùó瓟Ÿoê�Ê\JJ ß~û-–––Œ=ºì— {z"ûë/dß|ƒ~Ï´ ¢ß¾½lÏ!Z™9¿‘ãQ× äÆ_+D"Q0™ÆÍÌ^t›¿ö_gøÛ™\½dÅØ¾t‰¬Æâï\ÉÎ’›:DAs*oî9ª aíê>t›�¢‡1f~ò²äç(÷ã >^õ’ìß¾[“~F¿ ÈÎÌ å€Æôy·-ÝŠ6hY“oöŒÃÁÕŽ G®aim�Ou�Ïݦomû…{¼ëˆçiòŸúE«VÏ—áS{¾Öh©ÞÀw_gRndpûJg\aîè_ù ÓÜÿ=¤ FÖ´iSär9û÷ïä¶j½šCÚC,T-d‡|žžžåáÓ{ñÅ‹,’ÉdÔ®]›[·n•jOOO22þ½É”••ÅÎ�;iß¾=™™™\½zÕð�¥¥%~~~ÄÅÅ;ŽF£á›o¾yd"±¤˜år9µjÕ*óÎ�;ÉÊÊ¢[·n\»v�ZµjqðàAŽ=JõêÕÑét;v¬TßcE•’’‚—WñÕöåM¬LÈÏÏ�‰'2gξýö[^{íµ óâù( ,Y²„jÕª1räHãõ�$¤wßEÖ¨QaÙóþƒ4y²({.#bЊ`®D ´ æÎÜÊ›Û*]ÏêÈ¡Dö}àóÖ¶–¼<¾ ÕµÙŸ~ K«ÂÉÉR¯yuê5¯þÈó6ïRò�ʶ¯4)öX•`/úŽkoøúçÏÿ"¤U0¯N)Ú~eïïÇ™1üçGž[„²emmMûöíÙ±c-Z´xèêÄT}*»5»ñ—üÑÜÑ[•X‘ØØØ”X];;»" Š’““Ñét,]º”¥K—–¸�RYò{IË–-?ØüoÌ÷‹÷—=¬\¹ò‘qTÙÙÙdddP½ú£ß·ŒMd3„‡òðð`âĉ8;;3{öì Ÿå×étlÛ¶�yóæÊÛo¿].ÍK¥V­�Ÿ8�Ô±caÙsûöpû¶ÑÏ[™YÜN! ç6Ç’þöp’~˜%‰‚Ù¹WýÇÎü¼>‘–móù}¥=ÛTc`÷*lÙè€Vûø“AžFE*o~RÖ²ÂÕ-޲ÒO5;'m>˕ӷÐiu¨œØy�Ÿþ»‘^ïD™: þoWZ¿ØØÄÑ Â³ÉÆÆ†¾}û²dÉ6lˆo5ßö>ô‘ùö©Œí¿¼¼¼¸sçŽáëüüü"C>|}}©]»6[·neòäÉ&›©ðüóÏ#—ËÙºu+þ¹ŽŽˆˆààÁƒT¯^I’¸uëV±á:^^^äää P(°µ­¸ PΟ?Opp0r¹é['‰d¢P*2™Œ=zP·n]~úé'¾øâ ºtéBóæÍ‘$ó^USPPÀŽ;ˆ��Åßߟ�>úoooÓs¯ì9"]¿~è:uB?Ùÿý˜Á BE ­�(�6.½^OFZŠ|…1ŽNúíl®\¹b„cÞ5÷öö®p7넊ÅÜÊ›ŸV û¼;Ã>ïnêP„JB«Õ‘žš†ZUöŸrUY¤ÞÎ0Ú{�……^^^åRö(Mš4áðñÃLÛ6�à~Áô±ëC ,ð�ÛÛÙÙI¸U&‘‘‘|õÕW†$]nn.:�ŽÜÜ\ÃÀ—©S§òòË/3|øp¾üòKüüü¸ví¿þú+&L0znÀßߟQ£F1wî\¼¼¼xûí·©R¥ VVVìÞ½›ÔÔTŽ;V,™ÉôéÓ™1cü1’$¡R©ÈÊÊ2]nà1©ÕjΞ=[lÈ�©ˆd¢ðXjժŔ)Sؼy3üñû÷ï§cÇŽÔ¯_ßì’Š�†¸¸8¶mÛ†J¥âå—_æùçŸ7‹8¥¦M‘9‚nÈôÓ§£;tYt4üó‚lîîÞ½Ëþýû¹}ûª2?~V~SÎpÓ=ûßõÐrÛnjoÛCН7k†½LöÙspöÜc_&—ãæáIhx(.®.�ÞAŒ@L�.[çNŸãçù ÉËÉÄÇÇkkã|ÄQªó˜¾”QŽ �™™GF†Š6m:0fÌÄRMlŒ#%%…C‡qçÎmtºÒõ˜z‰™WHÏKå¼óõ2?6€ÜÒ /oo5m„í?m@ž…òf€$m*›ûŠü�e°)))L›6� &àëë[ΑþëîÝ»$$$\ì¦c^^/^¤F�†>‡÷\¹r•JEݺuK,æ„„Ôju‰1§§§sðàAîܹCBB¼ñÆ|úé§¼ôÒK4iR|@Ö±cÇ8wîVVVÔ¨QƒF�™EÉpiÌ�;OOO† fêP‘LÊ@JJ ›7oæðáÃØØØN³fÍðññ)·ôz=W¯^åàÁƒœ:u I’ˆŠŠâ…^ÀÑѱÜâxRú#GÐõëW¯"½ó²™3Á„wèJróæM† éÃÔ©Q´hQ£üN|+ ]�yè�ÝDšÐÙ=AVvòÏ�»ÍÈ·þ`ì§ŸR«n­2;nyÉÄÊK¥’ %Ðã­±³×‰èX·j ·Ž0ó«ÊW>˜œ|—þýW³zõf<<Ÿlm9ú|üäž8ËŠ¯ú½Xpƒ£ªs8Èì¨*÷¡¡uù~.ÉDáA¾ž:�ˆÆ Zº©çÉ©S·˜8q7ë×oÃʪ䞅å!55•9sæ ×ë0`À\|ñÅ„……ÑÑŒ€<­õë×séÒ%Æ�gêPJ-&&†øøxÞ{ï=Ö®]Ë… ˜4i’YT%–…„„¾ûî;>üðC³¾¢ÌY(^^^ 2„Þ½{sèÐ!öíÛÇ®]»ðôô¤^½zÔ«W�êÕ«—ùòu¥RÉ… ˆ��'>>ž»wïD¿~ý ÃÚÚô ·KKjÒù±cèFŒ(\©xò$²+̦ìY«ÕòÚk¯°hQwjÖ,¿»†úƒWÑõš™ùÈ–½Š4¨ì?@Õ«çËk‡Ð³÷§Ì^²{3\Á*àçŸfΜ9„‡‡ó /àåUôÆRhh(G�¥C‡•&Qu?�Nlj'hÙ²¥©Cy,¶¶¶(…ý²Û¶mË�8qâ„Ù”?­­[·b6‰DÉD¡ 9::Ò®];ÚµkÇõë×9}ú4§OŸfÏž=Èd2|}}  jÕª¸»»ãêꊋ‹Ë#Ë¢ ÈÈÈ 33“ÔÔTnܸÁÍ›7IIIA.—LÇŽ 5Ùòø2áìŒì×_ÑGF¢›0mh(²åË‘:u2udüòËOôîT¾‰Ä_ãÐ ].vÈöŒCjh´s¹»Û3q|+V,þ‰ï¯š < 1úÁbÖÿÉ[o6CV†«•ÍMóæÕ™:u7*•ªBÝ$«ˆfÌøœO>i]î‰ÄãÇoòâ‹ 9yòcŒó;5ªùùV¼õÖrvoó¦}—F9�±äèò8 :ÍnÅQ«Î¢E‡§Üõ‘ Ä9¶ã<7Î'ÓsT›"�{ËÝð–»pîàU­ûÃð\ý5iÑ=¥^M–6‡[š,% j•P. �¨¹ƒ\’‹�ÂS[·b“&¶1uF5xp:wþ¹Ì“‰¹º\*¢Ô+©*«ŠR¯ÄFzpë {{{FŽɉ'X¿~=Ó¦M# €5jàî­-2™Œ´´4Μ9ÃsÏU¾A�ÇŽ#//�ððpS‡òXîO&ºººÁÆ�©W¯^…ÿütêÔ)._¾Ì¤I“LJ"™(EµjÕ¨V­]»v%''‡+W®píÚ5C’1''(œ\ikk‹­­-–––†Õ‹*• �FƒB¡0¼(H’„««+DDDH�5*ü‹C÷¦=?ÿ<º—_F×¥‹Y”=ÿñÇJV¬èQ>'ÓëÑMùýg"…ø#Ûð¸ý´]ºÔgÖ7‹‘LÌ“˜]ÜÉÇûFS‡atÍšUåøñã4oÞÜÔ¡TjG�îgÚ4ãô!úøã Ô®íÍÀ�ÅWØ+•\¹’†N÷èƒk×gúô-ܺ•ÉsÏù3}zoBC«~ü&..O÷wõ¯¿Î0hÐæÎíG³fÕY¶ìQQ³9uêãJJ²å½÷ššÁ‡žÄÊʵ2ï©â0¦\]>ûï%ÕñhôœdöDÙ†ÓÆ&Œ¦6 øû·¬øb3¯õ0îMÎàFU nT€S{.{^† éÁeÓmmšpW—KŽ>W©ä‹òÓêËœ/¸ŠƒÌŽ`Ël©˜Ã~ã’Ë*ÿû9€¯¯ÉÉÉešLhkÕö‰ö“$‰   ‚‚‚Š=—ššÊgŸ}ÆÞ½{iÕªÕÓ†h6bccÉÉÉ¡]»v¦å±) llþ} µ±±¡[·n¬ZµŠ h¢ëè§µnÝ:4 =Œüž÷$ž�ÌŒ`v¬¬¬ðõõ5é,³çä„lÕ*ô�;£9m“&È~ú ©‹)Vá茊û­LìXæƒVJÃÝÍŽìÌl<½+p¹¼ðLyÖK +ÏZ€‡“Ë%4�©Ã¨Ô233qu}üd_n®ŠõëO??úõ ÇÍíßÞ»›6�F¡P“��Š»»=kÖ5<×¾}]\\þMFYXÈ8räþyGGk^y¥ ~~.†ç?ýtãÆu`øðHfÌèÃáÃ×øæ›XfÎìSb|£Fµ 'Ç’Å‹÷aeUø^.•Ç{úcPéÕS�g«âûT'Ñè58Ê쉲 3$åÈ Ûçfæ£ÕêÈÉü·¯¡•�%Ö¶E+8r2ó¹s=?\¼Š'Šï­&ʼs—´¤lªÖòÂæ)n`j5:/ÞÁÙÓOGœdö8ÉÞ‡ÙÓ• ÈÑå#»ï{¼_&™â0Î8áªw¥ŽTç‰c*¦gå½ÎÂBöDïu÷z"V‘Wy¬Õ‡OÃÓÓ“nݺ±iÓ&êÖ­[±[mý#))‰­[·Ò«W¯2Oè–‡üü|ììŠÞà çüùó,[¶ŒñãÇ{ÞÜ?~œƒ2zôh³Œ]$ÁÌIƒ#kР°ì¹[·Â²ç3 ­ž+�A+¥!IbÀ½P‰hAx:z½žÇ­T;qâ&={ΧV-o""j°eËY¦LÙÄ�©Q£púöÊ•G((Ð’””ÅÉ“‰(†ý›6­nH&ÊdsæÄ²víqÂÂXµê"3flãÂ…)8;ÛRP åèÑëüðÀ"1¼ôR+W)1¾ûË›ÃÂÒï›32•¾€cªxv)�²Wy¥^…ƒÌÎ�@lbS äEöùzd4î5|ÝÃm¬á¿_ß�7¾ê Àé½—YúÉ.»�ƒ‹i·²x¾g(“W ÇÂêßK½^ÏÜÑ¿³t¿!±øþ¢�D½üx}Âôz=kfmçç©áæãÄÝô<|kxðßÕ¯ã]íámZªÈ½¨"ÿw¸ÃuН@V  ƒtnèoà†+u(9™xQ ;Ég½’ƒ(�ž ç4çˆQÅ Ð+· /·d"@»ví8}ú4K–,a̘1ºõV^^K–,¡víÚDDD˜:œ'’””„··w±Ç_zé%fÍšÅòåË1br¹¼„½ÍÏ­[·X½z5�:u¢^½z¦§D"™(€Ô¸qѲç Ëž«W7uhO­<­Be'J ¡|¨Õú÷_Lß¾á|õO àÍ7WðÁ°zõ¢£ {06hðƒ5ãý÷Û—x<�NONŽŠÃ‡?@’$²²ò©Re6œbРf$%e£Óé©ZÕ�µk�3yòzÖ­{“ªU]ILÌ,v¼ÿ-o6Z¹ŽÊSìRåoå zö’--m&­ëa!=øÒä½xoÁVL‹a÷š£,<öQ‰Ûe§çÒ~Ps¦ÇŒÆÒÚ‚[—Sy'ò+6,ØCïÑÿ–;^:vƒ–½±.m–rNø�ÙoDÞ¡Ž®¥_²~Þn~�¹�o÷Œ£Fˆ?š-_�Œfæk?3cÛÓ“ðÃ�þôG+éPèKž2­CÇnv¡ûç†èK¼„ÅKßÕ¨±ÄR$…JÃYrÆCò •M«rM$Èd2^ýu¦M›ÆÒ¥K>|¸¡ÿE¢R©X¼x1r¹œ�VØ�III%Nn¶¶¶fèСÌ�;—•+W2`À³ÿÓÓÓY¸p!µkצ[·n¦ç�D2Q* GGd+W¢ïÔ Ý›o¢mÔÙ�?"½ø¢©#{2&´"ÏŠg½ZŒiß¾Ο¿Ã×_×áèцÇ4ðã‹/6?Ñ1'Nìh¸Àqq±#(È“›73ÈÏ/\YlkkÉ•+©\º”Bzz.¶¶–ä婊«¤òfSP£f¿~?Ñ¡+8Ñîk3·a-YÒØª­mÃhmÓk©l+-žïÙÐðß:­¹…ŒºM9³/¡H21¸q¯LìhøzègÝX?oG¶œ£m¿Ò­NÔjt,ýd##¦õ¤Fˆ?–r†MíÁK~ÉÉÏí IDATÈÃÑíá¥Î¥%G†ƒäPâs2d¼(½H¶>›»Ò]œõN%ÖÆîÕïå*WqĉÆR#‚ .“ØÁTüåþ ¶l²ó;::òÎ;ï0{öl–,Y°aÃ*TBQ¥R±hÑ"²²²5jT‘žƒIFF¹¹¹øûû£P(HOO'99™¤¤$nß¾Í�7P(?~+++^zé%³M(¦§§³`Á¼½½1b2YÉ-0Ì�H& B# Œ,, ]ß¾èúö­˜eÏ&´"ÏQ-e/%%I‚�>ZWì¹5ʦw–µµMa"Ðϯ°Ujj.ãÇwà�7ZáädÃ/¿ÂßߥÈ~¦.oÖ¢ã°þØ@¬~'¹äbék‰×UW‡u¡•M#l$ã½ç«•l\¸—ÝkŽ’“™�w5wRofàîçòÐý¬í¬póu&åFF©Ï•‘œMNFË?û“•Ó·yN’$îÜÈ(³d⣸⊫ôÏjÄ\#W“ªa…wõw± ä„Ç-nqš38ã„^Ô¤¦‘"„ÒQéUœÓœ£‘eñUgæÀ××—±cÇ2{öl¾ÿþ{† V!&!gffòã�?¢T*5jîîî¦é‰�>}KKKæÎ�KAAa;[[[üüüð÷÷§iÓ¦“žžÎüùóQ( 0À솻&%%±páB<==5j”Ù'¦Íë§'B©Hõë#?xÝÈ‘…eÏû÷–=רaêÐÍ ­³H”@ BÙ pC§Ó³víHª=¢/&Õê'_ ììl‹——#‡]¥Z57œœ W�5kN¦E‹äçpìØ ¾ü²¯¾Z4±4aBÚµû†ððiÔ¬éÉ�Œ÷xïmÿýo:vL AƒÏhذ*»v]¤ÿ&tï”Oyóý ÄýÒHCŽŒ)”Œ «Ô×”¥ˆ®!Ìý+Ó-%²G(jeHÿy5¢°?b³@–ö'¹™ùdÞÉ!vÕÔʜ܋öLKÊâÝV3i?°™)9ü:c+&ýß&qß/¬}]¾µ’ †Uqp±ÅÂÊ‚vš0f~Þoû5tšK›¾aXÙZqîÀr³òùà¾DoE#G†-¶ÿÏÞ]ÇU}ýÝ€K#­”„‚Šb v ³f`+8ÇfëÌù›S¿ºžnÆœ³sÆl�Ýí&³0f‹„(*-q�{ïïæU䢠  çùxì1¸Ÿs?Ÿs�»ñ¾ïÐyÌczHº“¨I$E’ª3�°W³‡Ç<Æ3JâˆCQnYx ‘‘ñìÛw…þýé<¾qã9LLù &ªÕöï¿Jf¦Š¼ e]]Ð/侪EI¡Pзo_jÔ¨Áš5k¸pámÛ¶Å××·X{ô©ÕjNž<ÉÞ½{‘J¥ 0 _�·ÒàèÑ£ØÚÚR©’îI÷ºØØØ0vìX6nÜÈ’%K¨Y³&þþþ˜››áNs»ví›7o&==�aÆQµjÕ·zý7%‚‰‚ð.¨\ééÓ¨GŒ@³hê��ì²ç’�^ÿŠA+ÁÁ·Ø°á,¿ý¦;£2<<ŽääôW^&<<Žÿýo+!!áØØ˜0bDszôð)´‡QPÿžý—…³çqýr(f–&Èd…ÿ SÄähTf*ú û¸ÐÏ �¡Ì"íI:�›7â³Ï‡acW8}À„’G”@çvÿ~"ãÆmÉ3˜˜_¿þzˆiÓösÿ~"66¦"˜øqs³æüù‰œ=εkP(äüþ{eËæî•U«–3ׯÇñãa>>¬Y³†Ÿþ???š4i‚¡¡î/R Kdd$ûöíãêÕ«4hЀÎ�;—ÊRsL„w…¡!ÒÅ‹Ñ4nŒú³ÏPùø ]¸I@@ñí)ƒVnÞ|HHHø]&))�¦M§Ó°aV¬ø”+W¢éÓg�†ž=ó7‘±0-_ø;û÷ïfÀ4ªÔ/š@ÀèØ_IÖ¤0ïܘ"»FVFo¾@߀OønÊ�ÔªSz3D…üy_J ïÞ�%3S…»» R}[>L >þYi£žž “gÏaO߸>z”̽{ ¸¹Ùh{Ù=õñÇu騱:[·^àçŸshJ?©T‚¯¯ ¾¾.¯\kkkJ—.¹+´AÁçUªT6×mr¹Tg†PQ”7‡Æ>Í~¶k¶ER¤T—T§¯¤/m%bEñ5ë/_¹,ŸÏï¥ó˜…�ƒ¦vÉu{…NÚŸk}ð,ƒÅ»É«'K¤ü‡4ÅHS�Ç-ËšÑ{â»<|]•%ÿý]}Égü 2´=U¨(Oî`¢%aÜÒöh4•”¾ÝÅA­Öö…B/ÏÞ®11I¨Tš¯u …#£gA¼§%—‘‘ñ$$¤R¡‚­¶µÃSãÆµfÔ¨˜>ýW®¼¼?éSJMg2ïr*óVRÝ“ÊK3###ºu놟Ÿ`óæÍìÚµ |}}±··/²kGFFÂÙ³gÉÊÊ¢^½zøùù•˜þ€…e÷îÝS·îë·œñðð૯¾âèÑ£ìÛ·�£G�R¿~}êÖ­‹��Ý«O�O*•Šk×®Ìõë×ñôôäË/¿Ä­4Ì<ȃ& Â;F„¬N�ì²çÀ@$»w#]¸Šø–\î%�Üb&F7péC/Ì~î‚Ûs�ÄË—£¹?‘cÇB‰�}ÂÆ�gµÇªT)‡—׳X¹\F\\ 7žãÉ“tš7¯DÍšÏ>,^ü7züñG¤R õê¹’��ÊW_mëÁÄ�[vpöÊ?ürlÒ"ÈF|ÛäúršÔÆ»iE¾éð3æÎÂÉÅéÕwJ½wµúرP\MJŠccññ©,XÐKä™;÷(Æ­Ó®·´­ý¹E‹Ê80Rû»¡¡'ncÞ¼cdffXׯ@Û粤¬­M°¶6ÁÆF|øŠFa–7? îd'šm±7½i#i� "C](\^xá%ñB…š,2u®‰'^ۣџð‰Îui¤a€�èѬ]{†Ï?߈‰‰‚ÌL2™”µkûQ·nvFô°aë˜;÷¨výó¯uÇ7cÖ¬žÚߥR AAËØµë2))J,,ŒØ·o$ÞÞÏÊÖíÿ›–na‘ÿö8�ÕO8–q'©Mô+r�3¯ûpK4kkkñ÷÷'88˜“'OrôèQlllðôôÄÓÓLL^? š””ÄÝ»w¹qã7nÜ 66Z¶lI�:uŠ<Ó®8DFFrâÄ øÆÙž2™Œ>ø€&MšÌáÇ9räNNNÔ¨QƒŠ+âààPà^†J¥’°°0®_¿ÎùóçIKK£Zµj|ùå—¸»çnUÚˆ`¢ ¼‹*UBzêêqã²§=_¾œ]ö\ñÕß¾†Œ¿o’ÜjFÊLV·¨Ì;36Öø‘%K>& ;¸·cÇE¾Á­[�ˆ‹KaÑ¢g�¼?þ¸nŽ`bhh S§îÃÛÛ‘ððXÆ�ÛÂîÝõÙÇ�ߢk×Z9²‹|ùâ‹?yð IgÉYQHˆO`ÕòL;:´À�ĬLÁÛþ¥iý³îßyÌÍs‘Ôlî‰iÞ¨«ræŒ^À�ÿ÷ ÿXòÖ¯/Ÿw©:,ìíÛÏeÚ´® Ô‰DÂöíùøãß©SÇGG †õcèP?öî½Â‡ÎF£Y�çù–/?Áøñmˆ‰™†D"á£�–òå—›s¡(FyóÓânvsWswÜ-ùœötÀNb[ˆ;ÝdH‘¡»ôÒ[m�ÆL‰î€#ÀŸšÍ¤“†)f´à¬$Å—=[œºN¿~+Ù²e­[g–˜6m?��K¹zõ ô˜3'€9søõ×C,^ü7W¯~›çù&OÞÃŒÝY±âSRR2øàƒ_ùþû�lÚ4è�öé +C?£†”•¾�÷éÅÍØØ˜V­ZѪU+¢¢¢¸xñ"W¯^åĉ¨T*ÌÍͱ··ÇÚÚ ÌÍÍÑ××G__™L†J¥"##¥RIbb" |ÈljŽÎÎÒuss£]»vÔ©S§T–3çEá]ehˆô·ßÐÔ®�³ì90°H/«Y‚º÷22Ñ�uðs‚š{tëV‹  åtèP ccãÇ·aüø6|óͼž#ÛçE»w_fÿþ‘”+—Ý÷Ãg³`Á_Ú`â½{ ´iãELL]º,dÀ€FÕCOOFTTü[ &nZ³�îcüÐ7(øT4ej?,¡iÖ¼\Ç’ãRTk2™ÊL¬ÊðÛßc°|K�éynÕ°t1âꥫT©V|SÏ„âSÚK 'MÚMÆî ÜD{›¿¿7Õª9°gÏ (XϨ¼sôT ªG§NóÉÊR#——þÌd¡ä{Ýòæ§Ä=š=Üá�@üLòþ’8!2Ð…’CŠ4_=½%ÕH$‘$MŠ<“4ÿò@òsÌ(Oyì)ºRÓâ2qâ6 j¢ $|ñEK¦LÙGHH8�¬§úˆÍùè¿�C&& ºw÷aéÒà|ß?ƒ,ôó;¼/�Ä9::âèèHÛ¶mQ*•DEEATT±±±„……‘˜˜Hjjî)òÆÆÆ( qww§eË–8::âààPê'3ç×öíÛ‰‹‹ã³Ï>+²k¸ººâêêJ@@�?æÆ�DEEÃ�7HMMÍñßG&“a``€¥¥%vvvÔ¨QƒÎ�;S±bÅw¦Gå‹D0QÞq’�?~VöÜ«’={�.XF…œÝöÜ •›2 ‡†7ÃßÅŠG·³K®*U*KFF—/GkK,òkØ0?m  ~}7v츨ýýÉ“tŒ�õ‰�MáäÉÛøú–çÓOëch¨Ç“'º:…ÁÁüðu¿×¾¿F£á«Nó 9p gÆ,ùG;þ=v“2¶¦,¿ú ‹ÇoeÝÔ}|6£{!î<ÿÚô¯ÃÞ5»D0ñ=WZK ¯^½OhèCÜÝ'æ¸ýáÃd"#ã |¾{F™™’•¥F©ÌD.7ß8 %GA˛勉=ý"'¾¾Ê>u'àY±=íÄà ¡Ôóæ¿¡/©rÎ$ƒ8b‰ÐD`ˆö’ÜÁÄdžAÄ=Í1•”®~~×®=àÖ­Çlßž3[99YIDD\�Ïg`�3d`ff@jê«_ãŸï‰ØQQƒ rÑ&A…B�»»{že¯*• ¥R‰��AŽ2ÛÍ›7ó×_ѵkWlmߟ òóçÏsüøq† †¥åÛþemm�µµµÎcéééÈåò·:X§¤xÿ± ¼�<=³ËžÇŽE3kª³g‘nØ€ÄË«pÎÿÜ MçÔÛr³µg˜½-ç›[[S”ʬ7¾œB!×ö'(WΜG�žP¥J9¢£§`ccJZZ&IIéØÛ›¿äL…'=]‰ÂDŽì5³‘4 µתöŽmMðö‹L꽌ù§Ç‘û„ò•Ë"•I ø²CëM)¶`¢‡�3k¾>Z,×JžÒVmjj@›6U˜4©S®c––9¿`y:�]­ÖèÐ"Å)¿åÍáª8¶¦_`cúY‚3n`¢gÈg’Ïh+i‹+.oiÇ‚P2øJ|ñÅ•D�Ý™ô1<Ðöh´Æš®äèð„'c\âz4ššðÉ'õèÛ·a®cvv9K,e2 juѼFïR^âZÖœ¤JÞ�Œ¹¢ “É0Ò‘Ò©S'ÂÃÃY´hÇÇÜüí|æ)N7oÞdíÚµ´mÛ–ªUKFKƒW/zG‰`¢ ¼/ ²Ëž›4Aݯêzõ�.X€ä£�Þì¼÷Pwœ‡æ\$’±­‘Mî„©ýXÆ�oÈÍ_yw}}9o`¬PÁ–³g³'BÛÙe—K„„„£PÈqrz;ßX=~ø§×Ÿ�ö(*ÏÚåéûcGªÔw£¿÷Ï mÓÆ ==��KèÚµJe*•º@=„OŸ¾ËæÍçøë¯›DEÅk_ëzôðÁ¥–&FŒÁôéÓ™3g xk¥¿oÓÍ›7ùý÷ßñööæ£�>Ê3È/¼]"˜(ï#¤'N<+{ Aº~=’jÕò} ÍúÔ}V@#¤}�¤Ž‹öØwßµçöíGxz~CëÖU033àܹœœ,Ù¹shŽótéR“)Söáã3™&M*’œœŽ½}fÍê™ï½4mêÁ�!MiÔhmÚxqõê}RS38ztt¾ÏQÞä…Í¡‚ &ü¸”ºm«rbÇEEÅsþð N켄D*A£ÖpîðuìÊ[ŠQ¡Ä+‰%Ð …œ}ûF²zõ)Ž¿ÅßßÄÓ³,Ë–å$H¥ÅôéX¿> #|}Ÿõ”ëÔ©FFú9îãädÁر­Ñӓ庶——}Ž)õBé—‚¾¾“·ß3:Ú�Ñ£}©^=Ž�ã‚Y™v‘?ÒNqXy5œe–ÚbC}÷S~©P(ÈHó6'ﺌôLô D¿ÕÒ@Ž<_=³È$N’Ý£ÑVb‹ ¹ƒ‰�5�‰‘<ÄsÊ`Ž oÖ£ÑÆÆ”3gÆóûïÁœ½k�®7xpzö¬ €Wƒïè² &çÔ\³ûô2¹&5áSýú,iÌïC?¡q× ¤µÍ 8ø#Gn 66…/¿Ì�(.nÝH‰W}ëö¢ižö.9Í—c'¾z¡PêÈ�æ™Áè-©Ž .$jQ ;35A�ƼÔcÈ�`!5f€Q#¤Åø…�±D¡í‡(z"– r¹œ~ýú±wï^¶oßNDDÝ»w/•B>|ÈÊ•+IHH`ðàÁT¯^½¸·$è ‚‰‚ @ùòH�Cýå—ÙeÏgÎd—={{?[ó éäN &œ¾Uk9÷¡P”ÄhAx™ƒ¯áåeÏGÕ²K'Mê˜cÍùó‘¬_BXظºfgÔÛÛ—ÁÏïþïÿZP®\þ'mJÌá¸AÓÎ’~:“5z§‘$XbñWG–v²£ƒ‰ê 5KNSî3Üܲ¯çåeÏ�1¬_R¢‚‰ã¿›Àô>SøyÿgÚ¡bÂ3;æÿ�ƒ]yªÖ(J…·'?=9-•ˆS§�®ÉÊ3�¸9=;cÙRjDM¹3VÒ¢Èá§ïñêEÂ[%•JiÛ¶-UªTaÉ’%Lž<|||JEypff&‡âðáøºº2bÄÊ”yý—BÑÁDA²)ÙeÏÍš=+{þùg$#G⟌ªöä\ƒV„ÂwÿÎc"®= =E™ãv§Jeq«æPàóÅF'¼í_b"âé2¢VåÌIŽOÅÔ¢dL„’T-y©\¹Ó¦`ëÖ tê¤;“þ¯¿nR¯ž›6�Às�× IDATа¡;ŽŽߢ[·Z/½Fª&ƒCÊëü‘vŠmÊÉÐda)5F¾KŠË¥iÜ]6�Ç÷ác’=t%µÎóê‘™YòþŸ©]¯6Ý»÷bb»EŒYÑ Ǽ'ïµJÍÆé‡¹z8š™‹f÷v„ÊH¢O]½WWßh€‡êd²RY^NçšpU�ÕO°�a#5ÁTª;síiOD{iÜäÖ:×%“‹‹ 'Nd×®]¬[·Ž'NСC\\\Š{k:i4.\¸ÀÎ�;ÉÈÈ €† –ŠèûLAÈAÒ©2oïì²çQ£�ìÙÃ�'®‚�i®A+BáZ0æO6Î8€‰¹aŽc]F6/p0ñÔîËüØk)îÕ¹s9šf=}°*gÎ7]Òk\kj·ªRh{„7URK ©“¹­zÌí¬ÇÜR=â¶ê1OÔÏ‚ýúÆ’‚L0• —ä¯�Þ%�hôõ8—|sIþ³Ûž2”æ9iôeÌ%æHó¹Ç§äÈ1•˜øZÆcô%ïsk!-x@J�#IÎ/TIDi�I¼:Uç}ÚôôâÓêÓ¥ËBjÖtbĈfú¢¯ÿì­tTT<åËg÷0`eÊ2mZW\\¬ˆŠŠ×yÞ'%;Ò/²!ý,{•WH×db)5æcúô0𡹢Æ£BË–czs^nß~Ìœ¢GŸ‚ü‘¼5�ztƽb¦õš‚kM;š}T“еœ‘É ö÷ì]ð0"ŽÓ»¯rxÕyZ´lÍÜe_¸·¦ ¼¨«AMT¨óì­x5+šs™‘ÔÑs¡¥¢r®5ײ°[y‰tM>zÎ"˜X еkW4hÀÆ�ùí·ßðôô¤E‹T¨�»�TqP«Õœ;wŽƒK£F�ð÷÷ÇXW»-¡ÄÁDArssC¬-{Ž23¢âéq ²ŠÌÃÈx6L?À—¿Ñòãz…òÁjÖðu|>¿Í}Xs’öözùrx]ˆ& %ÒÛ.�ÎDE„*Ž[Y�r og="I“žc½‘D…$ÿoŸR4dhÞpŠ­+À%¶>Ùúfçòf Œ€ù1ûò^31ûŸsDð)+ø4vEÎ㣳ÿµöþø>ûç_ïBºDÂ)ù¾�Ù•ë”Oÿ~˜K éiP›†>´TTF�ì‰àÑцdfNÆÙ9Šÿýï_�Û6lffÄÅ¥�@¯^uøî»’Û¨¾ZÍj¬Ø¸Šó§ÏslýÖ÷7*U&™Å½µ·BO_)6¶6ԫ߀¥«Fa`Xúzš %›Œ¼ßG¶RTÁWÏ…8u æRC�kÊH ±•šÑX¿‚è‰XÊ•+WŽ#FÉž={˜7ovvvøúúR·nÝb Ü%$$pîÜ9‚ƒƒIJJ¢víÚ >ÑS·4ÁDAtÓ×G:s&ÆOÿ›D ±HÅ?HÄÂÎŒ6}Êù?!5)�æ�¾¹Ž9¸Û°ÅÉB¹Ž ¥W•@gfšåë<‰š´<ƒ…ª8²^(µ—™ã&³¡³AMÜäָɬq—Ùà&·ÆNš¿k¾ ÔiÚß׬ ÁĤþþþ/½Ÿ%©Ý™u/“¬N&‹‚<Õ¨IT'øZiš4ÒIõÂ$ªQçQÖ›—,²HV'çkmll,'Nì¤}ûJÙ¾Wüy¤¤(Ù»÷ QQ Ü…BÎÁ3׈�M¡U«*¤¥e"“IÐ×—³uÿ*U*K¥Jes�G_"£¥~Z+ªè RÚ�Æ”� ¯Ÿûþýú5ÄÇÇ™2eŒps³ÆÒ²tdtÔ¬S“šuj÷6á½#CеÔk©IžkÊIÍùØP´5z—8991pà@¢¢¢8~ü8‡bïÞ½T®\™*UªP¹reÌÌŠî=NLL W¯^åÊ•+ܾ}kkk7nLÆ 17/xÕ…PüD0Q„—’4oŽòWQvSÔÊWÉîk“—‚i!|ÔSÈÉHÏD•¥Î•å}û1el ^†(Å%¯h™lƒE0|ø5ªÜ˪q;ëñ?g o«r–†êKä8JËà&·¡…¢2n2ëÿ‚†6xÈm1}�’àÂ$A‚…ôY®q–>ÆYƯUÒ›/²¢9miö ŒÌS×Ð:w0…ÈâqvO÷æµhÐÀ�•Qåøî»�,èÖ ‰yvyajjëFœá›-íinîY =-_^‘­[�ÑÓû W×@w0±fM'Z´È]¦(‚ /rtt$ €®]»ráÂÎ�;ǶmÛX¿~=ööö¸¸¸àì쌳³3¶¶¶H¥ÿ˜‘‘Att4DDDpçÎâââ°°° jÕªtìØÑ±”ÁDA„ÀÀXÁç zñë�5|µ¶?’7œ”mdj@…NüñÃ.>}®Ü-)6…�3Ò~`ã7ݲ ¼UdðHñÛî‘ôêEÈý¼t�Åe“Yd 1)9Ö[H�p“Yã£Wžî†>ÙC™5nrÊË,_Z&ÏÓh4 ºŽzõ\ ª§½=8øúúr<<ìh׮ƭcãÆsÚž…óæÃÔÔ€Æ� ÖŸ*:Ú�Ñ£}©^=Ž›7§= íñ‚ ‚žž¾¾¾øúú¢R© ãÚµkܽ{—óçÏ“ššŠT*ÅÜÜ ,--Ñ××ÇÀÀ===ôõõIOO'++‹ôôtRSS‰��'>>žääìª \\\ðóóÃËË GGÇb~ÔBaÁDA �J¥&#C…¡¡^qo¥ÔQ¦f°sÑq.þu“žÎãÑSä|zî0¨ _¶*Ð9GÎ äÿšÿJÈþ«<ŠŠgù7;¸q&œ²®ÖønR˜Û„B‘D‘DE$Qš¨ÿ~Ž"RI4Ñ9Ê\eeeèËä4°ªHÊÕÖ„¨NêõŠ8ªìèß"‹áŸDca‘ÎÆ�çØ¸ñ,Çï‡Q¡‚-4­aîFòYYj¾Ž““%•+ëÎ{•#Ö£Tæ.�íÖ­-[fgŽíÝ{…-[.h�ÙØ˜P§Ž+íÚUÃJ(‰D‚‡‡-Ÿ}¶–Ÿ~Ú‹—W9?NáÔ©;Ì™€µuv© ••1sæÐ§Ï ¶mû—ôôLöî½ÂŸBO¯`éŸmÛz�� £lÙ~¤§§0qâvfÌ8ˆ��){ö /Ї)B)•™©bñâãìÛw…¸¸T¼½6¬™ÎײÔÔ ¼N­ZN8¾F £øøTÆ�Û¢óØðáͨZÕ€eËþáäÉ;H¥ììÌhÞÜ“&M*øšBÑ“Édxzzâé™�A¯Ñhxôè< ..ŽØØXâããIJJ"..Ž´´ìV,R©ôõõ144ÄÑÑ+++,--qpp(Ò²i¡ø‰`¢ oìúõŒ¹�cÇBQ*³¨R¥cǶΑÁ°ÿU,ø‹‡“©WÏ� >ÄÂÂ(�³êvíÚÚ·Ÿ£óئMƒ¨YÓ Èž¤yøðu ûƒ ��mÚTaĈ昛ën6]œdr)�:U§Q§ê:�»W/ø7ynÕXzékÖü´¹¾U–š€/[Ñap“\ÁJAx²ÈâˆÔhC†Di²ºK8)äÌ.T Àœ$NÔ§>N8â(qÄw\qåÿÆbÿžOÁÒËØ°Á–éÓ½øv´Ó¿ÎÄÓó·n-eÌ'ZµªÂÙ³á´h1“ýûGj3Å23Uté²€Ó§ïòða2?üàÏĉm_ëñ¹¸X‘™©âäÉ;:t� > L™gÏ9çÏG²}û¿Œõ11I ²77Ž�ü=œj[Œõ½{×ý¯Ob<¶¶f¬Xñ©vzóSAAõ¨]»<{÷^AOOÆôé]qu-ØÔåË+ò￵èÞ}7Ý»;ýµÇ ŸM¼–ËelØ0€ê¯ñú »#(h§NÝeĈf(rþúë&µkO&4ô{ÊOß¾+9}úIIélÚ4赂‰r¹7·ìç´íÛ/“Ä€�02zöütôh(.DÒ«W4 wïÆâï?�.]jòûïA…𨅢$‘H°µµÅÖÖ¶¸·"”`âÓ¤ oD©ÌâÃgÓ¨Q._þµZÍ‘#¡üòË:tðÖ ·o¿HÏž‹ùöÛöxzÚ1gÎQš5›ÁéÓãÐ×ÏÿS‘‹‹6 à믷“žžÉÔ©]ððxö‚“Dݺ®üøcGžúØb›+»Ð'ÜpÅ�ÂÏnÔ(†F�b°±™ƒ›Ûx®_oO�ÍpwOfÀ€ Š¥¥ÈÈ<^afV<ƒW\\¬033 ::¡X®/¼= …ü¥ù£G7!9Y�¥KƒÑ×/ØôjAÞ?zz2$ ׯ?Ð�\ïsMM ´¯uÅÕRÃÛÛ€{÷D0QÞ"˜(Âqv¶D¡�3wîQ&O/Ô½{ „†ÆäÈè00УG�Ú>|£@ÁÄ7af–´HOÏ|+×+©6Ï:½›1' ¸·"”PJ”<â‘Îrä[Ü"eŽõO³ häÊ.´Çi1 ;ùé§ Ô?¿êÔ¨1ŠÚ0n\m~ü±:½zÝføðkT­_,{{ÞÙ³$&¦Q¹²îl6áÝÑ �; ¸ë<¶|yE¦Lqá›o.àãóXçA„çYZóÅ-4h5^gÔ¨¨Wϵ¸·¥ÓáÃ7�Ë¥Ú¡U‚ ”n"˜øšÂÂÂØ¸q#gΜááÇèééaooOƒ èÙ³'ÖÖâÛ–�xxØ1iÒÿqá‚?¿ÿ^‘E‹}:ƒ *†–\3gÎdýúõ|÷Ýw|ýõ×E~=µZÍôéÓùõ×_yðà�övccc™ÏsmàØÖ ø¹ó_S£ÑpjÏLÊlð�Púd’I 1:³ ïp—TRs¬š]è…­%­sd–ÃY1e¾©zõ\Ù¾ý3nÞ|ÈO?íeâÄ/ùã�kL™Òœ… +±dIEm ´Rù˜´´+E¾§Œ ·o?FOOFÅŠ¶ìß?’ºuKf&‰ðv Ú@”7 ‚ðÚÚ·¯FûöÕ ç›ovдé/üý÷ÅúÚò䉒۷c` ‡¯oy¾û®žž"+QÞ"˜X@lݺ™LF§N�èÔ©åÊ•#99™7n°téRnß¾ÍàÁƒ‘ÉdôïßÿÕ'ŠDŸ>}X¹r%ÞÞÞ8;;Î¥K—X²d G�åäÉ“XYYóNß eËš1iRG&Lø�_~9ÀÈ‘¨PÁ–¶m«bggF||**•šÙ³{òÅ-©R¥»v]¢\9ó"ÛSåÊå8°ÆÆ \]­©Tɉ$ÃÞ†êM+rëß(+fŽ‘H%LÝ7BçÚ².¯Îv^7u?kÞûÒ5Ê´L$R “¶Vð %Î˲ £‰F�ǰ“Æ4Æ]âN‰;Ž8á¬qÂTòng T¬hËï¿‘ššÁ’%Çùè£:üüsß~{ž \™>½*·n}Áôéé<~^¤%ÐeX¸ð£"9·Pú,_^‘­[�Ey³ o¬víòìØ1ŸÉ¬Xq²Xƒ‰µk—¯u‚ðÁÄØ·o[·n²3{ôÈ=!uÔ¨Q´oßž#GŽðÅ_ˆ±±q®uï£ &пÜÝ‹¾ŒkÛ¶m¬\¹}}}6lØ@ÇŽµÇ8€¿¿?aaaLž<™_~ù¥È÷ó>12Ò端ڱ}ûE¾AÛ¶U)_Þ�FÕ+÷ñövÐN¹ü÷ß(퀔¢àîn]¢']6êTƒF�j�’˜†D"Áç¿æØ¯C™–AÕ†î´ ª—ç}=*×u¥Œ(1)²Èâtf†ÁžäXÿ²a'î¸c@CwJNŒ½Ð¤¥e²iÓ9z÷®“ãK=LM žûýÙèÊ• —ç÷ßëæ*�–É4º.#oD”7 ‚ð&ºtéò6·YbU«V�jÕª½•k-Z´€¾}ûæ$´lÙ’#F0uêTvìØ!‚‰oh×®K9ʤIQ(²ŸRbcS�Ó–2”)cDË–•™1ã Ë—ÀíÛ�Ù²å;v -¶½¿‹œ<ËÒ´P…Ü^–]xŸû¨PåXÿ4»°! s ;qÀÉ»| çÏG0dÈ–,9N@@mÌÍ 9qâ6kמaÿþgÀ\ãÎ�ìl°´´#Ô¨F` ýåÇ™3Íóœ­ËŒÉÌTqòäžš7÷Ä××¥(®PJ‰òfAÞÄáÃ× ZNÇŽÕi×®zz2vì¸È�1¬YÓO»nãÆ³ÄÇg·7ÉÊRqàÀUbcŸ PÈùä“úù¾^rr:óæ $$œ˜˜$ík]÷î>Eš$ BÉ"‚‰€­­íK×U¨P�:uêJDDDžçÚ¼y3—.]"99ggg¼¼¼ð÷÷ÇÄ$ïFöW®\aË–-ܼyCCC<== ¤lÙ²¹ÖnÛ¶�ŒŒ :tè€\.gçÎ�9r„‡bkkK³fÍð÷÷G*ÕÝëÎ�;ìØ±ƒ;w¹9*T sçθ¹ålèMpp0vvv4iÒµZÍŽ;8|ø05jÔ OŸ>¯À’��ÀÖ­[9{ö,±±±X[[S»vm:v숹yÁJaÿùçzöì©óxÍš5�gÿM…×gl¬`ýúÖ­;CÓ¦@ö‡óš5�øôÓgoN~û­'�O§uëYT©RŽõëC ô¥ysÏ]ïöíÇ ´€+W¢Q©Ô´lùÛ×è¡Íz,m¤2)k9÷6„"ò²€aQ9Öꡇv:³ ]qÁÑï2?4pçÚµo™;÷(kמ!+K�§§§N�¥F 'íºK—îqòäêÔÉ.»pá8ffǹt)ŠíÛ«1{veíèž=ï`m­; ¸s§•*; äàË—gßb¯ütó¦3††Ý7.ÿÏ}—.Ù£¯ïNHˆêÕ‹…×_†sçz3n\…·v͘¶nuæë¯Ey³ ¯§W¯:x{;2þ1–. F&“àííÈ… )_ÞR»îäÉ;DFf·îð÷¯N\\*^ÇØX¿@ÁÄŒ gÏf¾up(ƒƒCíï­Z=û|çëëBf¦xÍ„w™&@¹rÙAŠÓ§OsíÚ5*WλñäÉ“y[°`_|ñ)))¹Ž•-[–+VЪU«·gdd0lØ0–.]škðËøñãùí·ßr |éÛ·/qqq\¾|™ÁƒsüøñÇgÍšE«V­Ø¹s'zzzÚÛ5 &L`Ú´ideeåÚã˜1cøþûï™8q¢ö¶��zôèA«V­¨^½:;v䨱ìo­† BŸ>}^:€eÕªUŒ9’¸¸¸\׳¶¶fΜ9y_”••¥ÍÍkjtXXÀ[)¹~×ùùyú=»v]âòåh 9AAõhÕªrŽÒBOO;._þšµkÏðøñ/îM»vÏTµ´4bàÀF:�ÙÙ™i;¶5z:וD†& æŸ÷FçÛ�¨Ä,dð�‡:Ë‘oq›tÒs¬Ù°{ì‘–Òa'%�““?¿bpÑèÑ-^z|ðàëxyíâäIg¶liÄï¿WF£É+ûS÷sÚõë¹o;}ú¥—Íã¼âƒYÑ1:òv¯Z½z&ä.ož9ó³gÉu»­­)'NŒ 3SE¥Jßh�YZãâbÅ'ŸÔ§}û·S "Bñ«ZÕž¹s_ºæ—_º½ô¸Z­áða/Vÿ©PÁ+¬¬ŒÙ°aÀ+÷4l˜ß+ׂPº‰`b|üñÇÌ�;—´´44hÀˆ#èÚµ+ÞÞÞù>Ç’%K2d­Zµ"(([[[ÂÃÙ5k—.]¢cÇŽœ9s†ªU«ÙÁ½ÀÀ@6oÞŒ¹¹9ãÇ�§V­ZáÕ õèÖ­ݺÕzé:[[SFŽl®óXRR:“'ïÉó¾]ºÔ¤NÊ”1ÊWĆ ß¿@±~) ž–F/Ë.¼Ç=4<‹äÊ‘S–²8Iœè@‡Ù…Î8cJÞèBÉ3uê^îßO¦Që…§¹¼ùæ›öEzýåËObbÒŽnÝ^þaPx}aaaÌ�û9¿þªû¿åéÓwiÒd:“'w¢]»jÜ»—Àš5§yòDɺuφí}õÕv&OÞƒZ­Áˆ¸¸¯µŸ¼©ZÕ€öíç2zt š7÷D¡ÈùåïíÛ�™3'€zõÜHLL#88Œ®]2kVO jüZ×áý“™©bܸ-y>¼..ùÏ`áÝ'‚‰àëëËüùó>|8 |ÿý÷|ÿý÷ØÛÛÓ A4h@Ë–-µAÀÅÆÆjƒWŸþ93fä|ƒÙ«W/êׯÏÅ‹ùé§ŸX½:»”sÍš5lÞ¼kkkBBB(_¾¼ö>�;wfÒ¤ILœ8‘Q£FѱcÇ\_.^¼Hpp0Õ«?kÌëïïÀâŋٹsgŽ`âìÙ³øæ›orevéÒOOOÂÃÃ9yòd®`bHHñññ|ûí·Œ7…âå�ãââ:t(�†ž={²zõjd2™öxPPlÞ¼™!C†ðá‡bffö’3ê¶~ýzΟ?Ï¥K—Ø»w/2™ŒŸ~ú‰Þ½{ø\‚P”©Lí»’¯Öåž¿é×C˜Y¿t°Š.µ†¿6ŸçÐêÓĄǢ0Ò§v«*ôø¿‹¦Ü/Ê$“btfÞ%œrf“+P`ƒ î¸çÊ.,G9dÈò¸’PڈޮŽñò²×f²zzÚѼ¹'juÎtð~ðç‡üY»ö C‡®}íë¹»ÛhKãe2)U«ÚÓ"�]+Úâã“Ý&£ysObb’ùý÷`L!ß 9!!ÿ+îm‚PŠˆ`b 8�¶mÛ2{ölÖ®]Kdd$ÑÑÑlÚ´‰M›6àììÌ Aƒ5jFFÏz[­Y³†äädÊ–-ËäÉ“s�ÛÈȈñãÇ3aÂîܹ£½}æÌ™üðÃ9‰O�?žõë×séÒ%þüóO‚‚‚r0`@Ž@âSþþþ,^¼˜ððpímjµ'''ìíí Ì�.¯P(pww'<<œäää\Çãââ0`ß|óM®cº¬\¹’¤¤$,,,X¼xqŽ@"€žžK–,áÀ�ÄÇdzzõjmfgAlÞ¼™ 6hwuuÅÖÖ•J•ëšBñ033xe9â»,+SűMçøJÇ1CSކ8˜8oôF¶Í;FýÞÔm[•ÄØv->Îþ•'™z¦–ïߤù—;‰FEÎ6OË‘Ñ(×x€ým IDAT°G‹éQ‚𶹸Xqýúþùç <Ë|—JKÞÀ#++cž<É{P� ‚ ›ÁÄ×àèèÈ”)S˜2e ¡¡¡üý÷ßüóÏ?=z”Û·oÁ„ Xµjû÷ïÇÑ1ûçÓ‚­ZµÂÀÀ@ç¹Ðþ˹sç¨S§ñññ:ïפI.]ºÄ¡C‡ró*3.S¦ @Ž>…R©”½{÷ê\Åúõëùûï¿uêù,ÇW9tè�Ø455Õ¹ÆÂ‚víÚ±nÝ::ôZÁĉ'2dÈîß¿ÏÎ�;Y·nýúõãàÁƒ¬^½:Go?A(iäz2žü7�/¿R“ÒÙ6ïßý9ˆúžµbÈø5“/[Ïbå÷»:S÷TúÒL…ŠûÜ×™]AÉ<ɱ^}l±Õ9ìÄ7 Ðý\-Âû%(¨»v]¢Q£é´n]…Q£>ÈÕ¸$ˆ�MaƳ4kV°áf‚ ‚ !‚‰oÈÃÃúõëÀùóçùí·ßX±b×®]£oß¾ìß¿@›m¨+»0/áááÚ�+>>¯îšë¶§ÁÌ‚P*•lß¾�ãÇ�sîÜ9._¾LBBÂ+ï'“ɨT©R¾¯ó4+ÒËËë¥ëž–Žß½{7ßç~^µjϑҽ{w:wîÌÚµk ¢M›6¯u^A(j)‰iøãž›>›i)J$R õ^r£o GÇÏš²mÞ±ÂÜæ[¥DÉ#å†i¸Å-îsÕ C*žf6 a®ìB1ìD„üÐÓ“±yó`ºÎŒiÛv6Õ«;²|ù§x{;ëÞÆ�Û´iHMÍàÂ…Hš5ódÒ¤ŽÅº'AAÞm"˜˜OOž<áÆ�Ô¬Y©T÷‡Ïš5k²|ùr¬¬¬˜1c$""gggÒÒÒ077Ï÷uŸŸ¦ü²ë>åììœë¶WÝçE[¶laذaDGG#•Jñðð I“&ÚÿöÛoÚŒÂÙÙÙå˜ ý*èëë¿tÝÓÞ‹Jeá”ítêÔ ???Ž=ÊÖ­[E0Q(6ë¦îgíÏ{Ñh@­RÓÑ2çP ”¤tlË0~å§:¯U9sl�,¸{õ>®ÿ5ñ*ñÑœ+•}Ó­©‚ ;ÑC;ìtfºPcÞ¿rnAŠÆTâƒ*qíÚ^M›6³¸yó{Œ‹±m»vÕðövÀÐPŸJ•ÊR¡‚M±íEA„÷ƒ&æÓíÛ·©]»6�]îëàðòo¡?ýôSf̘�F£!,, gggmYqtttž÷S©T$%%ÙeÈööς۶mÃÉ©`ÙIuëÖ-Q*•ôë×�É“'ckk›cÍœ9sò¼¿‰IÁ&”ÚØØpãÆ îÝ»÷Òu‘‘‘@v°òU6oÞÌäÉ“©\¹2üñGžëªU«ÆÑ£G_ymA(J­?©GµFî<ŽNäûž‹ð\ßH¹¾k{sª7õ@Oñê§ëäøÔåнÆÈ/Wñ¿?úhKñ²2Ul›ŒŸv +üSdð�‡:Ë‘os‡4Òr¬š]è…—Ža'öÈDv¡ oQåÊeY¾üÜÜ&rñâ=ê×w+¶½4n\�V­ªÛõAAxÿˆ`b>¹ºº¢¯¯OFFûöí£oß¾/]ÿ4 že"V¯^�'NpæÌ™<ï·sçN:uê„¥¥%�?ÆÑÑ{{{¢££¹zõjžÁÄàà`®\¹‚—— 6|�G˜mëÖ­(•JœœœX´h‘άÆG�½öù_äëëËñãÇÙ·oS§NÕ¹F£Ñ°oß>íúWÑh4œ={–ÐÐP²²²�Ëuÿ5¿ÿ>–––¯¹{AxsvfXØ™¡ÊR#‘Hh?ðõ§onžu˜ßîÌu{ï ¹Çºl˜~€srÝ^˜^–]M4êç†�È�QŽr8IœhOûÙ…Î'L%º{ª Âû@£¡Äõæ{ß|÷ÝNêÖu¥M›gmY®_€T*ÁÕÕºw&‚ðnÐh4âµNJLÌ'SSSÚµkÇ–-[˜8q"Í›7ÇÅÅ%Ïõ‹/ÀÚÚZÛ°K—.,X°€ãÇ�ó÷ßÓ¸qΠ�F£aÑ¢E|øá‡Ú'Ó€€f̘Á´iÓhÙ²e®_FF}ûö%44”•+W¾Q0ñé0+++��Äàà`.^¼¨Ýï›êÝ»7¿þú+/^dõêÕ|ôÑG¹Ö,[¶Œ7n ‘HèÝ»÷+ÏÙ°aCär9ÉÉÉÌŸ?_ç@˜ÐÐPvíÚ€ŸŸß?áÝ�•¥Î3ø\Ôdr)�c[¿Ñ9ºŒhN«�ó7ñÙÐôÍKò²Èâtf†Á“†�(P`ƒMÃNÜ1 �=‰÷•Bäzú(•Y(ò‘¹[šÅƦãêjUÜÛx§Éår²²Ô:�i4ÒÒ2ñ÷ŸG£F¨ZÕž˜˜$vì¸È?øS¶¬¡¡1Lœ¸€ˆˆ8RR2èÑ#ûý ¿¿7½{눧ˆ gÙ´){ŸR™Å¬YGغõ_,,ŒX¸0÷{¥‚Oª‚Pšh4ïGõÅãÇ©XY‰×:A(-Þíwß…lêÔ©¯ÔP¶lY>ýôS–,Y¸qã044¤wïÞ T*Ù´icÇŽ%--�Š+øÆ�ã]§V¿ob>LÆÜ¢L±]¿ß6Ì7µ0ÂÔ¨�v“-Y�Ê}Õcî«ñÿìÝgX”ÇÀñÿÒ;:ö®ˆ{Wì%vc‰]£¹vc�ÝD�{7öX‚ÑØ ؉€`/¨Ø”"R¤HÛå~@7nE„€Éù=œ�wæÌ ÷3sž'‡¤ ãÖx?ZªZÄs”hþãûíqäzé;±Ç…ü#Vd£2øø<¡AƒR¹JŽºxñ98~¸£È2+++‚ƒ£ÓýL¡P°`A'®Ï�׈ J•ÂLšÔ’jÕþº«ÚÜÜgçô‹Ð•.m•n{FJ”°P�õî˜FFÝ1­££Íúõ½©PÁö£ÆV¦Ÿ3BäQF¦æ¿RÿââßÊß?*ÍõZBˆ¼K’‰¡T©R¸¹¹ÑµkWž={Ƙ1c3f †††XZZJ||<�ZôdÆŒŒ5Jý¼B¡`÷îÝ´hÑ‚[·nñÅ_`jjб±1ÁÁÁ@j5äU«VQ¹reõs666ìß¿ŸöíÛsèÐ!:„¥¥%ZZZ„„„�?~\\\Ô…J²ª[·nÌ›7�û÷ï3`ÀF�Eþüù &11‘êÕ«Ó¾}{6oÞÌ‚ ¸rå ‡þ¤9×­[GXXüñ£G�fâĉX[[«çh×®+W®Ìô˜Ë–-ãÁƒœ={–!C†0bĬ¬¬xþü¹:Z¢D Ž=ªNöŠŒYZÚñìY$öö¹—hËiqq‰$«tÐÖþ÷%N““y›¨Ñ¦«§�Á›‚ï& Ÿ$ñ$9(5y¨ #F§ñœŽBKmʧ³»°Å1Äð[—-;´cíêÿêdb@@*•±ìÖÈaFFFÄĤ�”¤DWW;Ý>¥JYòí·Í3ÃÚÚŒ¡¸ªÂÓó!‡ÝÈðó3Úbd¤‡“SQœœŠ¾w,--Åçû»{÷B°¶ÏÙû·…Ù«UÇŽ¬]w‚Ù³>íK^vîÜ}ªU«-Çœ…øŒH2ñ#Õ®]›;wî°víZöìÙÃÍ›7yýú5þþþØÙÙÑ®];F�•î.:[[[|||Xµj{öìáöíÛS°`A7nÌ„ ¨U+í1˜† rçÎ~üñGŽ9‚¿¿?ÉÉÉ-Z”víÚ1eÊ”4Ea5jDtt´ºðËßåË—ggg�êÒÆÆÆüùçŸ,\¸�½{÷òüùs©X±"½{÷fĈËÉy³*+ïYüeĈÁ4h C�Us;”lwÎý ºÌÂõ+²üÑ{wî³ï�Í \Ð6KÏ'')ñ8p-MûY—Ëä·6cÀœö˜ÐL~�{¹”è”X6ZLK÷8ò)OTö)$XjîJT$+°Ñ/ˆ�Žå;‰B lµ-)¤c…‘âý»ug´ÙÄú-[²´N!²[rR2SGŒ¥MK{†}]-­Ç®†  (¾ùæ}ûŽ£S§ÜûEljR©¤sçVL�êD­ZÅr;œl·e‹7žW’;mRn‡"„øHQ‘QL>ŠoÇÖ¦}ûϵwî3räa,X‹“Ó‡ m !òI& !2%))‰áÃ`aÍ”)M07ÿü�³¾~�ÄòîœóeÎÒ…›d}§ê§&3’œ˜Ì„+<ï ê–ÔølÜË¥ÜJzˆ ÿ¶»ÐDaD̵8T¯Š½®%§\bòœ~Øj[²oò)Š”¶ÉråhI&мF¥R±góι¹R¿~1Ê•)ˆ‘ÑçùË£ÐÐ×øø<'2RÁìÙ‹©R¥Jn‡ôŸIß¾ÝhÖÌŠaÃêþ+Šû„‡Ç2k¶±fLœ3ý_y�‡ÿñ¯ãÙ¸|~·®Ñ¸a J7ÿ,ÿ?J¥J!((� ,ùþû%-úþk„y�$…åøñc¬_¿”„„WX[›¢¯¯›ís(UÉ$$¿FO'gî³LLRò"4š$¥m»t¡e‡ÖŸ|GKN%~_y¿KO™¼­¿FûüÈ-¼TE¥î,|s ÙVÛ;m ‚é_a6‡#—0°âÖxOÂÀXŸã·Ø»ô‹Ü²vÔM’‰"¯R*UܾáK ÿ3b^¥_LãSÝ ô E…n92¶¶¶6ÖÖÖT­Z5ÍÕ%⟣R©øå—­ìÙ³-­$¬¬LÐÕÍþ°')HV%£«­÷áÎYŸDHH4ºú&ôèß�šõkçÈ œ�SŽŒ¯@�©¹iŽŒ-„È=zzzT¯]�ê94~t|8¾ž ¬/× !2&ÉD!D–åÏŸ?GÆ�I ÇØÔ3s³?/JŒObÛ¬#mÊd�÷C¸pô6}õQã) Zö¯ÃoKO1~cZõ¯Ã„˹~öÞÇ}é:6çµBño¡­­�c×™E›bœdôŸú»N!„ÿ’LBˆ<@¥Tqﲚv³‚ÆLÞÖçÞ5?zÌž“Z—Z|¥\ÍbLÚÒ�³.—è6Ιnãœ?9f!„B!„ÿ=’LBˆ<ÀÀXŸE'²v‡aFŒÍ 1~§PNýNU¨ßIŠ9!„B!„ȺÏãÂ0!„ø�‰Žˆ#áuÒ‡;f�J©"îU|ŽŒ-„B!„âßM’‰B‘G¨”*vÎ;N›‰|Q`mMG3¡ùrßzž¥ñT˜EtD\šöý+ΰuÖáO W!„B!Ä�$…"�X7a¿-=E—ÑMYp|$Óv BGO›ñM—òêeìG�ôø%*¥*M{1[Ýx–! !„B!„ø�‘;…"ˆ�MàÀês¬òœH™êEÔí�ºUcZ‡5X}–¾3ÚfË\¯cHNRfËXB!„B!þ[$™(„y@€_mÍ4‰ …‚º*sÉív¦Æ‰{OTX )))„< Wß�¨LVüä%Ûf¡Z³rÙ»!„" ”JÚÚŸÇa©� P^†…QÐÂKk ´´>�¸…Bˆì&ÉD!„È,ìóüŠ˜È8Lòi|p/ û|™Ç}ÿU–³K]¼e˜Ó¼4}j·u̶]ŽB!þ�f~;‹ ^ÐhÓÒÒÂÊÚŠª5«Ò¥Wg +œåñ}<|˜=qO>¡]—vü¸zÁ§†œÆúeØ¿{?‡Ü¢¯¯@г ttt°´¶ÌÔJ¥Š=[w³cã/< P·èãܶ9£&�ľ°}–⋎Š&*2 ;ttåŸerÅû SFMeÆ‚éÔkRMNJ&øy0æùóajf’-ñ¼|ñ’„„ì ÙeËxBñ9‘¿µ„"ÈomFµfå˜Ùe=#Wô ˜ƒ ¯“8ù‹7WŸe™û·™§Uÿ:´ê_‡„×It²ü–eçÆcš?59©ÐRPÀÆ =Ýœ\ŠBˆ�—/^ø4�ÝÚ£o`@bBþOؼz[ÖnaòœIôÐ3KãO;¥RÅÌ…3°¶³ÉÎÐÕ"#" |HJÊ_mý;õ§hÉblؽþƒÏ'%%1fÐXκ�¥‚c&Ï�Œ]!["#¢ð8ãÁñÇ8ú<Ûl¥TÙRŸË/{Y2w ®ÞP¨h¡�~þ¿&>>�À§�¼Ž{ýÑÏú?ñ§}ƒLž;™¯†ôÉ–x¾Ÿò=/rþöŸÙ2žB|N$™(„yÄ„M}™ÿÕVœƒ¾¡.‰ñÉšè3fm/Ê:ý¨±ô uÑ7ÔźhÌ-²ç7ðB!þ{&Ìœ@‹m�>aô€Ñü0uv…íiäÜð£ÆLLL$Ðÿ½õ¦{ßîÙn¶Z½h gÝÎÒ³ÿ—LùaªÆqì.½:sòØ)Æ Ç´1ÓÙs|w.FúßP³n ¼ü<122úpg!„9J’‰B‘G°1c¡Û(î\xŒ¿_F¦TjXŠ|–¦YoÎþa›fs”B!þ늗,Æò-Ëù¢Ñ¬X°"M21üeþ¼Àë¸×-Q„굪£P(|HXh�ºsÐ÷ÆmlílÔ ËÄÄD.z\$$8…J—+�CeõóÊd%woûaie�•�•Ƽ�þψyM¹Šiï %ìE‰‰IÄFÇà{ã6æùÌ)T$ý#Êáaál]»•2åK§I$¾åܦ�œqú�ÓÜ»}�2ʨ?{ß:’’’¸wç>¡A!Ü¿{Ÿ¨¨W”s(§1Ï­k·¸wç>zzº8ÕqÂæ�œwnÞAß@Ÿ¥K¨ÛÞ¾cŠ–øë—�ÉIÉøÝ¹‡…eA¬m­Õí×/_çÉç$%&b_ħ:Nèꦞ^xà÷€¤Ä$Ê;–Ïð]–*[R}|ü]ñ¯ãyxÿ¶ö¶ráÏ ¼yA‹ÔnPcãtßùÝ[w¹ë{•*…ReKR±JE�{)ããã xH‘¢…157UÏS¤X õñr÷"äyù ä§^“z¥þ7Уû�xà÷àMìÁøÞ¸�}a;òåO½B&"<^E¾"ÁÔ¬W3s³tc„ÔãéþOxõŠde2¾7n£¯¯§±;59)™+>Wð€žžUkTù¤k„"¯‘d¢Bä! …‚ uJP¡N‰wþÇäJ!„ÈŒâ%‹áTÛ ïóÞ„…bm›šØÛ¶nËç¯ !!AÝ·b•Š¬Üº++–|¿×îÝ”£û�ª�žž;éÎô±Óyùâ¥Æ\ÕkUg£Ëôõõ‰ŽŽ¦{‹î û5#'�Ôè·òÇ•œq=ƒÏï4ñîÙº› Ë7J÷ÝiÓ© ‹Ö.Lw}®GÜHJJ¢×À^ï-3sá †�†�ý_‰¾s'Î1}ÜŒ ×I÷íÈÑ/u^~ž˜™›þ2‚ñCÇããá£î£­­ÅðqÃ>~8ó§-à®ï]<îœW'}oøÒ³M/ì Ùqâ’›úÙ+>WÐe V- }×vø?ögÌà±øùúiÄgmkÅ–}[(Z¢(;7íÂe» ÎþNér¥5ú}7ú;îß½Ïé+§Ò}'O>¡{‹îôú®‡Ýy“40Ïgμ?иEcu[Dx†MÄËÝKcœŠU*²ôç%ê; o\¹É�CX¾iÎm�yxï!Ý[ö`Úüïøåç�ãÐ:w �å·ÕB!>–Ö©»ccbQ©T¬X°‚굪3mþ4¬l¬026¢}×vŒ›6Ž«>W¹äu‰BE QîÍÑÙ‚–q¨T�xúè)EŠaäÄ”©P…B�©¹)½ö øYð'Åjmk…C¥ èééblj‚C¥ qx’zÛþo}|oÜfÉ÷KÓ|½­|íÿØ?u“Fj¬£×;ëÐÕÕÅ¡R¬Þ9.]®4•* ­­Å¹ç¸vñS˜‚s›f`_Øžy+æQÞ±<ë—mR�X+ <Îx¨c»äy‰VZahdˆ÷;»=ÏzR³~MLÍMQ©TÄÅÆÑgpo97DGW]º}Õ 3s3‚ž§¾g‡Jp¨T�c¿C¥R©Çr;â†R©¢s¯Î|çEŠáûeßcec…¶¶Nµ�X¸æG’’’زf+Ü/pÅû ]zwáß~CAË‚˜ç3§ïЯ:z�î?âø�ãï�DZª#“fOÄÆÎ===zèIñ’Åð½î @‰Ò%ÔG�­mmp¨T�|ùóñ,à)))T­YU½³¶TÙRL›÷¿ìHdDTºó™š›ªÈ:Ú:8Tª ÿ—ŸwÅŒ…3hÓ±5FÆFزãûes©Qljß÷üÎóÀç|wB‘×É1g!„ÈŒÍ IQ¥�’’‚En‡#„B|PüëÔÝô†F†<¼÷�àçÁÔiXG�X{ËÔ,µ˜�çEjÔ­‘îXåËãâæ¤îV{æÿŒ{wîñëöÔ¶”wK2ÿƒtt4ÿ¹ôôáöîØ«þsJŠŠèW1P»Aí ×±gÛ¯oú¿o“ƒúúiŽý/Uœc¿#,4 »BvT¨TϳŒ™:¥RÅÕ‹W˜úÃw„¿ Çû¼7]zu&<,œ»¾w™¾`ZZZÅb^„¼à�ßκ�åUÔ+�ùº}Õ�YfsÙû 5ê8pìÀqªÔ¨BñRÅ?øîÚvj£qç!@¥j•(Qº·®ÝP¯±kï.ižïÜ« «­ÆËý{tÌpžº�ë¦i3/��¨Èô“�o9TvÀÆÎ† Ë6ðøþc:7 VýZT­Y•ª5«~p}é¹àî…±‰1­:´LóY—Þ]¹èu ïóÞtú²S–ÆBˆ¡Ö:Í IDAT¼B’‰B‘.kMá²ÖœÝ{…¦_:åv8B!Ä>M½ξ°=AÏ‚ø}Ïïü¾ç÷tû¿yñÞñ.üy�më¶sÙû2±1±XXYP¾bÚ ÿ»B¶ ¤e­VÏ~Ê:^†…0j@ÆG°_„¼ÀÂÊç6άüq%áaá=&úU 5ëÕ 48„�›v%ëš¶jª~þÉÃ'l\ñ3çÏœ',4 S*U¯”¦0J›NmX8kGö¡F'‚Ÿsíâ5f-ž•©µØØÛ¦ÛnWØŽK^—Þ¬7õ^ÉBE ¥égec‰��þnÌó™g*ž¿315aûÁm¬Y¼–SœRßåY¢t ú ë—n‚óCÂ^¼Ä¾ˆ½º`л ¿YãÛ]¯Bñ9“d¢BäSÈÌÎëÈgiBµfi+Q !„yEüëx<ÎzbaeAáb…Õ;î�L·7÷íý�‘±Q†ãyžõdhϯqªãÄê«)_±&¦&<}ô”?ëþ™É˜^üB2P§Q]öíÚω#'4’‰wçæ�?¿]G�º5²´Ž·…\œýCCÃtûXÚXм­3Ëç/ÇËÝ‹°Ð0Š/‚�� 5ëÕdéËxüà1g=©R£ V@ê�‡_¶é‰™™ßÍ›JõZÕ)hY€¦U›jÌclbL›Nmp;ìÆwó¦âzÈCƒtwÝ¥'*ƒc‘á‘ä/�#ccu\o«+¿K||&¦&™š/+ì ÛóÃòœƒïõ[xŸ÷æ·_~cæø™¨”Ê ‹°dÄØÄ˜ð7 á¿ {S�ÇÄ4ýjÖBñ9‘;…"Hx�Äö9GÑ3ÐeBóåô.9MãkÏB·"„BüC~š»„WQ¯èÚ§+ …‚BE chdHàÓ -¤ñ¥«§ÇÏ«6ñèÁ£ Ç;~ð8))),\ó#5ê8©H¡Û•fð&Á¯Y”C©T©+öfç6Ͱµ·å—ŸwjTåÕ˜3YÉ–µ[5ÚÞ®ãÇÕ Þ»ŽŒ”­P€Èˆ¨4ïñÚ¥kl]· �ÔêÍÅK§d™’xœõàÒ…ËÔ|s„Ü¡’&¦&xŸ÷ÁËÝ çÖÍÔãŸ?ãAtT4c¦Ž¦E»êDbBBBºÉ¿î_uãUÔ+ÜOþɱÇiÙ¾ešŒq?垦íå‹—øùúQ²lI õ¾C@ãîÇ¿b=@¥jŽ™šïcyžõdÖ„Ù„…¢­­E¥j•2j¿ºþж¶V–Šþ8Vu$,4,ÝŸÅ¿ÖSéSCBˆ\'ÉD!„È ŧÝ礭­ ºs9:ŽhÌØu½è9©¥ÆWåF¥³1Z!„âãE¿ŠáªÏUÆǮͻ(]®4CF@[[‹Î=;ãvä‡öV?“œ”ÌÒ–°÷~ I{”õ­· ªww!A!,š¹0uœäd ô±¶µâ܉sÄÆÄ©w®^´Šg.l¡««Ë«ÈW(•ªöû~Ù\Ôm0—.\Òø<48”±CÆqûÆít×ñn5åàçÁiÖñv@£jp³ÖÎä/�ŸyßÍÓ(ÔñäáLÿ‘ÐàÔÄ×[ÍÛ:ãqÖ“Ë.S³^M´u´©^»:»·ì&48”fmœÿŠïÍîPÿwÞsüëxæLœK||IIIëq¨ì@Ç l\±ßë¾tî™ù»þ|<|ømç>õŸ“’’X0#µK—7\Z´kŽ•�k—¬ãªÏUuß{wî³xöbLLMÞ{_bf½}ב‘ê6•JÅÞ{Ù¼z“F‘™'ž Tª°-”þ1mõ˜zºÄÇÇó:½öD[[‹ãfªnw=ìÊþÝû©R£Ê+„ !Äç@Ž9 !D6015!îU‡;f@GO‡vCdcD9(E Ä!ÄEƒŠ Ó´iiiÑ®K;¦þ0Cuûè)£¸sëSFNaõ¢U.V„‡÷Æ´ùÓ°±³Épžv]Úñë6wBe§ÊÄÅÆñàîZ}Ñ’»·ýؽe…‹¦eû–ôÚ—E³ÓºNJ•-Å“‡�ÑÒÒ¦mç¶œq=óÞõ”«XŽãÿÀ©¸ºµgöO³3ì[»AmVnYÁw£§Ñ¯cŠ/B¡¢…xùŠ;·î`bb†=ë™0|¢ú™¶�Ûòë6uüÁu”¯˜z¥É—­{bfn†›�+¦æ¦,\»�QFÑ®^{J—/�¾¾>7®ÜÀÂÊ‚ïæ}§£sgÖ-] QܦV½š,<±ˆòŽå5ªVת_ ûÂö¬Z¸Š3®g000àÞ�{.Zˆ²e¹â}…•?®d䤑êgºöéÊœIs(V²ØG&iÚª)s'Ïeëš-زåÞ�û„…†Ñ£_wZ´k¤ïYúóR¾éó ý:õ£tù2èêêrçÖtttX²q‰úˆö§°¶³&�ü¬[²Žíë·3wéZ¶oI³ÖÍøåç�œ8z‚’eK‹ï _¬m­ø¿�ﳬCYŽî?J­Òµ(W±<.®¿R±JE&Ï�Ì‚é h[¯-å*–#*"ŠG÷Q¸Xa~\ýã'¯E!òI& !D6(hY�°ÀÈwüÌ%'&£¥ÐÎí0„Bä°/ºu j�*mºzzXZ[R£ŽSº cc¶îßÊñÇðr¿@ll,m:µá‹n(óæø.€®Žã¦�ÕØ¡U±JEößÍï{~'èy0ÅJcôäQÔkR�JÕ*sáü,­Rï ì?¼?Öv6¸Ÿå\žBä€€ð‡œº{€š%[}¸s2¤Ïf�nn‡’cn¸ßÇïH4#Æ�ÊíP„È)»¾™o[,Éí@Ä¿ÀUÿó<óÃÁ¾vn‡"Ä{m^³…eó–qêòI,­-?Øÿî­»tqîÊŒgУßÇ0¹/:>ßOÖŸ”Û¡!ò0¹3Q!²Iã¦Í8»çJn‡‘£Ž¯÷¦íís; !„Bä°§�žrëÚ-¶¬ÙB›Ž­3•HBñß ÉD!„È&»wâðOâ^Åçv(9â¶×cRâô(^ªxn‡"„BˆÖ£Uz´úÆ~7.·ÃB‘‡È�‰B‘MŒMŒ1v sº¬eöÁÁèéåvHÙ&À/„Ußìcݶ�¹ŠB!þ+¶¬ 6&§:505{ÿý�ï*V².n.ØÚ¿¿²BˆÏ—$…"5lÚ€WQQŒª³”Þ3ZP»mÅÏúÅÈÑœØæÃ‰­—øiÍR9â$„BüGÔ¬W3KÏhÂBñï#ÉD!„Èfí:µÃ±²#[7lfÓÄùÄDÇ‘œ”œÛa}4=}] Z EÛVì:¸cãÜI!„B!D.“d¢B䀢%Š2sÁìÜC!„B!„ÈVR€E!„B!„B‘)’LB!„B!„BdŠ$…B!„Ùjóš-üyúÏ�~Îÿ±?‡öÎ�ˆ„B‘]$™(„B!„È’{·ï1nÈxn^½©Ñ¾lÞ2N=ùÑãmX¾‘E³eWxB!„È’LB!„BdIXh®‡] yòIㄇ²xÎb~ßó{6E&„Bˆœ"Õœ…B!„¹"$(„NM:•Û¡!„"“$™(„B!„HãöÍÛ¬Z¸š+Þ—Q©Rp¨ìÀ7ß~C�:N ê6˜ gA,žû–o`梙8TvP�qòèIÖ/ÛÀ¿˜˜Ó¤e&Í™„±‰1&¦&ŒýnŒºÿ¯Û] ú´]ŽB!„ÈY’LB!„BhðñðaX¯áر竡}Q©TÙw„A]²fÇê7­OY‡²èééñôÑS -„}‘B½I\½x�#û�Ò¡[ÚuiËE¯KìÛµCC¦þ0ccº}ÕMýÌù³’LB!ò8I& !„B!Ô’“’ùnô4J–)ÉŽÃ;00Ð`ÐÿòeëžÌ�ò=Ç<�1qÖ<Ïzâ~Ê�}{àÜÖYcœÇ³ãàvªÔ¨@¿aýèÓá+Ž<®N& !„âó#X„B!„j>žyøœßôW'ŒŒ�è?¼?�OÓToNOµšÕԉķ*Vv âeIIIÙ·B!þ²3Q!„B¡öÀï‹f/fù‚Ÿ%&$àÿØŸ*N•ß;N¡¢…Ò´iik“’’‚2Y‰®®n6E,„Bˆ’$…B!„júú©»kÕ¯‰•�uº} §“(ü;íl�K!„yƒ$…B!„j%Ê” i«¦´h×Bã³ø×ñ„…†aam™¡ !„"�;…B!„j+;`jnÊ®M»P&+5>[¹pmë·#.&6µA¡ %%åŸS!„¹Dv& !„B!Ô � ?m³&̦o§~tìþ–Ö–\øó;7í¢÷ ^°(@�‚ùغn+üÐñËŽØÚÛæføB!„Èa’LB!„BhèöU7 Y½x5³&ÌÀÌÜŒaã†1lì0u¿²eéѯ;î'ÿdû†Ôª_ [{[ÌÍÍ004H3®��>fæfê�gddˆ©™iÎ,J!„ÙB‘"g„yL@øCNÝ=@Í’­r;!„xG Ç®oæÛKr;ñ/pÕÿ<Âüp°¯�Û¡|PøËTJ%V¹Š"‡ELJãàÉÀú“r;!D&;…B!„z{”Y!„¤‹B!„B!„"“$™(„B!„B!„ÈI& !„B!„B!2E’‰B!„B!„BˆL‘d¢B!„B!„"S$™(„B!„B!„ÈI& !„B!„B!2E’‰B!„B!„BˆL‘d¢B!„B¤£iÕ¦ü¯ïˆ�~nüÐñÔ-W/"ʺ{·ïqéÂ%�¶s'Îá`S‘s'ÎåRTY…ƒMEV,X‘Û¡äˆð°p¼Ü½ˆŒˆÌíP„" I& !„B!D:LLM126Êí0²Åš%k;h¬F›ŽŽfæfèèèäRT"#W¼¯0¸ûn_¿�Û¡!Dò·†B!„B¤ã�ûÁÜ!GÕkR/?ÏÜC!ÄgF’‰B!„Bˆ4n\¹�÷yob¢c)hY�&-S¸Xá4ýýŸqÆõ /B^`fnJ½Æõ(ïX>Ss„…†qâØI‚ŸchdH§ÊÔ¬W-­ÔTÑQÑxº{RÁ±zúú¸qãEÈ Z i«¦éÆ“œ”Ì×3Üõ½‹¶¶65êÖÀ©Ž …B£_RRg\ÏàwûÚZZ”(S‚f­›¡«««îsîÄ9ÌÌͨZ³jšçÜ}@||¶…liܼ¶ö¶™Zó[O>Áï¶ÍZ5#66–cŽcffJÛÎm åŒëYž<ÃÈØˆšukP­V5�1._¸Lll, ›5Ôhò‚+>W¨Z£*)))\»t��ç!$&&ázØcccê7­¯îW­f5,­-‰ŒˆÄû¼7Nµ�HIIá�C®„‡RТ­;¶ÆÊÆJcž””¼Ï{sÅû J¥’ª5ªR¿i}N?E¡"…(ëP6ÃõŸ;鎅eA*;píâ5<ÏyÒ¹WgÂ_†ð$€–í[jô�‰ŽÁã¬åÊQ´DÑ ÇMIIÁãŒ×._À±JEê7m€¶öûå]ºp e²’šõjrþÌy®]ºŽ¶–MZ6¡¼cyq;ìÆ¿‡˜š›Ò´USŠ—,¦ñüë¸×4hÚ@cÜÐàP®^¼ª~lj‰‰œDEFQ·\=¾3”Q“G©÷(Žì7ŠËÞ—1ÏgŽR©$&:†uœX½c5Æ&ÆÆ3äË¡ÄFÇbWÈ–SÇOSв ¡Á! P°híBÖ/ÛÀ£{�(`Q€!/P(`ÕöUêDîàîCxðŒã^Ç4Æ=ãz†ýF²vç6kHHPý;Àÿ±?Ö¶Ö¨T*^„¼ @Áülý}+%Ë”¤ZÑê$$$hŒóë{¨X¥b†ñg—èøp|<XRŽÏ%„ø|É�‰B!„BµK^—ømç>º÷íŽÇm\}\9sõ4å+–cÙ¼åÄÆÄpêø)–Ì]BÅ*9yùg®�ÆãŽ'm;·eß®ýlX¾á½óÌüvV6–œ¹zWï?ð¸íÁÐÑC¸táÇü¡Ñ÷ Ë!ú~Ý�;ç9qÉ WW*8Và‡©ó¸ês¥RŨþ£‰ŠŒb÷±]üyËŸûÞŒ™:·#nl\±HM–Ž<Ž Àç¬Þ¾Š?}ÿä̵ÓlÝ¿…ȈH¦ŽššaÌ ¦/ 6&×_9}õ4'.¹±çøn”*%;7íÊÒûž1~&«Td㯙ϩ+'Ù}ln‡Ýˆ‰ŽÍTl7®ÜddžíL˜ù-ûOí{ïNÆÌ˜:ê;ünû±~×:<ïzpážß/›ËŸ+,œµ(ñÜ ,4ŒÓ×Nqòò öºíE¡P0~è·”)_/?ON_=Åo'ö¢¥¥ÍŽ ;>:Æ5?­Åÿ±?›ÛÄé«§8{ý ›ÛDô«V/JMªž»q–ù+ç°|Ó2¼ü<)_1s»}…⟠ÉD!„B!„ZDxV֖꣡, 0cá þ7áâSwLmZµC–lX¢>âkjfÂË¿§Hñ"lÛ°�¤¤¤tçHII!2<Ss3LÌLÐÖÑfȨ!Œ›6»Âvý*U`äÄê#ȶö¶Ì[ñ …‚àÏSîܾy›‰³'R©Z%�197ä—Ÿw¢Tª¸tá2¾×}é9°'�[4VÏQ£n �Œ–B¡~gmkÃÐÑCp¨ì ns¬êˆ­½-á/Ã3ÿ’ßaaeÁÊ­+¨Û¨VlY»€EkR²LI ô™4gUjTaÿîý„‡e~.]]]ÌÌÍÐÕÓE¡3s3LLMÞûŒs›ftïÛ]ýýoÒ² EKåþÝÄ¿ŽÇeÇ^œj;1|üpu?ÇªŽŒ˜8’Ì~»÷>‹Ö-¢ÿðþ”u(‹žž^¦×õw~¾~œu;˰±Ã¨ß´> …‚N_v¢ÛWÝ8ðë¢"£Þ;†––‚×,$�ü”u(‹C%´u´™¹p¦úrY‡²8T®@ÀÓÀ�Ž32<…B�µ­µº­VýZÌþiõš¤V757ÅèÍ\FÆF˜™›½w—¯BüÓäÎD!„B!„Z�u(\¬0«­ÆËýu×¥výZ8VuT³LHHàÖµ›Ôª_ k[Í{ôtuuiÖº)[ÖlåÞí{‰·· ]ûte÷–Ý´­Ûަ­šR³^MjÖ«Á ƒÒôwnÛá<}ôD½“±Y«fiÆ6ök†�ý:Ãwóý²¹@j2íÞ�{Ü»s¯sž> T߇÷±:÷ì¬qœ÷ò…Ë+Yœ2ÊhôS(´lß’k¯qíÒ5š¶jš¥ù2ãÝ;"ß261&&:€Gÿ:ž†Í¦é×йAš¶ŒXÛZ¥¹c0«Þ~ÿ#Â#Ò|ÿ““•$'%sëê-uÂ.ýxlÒü<›cmc­N$¾edbLØ‹—g—Þ]8ãz†.Î]iÚª)µêÕ¤vƒÚ|Ñý‹�K!r‹$…B!„j¦æ¦ì:²“ívpòØIVþ¸’•?®Ä<Ÿ9ƒF dЈAļŠA©Tacg“îow*F¼L‡À”ï§P±Š]á²Ý…�›v¢­­E³ÖÎL_0�Ô}-¬,ÒÃÂÒŸ{>DG½`ÉÜŒï5 #âÍÂŒÆ|Ÿ[×n±|þr|×éUˆ ¨Û¸.óVü@ÕšU¹~éºF·#niÆô†Ÿ¯eʧ.ïXŸ7ÉÂwíÞº‡a½†“��€ã›£ÚgOœKÓoùüåôi×¥R™æ³«>Wˆ�‰¥ß°~T©QE�HLHHP'ù²CµZÕxüàü¤ùìÄ‘èèêP¹zj²ÌØØX]ç]W¼¯d[<é)V²úœ>~*ÍgG÷ý¤±��S+.ÿ}]ZÓû¾ÿ®‡]Ü}HºÉÏìblb”þ÷ÂG3î Ã'ª‹èhiiQÁ±ÃÆ~Í×c¿&.6Ž{wîçXŒB‘]$™(„B!„PË—ß/w/V,XÉë¸×@jÁ”3®g(^º8ƒF ".6ŽñC¿%$(€¸Ø8fŒŸÁ“‡Oè;´o†5,m¬¸uý+¬$àI€ºýñÃ'<º÷H=Ç[wnÞaÙ¼å$&&©»gŒ›�J¥¢÷ ^ÔkT�¥K°xÎb.¾¹?àÚÅk,Ÿ¿#ôõõ©ß¤~j�˜uÛp?å®îwòØ)¸¤Eû›§‰¹ eên±+>WP&§&ÃÙô¿ÉDGE“ð:!³¯ø½ ¤&�ž<|@bb"‹ç,æ²÷e:öèHAË‚”,[’ȈHºR¿OÇçÀ¯ÒŒ«¯¯O\l�î?úà.¿142¤ÛWÝð½q›eó–ÿ:¥RÅáߎ°{ËîO*R²ljÑ™v¨ ¹x¹{±yÍ–÷>Wº\ijÕ¯ÅÏ+æäÑ“¨T*ÝÄ™‹ˆ‰ŽÉò½–™Š»LI^¾x©@? IDATN¦¦¤¤pdßí=¤Ñ/9)™=[öpú�ÓêõÅÅÆqÁÝ ---Š—*€¾¡>�Z¤&"9±1±¨T*FLø‹f/Ö·ZÍjÙw„ö :P¼d1Žxù¤8ÇNKHP(WldÓªMhkk£JQ1}þ4L_ QTæc´îØš�+~fÕ¢ÕìÞº‡ä¤dbbb˜ß0zÐŒMŒ1ÏgNðó`lìlX¼nQ–âɬžz²wÇ^&~3‰Ÿæ.Q'lGLÁâ9}/ÆÏÏ�[wÙ æÇÄÌ”�ç!$''1vÚXõ}£åÊahdÈÂY‹X8k¿þ±G]I!r›"åí¯C„"�È©»¨Y²Un‡"„ïHáØõÍ|Û"ãâBdÖUÿó<óÃÁ¾vn‡’¡»·îâéîÅË/137£F§t‹C< àŒëB‚C1ÏgN½ÆuÓ­àœžÈˆHN9AÀÓ@tõt)Qª8ÍZ7SßWèçëGçf]˜¾`:-;´à�ƒèÿŒhÚ² ÅKO3f||§ÿ8�Ÿ¯:º:”¯Xž&-› ý·âñ¯ã9yì$÷nßÃÈØˆ²eiÔ¼‘úø2À¹ç037SW7NNJÆíè îÞº‹®®ÕjV£nãº> d”s,O›Ž­¹~ù:/_¼|oÅå'ŸàwÛ�úMê§»2$(”Óœ"Ðÿ&&ÆÔ¨W§ÚNiú…¿ŒàȾ#„…Pв ­:´ÄÄÔ/w/ªÖ¨Š•Í_÷Gú^÷%Ð?cccê7­Ï‹�\ñ¹BµšÕ°´¶$2"ïóÞ8VuÄ®��Æ<^î^ÔiXG£ýöÍÛ\¿|m--ê6ª‹‰™ õÊ×g䤑בֿ}î¤;¦¦&éþLÅÆÄrdßQüŸøcjfJó¶Î)^„Óœ¦œC9Š–(JRR§ÿ8M‰Ò%(]î¯ãôÊd%çNžÃ÷º/J¥ŠReKÒ¢}‹ wɾuéÂ%âbãhجa–ÛßîL ÅÂÒ‚V_´ÄÈØˆ ^P¿cHý9:{â~·ýˆ�{�m![šµn–¦�Ohp(7¯Þ$99™Ú jcžÏü½kÈÑñáøx2°þ¤wBügI2Q‘çH2Q‘7I2QdŸÏ!™˜¼›Lü²�ÜG¼cý² (˜Ÿn_uÓhß»c/³&ÌfíÎ5ip"ï“d¢"3䘳B!„Bˆ�rÿÎ=N;E²RIÛNm042äüéó,›·œ¥KP¯Q½ÜQ!D‘d¢B!„Bˆ�2ýÇ餤¤°`ú¾Ÿü½º½Z­jÌ_1°!„ÈÛ$™(„B!„È“J•+�—Ÿ§úE‘w˜ç3ç§ ?Å£{�HJJ¢p±Âê"B!þ½$™(„B!„È“´µµ037Ëí0Ä{˜ç3W¨Bñß õá.B!„B!„B!ÉD!„B!„B!D&I2Q!„B!„B‘)’LB!„B!„BdŠ`B!„Büë(“•p9È©c'ñ@rr2…Š¢VýšôÜC#à ŸõóõãäñSüïÛo²4÷¥ —8²ï(»A•U8èr�«¯¥ékhdHÑâEiЬ>ö…íß;îùÓç9yüc¦Ž&_þ|YŠ-«B‚BY»d-m;·¥F§tîñ<ëÉþÝûyôà1¯"_a[ÈǪŽ|5¤Ï¿¢ºô«¨Wü¼rý‡õ£€E�ÜG!dg¢B!„"÷øÞ¸M÷Ýñ<ë™mc&&&2¨û`fŒ›�ÿ“*Us¤ŠSež>gÙ¼åtoÙƒˆðˆtŸMIIaÝÒõìØ¸#Ëó?º÷ˆ½;öòøácuÛEÏKìݱ—ãŽãzÈUýµóç_˜;y.íêµçÄ‘ï÷®ï]öîØKlLl–c˪¨ˆHöîØË¿Yz~þ´ù|Ó'kÉÙ÷Y™‘/¿ü²ðþQ*Ê+2ýã™;gÅcüº§&U}Î?x`µ�˜$Ý÷èžn{tÏäW'çÃ>¬ñÚÅ‹3ã“Y´håïµ¢¼âï¾*pÑ¢/ }FI²há¢Òg´×{§ÏN}3ìòë²dÉ?ÿw ào!&%‹/I§6�sÓ57å¹§žKï.½³Ãæ;ä‹¿Ä”»o½'{tÜ3]ÚuÍÎ?ê–·Ø1—þêÒjꉇŸH§6�óØC�ÕØÿÝä§OJRL~rè I’3‡œ™Nm:ç™ÇŸ)m;qÌÄì½cŸti×5]7Û!=:ìžûï|`¥ï¡¬¬,I2ã“Ë\wé°Kò‹_ý¢´¬É:kåú;®+ýéйC‘SõÕbƒª{û}:ýÓ•nûî”wsðÞ‡¤cëNéÖ¾{ºlÞ5ÿýëËR^^^m»çŸ~>û‘­6Ü:Ý·Ú%Û·ê˜}ºí“Ç'>^m»¹sæå쟟“Nm;§[ûîÙz£mÒ·yxìÃ+GeeeÎûåùéÔ¦sn¸êÆen3ú¾ÑéÔ¦sž˜ôD¦<=�ÚtÎa}/­ŸóÅœœuòÙéÔ¶sºoÕ=[wÌ>Ý÷ÍÄ1Wz²ôsž^ósN’Ÿžzb.½î’¬±æ¥eåååùï__–®›ï�ní»gÛl›#ö;2ï½ý×)éK¿¿o¼òFþxÝÍÙqË�rô€crì�¥ûVÝkÈÊÊÊì½cŸÈOJ˦Mý0'þÓl×r»tkß=ÛµÚ>¿þÏó²há¢Ò6çŸ~~úî¼OÌ_�SŽ?5ÛµÜ.7_ws’䢫/,}xàÊÏÀ·È4g š9_ÌÉ{o¿—ß ½*ßûþ÷²ßAýR¯~½\åõùï__–ÖíZåÌ ÏÌk6ÈèûÆä†«nÌ[oLÉ5·\�²²²”WTdÎsRQQQcßóæÍË‚ù ’${í·W¦Lž’‘÷ŒLÇ:f“V›¤ùúÍ“$#ï™SŽ?5w蘣N<*‹WäÎ[îÊ/NøEU¼é¿×rÇ¿Ç޻籇ËÀ~3ðø#²ËžÝÓ²MËÒúm:nSmûÕW_=�vìTúùîáwgò·|«½çŸ~!I²á6\é¶¿øÉiÙb«-2ôÚ¡©U«,Üõ`®¿òú|üáǹèê “$ÓÞŸ–£÷?:Í[¬—³.:3ÍÖož©ïMÍU_•!Çü,�¼üpêÕ¯—Å‹3è Ayåù—³ÿa¤ÓŽ3{ÖçùÃoÿ�;1×Üruvè¾C�1,^¼$gý쬌¸}D~~ÖÉ5®]j£l”þ‡ôϘûÇäóYŸ§ÿ!ýÓ´yÓ$UWí ìwD&¿:9}ôÉ»ì�Ï>ý,7]sSN<ü§¹ðª Òkß^Ë=»öÜ%×^zm.8ゼûÖ»éµo¯üpë¦v�ÚI’M[ošM[oZÚ¾²²2'{r&Ž}8yP¶êÐ>¼?-¿»êw9´Ï¡¹sü]i¾~³Ò÷wÄí#2üÆ[³}×í³}×íÒ°Q£<öÐcyl£ٵ׮¥ý¾úâ«yç­wrÈÑ'©ŠØïupÊÊÊrò™'§ùúÍòÌãÏä¶›nˇS§åꛯ®zÿ e9í§ÿ™§}*=z÷Èæí7O’l½ýÖ¥ý¿óÖ»+ýN|›ÄD †{n»'ƒÊq?;.eee™ñÉŒ\yÑoÒªm«Ü:ê¶Ô«W5­´w¿Þ9ëggåÎ[îʸÇ¥Gï…�qÌIGçÙ'žÍÈ{F¦ç>=Ó³ïžIªî÷ëÿ9´Ï!¹äW—dϾ{dµÕV[æ~÷9`ŸÌŸ· Ã.–+.¸"W\pEš¬Ý$[o¿uºìÜ%½öí™5®ù>ê ŒûóØ\;üšqüÀlÜrã<:áÑœ{ê¹ÙmÛ¹÷Ž{ÿ!cý[ >jHôPúsüÁÇç¾?ÝŸv[¶Ëå7^V „+rè±‡ÖØî¨Ÿ•$yìáª)Ìýê—1O�N»-Ú–¶™=kv^ùõ$)ÝÃo¨‡Rgµ:9àðý«íoíu×ΟÆÞ‘SÏ=¥Úòò¯Ê3øè!9bTμð̆ĕ?r\¬Ñ 2°Úòµš¬•ƒ�:8³gÍΟŸxv…ûèÚ½kF<|Onyà–œxê‰éЩC&¿úF.;ïòôìÜ+CϹ¸tÏÁÑ÷ŽNýõÓ÷cÞ¤Õ&é´S§Œ9¡Úò½úï] ‰IÒx­Æé¶{·<2~RµéÊc—�vÛ)�7JEyEÆ=8>;ï¶S)$.µÿaûgµÕVË„QãKË/^’!g �)®Ljh»EÛjÁêƒ÷§&IZo֦ƶÍ×o–&k7Éûï¾ÿ9öûïVké½—å£>J:-wu’¤nݺ١û¥+ëæÎ™—1÷�ÎÅ¿º$g >#m6k“¶_‹m߆SÏ=5Í×oVú¹^ýúi±ÁúiÙ¦eµpº"­Ú¶\æ²Zµj•>ƒµš¬•ùóægØeÃòÒs/gÊä)ùøÃ�«Ý?0I¦¾75M›5M£Æ�jìsYWI^}ñUIªf3îÁqé÷ã} �û›¦¾75m²Q�‡§$I›ÍZ'IÞïýtM×¬,í·ýQÚoû£$U÷E|âá'2ôœ‹sÓ57eÃ�7Ìþ‡ Èû゚… æ‡üh¹ûúú½?ÛmÑ®Æú>öΘûÇdÒ„IéÑ»GÞxå�L{ZNûË=8g~:3 æ/ÈÈ£2rĨeãéUûy³-7[ævßUb"PúÍÖ©ös­²ª°¸x÷AL’ŠÅ)+pU]‘§Ú6lT5ùˆã.÷‚›ý°fèIª¦ ÿfèUéÚ­kví¹K�ýîwð~©³Z�üò¤ÓóÐ臾õ˜Øµ[—BS™WdYçpÉâ%Y²dI)�}`l~~Ü)Ùè¥×¾½Òï ~Ù´õ&yæñgsî©çþõu_{Mõê×ϰۆåŽ?Ü‘[wkî¾õžjS†ÿeµjeñâe–Þo³VíÚË}ý…g]”fÍ›eàñ‡W[¾Új«e§ÝvÊÆ›nœž�{eü¨ñÙÿ°iظQ5nTmªõ7U.©,ýý›¿IÒµ[׬Ót�Œ¾wLzôŒÍÚë4I×nUÁs͆k¦¬¬,:w(MÛÿ¦ušþu¿µk×ÊÚ뮽Üñ|‰‰@ µkWÿ¯Â&­«Øk/¿žv[VySß›š¹_Ì-=ì¢Î_ÐÒé¥K}õÕW™þÉô•>ddilk³y›ôî×»ÚºY3gåÍ×ß,=¨å›êÖ­›»‡ß•O¯—Z¯ÅzI²ÌÄü+xõ¥×òý�¿_mÙÒéËKÏí5—\“Æk5Îí£oKýõKÛM?©Úë6Øhƒ<6ñ±|>ûó¬Õd­jëþëÿ•òòòœsÉ9¥eÇþÇ1iÝ®U†œ>8“ÆOÊг/J—�;—Îéßb“V›ä•ç_μ¹ójÜÃòµ—ªž€³é ÂëS�>•™Ó?Í!Gœ:«Õü¯móëU=è«òÒñž{ê¹ìµß^©W¿^µmßzý­Ì™3§ÚòÚË™µëÔNï~½sûïoÏ 3î�qÙ³oÏÒñ×l¸fš­×, Öh�þ‡ô¯öÚÊÊÊ<ýØÓÕ¾»eµjýÝWv¬*T·Ý»¥Á 2ì²a™=kviùâŠÅ¹äW—$I)ü5]¯jïk \KýqØSQ^=à•Õª )•_ �[n½eš6ošß]sSæÏ›_mû¡ç Í ‡�¸Ü«é6n˜®ÝºfÒ„Gsߟ~É’%ùÓÿ”$Ù¶ã¶5Öÿ+¸þÊë³hÑ_§ãVVV憫nLYYYvî±s’dÞÜùiÔ¸Qµ�¸pÁÂŒ¸}D’dIeÕùÞµç®Y\±8Ã.¿®Ú1Þxå�ÜqóŸÒ`�Õþ—ðÕ`�9ûâ³3oîüœ1äÌTVVfEÊÊ’%Kª_…Ø{ß^Y´èË\qÁ•Õ^?mê‡~ãð´Ø E¶Ù~›ogß=3ë³Ù¹ð¬‹–yµæ¸#•••éйC’¤ûÝR^^žß^öÛjÛ}ñù9ú€crËõÃWø–ê; O-\”민>ï½ó?5ž,Þ}÷nyt¤¼üüËÕ–OšðhŽìT)”ü«re"°R�×jœÓÏÿeNÿ�3Òo—~é3 OÖXs�Œ{p|^}ñÕì{à>¥'Ô¶l³iZ¶i™®¼!s¿˜›ï}¿Ežö…¼ðÌ ÙxÓ�«í·ùzUWi]qÁyüáÇsä GfÓÖ›æŒ NÏࣧ߮û¥Gïi¶^³<9éÉ<<öá 9cÈ ŸÆüËó™·úžÓN<-Ãož.ݺdݦëäÓéŸf¨‡òö›oW�wçÎÿ´óõÏ4oî¼ôß­é »ñŽÏsO?—? ôäæíºl—·�ÈIGþG¶ëÜ!Ó?šž‘#Feõº«'Iî¾åî¬÷óõÓ§ÿÞ¹ïŽ{óûkŸ�¦}”�¶ÍGÓ>Î]·Ü™u›®“£O:f¹ãè¼S§ì{à>¹køÝ¹ë–»²ßÁû-wÛæ-ÖË#ã'eÐ��Kûí3hð±ÙçÀ}3æþ1¹å†[òÎ[ï¤K·.ùìÓÏr×ð»ò墯réuç¤v�åOs>ôØCóøÃOdø�ÃóȸGÒc¯ÝÒbƒ™;g^žzô©<óø3Ùü‡›eàq‡'I:íØ){í×;Ã.¿.¯¾ôZ:vÝ>‹sï÷fÑÂE9þäã �ÿÖ›µNÛ-ÚæúßÜ�´üA¶h¿Eµõ?9å'™4áѾÏÀìµ_ï´lÛ*N�–»†ß�öÛþ(=ö*þÄs€ï¢ÚgŸ}öÙ«z_7gáì¼7sr¾·vÍ›‹¬JS¦¿�Λ‡Á¿�O¾˜šY >K³F¬ê¡,Ce&�{$í;´ÏÖÛmUmMÛÍÛf«íóî”÷2~äø<ýèÓi´V£÷³ãrÂ)'”¦k–••e».òî”w3aÔ„<óøÓY·yÓ\òÛ‹3ããéY{ݵ³Ó®;%©Š” ®™™Ÿ~–éMOÇ:f½ëe“V›dÛÎ2å�)?r|žœôdêÖ]=ƒ98<`…ï QãF鳟T.©Ì+/¼’‰c&fÒ„GóÚ‹¯fƒ�¿Ÿ“N;)Ç>v¹ÓK_ù�TTT¤ïþ}ÿ®3øñ´�óÁÿLÍŽ»ìXЧ“_�œóæ§ç¾½–ù°“"¦þÏÔLÿè“\2ìâÌž5;#n‘‰c'¦^½z4xPŽ?ùøÒ{Ú¾ëv™5ó³<ùÈ“™0ú¡Ìúlv8|ÿœrÎ)?r|^~þ•ôÐ'MÖi’=ú쑲²äÉIOeô}£3ý£ééÚ­K.ºæ¢4mÞ4IUÀ|ñÙÓµ[—Òtö¤êêÎÿüRÞ~óíìÖk׬¾úêË{«¶-óÙ§Ÿe挙©¨¨H�Þ»¥V­²ìÑg�Ô«W/Ï?õ\Æ>8.S&OÉ6Ûo“ó¯§Mý0MýðÿôÝ)꫊…ùtÎÙjÃ?ôøÿ­¬re×£|Ë>˜õN&L‘í6ÝcUàk*3ò¥sr�KWõ@ø7ðÂÔÇòöÌ7³ù÷:®ê¡ü¿°`þ‚”——§ñZ�WõPø'Z´èË,Z¸0 5JíÚîèõ÷˜»hV^ûà‰ÑõÔU=à;Ì4gàßZ�ûþýž}âÙ ={èJ·ûÝÝ¿Ëk®ñ>»zõê¦^½º«zÿöÄD€•Ø¢ý¹ôº•_™üõ)µðïHLX‰ú êgƒ�¾‹÷¸€o—I…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!uVõ–eÁWsóáì·Wõ0àŸfÞÂYþ­¾S~5oUø &ß9kÖkœ ×n™/¿š»ª‡PMûïwYÕCàßDÓ†ë§iÃõý[|§ÔJ²Ùú[¯êaßqe••••«zÀwŸ{&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!ê;qþIDATb"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"Pˆ˜"&…ˆ‰@!b"PÈÿ/%ä7�"dIEND®B`‚sslh-2.3.1/doc/sslh-examples-v3.svg000066400000000000000000004736311515234404100171040ustar00rootroot00000000000000 Viewer does not support full SVG 1.1 Families Prerouting Hook SYN-ACK-connection SYN-connection SYN-connection Prerouting Hook SYN-connection SYN-connection SYN-connection Application Layer Server Prerouting Hook dummy0D0_IP Prerouting Hook eth0S0_IP Prerouting Hook sslh Prerouting Hook sshd Prerouting Hook internet Prerouting Hook ClientC_IP Prerouting Hook routingtable Application Layer Server1/Router Prerouting Hook eth0S0_IP Prerouting Hook sslh Prerouting Hook internet Prerouting Hook ClientC_IP Prerouting Hook routingtable Prerouting Hook eth1S1_IP Application Layer Server2 Prerouting Hook eth0S0_IPS1_IP Prerouting Hook sshd Application Layer Additional S1_IP configuredonly for sshd!Server1 is Default Gatewayback to the internet,no additional configurationneeded Prerouting Hook internet Prerouting Hook ClientC_IP Application Layer Server1/Router Prerouting Hook eth0S0_IP Prerouting Hook sslh Prerouting Hook routingtable Prerouting Hook eth1S1_IP Application Layer Server2Router Prerouting Hook sshd Prerouting Hook routingtable Prerouting Hook eth1S1_IP Prerouting Hook internet Prerouting Hook eth0S0_IPS1_IP Application Layer Default Gateway points toeth1so special routing rule mustroute S1_IP back to Server1 Prerouting Hook connection withoutrouting deflection SYN-connection SYN-connection Application Layer Scenario 1 Scenario1 Scenario 2 Scenario 3 Prerouting Hook Version 3 2024-06-07 SYN-connection SYN-connection Application Layer Scenario 2 Scenario1 Scenario 2 Scenario 3 Application Layer Scenario 3 Scenario1 Scenario 2 Scenario 3 sslh-2.3.1/doc/tproxy.md000066400000000000000000000363651515234404100151360ustar00rootroot00000000000000# Transparent proxy using packet marking Before reading further, make sure you try to set up transparent proxying using [IP routing](simple_transparent_proxy.md). It is conceptually easier to understand, cleaner, and more portable. Using this method is very tricky and detail-dependant: depending on whether the target server and sslh are on the same machine, different machines, or different dockers, and tool versions, all seem to change the required network configuration somewhat. If it doesn't work, it's almost certain that the problem is not linked to `sslh` but to the network setup that surrounds it. If in trouble, it might be worth trying to set up the network rules with a simpler server than `sslh`, such as [`socat`](http://www.dest-unreach.org/socat/) Users have tried to do at least the following: * `sslh` and the target servers run on the same host (see [below](#transparent-proxy-to-one-host)) * `sslh` runs on a host, and the target servers run on LXC or dockers running on the same host. No known working setup. * `sslh` runs on a host, and the target servers run on different hosts on the same local network(see [below](#transparent-proxy-to-two-hosts)) * `sslh` runs on a host, and the target servers run on a different host on a different network (there is a [usecase](https://github.com/yrutschle/sslh/issues/295) for this). No known working setup, and it's unclear it is possible. ## Transparent proxy to one host ### Linux `sslh` needs extended rights to perform this: you'll need to give it `CAP_NET_RAW` capabilities (see appropriate chapter) or run it as root (but don't do that). The firewalling tables also need to be adjusted as follows. I don't think it is possible to have `httpd` and `sslh` both listen to 443 in this scheme -- let me know if you manage that: # Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination sysctl -w net.ipv4.conf.default.route_localnet=1 sysctl -w net.ipv4.conf.all.route_localnet=1 # DROP martian packets as they would have been if route_localnet was zero # Note: packets not leaving the server aren't affected by this, thus sslh will still work iptables -t raw -A PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP iptables -t mangle -A POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP # Mark all connections made by ssl for special treatment (here sslh is run as user "sslh") iptables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f # Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark) iptables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f # Configure routing for those marked packets ip rule add fwmark 0x1 lookup 100 ip route add local 0.0.0.0/0 dev lo table 100 Transparent proxying with IPv6 is similarly set up as follows: # Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination # Not sure if this is needed for ipv6 though sysctl -w net.ipv4.conf.default.route_localnet=1 sysctl -w net.ipv4.conf.all.route_localnet=1 # DROP martian packets as they would have been if route_localnet was zero # Note: packets not leaving the server aren't affected by this, thus sslh will still work ip6tables -t raw -A PREROUTING ! -i lo -d ::1/128 -j DROP ip6tables -t mangle -A POSTROUTING ! -o lo -s ::1/128 -j DROP # Mark all connections made by ssl for special treatment (here sslh is run as user "sslh") ip6tables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f # Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark) ip6tables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f # Configure routing for those marked packets ip -6 rule add fwmark 0x1 lookup 100 ip -6 route add local ::/0 dev lo table 100 Explanation: To be able to use `localhost` as destination in your sslh config along with transparent proxying you have to allow routing of loopback addresses as done above. This is something you usually should not do (see [this stackoverflow post](https://serverfault.com/questions/656279/how-to-force-linux-to-accept-packet-with-loopback-ip/656484#656484)) The two `DROP` iptables rules emulate the behaviour of `route_localnet` set to off (with one small difference: allowing the reroute-check to happen after the fwmark is set on packets destined for sslh). See [this diagram](https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg) for a good visualisation showing how packets will traverse the iptables chains. Note: You have to run `sslh` as dedicated user (in this example the user is also named `sslh`), to not mess up with your normal networking. These rules will allow you to connect directly to ssh on port 22 (or to any other service behind sslh) as well as through sslh on port 443. Also remember that iptables configuration and ip routes and rules won't be necessarily persisted after you reboot. Make sure to save them properly. For example in CentOS7, you would do `iptables-save > /etc/sysconfig/iptables`, and add both `ip` commands to your `/etc/rc.local`. ### FreeBSD Given you have no firewall defined yet, you can use the following configuration to have ipfw properly redirect traffic back to sslh /etc/rc.conf firewall_enable="YES" firewall_type="open" firewall_logif="YES" firewall_coscripts="/etc/ipfw/sslh.rules" /etc/ipfw/sslh.rules #! /bin/sh # ssl ipfw add 20000 fwd 192.0.2.1,443 log tcp from 192.0.2.1 8443 to any out ipfw add 20010 fwd 2001:db8::1,443 log tcp from 2001:db8::1 8443 to any out # ssh ipfw add 20100 fwd 192.0.2.1,443 log tcp from 192.0.2.1 8022 to any out ipfw add 20110 fwd 2001:db8::1,443 log tcp from 2001:db8::1 8022 to any out # xmpp ipfw add 20200 fwd 192.0.2.1,443 log tcp from 192.0.2.1 5222 to any out ipfw add 20210 fwd 2001:db8::1,443 log tcp from 2001:db8::1 5222 to any out # openvpn (running on other internal system) ipfw add 20300 fwd 192.0.2.1,443 log tcp from 198.51.100.7 1194 to any out ipfw add 20310 fwd 2001:db8::1,443 log tcp from 2001:db8:1::7 1194 to any out General notes: This will only work if `sslh` does not use any loopback addresses (no `127.0.0.1` or `localhost`), you'll need to use explicit IP addresses (or names): sslh --listen 192.168.0.1:443 --ssh 192.168.0.1:22 --tls 192.168.0.1:4443 This will not work: sslh --listen 192.168.0.1:443 --ssh 127.0.0.1:22 --tls 127.0.0.1:4443 Transparent proxying means the target server sees the real origin address, so it means if the client connects using IPv6, the server must also support IPv6. It is easy to support both IPv4 and IPv6 by configuring the server accordingly, and setting `sslh` to connect to a name that resolves to both IPv4 and IPv6, e.g.: sslh --transparent --listen :443 --ssh insideaddr:22 /etc/hosts: 192.168.0.1 insideaddr 201::::2 insideaddr Upon incoming IPv6 connection, `sslh` will first try to connect to the IPv4 address (which will fail), then connect to the IPv6 address. ## Transparent Proxy to Two Hosts Tutorial by Sean Warner. 19 June 2019 20:35 ### Aim * Show that `sslh` can transparently proxy requests from the internet to services on two separate hosts that are both on the same LAN. * The IP address of the client initiating the request is what the destination should see… and not the IP address of the host that `sslh` is running on, which is what happens when `sslh` is not running in transparent mode. * The solution here only works for my very specific use-case but hopefully others can adapt it to suits their needs. ### Overview of my Network Two Raspberry Pis on my home LAN: * Pi A: 192.168.1.124 – `sslh` (Port 4433), Apache2 web server for https (port 443), `stunnel` (port 4480) to decrypt ssh traffic and forward to SSH server (also on Pi A at Port 1022) * Pi B: 192.168.1.123 - HTTP server (port 8000), SSH server (port 1022 on PiB). * I send traffic from the internet to my router's external port 443 then use a port forward rule in my router to map that to internal port 4433 where sslh is listening. ![Architecture](tproxy.svg) ### `sslh` build   `sslh` Version: sslh v1.19c-2-gf451cc8-dirty. I compiled sslh from sources giving the binary pretty much all possible options such as Posix capabilities and systemd support.. here are the first few lines of the makefile:   ``` # Configuration VERSION=$(shell ./genver.sh -r) ENABLE_REGEX=1         # Enable regex probes USELIBCONFIG=1         # Use libconfig? (necessary to use configuration files) USELIBPCRE=1 # Use libpcre? (needed for regex on musl) USELIBWRAP=1         # Use libwrap? USELIBCAP=1         # Use libcap? USESYSTEMD=1         # Make use of systemd socket activation COV_TEST=         # Perform test coverage? PREFIX=/usr/local BINDIR=$(PREFIX)/sbin MANDIR=$(PREFIX)/share/man/man8 MAN=sslh.8.gz         # man page name # End of configuration -- the rest should take care of # itself ```   ### systemd setup Create an sslh systemd service file... ``` # nano /lib/systemd/system/sslh.service ``` Paste in this contents… ``` [Unit] Description=SSL/SSH multiplexer After=network.target Documentation=man:sslh(8) [Service] #EnvironmentFile=/etc/default/sslh #ExecStart=/usr/local/sbin/sslh $DAEMON_OPTS ExecStart=/usr/local/sbin/sslh -F /etc/sslh/sslh.cfg KillMode=process [Install] WantedBy=multi-user.target ``` Save it and then… ``` # systemctl daemon-reload ``` Start it again to test… ``` # systemctl start sslh ```   ### Configure `sslh` First stop `sslh` then open the config file and replace with below, save and start `sslh` again ``` # systemctl stop sslh # nano /etc/sslh/sslh.cfg # systemctl start sslh ``` ``` verbose: true; foreground: true; inetd: false; numeric: true; transparent: true; timeout: 2; user: "sslh"; pidfile: "/var/run/sslh.pid"; chroot: "/var/empty"; # You must have a port forward rule in the router: external port 443 <-> internal port 4433 # Local ip address of PiA is: 192.168.1.124, sslh and stunnel4 are running on this Pi # Local ip address of PiB is: 192.168.1.123, http server and ssh server on this Pi listen: ( { host: "192.168.1.124"; port: "4433"; } ); # sslh demultiplexes based on the Protocol and Hostname protocols: ( { name: "tls"; sni_hostnames: [ "www.example.com" ]; host: "192.168.1.124"; port: "443"; log_level: 1; }, # This probe is for tls encrypted ssh. SSLH forwards it to stunnel on port 4480 which decrypts it and sends it to the ssh server on PiA port 1022 { name: "tls"; sni_hostnames: [ "ssh.example.com" ]; host: "192.168.1.124"; port: "4480"; log_level: 1; }, { name: "http"; host: "192.168.1.123"; port: "8000"; log_level: 1; }, { name: "ssh"; host: "192.168.1.123"; port: "1022"; log_level: 1; } ); ```   ### Configure `stunnel` First stop `stunnel` then open the config file and replace with below, save and start `stunnel` again ``` # systemctl stop stunnel4 # nano /etc/stunnel/stunnel.conf # systemctl start stunnel4 ``` ``` # Debugging stuff (may be useful for troubleshooting) foreground = yes #debug = 5 # this is the default debug = 7 output = /var/log/stunnel4/stunnel.log pid = /var/run/stunnel4/stunnel.pid fips = no cert = /etc/letsencrypt/live/example.com/fullchain.pem key = /etc/letsencrypt/live/example.com/privkey.pem [ssh] accept = 192.168.1.124:4480 connect = 192.168.1.124:1022 TIMEOUTclose = 0 ```   ### Configure iptables for Pi A The `_add.sh` script creates the rules, the `_rm.sh` script removes the rules. They will be lost if you reboot but there are ways to make them load again on start-up.. ``` # nano /usr/local/sbin/piA_tproxy_add.sh ``` ``` piA_tproxy_add.sh iptables -t mangle -N SSLH iptables -t mangle -A PREROUTING -p tcp -m socket --transparent -j SSLH iptables -t mangle -A OUTPUT --protocol tcp --out-interface eth0 -m multiport --sport 443,4480 --jump SSLH iptables -t mangle -A SSLH --jump MARK --set-mark 0x1 iptables -t mangle -A SSLH --jump ACCEPT ip rule add fwmark 0x1 lookup 100 ip route add local 0.0.0.0/0 dev lo table 100 ``` ``` # nano /usr/local/sbin/piA_tproxy_rm.sh ``` ``` piA_tproxy_rm.sh iptables -t mangle -D PREROUTING -p tcp -m socket --transparent -j SSLH iptables -t mangle -D OUTPUT --protocol tcp --out-interface eth0 -m multiport --sport 443,4480 --jump SSLH iptables -t mangle -D SSLH --jump MARK --set-mark 0x1 iptables -t mangle -D SSLH --jump ACCEPT iptables -t mangle -X SSLH ip rule del fwmark 0x1 lookup 100 ip route del local 0.0.0.0/0 dev lo table 100 ``` Make them executable.. ``` # chmod +rx piA_tproxy_add.sh # chmod +rx piA_tproxy_rm.sh ``` Now run the "add" script on Pi A! ``` # piA_tproxy_add.sh # piA_tproxy_rm.sh ``` ## Configure iptables for Pi B ``` # nano /usr/local/sbin/piB_tproxy_add.sh ``` ``` piB_tproxy_add.sh iptables -t mangle -N SSLHSSL iptables -t mangle -A OUTPUT -o eth0 -p tcp -m multiport --sport 1022,8000 -j SSLHSSL iptables -t mangle -A SSLHSSL --jump MARK --set-mark 0x1 iptables -t mangle -A SSLHSSL --jump ACCEPT ip rule add fwmark 0x1 lookup 100 ip route add default via 192.168.1.124 table 100 ip route flush cache ``` ``` # nano /usr/local/sbin/piB_tproxy_rm.sh ``` ``` iptables -t mangle -D OUTPUT -o eth0 -p tcp -m multiport --sport 1022,8000 -j SSLHSSL iptables -t mangle -D SSLHSSL --jump MARK --set-mark 0x1 iptables -t mangle -D SSLHSSL --jump ACCEPT iptables -t mangle -X SSLHSSL ip rule del fwmark 0x1 lookup 100 ip route del default via 192.168.1.124 table 100 ip route flush cache ``` Make them executable.. ``` # chmod +rx piB_tproxy_add.sh # chmod +rx piB_tproxy_rm.sh ``` Now run the "add" script on Pi B! ``` # piB_tproxy_add.sh # piB_tproxy_rm.sh ```   ### Testing * Getting to sshd on PiA I did this test using 4G from my phone (outside the LAN) To simulate this I use `proxytunnel`. External port 443 is forwarded by my router to 4433. I need to arrive at `sslh` (port 4433) with ssh encrypted as TLS (hence I use the -e switch) and the `sni_hostname` set to ssh.example.com so that `sslh` will demultiplex to `stunnel` (port 4480) which will decrypt and forward to ssh server on PiA… see `sslh.cfg` and `stunnel.conf`. The first IP:port is just a free HTTPS proxy I found on https://free-proxy-list.net I execute this command from a terminal window.. ``` # proxytunnel -v -e -C root.pem -p 78.141.192.198:8080 -d ssh.example.com:443 ``` * Getting to sshd on PiB I did this test using 4G from my phone (outside the LAN) My smartphone telecom provider blocks ssh over port 443 so I need to use `proxytunnel` to encrypt. Use the Proxytunnel `-X` switch to encrypt from local proxy to destination only so by the time we get to the destination it is unencrypted and `sslh` will see the ssh protocol and demultiplex to PiB as per `sslh.cfg`. ``` # proxytunnel -v -X -C root.pem -p 78.141.192.198:8080 -d ssh.example.com:443 ``` Now when you test it all look at the output in daemon.log like this: ``` # grep -i 'ssl' /var/log/daemon.log ``` You should see that the IP address and port from the “connection fromâ€� and “forwarded fromâ€� fields are the same. Special thanks and appreciation to Michael Yelsukov without whom I would never have got this working. Any feedback or corrections very welcome! sslh-2.3.1/doc/tproxy.svg000066400000000000000000000775221515234404100153350ustar00rootroot00000000000000 image/svg+xml Client Internet Router Local Area Network 443 443 443 4433 4433 SSLH 192.168.1.124 (Pi A) 192.168.1.123 (Pi B) Web Server SSH Server http 8000 8000 ssh 1022 1022 Web Server STUNNEL SSH Server 443 443 tls 4480 tls 1022 ssh sslh-2.3.1/echo_test.cfg000066400000000000000000000002431515234404100151220ustar00rootroot00000000000000 # TODO: c2s does not warn if udp: 1 (instead of 'true') udp: true; prefix: "hello"; listen: "localhost:9000"; listen-host: "localhost"; listen-port: "9000"; sslh-2.3.1/echosrv-conf.c000066400000000000000000001163221515234404100152320ustar00rootroot00000000000000/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) * on Wed Sep 10 15:49:49 2025. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2024 Yves Rutschle # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. */ #define _GNU_SOURCE #include #ifdef LIBCONFIG # include #endif #include #include #include #include #include #include "echosrv-conf.h" #include "argtable3.h" #ifdef LIBPCRE #define PCRE2_CODE_UNIT_WIDTH 8 #include typedef struct { PCRE2_SIZE rm_so; PCRE2_SIZE rm_eo; } regmatch_t; #else #include #endif /* This gets included in the output .c file */ /* Libconfig 1.4.9 is still used by major distributions * (e.g. CentOS7) and had a different name for * config_setting_lookup */ #if LIBCONFIG_VER_MAJOR == 1 #if LIBCONFIG_VER_MINOR == 4 #if LIBCONFIG_VER_REVISION == 9 #define config_setting_lookup config_lookup_from #endif #endif #endif /* config_type, lookup_fns, type2str are related, keep them together */ typedef enum { CFG_BOOL, CFG_INT, CFG_INT64, CFG_FLOAT, CFG_STRING, CFG_GROUP, CFG_ARRAY, CFG_LIST, } config_type; /* /config_type */ const char* type2str[] = { "boolean", "int", "int64", "float", "string", "group", "array", "list", }; typedef union { int def_bool; int def_int; long long def_int64; double def_float; char* def_string; } any_val; struct config_desc { const char* name; int type; struct config_desc * sub_group; /* Table for compound types (list and group) */ void* arg_cl; /* command-line argument for this setting */ void* base_addr; /* Base of the structure (filled at runtime). Probably not useable for list elements */ size_t offset; /* Offset of setting in the structure */ size_t offset_len; /* Offset of *_len field, for arrays and lists */ size_t offset_present; /* offset of *_is_present field, for optional settings */ size_t size; /* Size of element, or size of group for groups and lists */ int array_type; /* type of array elements, when type == CFG_ARRAY */ int mandatory; int optional; any_val default_val; }; #ifndef LIBCONFIG /* Stubs in case you don't want libconfig */ typedef void config_setting_t; typedef int config_t; #define CONFIG_TRUE 1 #define CONFIG_FALSE 0 #define make_config_setting_lookup(type) \ int config_setting_lookup_##type(const config_setting_t* a, const char* b, void* c) { \ return 0; \ } #define make_config_setting_get(type, ret_type) \ ret_type config_setting_get_##type(const config_setting_t* a) { \ return 0; \ } enum { CONFIG_TYPE_INT, CONFIG_TYPE_BOOL, CONFIG_TYPE_INT64, CONFIG_TYPE_FLOAT, CONFIG_TYPE_STRING }; make_config_setting_lookup(bool); make_config_setting_lookup(int); make_config_setting_lookup(int64); make_config_setting_lookup(float); make_config_setting_lookup(string); make_config_setting_get(bool, int); make_config_setting_get(int, int); make_config_setting_get(int64, long long int); make_config_setting_get(float, double); make_config_setting_get(string, char*); config_setting_t* config_root_setting(config_t* c) { return NULL; } config_setting_t* config_lookup(config_t* c, const char* b) { return NULL; } void config_init(config_t* c) { return; } char* config_setting_name(config_setting_t* c) { return NULL; } int config_setting_is_list(config_setting_t* c) { return 0; } int config_setting_is_array(config_setting_t* c) { return 0; } int config_setting_is_scalar(config_setting_t* c) { return 0; } int config_setting_index(const config_setting_t *setting) { return 0; } config_setting_t* config_setting_lookup(config_setting_t* a, char* b) { return NULL; } int config_setting_remove(config_setting_t* cfg, char* name) { return 0; } int config_setting_type(config_setting_t* s) { return -1; } int config_setting_length(config_setting_t* a) { return 0; } config_setting_t* config_setting_get_elem(config_setting_t* a, int i) { return NULL; } int config_read_file(config_t* a, const char* b) { return CONFIG_TRUE; } int config_error_line(config_t* c) { return 0; } char* config_error_text(config_t* c) { return NULL; } #endif static jmp_buf c2s_asprintf_fail; static int c2s_asprintf(char **restrict strp, const char *restrict fmt, ...) { va_list ap; va_start(ap,fmt); int res = vasprintf(strp, fmt, ap); va_end(ap); if (res == -1) longjmp(c2s_asprintf_fail, res); return res; } /* This is the same as config_setting_lookup_string() except it allocates a new string which belongs to the caller */ static int myconfig_setting_lookup_stringcpy( const config_setting_t* setting, const char* name, char** value) { const char* str; *value = NULL; if (config_setting_lookup_string(setting, name, &str) == CONFIG_TRUE) { c2s_asprintf(value, "%s", str); return CONFIG_TRUE; } else { return CONFIG_FALSE; } } typedef int (*lookup_fn)(const config_setting_t*, const char*, void*); lookup_fn lookup_fns[] = { (lookup_fn)config_setting_lookup_bool, (lookup_fn)config_setting_lookup_int, (lookup_fn)config_setting_lookup_int64, (lookup_fn)config_setting_lookup_float, (lookup_fn)myconfig_setting_lookup_stringcpy, NULL, /* CFG_GROUP */ NULL, /* CFG_ARRAY */ NULL, /* CFG_LIST */ }; /* Copy an any_val to arbitrary memory location */ /* 0: success * <0: error */ static int any_valcpy(config_type type, void* target, any_val val) { switch(type) { case CFG_BOOL: *(int*)target = val.def_bool; break; case CFG_INT: *(int*)target = val.def_int; break; case CFG_INT64: *(long long*)target = val.def_int64; break; case CFG_FLOAT: *(double*)target = val.def_float; break; case CFG_STRING: *(char**)target = val.def_string; break; default: fprintf(stderr, "Unknown type specification %d\n", type); return -1; } return 1; } /* Copy the value of a setting to an arbitrary memory that * must be large enough */ /* 0: success * <0: error */ static int settingcpy(config_type type, void* target, const config_setting_t* setting) { any_val val; char* str; switch(type) { case CFG_BOOL: val.def_bool = config_setting_get_bool(setting); *(int*)target = val.def_bool; break; case CFG_INT: val.def_int = config_setting_get_int(setting); *(int*)target = val.def_int; break; case CFG_INT64: val.def_int64 = config_setting_get_int64(setting); *(long long*)target = val.def_int64; break; case CFG_FLOAT: val.def_float = config_setting_get_float(setting); *(double*)target = val.def_int64; break; case CFG_STRING: c2s_asprintf(&str, "%s", config_setting_get_string(setting)); val.def_string = str; *(char**)target = val.def_string; break; default: fprintf(stderr, "Unknown type specification %d\n", type); return -1; } return 0; } /* Copy the value of a command line arg to arbitrary memory * that must be large enough for the type */ /* 0: success * <0: error */ static int clcpy(config_type type, void* target, const void* cl_arg) { any_val val; char* str; switch(type) { case CFG_BOOL: val.def_bool = (*(struct arg_lit**)cl_arg)->count; *(int*)target = val.def_bool; break; case CFG_INT: val.def_int = (*(struct arg_int**)cl_arg)->ival[0]; *(int*)target = val.def_int; break; case CFG_INT64: val.def_int64 = (*(struct arg_int**)cl_arg)->ival[0]; *(long long*)target = val.def_int64; break; case CFG_FLOAT: val.def_float = (*(struct arg_dbl**)cl_arg)->dval[0]; *(double*)target = val.def_float; break; case CFG_STRING: c2s_asprintf(&str, "%s", (*(struct arg_str**)cl_arg)->sval[0]); val.def_string = str; *(char**)target = val.def_string; break; default: fprintf(stderr, "Unknown type specification %d\n", type); return -1; } return 0; } /* Copy the value of a string argument to arbitary memory * location that must be large enough, converting on the way * (i.e. CFG_INT gets atoi() and so on) */ /* 0: success * <0: error */ static int stringcpy(config_type type, void* target, char* from) { any_val val; switch(type) { case CFG_BOOL: val.def_bool = (*from != '0'); *(int*)target = val.def_bool; break; case CFG_INT: val.def_int = strtol(from, NULL, 10); *(int*)target = val.def_int; break; case CFG_INT64: val.def_int64 = strtoll(from, NULL, 10); *(long long*)target = val.def_int64; break; case CFG_FLOAT: val.def_float = strtod(from, NULL); *(double*)target = val.def_float; break; case CFG_STRING: val.def_string = from; *(char**)target = val.def_string; break; default: fprintf(stderr, "Unknown type specification %d\n", type); return -1; } return 0; } /* Element to describe the target of a compound element * element: which config entry is being changed * match: if >0, index in pmatch to set * if 0, don't match but init with value * value: constant if not matching */ struct compound_cl_target { struct config_desc * element; int match; any_val value; }; /* Element to describe one compound command line argument * An argument is string that gets matched against a regex, * then match-groups get evaluated to each targets[]. * For lists, base_entry points to the config_setting so we * can append to it */ struct compound_cl_arg { const char* regex; struct arg_str** arg_cl; /* arg_str entry for this compound option */ struct config_desc * base_entry; struct compound_cl_target* targets; /* If override_desc is set, it points to the descriptor of the element in the group which will be checked for override. Then, override_matchindex indicates the command-line parameter match used to compare against override_desc to know if this group is overridden. If override_matchindex is 0, we don't match from the command-line but from a constant stored in override_const instead */ struct config_desc * override_desc; int override_matchindex; char* override_const; }; struct arg_file* echocfg_conffile; struct arg_lit* echocfg_udp; struct arg_str* echocfg_prefix; struct arg_str* echocfg_listen_host; struct arg_str* echocfg_listen_port; struct arg_str* echocfg_listen; struct arg_end* echocfg_end; static struct config_desc table_echocfg_listen[] = { { /* name */ "host", /* type */ CFG_STRING, /* sub_group*/ NULL, /* arg_cl */ & echocfg_listen_host, /* base_addr */ NULL, /* offset */ offsetof(struct echocfg_listen_item, host), /* offset_len */ 0, /* offset_present */ 0, /* size */ sizeof(char*), /* array_type */ -1, /* mandatory */ 1, /* optional */ 0, /* default_val*/ .default_val.def_string = NULL }, { /* name */ "port", /* type */ CFG_STRING, /* sub_group*/ NULL, /* arg_cl */ & echocfg_listen_port, /* base_addr */ NULL, /* offset */ offsetof(struct echocfg_listen_item, port), /* offset_len */ 0, /* offset_present */ 0, /* size */ sizeof(char*), /* array_type */ -1, /* mandatory */ 1, /* optional */ 0, /* default_val*/ .default_val.def_string = NULL }, { 0 } }; static struct config_desc table_echocfg[] = { { /* name */ "udp", /* type */ CFG_BOOL, /* sub_group*/ NULL, /* arg_cl */ & echocfg_udp, /* base_addr */ NULL, /* offset */ offsetof(struct echocfg_item, udp), /* offset_len */ 0, /* offset_present */ 0, /* size */ sizeof(int), /* array_type */ -1, /* mandatory */ 0, /* optional */ 0, /* default_val*/ .default_val.def_bool = 0 }, { /* name */ "prefix", /* type */ CFG_STRING, /* sub_group*/ NULL, /* arg_cl */ & echocfg_prefix, /* base_addr */ NULL, /* offset */ offsetof(struct echocfg_item, prefix), /* offset_len */ 0, /* offset_present */ 0, /* size */ sizeof(char*), /* array_type */ -1, /* mandatory */ 1, /* optional */ 0, /* default_val*/ .default_val.def_string = NULL }, { /* name */ "listen", /* type */ CFG_LIST, /* sub_group*/ table_echocfg_listen, /* arg_cl */ NULL, /* base_addr */ NULL, /* offset */ offsetof(struct echocfg_item, listen), /* offset_len */ offsetof(struct echocfg_item, listen_len), /* offset_present */ 0, /* size */ sizeof(struct echocfg_listen_item), /* array_type */ -1, /* mandatory */ 1, /* optional */ 0, /* default_val*/ .default_val.def_int = 0 }, { 0 } }; static struct compound_cl_target echocfg_listen_targets [] = { { & table_echocfg_listen[0], 1, .value.def_string = "0" }, { & table_echocfg_listen[1], 2, .value.def_string = "0" }, { 0 } }; static struct compound_cl_arg compound_cl_args[] = { { /* arg: listen */ .regex = "(.+):(\\w+)", .arg_cl = & echocfg_listen, .base_entry = & table_echocfg [2], .targets = echocfg_listen_targets, .override_desc = NULL, .override_matchindex = 0, .override_const = NULL, }, { 0 } }; /* Enable debug to follow the parsing of tables */ #if 0 #define TRACE_READ(x) printf x #define TRACE_READ_PRINT_SETTING 1 #else #define TRACE_READ(x) #define TRACE_READ_PRINT_SETTING 0 #endif /* Enable debug to follow the parsing of compound options */ #if 0 #define TRACE_CMPD(x) printf x #define TRACE_CMPD_PRINT_SETTING 1 #else #define TRACE_CMPD(x) #define TRACE_CMPD_PRINT_SETTING 0 #endif static void print_setting(config_type type, void* val) { if (TRACE_READ_PRINT_SETTING || TRACE_CMPD_PRINT_SETTING) { switch(type) { case CFG_BOOL: case CFG_INT: printf("%d", *(int*)val); break; case CFG_INT64: printf("%lld", *(long long*)val); break; case CFG_FLOAT: printf("%f", *(double*)val); break; case CFG_STRING: printf("`%s'", *(char**)val); break; case CFG_GROUP: case CFG_LIST: case CFG_ARRAY: break; } } } /* Changes all dashes to underscores in a string of * vice-versa */ static void strswap_ud(const char target, char* str) { char* c; for (c = str; *c; c++) if (*c == (target == '_' ? '-' : '_')) *c = (target == '_' ? '_' : '-'); } /* Same as config_setting_lookup() but looks up with dash or * underscore so `my_setting` and `my-setting` match the same */ static config_setting_t* config_setting_lookup_ud(config_setting_t* cfg, struct config_desc* desc) { config_setting_t* setting; char name[strlen(desc->name)+1];; strcpy(name, desc->name); strswap_ud('_', name); setting = config_setting_lookup(cfg, name); if (setting) return setting; strswap_ud('-', name); setting = config_setting_lookup(cfg, name); return setting; } static int lookup_typed_ud(config_setting_t* cfg, void* target, struct config_desc *desc) { lookup_fn lookup_fn = lookup_fns[desc->type]; char name[strlen(desc->name)+1];; strcpy(name, desc->name); strswap_ud('_', name); if (lookup_fn(cfg, name, ((char*)target) + desc->offset) == CONFIG_TRUE) return CONFIG_TRUE; strswap_ud('-', name); return lookup_fn(cfg, name, ((char*)target) + desc->offset); } /* Removes a setting, trying both underscores and dashes as * name (so deleting 'my-setting' deletes both 'my_setting' * and 'my-setting') */ static int setting_delete_ud(config_setting_t* cfg, struct config_desc *desc) { char name[strlen(desc->name)+1];; strcpy(name, desc->name); strswap_ud('_', name); if (config_setting_remove(cfg, name) == CONFIG_TRUE) return CONFIG_TRUE; strswap_ud('-', name); return config_setting_remove(cfg, name); } /* When traversing configuration, allocate memory for plural * types, init for scalars */ static void read_block_init(void* target, config_setting_t* cfg, struct config_desc* desc) { size_t len = 0; void* block; config_setting_t* setting; switch (desc->type) { case CFG_LIST: case CFG_ARRAY: if (cfg) { setting = config_setting_lookup_ud(cfg, desc); if (setting) len = config_setting_length(setting); } block = calloc(len, desc->size); *(size_t*)(((char*)target) + desc->offset_len) = len; *(void**)(((char*)target) + desc->offset) = block; TRACE_READ((" sizing for %zu elems ", len)); break; case CFG_GROUP: block = calloc(1, desc->size); *(void**)(((char*)target) + desc->offset) = block; TRACE_READ((" sizing for %zu elems ", len)); break; default: /* scalar types: copy default */ memcpy(((char*)target) + desc->offset, &desc->default_val, desc->size); TRACE_READ(("setting %s to default ", desc->name)); print_setting(desc->type,(char*)target + desc->offset); break; } } static int read_block(config_setting_t* cfg, void* target, struct config_desc* desc, char** errmsg); /* When traversing configuration, set value from config * file, or command line * return: 0 if not set, 1 if set somehow */ static int read_block_setval(void* target, config_setting_t* cfg, struct config_desc* desc, char** errmsg) { int i; size_t len = 0; void* block; int in_cfg = 0, in_cl = 0; /* Present in config file? present on command line? */ config_setting_t* setting = NULL; switch (desc->type) { case CFG_LIST: if (cfg) { setting = config_setting_lookup_ud(cfg, desc); if (setting) len = config_setting_length(setting); block = *(void**)(((char*)target) + desc->offset); for (i = 0; i < len; i++) { config_setting_t* elem = config_setting_get_elem(setting, i); if (!read_block(elem, (char*)block + desc->size * i, desc->sub_group, errmsg)) return 0; } } break; case CFG_ARRAY: if (cfg) { setting = config_setting_lookup_ud(cfg, desc); if (setting) len = config_setting_length(setting); block = *(void**)(((char*)target) + desc->offset); for (i = 0; i < len; i++) { config_setting_t* elem = config_setting_get_elem(setting, i); settingcpy(desc->array_type, (char*)block + desc->size * i, elem); TRACE_READ(("[%d] = ", i)); print_setting(desc->array_type, (char*)block + desc->size *i); TRACE_READ(("\n")); } setting_delete_ud(cfg, desc); } break; case CFG_GROUP: if (cfg) setting = config_setting_lookup_ud(cfg, desc); block = *(void**)(((char*)target) + desc->offset); if (!read_block(setting, block, desc->sub_group, errmsg)) return 0; break; default: /* scalar types */ TRACE_READ((" `%s'", desc->name)); if (cfg && config_setting_lookup_ud(cfg, desc)) { TRACE_READ((" in config file: ")); /* setting is present in cfg, look it up */ if (lookup_typed_ud(cfg, target, desc) != CONFIG_TRUE) { TRACE_READ((" but wrong type (expected %s) ", type2str[desc->type])); c2s_asprintf(errmsg, "Option \"%s\" wrong type, expected %s\n", desc->name, type2str[desc->type]); return 0; } print_setting(desc->type, (((char*)target) + desc->offset)); setting_delete_ud(cfg, desc); in_cfg = 1; } else { TRACE_READ((" not in config file")); } if (desc->arg_cl && (*(struct arg_int**)desc->arg_cl)->count) { clcpy(desc->type, ((char*)target) + desc->offset, desc->arg_cl); TRACE_READ((", command line sets to ")); print_setting(desc->type, (((char*)target) + desc->offset)); in_cl = 1; } else { TRACE_READ((", not in command line")); } if (!(in_cfg || in_cl)) { TRACE_READ(("\n")); return 0; } TRACE_READ(("\n")); break; } return 1; } /* Set *_is_present flag for target */ static void target_is_present(void* target, struct config_desc* desc, int val) { if (desc->optional) { /* _is_present only exists in target for optional settings */ TRACE_READ((" mark as set")); *(int*)((char*)target + desc->offset_present) = val; } } /* traverses the configuration; allocates memory if needed, * set to default if exists, * fill from configuration file if present, overrides or set from * command line if present, verifies mandatory options have * been set * target: base address of the group being processed */ static int read_block(config_setting_t* cfg, void* target, struct config_desc* desc, char** errmsg) { int set; for (; desc->name; desc++) { TRACE_READ(("reading %s%s%s: ", desc->optional ? "optional " : "", desc->mandatory ? "mandatory " : "", desc->name)); desc->base_addr = target; read_block_init(target, cfg, desc); set = read_block_setval(target, cfg, desc, errmsg); if (!set && desc->mandatory) { c2s_asprintf(errmsg, "Mandatory option \"%s\" not found", desc->name); return 0; } if (desc->optional) target_is_present(target, desc, set && desc->optional); } return 1; } /* Copy regex match into newly allocated string * out: newly allocated string (caller has to free it) * in: string into which the match was made * pmatch: the match to extract */ static void pmatchcpy(char** out, const char* in, regmatch_t* pmatch) { int len = pmatch->rm_eo - pmatch->rm_so; *out = calloc(len+1, 1); memcpy(*out, in + pmatch->rm_so, len); } /* Processes a list of targets within one element, setting * the values in the target setting * target: where to put the data * arg: CL arg containing the target fields * clval: command line parameter * pmatch: regex match array into clval */ static int set_target_fields(void* target_addr, struct compound_cl_arg* arg, const char* clval, regmatch_t* pmatch) { int pmatch_cnt = 1; struct compound_cl_target* target; for (target = arg->targets; target->element; target++) { struct config_desc * element = target->element; if (target->match) { TRACE_CMPD((" match %d rm_so %d rm_eo %d type %d\n", pmatch_cnt, pmatch[pmatch_cnt].rm_so, pmatch[pmatch_cnt].rm_eo, element->type )); if (pmatch[pmatch_cnt].rm_so == -1) { /* This should not happen as regexec() did * match before, unless there is a * discrepency between the regex and the * number of backreferences */ return 0; } char* str; pmatchcpy(&str, clval, &pmatch[pmatch_cnt]); stringcpy(element->type, (char*)target_addr + element->offset, str); TRACE_CMPD(("setting %p+%zu to : ", target_addr , element->offset)); print_setting(element->type , (char*)target_addr + element->offset); TRACE_CMPD(("\n")); /* str is temporary buffer for type conversion, except for strings which we * need to keep around so don't free them */ if (element->type != CFG_STRING) free(str); pmatch_cnt++; } else { /* don't use matching, set constant */ any_valcpy(element->type, (char*)target_addr + element->offset, target->value); } } return 1; } /* Goes over a list, finds if a group matches the specified string and overwrite * it if it does. */ static int override_on_str(struct compound_cl_arg* arg, const char* str, regmatch_t* pmatch) { struct config_desc * desc = arg->base_entry; void* list_base = *(void**)(desc->base_addr + desc->offset); size_t list_len = *(size_t*)(desc->base_addr + desc->offset_len); size_t elem_size = desc->size; int i; for (i = 0; i < list_len; i++) { char* group_base = ((char*)list_base + i * elem_size); char* cfg_member = *(char**)(group_base + arg->override_desc->offset); if (!strcmp(str, cfg_member)) { memset(group_base, 0, elem_size); struct arg_str* arg_cl = *arg->arg_cl; if (!set_target_fields(group_base, arg, arg_cl->sval[0], pmatch)) return 0; return 1; } } return 0; } /* Goes over a list and override group if needed */ static int override_elem(struct compound_cl_arg* arg, int arg_index, regmatch_t* pmatch) { char* str; int allocated = 0; int res; if (arg->override_matchindex) { struct arg_str* arg_cl = *arg->arg_cl; pmatchcpy(&str, arg_cl->sval[arg_index], &pmatch[arg->override_matchindex]); allocated = 1; } else { str = arg->override_const; } res = override_on_str(arg, str, pmatch); if (allocated) free(str); return res; } /* Add an argument to a list, overriding if required or * appending otherwise */ static int add_arg_to_list(struct compound_cl_arg* arg, int arg_index, regmatch_t* pmatch) { struct config_desc * desc = arg->base_entry; void* list_base = *(void**)(desc->base_addr + desc->offset); size_t list_len = *(size_t*)(desc->base_addr + desc->offset_len); size_t elem_size = desc->size; /* are we overriding an existing group? */ if (arg->override_desc) if (override_elem(arg, arg_index, pmatch)) return 1; /* override not found or no override, append element and * zero it out */ list_len++; list_base = realloc(list_base, list_len * elem_size); *(size_t*)(desc->base_addr + desc->offset_len) = list_len; *(void**)(desc->base_addr + desc->offset) = list_base; memset(list_base + (list_len - 1) * elem_size, 0, elem_size); struct arg_str* arg_cl = *arg->arg_cl; if (!set_target_fields((char*)list_base + (list_len - 1) * elem_size, arg, arg_cl->sval[arg_index], pmatch)) { return 0; } return 1; } /* TODO: pass pmatch size as parameter or something */ #define MAX_MATCH 10 #ifndef LIBPCRE static int regcompmatch_posix( regmatch_t* pmatch, struct compound_cl_arg* arg, int arg_index, char** errmsg) { char* regerr; struct arg_str* arg_cl = *arg->arg_cl; regex_t preg; int res = regcomp(&preg, arg->regex, REG_EXTENDED); if (res) { int errlen = regerror(res, &preg, NULL, 0); regerr = malloc(errlen); regerror(res, &preg, regerr, errlen); c2s_asprintf(errmsg, "compiling pattern /%s/:%s", arg->regex, regerr); free(regerr); return 0; } res = regexec(&preg, arg_cl->sval[arg_index], MAX_MATCH, &pmatch[0], 0); if (res) { c2s_asprintf(errmsg, "--%s %s: Illegal argument", arg_cl->hdr.longopts, arg->regex); return 0; } return 1; } #endif #ifdef LIBPCRE static int regcompmatch_pcre2( regmatch_t* pmatch, struct compound_cl_arg* arg, int arg_index, char** errmsg) { int i, error; pcre2_code* pcre; PCRE2_UCHAR8 err_str[120]; /* ample, according to pcre2api(3) */ pcre2_match_data* matches; PCRE2_SIZE error_offset; struct arg_str* arg_cl = *arg->arg_cl; pcre = pcre2_compile((PCRE2_SPTR8)arg->regex, PCRE2_ZERO_TERMINATED, 0, &error, &error_offset, NULL); if (!pcre) { pcre2_get_error_message(error, err_str, sizeof(err_str)); c2s_asprintf(errmsg, "compiling pattern /%s/:%d: %s at offset %ld\n", arg->regex, error, err_str, error_offset); return 0; } matches = pcre2_match_data_create(MAX_MATCH, NULL); int res = pcre2_match(pcre, (PCRE2_SPTR8)arg_cl->sval[arg_index], PCRE2_ZERO_TERMINATED, 0, 0, matches, NULL); if (res < 0) { pcre2_get_error_message(res, err_str, sizeof(err_str)); c2s_asprintf(errmsg, "matching %s =~ /%s/:%d: %s\n", arg_cl->sval[arg_index], arg->regex, res, err_str); return 0; } PCRE2_SIZE *ovec = pcre2_get_ovector_pointer(matches); if (res > MAX_MATCH) res = MAX_MATCH; /* From pcre2posix.c */ for (i = 0; i < res; i++) { pmatch[i].rm_so = (ovec[i*2] == PCRE2_UNSET) ? -1 : ovec[i*2]; pmatch[i].rm_eo = (ovec[i*2+1] == PCRE2_UNSET) ? -1 : ovec[i*2+1]; } for (; i < MAX_MATCH; i++) pmatch[i].rm_so = pmatch[i].rm_eo = -1; pcre2_match_data_free(matches); return 1; } #endif /* Regex fiddling: uses info in arg to fill pmatch * arg: description of the command line argument * arg_index: occurence of this argument on the command line */ static int regcompmatch(regmatch_t* pmatch, struct compound_cl_arg* arg, int arg_index, char** errmsg) { #if LIBPCRE return regcompmatch_pcre2(pmatch, arg, arg_index, errmsg); #else return regcompmatch_posix(pmatch, arg, arg_index, errmsg); #endif } /* Read compound options described in `arg`, from `cfg`, to `setting` */ static int read_compounds(config_setting_t* cfg, void* setting, struct compound_cl_arg* arg, char** errmsg) { int arg_i; struct arg_str* arg_cl; regmatch_t pmatch[MAX_MATCH]; for (; arg->regex; arg++) { arg_cl = *arg->arg_cl; TRACE_CMPD(("Compound %s occurs %d : ", arg_cl->hdr.longopts, arg_cl->count)); for (arg_i = 0; arg_i < arg_cl->count; arg_i++) { if (!regcompmatch(&pmatch[0], arg, arg_i, errmsg)) return 0; TRACE_CMPD(("`%s' matched\n", arg_cl->sval[arg_i])); switch (arg->base_entry->type) { case CFG_LIST: /* In a list, find the end or the element to override */ if (!add_arg_to_list(arg, arg_i, pmatch)) { return 0; } break; /* Semantics for CFG_ARRAY TBD */ case CFG_GROUP: if (!set_target_fields( /* base_addr is the same for all elements in the group */ arg->targets[0].element->base_addr, arg, arg_cl->sval[arg_i], pmatch)) return 0; default: TRACE_CMPD(("error, compound on type %d\n", arg->base_entry->type)); break; } } TRACE_CMPD(("done %s\n", arg_cl->hdr.longopts)); } return 1; } /* read config file `filename` into `c` */ static int c2s_parse_file(const char* filename, config_t* c, char**errmsg) { /* Read config file */ if (config_read_file(c, filename) == CONFIG_FALSE) { if (config_error_line(c) != 0) { c2s_asprintf(errmsg, "%s:%d:%s", filename, config_error_line(c), config_error_text(c)); return 0; } c2s_asprintf(errmsg, "%s:%s", filename, config_error_text(c)); return 0; } return 1; } /* Allocates a new string that represents the setting value, which must be a scalar */ static void scalar_to_string(char** strp, config_setting_t* s) { switch(config_setting_type(s)) { case CONFIG_TYPE_INT: c2s_asprintf(strp, "%d\n", config_setting_get_int(s)); break; case CONFIG_TYPE_BOOL: c2s_asprintf(strp, "%s\n", config_setting_get_bool(s) ? "[true]" : "[false]" ); break; case CONFIG_TYPE_INT64: c2s_asprintf(strp, "%lld\n", config_setting_get_int64(s)); break; case CONFIG_TYPE_FLOAT: c2s_asprintf(strp, "%lf\n", config_setting_get_float(s)); break; case CONFIG_TYPE_STRING: c2s_asprintf(strp, "%s\n", config_setting_get_string(s)); break; default: /* This means a bug */ fprintf(stderr, "Unexpected type %d\n", config_setting_type(s)); exit(1); } } /* Typesets all the settings in a configuration as a * newly-allocated string. The string management is caller's * responsability. * Returns the number of scalars in the configuration */ static int cfg_as_string(config_setting_t* parent, const char* path, char** strp) { int i, len, res = 0; config_setting_t* child; char* subpath, *value, *old; const char* name; len = config_setting_length(parent); for (i = 0; i < len; i++) { child = config_setting_get_elem(parent, i); name = config_setting_name(child); if (!name) name = ""; if(config_setting_is_list(parent) || config_setting_is_array(parent)) { c2s_asprintf(&subpath, "%s[%d]%s", path, config_setting_index(child), name); } else { c2s_asprintf(&subpath, "%s/%s", path, name); } if (config_setting_is_scalar(child)) { scalar_to_string(&value, child); /* Add value to the output string */ if (*strp) { c2s_asprintf(&old, "%s", *strp); free(*strp); } else { c2s_asprintf(&old, "%s", ""); } c2s_asprintf(strp, "%s%s:%s", old, subpath, value); free(value); free(old); res++; /* At least one scalar was found */ } else { /* It's an aggregate -- descend into it */ res += cfg_as_string(child, subpath, strp); } free(subpath); } return res; } /* 0: success <0: error */ int echocfg_cl_parse(int argc, char* argv[], struct echocfg_item* cfg) { int nerrors, res; config_t c; char* errmsg; config_setting_t* s; void* argtable[] = { #ifdef LIBCONFIG echocfg_conffile = arg_filen("F", "config", "", 0, 1, "Specify configuration file"), #endif echocfg_udp = arg_litn(NULL, "udp", 0, 1, ""), echocfg_prefix = arg_strn(NULL, "prefix", "", 0, 1, ""), echocfg_listen_host = arg_strn(NULL, "listen-host", "", 0, 10, ""), echocfg_listen_port = arg_strn(NULL, "listen-port", "", 0, 10, ""), echocfg_listen = arg_strn("p", "listen", "", 0, 10, "Listen on host:port"), echocfg_end = arg_end(10) }; /* Set up failure handler in case asprintf() runs out of * memory */ ; if (setjmp(c2s_asprintf_fail)) { fprintf(stderr, "asprintf: probably out of memory\n"); return -1; } /* Parse command line */ nerrors = arg_parse(argc, argv, argtable); if (nerrors) { arg_print_errors(stdout, echocfg_end, "echocfg"); arg_print_syntax(stdout, argtable, "\n"); arg_print_glossary(stdout, argtable, " %-25s\t%s\n"); return -1; } config_init(&c); if (echocfg_conffile && echocfg_conffile->count) { if (!c2s_parse_file(echocfg_conffile->filename[0], &c, &errmsg)) { fprintf(stderr, "%s\n", errmsg); return -1; } } s = config_root_setting(&c); res = read_block(s, cfg, table_echocfg, &errmsg); if (!res) { fprintf(stderr, "%s\n", errmsg); return -1; } res = read_compounds(s, cfg, compound_cl_args, &errmsg); if (!res) { fprintf(stderr, "%s\n", errmsg); return -1; } errmsg = NULL; res = cfg_as_string(s, "", &errmsg); if (res) fprintf(stderr, "Unknown settings:\n%s\n", errmsg); return 0; } static void indent(FILE* out, int depth) { int i; for (i = 0; i < depth; i++) fprintf(out, " "); } static void echocfg_listen_fprint( FILE* out, struct echocfg_listen_item* echocfg_listen, int depth) { indent(out, depth); fprintf(out, "host: %s", echocfg_listen->host); fprintf(out, "\n"); indent(out, depth); fprintf(out, "port: %s", echocfg_listen->port); fprintf(out, "\n"); } void echocfg_fprint( FILE* out, struct echocfg_item* echocfg, int depth) { int i; indent(out, depth); fprintf(out, "udp: %d", echocfg->udp); fprintf(out, "\n"); indent(out, depth); fprintf(out, "prefix: %s", echocfg->prefix); fprintf(out, "\n"); indent(out, depth); fprintf(out, "listen [%zu]:\n", echocfg->listen_len); for (i = 0; i < echocfg->listen_len; i++) { echocfg_listen_fprint(out, &echocfg->listen[i], depth+1); } } sslh-2.3.1/echosrv-conf.h000066400000000000000000000040651515234404100152370ustar00rootroot00000000000000/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) * on Wed Sep 10 15:49:49 2025. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2024 Yves Rutschle # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. */ #ifndef C2S_ECHOCFG_H #define C2S_ECHOCFG_H #ifdef LIBCONFIG # include #endif struct echocfg_listen_item { char* host; char* port; }; struct echocfg_item { int udp; char* prefix; size_t listen_len; struct echocfg_listen_item* listen; }; int echocfg_parse_file( const char* filename, struct echocfg_item* echocfg, const char** errmsg); void echocfg_fprint( FILE* out, struct echocfg_item *echocfg, int depth); int echocfg_cl_parse( int argc, char* argv[], struct echocfg_item *echocfg); #endif sslh-2.3.1/echosrv.c000066400000000000000000000216631515234404100143120ustar00rootroot00000000000000/* echosrv: a simple line echo server with optional prefix adding. * * echosrv --listen localhost6:1234 --prefix "ssl: " * * This will bind to 1234, and echo every line pre-pending "ssl: ". This is * used for testing: we create several such servers with different prefixes, * then we connect test clients that can then check they get the proper data * back (thus testing that shoveling works both ways) with the correct prefix * (thus testing it connected to the expected service). * **/ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define cfg sslhcfg #include "common.h" #undef cfg #include "echosrv-conf.h" /* Added to make the code compilable under CYGWIN * */ #ifndef SA_NOCLDWAIT #define SA_NOCLDWAIT 0 #endif struct echocfg_item cfg; void check_res_dump(int res, struct addrinfo *addr, char* syscall) { char buf[NI_MAXHOST]; if (res == -1) { if (addr) fprintf(stderr, "error %s:%s: %s\n", sprintaddr(buf, sizeof(buf), addr), syscall, strerror(errno)); else fprintf(stderr, "Dying just because\n"); exit(1); } } void start_echo(int fd) { ssize_t res; char buffer[1 << 20]; ssize_t ret; size_t prefix_len; int first = 1; prefix_len = strlen(cfg.prefix); memset(buffer, 0, sizeof(buffer)); strcpy(buffer, cfg.prefix); while (1) { ret = read(fd, buffer + prefix_len, sizeof(buffer) - prefix_len); if (ret <= 0) { fprintf(stderr, "%s", strerror(errno)); return; } if (first) { res = write(fd, buffer, ret + prefix_len); first = 0; if (write(1, buffer, ret + prefix_len) < 0) { fprintf(stderr, "%s", strerror(errno)); } } else { res = write(fd, buffer + prefix_len, ret); } if (res < 0) { fprintf(stderr, "%s", strerror(errno)); return; } } } /* TCP echo server: accepts connections to an endpoint, forks an echo for each * connection, forever. Prefix is added at start of response stream */ void tcp_echo(struct listen_endpoint* listen_socket) { while (1) { int in_socket = accept(listen_socket->socketfd, 0, 0); if (in_socket == -1) { perror("tcp_echo:accept"); exit(1); } if (!fork()) { close(listen_socket->socketfd); start_echo(in_socket); exit(0); } close(in_socket); waitpid(-1, NULL, WNOHANG); } } void print_udp_xchange(int sockfd, struct sockaddr* addr, socklen_t addrlen) { struct addrinfo src_addrinfo, to_addrinfo; char str_addr[NI_MAXHOST+1+NI_MAXSERV+1]; char str_addr2[NI_MAXHOST+1+NI_MAXSERV+1]; struct sockaddr_storage ss; src_addrinfo.ai_addr = (struct sockaddr*)&ss; src_addrinfo.ai_addrlen = sizeof(ss); getsockname(sockfd, src_addrinfo.ai_addr, &src_addrinfo.ai_addrlen); to_addrinfo.ai_addr = addr; to_addrinfo.ai_addrlen = sizeof(*addr); fprintf(stderr, "UDP local %s remote %s\n", sprintaddr(str_addr, sizeof(str_addr), &src_addrinfo), sprintaddr(str_addr2, sizeof(str_addr2), &to_addrinfo) ); } /* UDP echo server: receive packets, return them, forever. * Prefix is added at each packet */ void udp_echo(struct listen_endpoint* listen_socket) { char data[65536]; struct sockaddr src_addr; socklen_t addrlen; memset(data, 0, sizeof(data)); size_t prefix_len = strlen(cfg.prefix); memcpy(data, cfg.prefix, prefix_len); while (1) { addrlen = sizeof(src_addr); ssize_t len = recvfrom(listen_socket->socketfd, data + prefix_len, sizeof(data) - prefix_len, 0, &src_addr, &addrlen); if (len < 0) { perror("recvfrom"); } *(data + prefix_len + len) = 0; fprintf(stderr, "%zd %s\n", len, data + prefix_len); print_udp_xchange(listen_socket->socketfd, &src_addr, addrlen); ssize_t res = sendto(listen_socket->socketfd, data, len + prefix_len, 0, &src_addr, addrlen); if (res < 0) { perror("sendto"); } } } void main_loop(struct listen_endpoint listen_sockets[], int num_addr_listen) { int i; for (i = 0; i < num_addr_listen; i++) { if (!fork()) { if (cfg.udp) { udp_echo(&listen_sockets[i]); } else { tcp_echo(&listen_sockets[i]); } } } wait(NULL); } /* Following is a number of utility functions copied from common.c: linking * against common.o directly means echosrv has to work with sslh config struct, * which makes it all too awkward */ /* simplified from common.c */ char* sprintaddr(char* buf, size_t size, struct addrinfo *a) { char host[NI_MAXHOST], serv[NI_MAXSERV]; int res; res = getnameinfo(a->ai_addr, a->ai_addrlen, host, sizeof(host), serv, sizeof(serv), 0 ); if (res) { /* Name resolution failed: do it numerically instead */ res = getnameinfo(a->ai_addr, a->ai_addrlen, host, sizeof(host), serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV); /* should not fail but... */ if (res) { strcpy(host, "?"); strcpy(serv, "?"); } } snprintf(buf, size, "%s:%s", host, serv); return buf; } /* simplified from common.c */ int listen_single_addr(struct addrinfo* addr, int keepalive, int udp) { struct sockaddr_storage *saddr; int sockfd, one, res; saddr = (struct sockaddr_storage*)addr->ai_addr; sockfd = socket(saddr->ss_family, udp ? SOCK_DGRAM : SOCK_STREAM, 0); check_res_dump(sockfd, addr, "socket"); one = 1; res = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)); check_res_dump(res, addr, "setsockopt(SO_REUSEADDR)"); if (addr->ai_addr->sa_family == AF_INET6) { res = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&one, sizeof(one)); check_res_dump(res, addr, "setsockopt(IPV6_V6ONLY)"); } res = bind(sockfd, addr->ai_addr, addr->ai_addrlen); check_res_dump(res, addr, "bind"); if (!udp) { res = listen (sockfd, 50); check_res_dump(res, addr, "listen"); } return sockfd; } /* simplified from common.c */ int resolve_split_name(struct addrinfo **out, char* host, char* serv) { struct addrinfo hint; char *end; int res; memset(&hint, 0, sizeof(hint)); hint.ai_family = PF_UNSPEC; hint.ai_socktype = SOCK_STREAM; /* If it is a RFC-Compliant IPv6 address ("[1234::12]:443"), remove brackets * around IP address */ if (host[0] == '[') { end = strrchr(host, ']'); if (!end) { fprintf(stderr, "%s: no closing bracket in IPv6 address?\n", host); return -1; } host++; /* skip first bracket */ *end = 0; /* remove last bracket */ } res = getaddrinfo(host, serv, &hint, out); if (res) fprintf(stderr, "%s `%s:%s'\n", gai_strerror(res), host, serv); return res; } int start_listen_sockets(struct listen_endpoint *sockfd[]) { struct addrinfo *addr, *start_addr; char buf[NI_MAXHOST]; int i, res; int num_addr = 0, keepalive = 0, udp = 0; *sockfd = NULL; fprintf(stderr, "Listening to:\n"); for (i = 0; i < cfg.listen_len; i++) { udp = cfg.udp; res = resolve_split_name(&start_addr, cfg.listen[i].host, cfg.listen[i].port); if (res) exit(4); for (addr = start_addr; addr; addr = addr->ai_next) { num_addr++; *sockfd = realloc(*sockfd, num_addr * sizeof(*sockfd)); (*sockfd)[num_addr-1].socketfd = listen_single_addr(addr, keepalive, udp); (*sockfd)[num_addr-1].type = udp ? SOCK_DGRAM : SOCK_STREAM; fprintf(stderr, "%d:\t%s\n", (*sockfd)[num_addr-1].socketfd, sprintaddr(buf, sizeof(buf), addr)); } freeaddrinfo(start_addr); } return num_addr; } int main(int argc, char *argv[]) { int num_addr_listen; struct listen_endpoint *listen_sockets; memset(&cfg, 0, sizeof(cfg)); if (echocfg_cl_parse(argc, argv, &cfg)) exit(1); echocfg_fprint(stdout, &cfg, 0); num_addr_listen = start_listen_sockets(&listen_sockets); main_loop(listen_sockets, num_addr_listen); return 0; } sslh-2.3.1/echosrv.cfg000066400000000000000000000017271515234404100146260ustar00rootroot00000000000000# conf2struct for echosrv header: "echosrv-conf.h"; parser: "echosrv-conf.c"; printer: true; conffile_option: ("F", "config"); config: { name: "echocfg", type: "list", items: ( {name: "udp", type: "bool"; default: false; }, {name: "prefix", type: "string"; }, { name: "listen", type: "list", items: ( { name: "host"; type: "string"; var: true; }, { name: "port"; type: "string"; var: true; } ) } ) } cl_groups: ( { name: "listen"; pattern: "(.+):(\w+)"; description: "Listen on host:port"; short: "p"; argdesc: ""; list: "listen"; # no override, this just adds to the list (and thus can be specified several times) targets: ( { path: "host"; value: "$1" }, { path: "port"; value: "$2" } ); } ) sslh-2.3.1/echoÑ•rv-conf.h000066400000000000000000000055641515234404100156270ustar00rootroot00000000000000/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) * on Sat Nov 7 09:19:26 2020. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2019 Yves Rutschle # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. */ #ifndef C2S_SSLHCFG_H #define C2S_SSLHCFG_H #ifdef LIBCONFIG # include #endif #include "probe.h" #include #include #include struct sslhcfg_listen_item { char* host; char* port; int keepalive; }; struct sslhcfg_protocols_item { char* name; char* host; char* port; int service_is_present; char* service; int fork; int tfo_ok; int log_level; int keepalive; size_t sni_hostnames_len; char** sni_hostnames; size_t alpn_protocols_len; char** alpn_protocols; size_t regex_patterns_len; char** regex_patterns; int minlength_is_present; int minlength; T_PROBE* probe; struct addrinfo* saddr; void* data; }; struct sslhcfg_item { char* prefix; int verbose; int foreground; int inetd; int numeric; int transparent; int timeout; int user_is_present; char* user; int pidfile_is_present; char* pidfile; int chroot_is_present; char* chroot; char* syslog_facility; char* on_timeout; size_t listen_len; struct sslhcfg_listen_item* listen; size_t protocols_len; struct sslhcfg_protocols_item* protocols; }; int sslhcfg_parse_file( const char* filename, struct sslhcfg_item* sslhcfg, const char** errmsg); void sslhcfg_fprint( FILE* out, struct sslhcfg_item *sslhcfg, int depth); int sslhcfg_cl_parse( int argc, char* argv[], struct sslhcfg_item *sslhcfg); #endif sslh-2.3.1/example.cfg000066400000000000000000000176631515234404100146160ustar00rootroot00000000000000# This file is provided as documentation to show what is # possible. It should not be used as-is, and probably should # not be used as a starting point for a working # configuration. Instead use basic.cfg. foreground: true; inetd: false; numeric: false; transparent: false; timeout: 2; user: "nobody"; pidfile: "/var/run/sslh.pid"; chroot: "/var/empty"; # Logging configuration # Value: 1: stdout; 2: syslog; 3: stdout+syslog; 4: logfile; ...; 7: all # Defaults are indicated here, and should be sensible. Generally, you want *-error # to be always enabled, to know if something is going wrong. # Each option relates to a different set of messages. verbose-config: 0; # print configuration at startup verbose-config-error: 3; # print configuration errors verbose-connections: 3; # trace established incoming address to forward address verbose-connections-error: 3; # connection errors verbose-connections-try: 0; # connection attempts towards targets verbose-fd: 0; # file descriptor activity, open/close/whatnot verbose-packets: 0; # hexdump packets on which probing is done verbose-probe-info: 0; # what's happening during the probe process verbose-probe-error: 3; # failures and problems during probing verbose-system-error: 3; # system call problem, i.e. malloc, fork, failing verbose-int-error: 3; # internal errors, the kind that should never happen # This one is special and overrides all previous options if # set, as a quick way to get "as much as possible" #verbose: 3; # Specify a path to the logfile. #logfile: "/var/log/sslh.log" # Specify the number of concurrent UDP connection that can # be managed (default 1024) udp_max_connections: 16; # Specify which syslog facility to use (names for your # system are usually defined in /usr/include/*/sys/syslog.h # or equivalent) # Default is "auth" # "none" disables use of syslog syslog_facility: "auth"; # List of interfaces on which we should listen # Options: # host: name of the interface to listen to # port: name of the service to listen to # is_udp: listen in the UDP domain (default is TCP) # is_unix: listen in the UNIX socket domain (default is TCP) # keepalive: set TCP_KEEPALIVE # max_connections: drop incoming connections after this count # proxyprotocol: [true|false]: this endpoint expects # proxyprotocol headers on incoming connections. Refer to # doc/proxyprotocol.md listen: ( { host: "thelonious"; port: "443"; max_connections: 5; }, { host: "thelonious"; port: "8080"; keepalive: true; }, { host: "thelonious"; is_udp: true; port: "443"; }, { host: "/tmp/unix_socket"; is_unix: true; port: ""; } ); # List of protocols # # Each protocol entry consists of: # name: name of the probe. These are listed on the command # line (ssh -?), plus 'regex' and 'timeout'. # service: (optional) libwrap service name (see hosts_access(5)) # host, port: where to connect when this probe succeeds # log_level: 0 to turn off logging # 1 to log each incoming connection # keepalive: Should TCP keepalive be on or off for that # connection (default is off) # fork: Should a new process be forked for this protocol? # (only useful for sslh-select and sslh-ev) # max_connections: further connections for this protocol # will be rejected once the limit is reached. Does not # work with sslh-fork. # tfo_ok: Set to true if the server supports TCP FAST OPEN # resolve_on_forward: Set to true if server address should be resolved on # (every) newly incoming connection (again) # transparent: Set to true to proxy this protocol # transparently (server sees the remote client IP # address). Same as the global option, but per-protocol # is_unix: [true|false] connect to a UNIX socket. The host # field becomes the pathname to the socket, and the port # field is unused (but necessary). # proxyprotocol: <1|2>; When connecting to the backend # server, a proxyprotocol header of the specified # version will be added, containing the client's # connection information. # # Probe-specific options: # (sslh will try each probe in order they are declared, and # connect to the first that matches.) # # tls: # sni_hostnames: list of FQDN for that target. Each name can # include wildcard following glob(7) rules. # alpn_protocols: list of ALPN protocols for that target, see: # https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids # # if both sni_hostnames AND alpn_protocols are specified, both must match # # if neither are set, it is just checked whether this is the TLS protocol or not # # Obviously set the most specific probes # first, and if you use TLS with no ALPN/SNI # set it as the last TLS probe # regex: # regex_patterns: list of patterns to match for # that target. # # You can specify several of 'regex' and 'tls'. # # If you want to filter on incoming IP addresses, you can # use libwrap which will use /etc/hosts.allow and # /etc/hosts.deny. protocols: ( { name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; keepalive: true; fork: true; tfo_ok: true }, # UNIX socket to a local NGINX. The socket name is in 'host'; 'port' is necessary but not used. { name: "http"; is_unix: true; host: "/tmp/nginx.sock"; port: ""; }, # match BOTH ALPN/SNI { name: "tls"; host: "localhost"; port: "5223"; alpn_protocols: [ "xmpp-client" ]; sni_hostnames: [ "im.somethingelse.net" ]; log_level: 0; tfo_ok: true }, # just match ALPN { name: "tls"; host: "localhost"; port: "443"; alpn_protocols: [ "h2", "http/1.1", "spdy/1", "spdy/2", "spdy/3" ]; log_level: 0; tfo_ok: true }, { name: "tls"; host: "localhost"; port: "xmpp-client"; alpn_protocols: [ "xmpp-client" ]; log_level: 0; tfo_ok: true }, # just match SNI { name: "tls"; host: "localhost"; port: "993"; sni_hostnames: [ "mail.rutschle.net", "mail.englishintoulouse.com" ]; log_level: 0; tfo_ok: true }, { name: "tls"; host: "localhost"; port: "xmpp-client"; sni_hostnames: [ "im.rutschle.net", "im.englishintoulouse.com" ]; log_level: 0; tfo_ok: true }, # Let's Encrypt (tls-alpn-* challenges) { name: "tls"; host: "localhost"; port: "letsencrypt-client"; alpn_protocols: [ "acme-tls/1" ]; log_level: 0;}, # catch anything else TLS { name: "tls"; host: "localhost"; port: "443"; tfo_ok: true }, # Forward UDP { name: "regex"; host: "localhost"; is_udp: true; port: "123"; udp_timeout: 20; # Time after which the "connection" is forgotten regex_patterns: [ "hello" ]; }, # Forward Teamspeak3 (Voice only) { name: "teamspeak"; host: "localhost"; is_udp: true; port: "9987"; }, # Forward IETF QUIC-50 ("Q050" -> "\x51\x30\x35\x30") # Remember that the regex needs to be adjusted for every supported QUIC version. { name: "regex"; host: "localhost"; is_udp: true; port: "4433"; regex_patterns: [ "\x51\x30\x35\x30" ]; }, # Regex examples -- better use the built-in probes for real-world use! # OpenVPN { name: "regex"; host: "localhost"; port: "1194"; regex_patterns: [ "^\x00[\x0D-\xFF]$", "^\x00[\x0D-\xFF]\x38" ]; }, # Jabber { name: "regex"; host: "localhost"; port: "5222"; regex_patterns: [ "jabber" ]; minlength: 60; # Won't even try to match the regex if we don't have that many bytes }, # Catch-all (but better use 'anyprot') { name: "regex"; host: "localhost"; port: "443"; regex_patterns: [ "" ]; }, # Where to connect in case of timeout (defaults to ssh) { name: "timeout"; service: "daytime"; host: "localhost"; port: "daytime"; } ); # Optionally, specify to which protocol to connect in case # of timeout (defaults to "ssh"). # You can timeout to any arbitrary address by setting an # entry in 'protocols' named "timeout". # This enables you to set a tcpd service name for this # protocol too. on-timeout: "timeout"; sslh-2.3.1/gap.c000066400000000000000000000054111515234404100134010ustar00rootroot00000000000000/* gap.c: gap, a simple, dynamically-growing array of pointers that never shrinks # Copyright (C) 2021 Yves Rutschle # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either # version 2 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 General Public License for more # details. # # The full text for the General Public License is here: # http://www.gnu.org/licenses/gpl.html */ #include #include #include #include #include "sslh-conf.h" #include "gap.h" /* Allocate one page-worth of elements */ static int gap_len_alloc(int elem_size) { return getpagesize() / elem_size; } /* Creates a new gap at least `len` big, all pointers are initialised at NULL */ gap_array* gap_init(int len) { gap_array* gap = malloc(sizeof(*gap)); if (!gap) return NULL; memset(gap, 0, sizeof(*gap)); int elem_size = sizeof(gap->array[0]); gap->len = gap_len_alloc(elem_size); if (gap->len < len) gap->len = len; gap->array = malloc(gap->len * elem_size); if (!gap->array) { free(gap); return NULL; } for (int i = 0; i < gap->len; i++) gap->array[i] = NULL; return gap; } void gap_set_hardlimit(gap_array* gap, int index) { gap->hardlimit = index; } int gap_extend(gap_array* gap) { int elem_size = sizeof(gap->array[0]); int new_length = gap->len + gap_len_alloc(elem_size); void** new = realloc(gap->array, new_length * elem_size); if (!new) return -1; gap->array = new; for (int i = gap->len; i < new_length; i++) { gap->array[i] = NULL; } gap->len = new_length; return 0; } void gap_destroy(gap_array* gap) { free(gap->array); free(gap); } /* In gap, find element pointing to ptr, then shift the rest of the array that * is considered len elements long. * A poor man's list, if you will. Currently only used to remove probing * connections, so it only copies a few pointers at most. * Returns: * -1 if ptr was not found * -2 if `len` is inconsistent with gap->len (i.e. trying to shift beyond the * end of the array) * */ int gap_remove_ptr(gap_array* gap, void* ptr, int len) { int start, i; for (i = 0; i < len; i++) if (gap->array[i] == ptr) break; if (i < len) start = i; else return -1; if (gap->len < len) return -2; for (i = start; i < len - 1; i++) { gap->array[i] = gap->array[i+1]; } return 0; } sslh-2.3.1/gap.h000066400000000000000000000026601515234404100134110ustar00rootroot00000000000000#ifndef GAP_H #define GAP_H typedef struct gap_array gap_array; gap_array* gap_init(int len); void gap_set_hardlimit(gap_array* ga, int index); static void* gap_get(gap_array* gap, int index); static int gap_set(gap_array* gap, int index, void* ptr); void gap_destroy(gap_array* gap); int gap_remove_ptr(gap_array* gap, void* ptr, int len); /* Private declarations to allow inlining. * Don't assume my implementation. */ typedef struct gap_array { int len; /* Number of elements in array (corresponds to the number of pages allocated) */ int hardlimit; /* Maximum index allowed after which sets will fail; 0 means no limit */ void** array; } gap_array; int gap_extend(gap_array* gap); static inline int __attribute__((unused)) gap_set(gap_array* gap, int index, void* ptr) { if (gap->hardlimit && (index > gap->hardlimit)) return -1; while (index >= gap->len) { int res = gap_extend(gap); if (res == -1) return -1; } gap->array[index] = ptr; return 0; } static inline void* __attribute__((unused)) gap_get(gap_array* gap, int index) { /* sslh-ev routinely reads before it writes. It's not clear if it should be * its job to check the length (and add a gap_getlen()), or if it should be * gap_get()'s job. This will do for now */ if (index >= gap->len) return NULL; if (gap->hardlimit && (index > gap->hardlimit)) return NULL; return gap->array[index]; } #endif sslh-2.3.1/genver.sh000077500000000000000000000027111515234404100143130ustar00rootroot00000000000000#! /bin/sh if [ ${#} -eq 1 ] && [ "x$1" = "x-r" ]; then # release text only QUIET=1 else QUIET=0 fi if [ ! -d .git ] || ! `(git status | grep -q "On branch") 2> /dev/null`; then # If we don't have git, we can't work out what # version this is. It must have been downloaded as a # zip file. # If downloaded from the release page, the directory # has the version number. release=`pwd | sed s/.*sslh-// | grep "[[:digit:]]"` if [ "x$release" = "x" ]; then # If downloaded from the head, GitHub creates the # zip file with all files dated from the last # change: use the Makefile's modification time as a # release number release=head-`perl -MPOSIX -e 'print strftime "%Y-%m-%d",localtime((stat "Makefile")[9])'` fi fi if [ -d .git ] && head=`git rev-parse --verify HEAD 2>/dev/null`; then # generate the version info based on the tag release=`(git describe --tags || git --describe || git describe --all --long) \ 2>/dev/null | tr -s '/' '-' | tr -d '\n'` # Are there uncommitted changes? git update-index --refresh --unmerged > /dev/null if git diff-index --name-only HEAD | grep -v "^scripts/package" \ | read dummy; then release="$release-dirty" fi fi if [ $QUIET -ne 1 ]; then printf "#ifndef VERSION_H \n" printf "#define VERSION_H \n\n" printf "#define VERSION \"$release\"\n" printf "#endif\n" else printf "$release\n" fi sslh-2.3.1/hash.c000066400000000000000000000135571515234404100135670ustar00rootroot00000000000000/* * a fixed-sized hash * # Copyright (C) 2022 Yves Rutschle # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either # version 2 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 General Public License for more # details. # # The full text for the General Public License is here: # http://www.gnu.org/licenses/gpl.html # # */ /* * The hash is open-addressing, linear search, robin-hood insertion, with * backward shift deletion. References: * https://codecapsule.com/2013/11/11/robin-hood-hashing/ * https://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/ * This means items are reordered upon insertion and deletion, and the hash * is well-ordered at all times with no tombstones. * * Each pointer is either: * - to a connection struct * - FREE (NULL) if not allocated * * */ #include #include #if HASH_DEBUG #include #include #endif #include "gap.h" #if 0 #define DEBUG 1 #include #endif typedef void* hash_item; typedef struct hash hash; #include "hash.h" static void* const FREE = NULL; /* Define DEBUG adds two functions: * hash_dump() that prints the hash to a file as text * hash_item_print() takes a pointer to a function that prints a hash item * See test suite in hashtest/ for an example * */ #if 0 #define HASH_DEBUG 1 #endif struct hash { int hash_size; /* Max number of items in the hash */ int item_cnt; /* Number of items in the hash */ gap_array* data; hash_make_key_fn hash_make_key; hash_cmp_item_fn cmp_item; #ifdef HASH_DEBUG void (*hash_item_print)(FILE* out, hash_item item); #endif }; static int hash_make_key(hash* h, hash_item item) { return h->hash_make_key(item) % h->hash_size; } hash* hash_init(int hash_size, hash_make_key_fn make_key, hash_cmp_item_fn cmp_item) { hash* h = malloc(sizeof(*h)); if (!h) return NULL; h->hash_size = hash_size; h->item_cnt = 0; h->data = gap_init(hash_size); h->hash_make_key = make_key; h->cmp_item = cmp_item; return h; } /* Return the index following i in h */ static int hash_next_index(hash* h, int i) { return (i + 1) % h->hash_size; } /* Returns the index in h of specified address, -1 if not found * item is an item object that must return the target wanted index and for * which comparison with the searched object will succeed. * */ static int hash_find_index(hash* h, hash_item item) { hash_item cnx; int index = hash_make_key(h, item); int cnt = 0; cnx = gap_get(h->data, index); #ifdef DEBUG fprintf(stderr, "searching %d\n", index); #endif while (cnx != FREE) { if (cnt++ > h->hash_size) return -1; if (!h->cmp_item(cnx, item)) break; index = hash_next_index(h, index); cnx = gap_get(h->data, index); #ifdef DEBUG fprintf(stderr, "searching %d\n", index); #endif } if (cnx == FREE) return -1; return index; } hash_item hash_find(hash* h, hash_item item) { int index = hash_find_index(h, item); if (index == -1) return NULL; hash_item out = gap_get(h->data, index); return out; } /* Returns DIB: distance to initial bucket */ static int distance(int current_index, hash* h, hash_item item) { int wanted_index = hash_make_key(h, item); if (wanted_index <= current_index) return current_index - wanted_index; else return current_index - wanted_index + h->hash_size; } int hash_insertable(hash* h) { return (h->item_cnt < h->hash_size); } int hash_insert(hash* h, hash_item new) { int bubble_wanted_index = hash_make_key(h, new); int index = bubble_wanted_index; gap_array* hash = h->data; if (h->item_cnt == h->hash_size) return -1; hash_item curr_item = gap_get(hash, index); while (curr_item) { if (distance(index, h, curr_item) < distance(index, h, new)) { gap_set(h->data, index, new); #if DEBUG fprintf(stderr, "intermediate insert at %d\n", index); #endif new = curr_item; } index = hash_next_index(h, index); curr_item = gap_get(hash, index); } #if DEBUG fprintf(stderr, "final insert at %d\n", index); #endif gap_set(hash, index, new); h->item_cnt++; return 0; } /* Remove cnx from the hash */ int hash_remove(hash* h, hash_item item) { gap_array* hash = h->data; int index = hash_find_index(h, item); if (index == -1) return -1; /* Tried to remove something that isn't there */ while (1) { int next_index = hash_next_index(h, index); hash_item next = gap_get(h->data, next_index); if ((next == FREE) || (distance(next_index, h, next) == 0)) { h->item_cnt--; gap_set(hash, index, FREE); return 0; } gap_set(hash, index, next); index = hash_next_index(h, index);; } return 0; } /******************************************************************************/ #if HASH_DEBUG void hash_item_print(hash* h, void fn(FILE*, hash_item)) { h->hash_item_print = fn; } void hash_dump(hash* h, char* filename) { FILE* out = fopen(filename, "w"); if (!out) { perror(filename); exit(1); } fprintf(out, "\n", h->item_cnt); for (int i = 0; i < h->hash_size; i++) { hash_item item = gap_get(h->data, i); fprintf(out, "\t%d:", i); if (item) h->hash_item_print(out, item); else fprintf(out, ""); fprintf(out, "\n"); } fprintf(out, "\n"); fclose(out); } #endif sslh-2.3.1/hash.h000066400000000000000000000017341515234404100135660ustar00rootroot00000000000000#ifndef HASH_H #define HASH_H /* You will need to typedef a pointer type to hash_item before including this * .h */ /* Function that returns a key (index) for a given item. The key must be always * the same for an item. It doesn't need to be bounded (hash.c masks it for you) */ typedef int (*hash_make_key_fn)(hash_item item); /* Function that compares two items: returns 0 if they are the same */ typedef int (*hash_cmp_item_fn)(hash_item item1, hash_item item2); hash* hash_init(int hash_size, hash_make_key_fn make_key, hash_cmp_item_fn cmp_item); int hash_insertable(hash* h); /* Is it possible to insert: any space left? */ int hash_insert(hash* h, hash_item new); int hash_remove(hash* h, hash_item item); /* Returns the hash item that matches specification (meaning the * comparison function returns true for cmp(x, item), or NULL if not found */ hash_item hash_find(hash* h, hash_item item); void hash_dump(hash* h, char* filename); /* For development only */ #endif sslh-2.3.1/hashtest/000077500000000000000000000000001515234404100143105ustar00rootroot00000000000000sslh-2.3.1/hashtest/Makefile000066400000000000000000000001451515234404100157500ustar00rootroot00000000000000 CFLAGS=-DHASH_DEBUG -O2 -Wall OBJ=../hash.o ../gap.o htest.o htest: $(OBJ) $(CC) -o htest $(OBJ) sslh-2.3.1/hashtest/delete.tst000066400000000000000000000001001515234404100162750ustar00rootroot00000000000000# Basic delete a 10 aa a 10 ab a 10 ac a 20 ba a 21 bb d 21 bb sslh-2.3.1/hashtest/delete.tst.ref000066400000000000000000000006041515234404100170610ustar00rootroot00000000000000 0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:10:aa 11:10:ab 12:10:ac 13: 14: 15: 16: 17: 18: 19: 20:20:ba 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: sslh-2.3.1/hashtest/delete_at_end.tst000066400000000000000000000001351515234404100176170ustar00rootroot00000000000000# Delete inside a block with nothing after a 10 aa a 10 ab a 12 ac a 13 ad a 14 ae d 14 ae sslh-2.3.1/hashtest/delete_at_end.tst.ref000066400000000000000000000006041515234404100203730ustar00rootroot00000000000000 0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:10:aa 11:10:ab 12:12:ac 13:13:ad 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: sslh-2.3.1/hashtest/delete_below_floor.tst000066400000000000000000000001341515234404100206750ustar00rootroot00000000000000# wrap-around and delete below floor a 2 ba a 30 aa a 30 ab a 30 ac a 30 ad a 2 bb d 30 ab sslh-2.3.1/hashtest/delete_below_floor.tst.ref000066400000000000000000000006001515234404100214460ustar00rootroot00000000000000 0:30:ad 1: 2:2:ba 3:2:bb 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:30:aa 31:30:ac sslh-2.3.1/hashtest/delete_discont.tst000066400000000000000000000001251515234404100200270ustar00rootroot00000000000000# delete in a discontinuous block a 10 aa a 11 ab a 12 ac a 14 ad a 10 bc d 11 ab sslh-2.3.1/hashtest/delete_discont.tst.ref000066400000000000000000000006041515234404100206040ustar00rootroot00000000000000 0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:10:aa 11:10:bc 12:12:ac 13: 14:14:ad 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: sslh-2.3.1/hashtest/delete_empty.tst000066400000000000000000000001621515234404100175230ustar00rootroot00000000000000# Delete an unexisting element. And on an empty hash a 10 aa d 10 ab d 12 bc # Empty for real d 10 aa d 10 aa sslh-2.3.1/hashtest/delete_empty.tst.ref000066400000000000000000000006141515234404100203000ustar00rootroot00000000000000 0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: sslh-2.3.1/hashtest/delete_full.tst000066400000000000000000000004671515234404100173370ustar00rootroot00000000000000# delete on a full hash # First, fill the hash :-) a 0 aa a 1 ab a 2 ac a 3 ad a 4 ae a 5 af a 6 ag a 7 ah a 8 ai a 9 af a 10 ba a 11 bb a 12 bc a 13 bd a 14 be a 15 bf a 16 bg a 17 bh a 18 bi a 19 bj a 20 ca a 21 cb a 22 cd a 23 ce a 24 cf a 25 cg a 26 ch a 27 ci a 28 cj a 29 ck a 30 da a 31 db d 21 cb sslh-2.3.1/hashtest/delete_full.tst.ref000066400000000000000000000005051515234404100201030ustar00rootroot00000000000000 0:0:aa 1:1:ab 2:2:ac 3:3:ad 4:4:ae 5:5:af 6:6:ag 7:7:ah 8:8:ai 9:9:af 10:10:ba 11:11:bb 12:12:bc 13:13:bd 14:14:be 15:15:bf 16:16:bg 17:17:bh 18:18:bi 19:19:bj 20:20:ca 21: 22:22:cd 23:23:ce 24:24:cf 25:25:cg 26:26:ch 27:27:ci 28:28:cj 29:29:ck 30:30:da 31:31:db sslh-2.3.1/hashtest/delete_middle.tst000066400000000000000000000002101515234404100176150ustar00rootroot00000000000000# Delete inside a block with something discontinuous a 10 aa a 10 ab a 12 ac a 13 ad a 14 ae # ab shifts, ac and next doesn't d 10 aa sslh-2.3.1/hashtest/delete_middle.tst.ref000066400000000000000000000006041515234404100203770ustar00rootroot00000000000000 0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:10:ab 11: 12:12:ac 13:13:ad 14:14:ae 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: sslh-2.3.1/hashtest/delete_wrap.tst000066400000000000000000000001461515234404100173400ustar00rootroot00000000000000# Basic delete when wrapping, between wrap and floor a 30 aa a 30 ab a 30 ac a 30 ba a 30 bb d 30 ac sslh-2.3.1/hashtest/delete_wrap.tst.ref000066400000000000000000000006041515234404100201120ustar00rootroot00000000000000 0:30:ba 1:30:bb 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:30:aa 31:30:ab sslh-2.3.1/hashtest/delete_wrap_at_end.tst000066400000000000000000000002021515234404100206430ustar00rootroot00000000000000# Delete inside a block with wrapping, with something after a 30 aa a 30 ab a 30 ac a 1 ad a 3 ae # shift ad but not ae d 14 ae sslh-2.3.1/hashtest/delete_wrap_at_end.tst.ref000066400000000000000000000006001515234404100214200ustar00rootroot00000000000000 0:30:ac 1:1:ad 2: 3:3:ae 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:30:aa 31:30:ab sslh-2.3.1/hashtest/delete_wrap_below_floor.tst000066400000000000000000000001201515234404100217210ustar00rootroot00000000000000# delete before wrap a 30 aa a 30 ab a 30 ac a 30 ad # shift ac and ad d 30 ab sslh-2.3.1/hashtest/delete_wrap_below_floor.tst.ref000066400000000000000000000006061515234404100225050ustar00rootroot00000000000000 0:30:ad 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:30:aa 31:30:ac sslh-2.3.1/hashtest/delete_wrap_discont.tst000066400000000000000000000002121515234404100210550ustar00rootroot00000000000000# Delete with wrapping in discontinuous group a 30 aa a 30 ab a 30 ac a 31 ad a 2 ba a 3 bb # shift ac and ad but not ba and bb d 30 ab sslh-2.3.1/hashtest/delete_wrap_discont.tst.ref000066400000000000000000000006001515234404100216310ustar00rootroot00000000000000 0:31:ad 1: 2:2:ba 3:3:bb 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:30:aa 31:30:ac sslh-2.3.1/hashtest/htest000077500000000000000000000415501515234404100153720ustar00rootroot00000000000000ELF> @¨;@8 @@@@ØØX X y y  ””Ð-Ð=Ð=°Àà-à=à=àà888 XXXDDSåtd888 PåtdÀ À À ¤¤QåtdRåtdÐ-Ð=Ð=00/lib64/ld-linux-x86-64.so.2GNU€ÀGNU% ÝŽ“DΫâÞG; 7¿©n¤GNU�ÑeÎm9ò‹3À Tsz�ŽLÜ ,$ ‡ë d"E€@getpagesizeperrorfreeexitfopenreallocmalloc__libc_start_mainstderrfprintf__isoc99_fscanf__cxa_finalizefclosememsetfputcfwritestrcmplibc.so.6GLIBC_2.7GLIBC_2.34GLIBC_2.2.5_ITM_deregisterTMCloneTable__gmon_start___ITM_registerTMCloneTable•ii Ÿ´‘–©ui ´Ð=Ø=Àx@x@À?È?Ð? Ø?à?€@@@@@ @(@0@ 8@ @@ H@ P@X@`@h@HƒìH‹Å/H…ÀtÿÐHƒÄÃÿ5Ê/ÿ%Ì/@ÿ%Ê/héàÿÿÿÿ%Â/héÐÿÿÿÿ%º/héÀÿÿÿÿ%²/hé°ÿÿÿÿ%ª/hé ÿÿÿÿ%¢/hé�ÿÿÿÿ%š/hé€ÿÿÿÿ%’/hépÿÿÿÿ%Š/hé`ÿÿÿÿ%‚/h éPÿÿÿÿ%z/h é@ÿÿÿÿ%r/h é0ÿÿÿÿ%j/h é ÿÿÿÿ%b/h éÿÿÿÿ%Ê.f�AWH�7 AVAUATUH‰õH�5ö S‰û¿ Hƒì(èuH�5î H‰$H‰Ç1Àè ƒût'H‹ /º'¾H�=è~ÿÿÿ¿èdÿÿÿH‹]H‹EH�5—H‰ßH‰D$èÿÿÿI‰ÄH…À„TE1ÿL�t$L�-|¿AƒÇèÏþÿÿÆD$ H‰ÃH�hL‰ò1ÀI‰èH‰ÙL‰îL‰çèJþÿÿ�Pƒâûuâƒøÿ„žL$D‹I‰éD‰úH‹=d.H�51Àèfþÿÿ¶D$ %d: %d:%sraction %d: %c %d %s inserting [%s] at %d removing [%s] at %d searching searching %d[%s]: %p Usage: htest