pax_global_header00006660000000000000000000000064144041425050014511gustar00rootroot0000000000000052 comment=b781dd6b03f45e2e7c31939f9c034d568992a27e ruby-magic-0.6.0/000077500000000000000000000000001440414250500135535ustar00rootroot00000000000000ruby-magic-0.6.0/.editorconfig000066400000000000000000000004301440414250500162250ustar00rootroot00000000000000root = true [*] charset = utf-8 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true [{*.rb,*.rake,Rakefile}] indent_style = space indent_size = 2 [{*.yml,*.yaml}] indent_style = space indent_size = 2 [Vagrantfile] indent_size = 2 indent_style = space ruby-magic-0.6.0/.gitattributes000066400000000000000000000003271440414250500164500ustar00rootroot00000000000000* text=auto *.c eol=lf linguist-language=c *.h eol=lf linguist-language=c *.rb eol=lf diff=ruby *.gemspec eol=lf diff=ruby *.sh eol=lf Guardfile eol=lf diff=ruby Rakefile eol=lf diff=ruby .github/ export-ignore ruby-magic-0.6.0/.gitignore000066400000000000000000000007051440414250500155450ustar00rootroot00000000000000._* *~ *.[568avq] [568avq].out core *.o *.a *.obj *.elf *.dylib *.[as]o *.[568ao] *.bundle *.rbc *.exe *.exe~ *.com *.dll *.sw[a-z] .*.sw[a-z] *.[7gx]z *.[jrt]ar *.zip *.gem *.rej *.orig *.log *.test *.out .git .bundle Gemfile.lock .gems .rbenv .rbenv-gemsets .ruby-version .ruby-gemset .DS_Store .DS_Store? .AppleDouble .LSOverride .Spotlight-* .Trash* .vagrant .direnv .envrc Icon? Icon[ ] .idea .vscode pkg ports tmp ext/magic/share/ ruby-magic-0.6.0/.gitlab-ci.yml000066400000000000000000000017771440414250500162230ustar00rootroot00000000000000.test-template: &test cache: paths: - vendor/ruby before_script: - gem install bundler --no-document - bundle config set --local path 'vendor/bundle' - bundle config set --local without 'development' - bundle install -j $(nproc) - ruby -v # Print out ruby version for debugging script: - bundle exec rake compile - bundle exec rake test default: image: "ruby:${RUBY_VERSION}" rspec: parallel: matrix: - RUBY_VERSION: ["2.6", "2.7", "3.0"] <<: *test truffleruby: image: "flavorjones/truffleruby:buster" allow_failure: true <<: *test gems: services: - docker:${DOCKER_VERSION}-dind variables: DOCKER_VERSION: "20.10.1" DOCKER_DRIVER: overlay2 DOCKER_HOST: tcp://docker:2375 DOCKER_TLS_CERTDIR: "" RUBY_VERSION: "2.7" stage: test when: manual <<: *test script: - apt update && apt-get install -y docker.io - bundle exec rake gem:native artifacts: paths: - pkg/*.gem ruby-magic-0.6.0/.mailmap000066400000000000000000000003561440414250500152000ustar00rootroot00000000000000Krzysztof Wilczyński kwilczynski Krzysztof Wilczyński kwilczynski Krzysztof Wilczyński Krzysztof Wilczyński ruby-magic-0.6.0/.rubocop.yml000066400000000000000000000001601440414250500160220ustar00rootroot00000000000000AllCops: NewCops: enable Include: - '**/*.rb' SuggestExtensions: false Layout/LineLength: Max: 120 ruby-magic-0.6.0/AUTHORS000066400000000000000000000000641440414250500146230ustar00rootroot00000000000000Krzysztof Wilczyński (@kwilczynski) ruby-magic-0.6.0/CHANGELOG.md000066400000000000000000000141571440414250500153740ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [0.6.0] - 2023-03-14 ### Added - Add --with-magic-flags option for building libmagic. ## [0.5.5] - 2023-01-23 ### Changed - Update to latest libmagic version (5.44). - Update mini_portile2 to version 2.8.0. - Update RDoc in the Ruby gemspec and the Rake task. - Update PKG_CONFIG_PATH paths to include more platforms. - Add new library flag called MAGIC_NO_COMPRESS_FORK. - Add assert to ensure that the internal object is initialised. - Reduce scope of some string variables. - Relax rake-compiler and rake-compiler-dock dependencies. - Only enable support for the GC compaction when there is platform support. - Remove workaround for linux build per RCD. - Work around Ruby 3.1 pkg_config limitations. ## [0.5.4] - 2022-01-28 ### Added - Added a pessimistic version pin of `rake-compiler` and `rake-compiler-dock` versions in `Gemfile`. ### Changed - Removed _RubyGems_ version pin from the Gem gemspec file. - Simplified the `.gitlab-ci.yml` used to run _CI_ remotely on _GitLab_. - Enabled verbose log when cross-compiling a native Ruby Gem using the `rake-compiler-dock` Gem. This allows for commands run to be shown. ### Deprecated - Retired support for Ruby version 2.5 as it has reached _End of Life_ (EOL). ## [0.5.3] - 2021-12-22 ### Fixed - ext: load C extension files from non-native gems via "require" ## [0.5.2] - 2021-11-20 - No changes ## [0.5.1] - 2021-11-20 ### Fixed - Check for pkg-config when building static libraries. ## [0.5.0] - 2021-09-30 ### Added - Introduce support for building native gems. ### Changed - Relax mini_portile2 dependency. - Use RB_ALLOC() over calling ruby_xmalloc() directly - Address warnings reported by cppcheck. - Address code style that checkpatch.pl script reported. - Fix how flags are set for the open() function. - Clean up type definitions. - Add alias Magic::mime_type for Magic::mime. - Make magic_set_flags() return void as its return value was never used. ### Fixed - Fix truffleruby test failure - Fix --use-system-libraries not working with Rake install ## [0.2.0] - 2015-03-25 ### Added - Added _Gemnasium_, plus _Coveralls_ and _Code Climate_ integration (and hence improved code test coverage). - Added functionality to handle releasing the `GVL` for any _file_ and/or _I/O_ operations. - Added ability to `Magic#flags_array` to return name of each flag that is set. - Added naïve synchronization via `Mutex#lock` and `Mutex#unlock` methods to make interactions with _libmagic_ more thread-safe. - Added ability for _Travis CI_ test against multiple versions of vanilla _libmagic_. - Added _LLVM_ (`clang`) compiler to build with to _Travis CI_, and fixed various issues reported by `clang` compiler during build-time. - Added ability for `Magic#load` to take nil as valid argument. - Added support for the `MAGIC_CONTINUE` flag so that `Magic#file`, `Magic#buffer` and `Magic#descriptor` methods will return an _array_ for multiple results when appropriate. - Added rudimentary `Vagrantfile` that can be used to build a development environment. - Added the `Guard` Ruby gem for convenience, with an appropriate `Guardfile`. ### Changed - Re-factored the _API_ and cleaned up small portions of code and documentation. - Changed `Magic#version_array` and `Magic#version_string` methods to be a singleton methods. - Renamed the `Magic#flags_array` method to `Magic#flags_to_a`. - Changed the `Magic::new` method, so that it accepts an array of paths from which to load the _Magic_ database. - Moved integration with _File_ and _String_ core classes into separate namespace. - Changed the behavior not to catch the generic `Magic::Error`, plus always to raise on errors coming from _libmagic_. This is to make it more aligned with the standard library, where _file_ and _I/O_ related errors would raise an appropriate exception. - Changed behavior consistent among various versions of _libmagic_ adhering to the _POSIX_ standard. This concerns the following _IEEE 1003.1_ standards: - http://pubs.opengroup.org/onlinepubs/007904975/utilities/file.html - http://pubs.opengroup.org/onlinepubs/9699919799/utilities/file.html ### Fixed - Fixed formatting and white spaces. - Fixed _Travis CI_ build against _Rubinius_. - Fixed setting of global `errno` value to avoid race conditions. - Fixed issue with _libmagic_'s regular expression (`regex`) library not working with _UTF-8_ (or any other wide-character encoding). - Fixed build to make it work with _C++_ compilers. - Fixed any _C90_ standard related build-time warnings. - Fixed version number to comply with _Semantic Versioning 2_ (http://semver.org/). ### Deprecated - Retired support for Ruby 1.8.x (no support for _MRI_, _Ruby Enterprise Edition_ and _Rubinius_). - Retired testing with Ruby _1.9.2_ and _2.1.0_, and added _2.2.0_ on _Travis CI_. - Removed forward declaration of `errno` as it's not needed on systems with modern _C/C++_ libraries and compilers. - Removed the `-Wl,--no-undefined` option from `LDFLAGS`, as they might break on some systems. ## [0.1.0] - 2014-03-21 ### Added - First version of Magic. [Unreleased]: https://github.com/kwilczynski/ruby-magic/compare/v0.5.4...HEAD [0.5.4]: https://github.com/kwilczynski/ruby-magic/compare/v0.5.3...v0.5.4 [0.5.3]: https://github.com/kwilczynski/ruby-magic/compare/v0.5.2...v0.5.3 [0.5.2]: https://github.com/kwilczynski/ruby-magic/compare/v0.5.1...v0.5.2 [0.5.1]: https://github.com/kwilczynski/ruby-magic/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/kwilczynski/ruby-magic/compare/v0.4.0...v0.5.0 [0.4.0]: https://github.com/kwilczynski/ruby-magic/compare/v0.3.2...v0.4.0 [0.3.2]: https://github.com/kwilczynski/ruby-magic/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/kwilczynski/ruby-magic/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/kwilczynski/ruby-magic/compare/v0.2.0...v0.3.0 [0.2.0]: https://github.com/kwilczynski/ruby-magic/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/kwilczynski/ruby-magic/compare/29e6c26...v0.1.0 ruby-magic-0.6.0/CODE_OF_CONDUCT.md000066400000000000000000000062241440414250500163560ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at kw@linux.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ ruby-magic-0.6.0/CONTRIBUTING.md000066400000000000000000000000311440414250500157760ustar00rootroot00000000000000See [README](README.md). ruby-magic-0.6.0/CONTRIBUTORS.md000066400000000000000000000015331440414250500160340ustar00rootroot00000000000000# Ruby Magic contributors We thank all of our [contributors][1]! The following is a list of people who have contributed at some point to the code of Ruby Magic. They are hereby acknowledged and collectively identified as "The Ruby Magic Authors". Copyright is held by the original contributor according to the versioning history; see [LICENSE](LICENSE) file. - Antonio Terceiro ([@terceiro](https://github.com/terceiro)) - Igor Victor ([@gogainda](https://github.com/gogainda)) - John Hawthorn ([@jhawthorn](https://github.com/jhawthorn)) - Lars Kanis ([@larskanis](https://github.com/larskanis)) - Mike Dalessio ([@flavorjones](https://github.com/flavorjones)) - Shinya Maeda ([@dosuken123](https://github.com/dosuken123)) - Stan Hu ([@stanhu](https://github.com/stanhu)) [1]: https://github.com/kwilczynski/ruby-magic/graphs/contributors "Contributors" ruby-magic-0.6.0/COPYRIGHT000066400000000000000000000000521440414250500150430ustar00rootroot00000000000000Copyright 2013-2022 Krzysztof Wilczyński ruby-magic-0.6.0/Gemfile000066400000000000000000000004441440414250500150500ustar00rootroot00000000000000source 'https://rubygems.org' gemspec gem 'rake' gem 'rake-compiler', '~> 1.2' gem 'rake-compiler-dock', '~> 1.2' gem 'rdoc' group :test do gem 'mocha' gem 'rubocop', require: false gem 'test-unit' end group :development do gem 'guard' gem 'guard-bundler' gem 'guard-rake' end ruby-magic-0.6.0/Guardfile000066400000000000000000000004061440414250500154000ustar00rootroot00000000000000guard 'bundler' do watch('Gemfile') end guard 'rake', task: 'compile' do watch(%r{^ext/(.+)\.(c|h)}) watch(%r{^lib/(.+)\.rb}) end guard 'rake', task: 'test' do watch(%r{^ext/(.+)\.(c|h)}) watch(%r{^lib/(.+)\.rb}) watch(%r{^test/test_(.+)\.rb}) end ruby-magic-0.6.0/LICENSE000066400000000000000000000261361440414250500145700ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ruby-magic-0.6.0/MAINTAINERS000066400000000000000000000002201440414250500152420ustar00rootroot00000000000000Krzysztof Wilczyński (@kwilczynski) Mike Dalessio (@flavorjones) Stan Hu (@stanhu) ruby-magic-0.6.0/NOTICE000066400000000000000000000531601440414250500144640ustar00rootroot00000000000000Ruby Magic Copyright 2013-2022 Krzysztof Wilczyński This product relies on and/or includes a number of Open Source software projects, including those that have been modified. * file file(1) Command and the libmagic(3) library. LICENSE: BSD, CDDL HOMEPAGE: http://darwinsys.com/file Copyright (c) Ian F. Darwin 1986, 1987, 1989, 1990, 1991, 1992, 1994, 1995. Software written by Ian F. Darwin and others; maintained 1994- Christos Zoulas. This software is not subject to any export provision of the United States Department of Commerce, and may be exported to any country or planet. 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 immediately at the beginning of the file, without modification, 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 AUTHOR 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 AUTHOR 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. * guard Guard is a command line tool to easily handle events on file system modifications. LICENSE: MIT HOMEPAGE: https://github.com/guard/guard Copyright (c) 2009-2016 Thibaud Guillaume-Gentil Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * guard-bundler Guard::Bundler automatically install/update your gem bundle when needed. LICENSE: MIT HOMEPAGE: https://github.com/guard/guard-bundler Copyright (c) 2010-2014 Yann Lugrin, Rémy Coutable Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * guard-rake guard-rake runs a rake task when files change. LICENSE: MIT HOMEPAGE: https://github.com/rubyist/guard-rake Copyright (c) 2011 Scott Barron Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * mini_portile2 mini_portile and mini_portile2 - Simple autoconf builder for developers LICENSE: MIT HOMEPAGE: https://github.com/flavorjones/mini_portile Copyright (c) 2011-2016 Luis Lavena and Mike Dalessio Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * mocha Mocha is a mocking and stubbing library for Ruby. LICENSE: The Ruby License, MIT HOMEPAGE: https://mocha.jamesmead.org/ Copyright Revieworld Ltd. 2006 Ruby is copyrighted free software by Yukihiro Matsumoto . You can redistribute it and/or modify it under either the terms of the 2-clause BSDL (see the file BSDL), or the conditions below: 1. You may make and give away verbatim copies of the source form of the software without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may modify your copy of the software in any way, provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or by allowing the author to include your modifications in the software. b) use the modified software only within your corporation or organization. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 3. You may distribute the software in object code or binary form, provided that you do at least ONE of the following: a) distribute the binaries and library files of the software, together with instructions (in the manual page or equivalent) on where to get the original distribution. b) accompany the distribution with the machine-readable source of the software. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 4. You may modify and include the part of the software into any other software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under these terms. For the list of those files and their copying conditions, see the file LEGAL. 5. The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the copyright of the software, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this software. 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * rake A make-like build utility for Ruby. LICENSE: MIT HOMEPAGE: https://ruby.github.io/rake Copyright (c) Jim Weirich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * rake-compiler Provide a standard and simplified way to build and package Ruby C and Java extensions using Rake as glue. LICENSE: MIT HOMEPAGE: https://github.com/rake-compiler/rake-compiler Copyright (c) 2008-2011 Luis Lavena. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * rake-compiler-dock Easy to use and reliable cross compiler environment for building Windows, Linux, Mac and JRuby binary gems. LICENSE: MIT HOMEPAGE: https://github.com/rake-compiler/rake-compiler-dock Copyright (c) 2015 Lars Kanis MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * rdoc RDoc - Ruby Documentation System. LICENSE: The Ruby License, GPL-2.0 HOMEPAGE: https://ruby.github.io/rdoc RDoc is copyrighted free software. You can redistribute it and/or modify it under either the terms of the GPL version 2 (see the file GPL), or the conditions below: 1. You may make and give away verbatim copies of the source form of the software without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may modify your copy of the software in any way, provided that you do at least ONE of the following: a. place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or by allowing the author to include your modifications in the software. b. use the modified software only within your corporation or organization. c. give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d. make other distribution arrangements with the author. 3. You may distribute the software in object code or binary form, provided that you do at least ONE of the following: a. distribute the binaries and library files of the software, together with instructions (in the manual page or equivalent) on where to get the original distribution. b. accompany the distribution with the machine-readable source of the software. c. give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d. make other distribution arrangements with the author. 4. You may modify and include the part of the software into any other software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under these terms. For the list of those files and their copying conditions, see the file LEGAL. 5. The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the copyright of the software, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this software. 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * rubocop LICENSE: MIT HOMEPAGE: https://github.com/rubocop-hq/rubocop Copyright (c) 2012-22 Bozhidar Batsov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ruby The Ruby Programming Language. LICENSE: The Ruby License HOMEPAGE: https://www.ruby-lang.org Ruby is copyrighted free software by Yukihiro Matsumoto . You can redistribute it and/or modify it under either the terms of the 2-clause BSDL (see the file BSDL), or the conditions below: 1. You may make and give away verbatim copies of the source form of the software without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may modify your copy of the software in any way, provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or by allowing the author to include your modifications in the software. b) use the modified software only within your corporation or organization. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 3. You may distribute the software in object code or binary form, provided that you do at least ONE of the following: a) distribute the binaries and library files of the software, together with instructions (in the manual page or equivalent) on where to get the original distribution. b) accompany the distribution with the machine-readable source of the software. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 4. You may modify and include the part of the software into any other software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under these terms. For the list of those files and their copying conditions, see the file LEGAL. 5. The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the copyright of the software, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this software. 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * test-unit An xUnit family unit testing framework for Ruby. LICENSE: The Ruby License HOMEPAGE: https://test-unit.github.io test-unit is copyrighted free software by Kouhei Sutou , Ryan Davis and Nathaniel Talbott . You can redistribute it and/or modify it under either the terms of the GPL version 2 (see the file GPL), or the conditions below: 1. You may make and give away verbatim copies of the source form of the software without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may modify your copy of the software in any way, provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or by allowing the author to include your modifications in the software. b) use the modified software only within your corporation or organization. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 3. You may distribute the software in object code or binary form, provided that you do at least ONE of the following: a) distribute the binaries and library files of the software, together with instructions (in the manual page or equivalent) on where to get the original distribution. b) accompany the distribution with the machine-readable source of the software. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 4. You may modify and include the part of the software into any other software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under these terms. For the list of those files and their copying conditions, see the file LEGAL. 5. The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the copyright of the software, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this software. 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ruby-magic-0.6.0/README.md000066400000000000000000000023401440414250500150310ustar00rootroot00000000000000# File Magic in Ruby [![Gem Version](http://badge.fury.io/rb/ruby-magic.svg)](http://badge.fury.io/rb/ruby-magic) [![License](http://img.shields.io/badge/License-Apache%202.0-blue.svg)](http://opensource.org/licenses/Apache-2.0) ## Introduction Provides simple interface to [libmagic][1] for Ruby Programming Language. ## Table of Contents 1. [Contributing](#contributing) 2. [Versioning](#versioning) 3. [Author](#author) 4. [Contributors](#contributors) 4. [Copyright](#copyright) 5. [License](#license) ## Contributing See the [CONTRIBUTING.md](CONTRIBUTING.md) for best practices and instructions on setting up your development environment. ## Versioning This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). For the versions available, see the tags on this repository. ## Author Krzysztof Wilczyński () ## Contributors See the [CONTRIBUTORS.md](CONTRIBUTORS.md) file for a list of contributors to the project. ## Copyright Copyright 2013-2022 Krzysztof Wilczyński ## License This project is licensed under the terms of the Apache License, Version 2.0 license. To view the full license see the included [LICENSE](LICENSE) file. [1]: https://en.wikipedia.org/wiki/File_(command) ruby-magic-0.6.0/Rakefile000066400000000000000000000073441440414250500152300ustar00rootroot00000000000000require 'bundler/gem_tasks' require 'rake' require 'rake/clean' require 'rake/extensiontask' require 'rake/testtask' require 'rdoc/task' require 'rubocop/rake_task' RakeFileUtils.verbose_flag = false CLEAN.include FileList['**/*{.o,.so,.dylib,.bundle}'], FileList['**/extconf.h'], FileList['**/Makefile'], FileList['pkg/'], FileList['ext/magic/share/'] CLOBBER.include FileList['**/tmp'], FileList['**/*.log'], FileList['doc/**'], FileList['tmp/'] CLOBBER.add("ports/*").exclude(%r{ports/archives$}) RUBY_MAGIC_GEM_SPEC = Gem::Specification.load('ruby-magic.gemspec') RDoc::Task.new do |d| d.title = 'File Magic in Ruby' d.main = 'README.md' d.options << '--line-numbers' d.rdoc_dir = 'doc/rdoc' d.rdoc_files.include FileList['ext/**/*.c', 'lib/**/*.rb'] d.rdoc_files.include.add(%w[ README.md ]) end Rake::TestTask.new do |t| t.test_files = FileList['test/**/test_*'] t.warning = true end RuboCop::RakeTask.new('lint') do |t| t.patterns = FileList['lib/**/*.rb', 'test/**/*.rb'] t.fail_on_error = false end Gem::PackageTask.new(RUBY_MAGIC_GEM_SPEC) do |p| p.need_zip = false p.need_tar = false end CROSS_RUBY_PLATFORMS = ["x86_64-linux", "x86-linux"] CROSS_RUBY_VERSIONS = ["2.6.0", "2.7.0", "3.0.0"].join(":") require "rake_compiler_dock" ENV["RUBY_CC_VERSION"] = CROSS_RUBY_VERSIONS Rake::ExtensionTask.new('magic', RUBY_MAGIC_GEM_SPEC) do |e| e.source_pattern = '*.{c,h}' e.ext_dir = 'ext/magic' e.lib_dir = 'lib/magic' e.cross_compile = true e.cross_config_options << "--enable-cross-build" e.cross_platform = CROSS_RUBY_PLATFORMS e.cross_compiling do |spec| spec.files.reject! { |path| File.fnmatch?('ports/*', path) } spec.files.reject! { |path| File.fnmatch?('patches/*', path) } spec.dependencies.reject! { |dep| dep.name=='mini_portile2' } db_glob = "ext/magic/share/*.mgc" raise "magic files are not present at #{db_glob}" if Dir[db_glob].empty? Dir[db_glob].each { |db| spec.files << db } end end namespace "gem" do def gem_builder(platform) # use Task#invoke because the pkg/*gem task is defined at runtime Rake::Task["native:#{platform}"].invoke Rake::Task["pkg/#{RUBY_MAGIC_GEM_SPEC.full_name}-#{Gem::Platform.new(platform).to_s}.gem"].invoke end CROSS_RUBY_PLATFORMS.each do |platform| desc "build native gem for #{platform} platform" task platform do RakeCompilerDock.sh <<~EOT, platform: platform, verbose: true gem install bundler --no-document && bundle && bundle exec rake gem:#{platform}:builder MAKE='nice make -j`nproc`' EOT end namespace platform do desc "build native gem for #{platform} platform (guest container)" task "builder" do gem_builder(platform) end end end desc "build all native gems" task "native" => CROSS_RUBY_PLATFORMS end def add_file_to_gem(relative_source_path) dest_path = File.join(gem_build_path, relative_source_path) dest_dir = File.dirname(dest_path) mkdir_p dest_dir unless Dir.exist?(dest_dir) rm_f dest_path if File.exist?(dest_path) safe_ln relative_source_path, dest_path RUBY_MAGIC_GEM_SPEC.files << relative_source_path end def gem_build_path File.join "pkg", RUBY_MAGIC_GEM_SPEC.full_name end def add_libmagic_and_patches dependencies = YAML.load_file(File.join(File.dirname(__FILE__), "dependencies.yml")) archive = File.join("ports", "archives", "file-#{dependencies["libmagic"]["version"]}.tar.gz") add_file_to_gem archive patches = Dir['patches/**/*.patch'] patches.each { |patch| add_file_to_gem patch } end task gem_build_path do add_libmagic_and_patches end task('default').clear task default: %w[lint test] ruby-magic-0.6.0/VERSION000066400000000000000000000000061440414250500146170ustar00rootroot000000000000000.6.0 ruby-magic-0.6.0/Vagrantfile000066400000000000000000000047761440414250500157560ustar00rootroot00000000000000# A little helper to determine underlying platform. def platform_bits ['x'].pack('P').size * 8 end # Simple provisioning elements. script = %{ #!/bin/bash set -e export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin echo 'Starting provisioning ...' # Avoid the configuration file questions ... cat <<'EOF' | sudo tee /etc/apt/apt.conf.d/99vagrant &>/dev/null DPkg::options { "--force-confdef"; "--force-confnew"; } EOF # Disable need for user interaction ... export DEBIAN_FRONTEND=noninteractive # Update package repositories ... sudo apt-get update &> /dev/null # Install needed build time dependencies ... sudo apt-get install --force-yes -y \ curl \ git \ gawk \ make \ patch \ bison \ flex \ build-essential \ sqlite3 \ libsqlite3-dev \ openssl \ pkg-config \ autoconf \ automake \ autotools-dev \ libffi-dev \ libc6-dev \ libssl-dev \ zlib1g \ zlib1g-dev \ libncurses5-dev \ libreadline6 \ libreadline6-dev \ libltdl-dev \ libyaml-dev \ libxml2-dev \ libxslt1-dev \ libtool \ libtool-doc &> /dev/null # Remove existing "libmagic-dev" package. sudo apt-get remove --purge --force-yes -y libmagic-dev &> /dev/null # Clean up unneeded packages ... { sudo apt-get autoremove --force-yes -y sudo apt-get autoclean --force-yes -y sudo apt-get clean --force-yes -y } &> /dev/null # Download and install "rvm" for local user. { cat <<'EOS' | sudo -u vagrant -- bash -s curl -s -k -L https://rvm.io/mpapis.asc | gpg --import - curl -s -k -L https://get.rvm.io | bash -s stable --ruby EOS } &> /dev/null echo 'All done!' } # Select appropriate Vagrant box per underlying architecture. box = "precise#{platform_bits}" # Virtual Machine name et al. name = "ruby-magic-#{box}" Vagrant.configure("2") do |config| config.ssh.forward_agent = true config.vm.define name.to_sym do |machine| machine.vm.box = "hashicorp/#{box}" machine.vm.box_check_update = false machine.vm.hostname = name machine.vm.provider :virtualbox do |vb| vb.name = name vb.gui = false vb.customize ['modifyvm', :id, '--memory', '384', '--cpus', '1', '--rtcuseutc', 'on', '--natdnshostresolver1', 'on', '--natdnsproxy1', 'on' ] end machine.vm.provision :shell, privileged: false, inline: script end end ruby-magic-0.6.0/checksum/000077500000000000000000000000001440414250500153555ustar00rootroot00000000000000ruby-magic-0.6.0/checksum/ruby-magic-0.2.0.gem.SHA256000066400000000000000000000001271440414250500214100ustar00rootroot00000000000000785ad89e578509480dd858c0d670915cd73b302b036b393f8579b177f30f287b ruby-magic-0.2.0.gem ruby-magic-0.6.0/checksum/ruby-magic-0.2.0.gem.SHA256.sig000066400000000000000000000010661440414250500221740ustar00rootroot000000000000003!}]|||dv=4_; |dv=4P@{Pm!ɕۤ' *tW67uMuבCKα!d>4FB(ϒl݌E*Dia uOvOma&B(-n=tWW<=_Jav%tCy [-3T})OI2g8dquF@ +=NUNU0b),N>w99BnGޣ/;&GȁLZނ{딴'd@/g;uC8k# 0 .Vi6~6_@UFLe@o7X`ѯ8գb!bkW$JfSmO̧` 0wEH+*LURte9ItUr݉E*=ٿ:8`wHB=h"']ZҤ/<8múu!ݱ$v|%N-2;B*̎5!`)_2Uruby-magic-0.6.0/checksum/ruby-magic-0.5.4.gem.SHA256000066400000000000000000000001271440414250500214170ustar00rootroot000000000000002c17b185130d10a83791f63a40baa358c4b138af37da3f4dab53690121c421d5 ruby-magic-0.5.4.gem ruby-magic-0.6.0/checksum/ruby-magic-0.5.4.gem.SHA256.sig000066400000000000000000000013001440414250500221720ustar00rootroot00000000000000XRk9㚊$ҤJd]=S=\`G#SϺ ͓ -L R -- ̌M M-M -ӌSLRL, M SLYd +"t6oU{jj`NceY)9rFKMjEA*i77Ws67Ѷ?mR֗TǙ-KwT?Ҭq:1;.}|xT<`[lO^s2K՗NXQܥ6Ã}?^*Bb\Y6o:Ur!eڭgOuS~g䟋G=qo}ڕ NXîy7ݵ:76Y~ޫ ,xhףٟ%~nft_HE'ӮXvd<%Rӣdw;?^qoVc:Ţ+܋W_Fs)7 aqqAј,!۹z3߾ vNTczqxc\ݓ/qe;܊W; fTvɖ1[~\Hxסl,5`S>TwasoJ۲Y/\7/YҶu%9L~0d^5x_}ϰ>dS8uon0< ruby-magic-0.6.0/dependencies.yml000066400000000000000000000020251440414250500167230ustar00rootroot00000000000000libmagic: version: "5.44" sha256: "3751c7fba8dbc831cb8d7cc8aff21035459b8ce5155ef8b0880a27d028475f3b" # Manually verified checksum: # # $ gpg --verify file-5.44.tar.gz.asc file-5.44.tar.gz # gpg: Signature made Tue 27 Dec 2022 03:27:03 JST # gpg: using DSA key BE04995BA8F90ED0C0C176C471112AB16CB33B3A # gpg: Good signature from "Christos Zoulas (personal key) " [unknown] # gpg: aka "Christos Zoulas (NetBSD key) " [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: BE04 995B A8F9 0ED0 C0C1 76C4 7111 2AB1 6CB3 3B3A # # Using this PGP signature: # # -----BEGIN PGP SIGNATURE----- # # iF0EABECAB0WIQS+BJlbqPkO0MDBdsRxESqxbLM7OgUCY6nndwAKCRBxESqxbLM7 # OiUWAJ9ygauXJ3pohF38SQuLYu+J8qayuwCeIFPcEukUyNuYv04B9FIXkumreI8= # =/CFO # -----END PGP SIGNATURE----- ruby-magic-0.6.0/ext/000077500000000000000000000000001440414250500143535ustar00rootroot00000000000000ruby-magic-0.6.0/ext/magic/000077500000000000000000000000001440414250500154335ustar00rootroot00000000000000ruby-magic-0.6.0/ext/magic/common.h000066400000000000000000000076561440414250500171120ustar00rootroot00000000000000#if !defined(_COMMON_H) #define _COMMON_H 1 #if !defined(_GNU_SOURCE) # define _GNU_SOURCE 1 #endif #if !defined(_BSD_SOURCE) # define _BSD_SOURCE 1 #endif #if !defined(_DEFAULT_SOURCE) # define _DEFAULT_SOURCE 1 #endif #if defined(__cplusplus) extern "C" { #endif #include #include #include #include #include #include #include #include #include #include #include #include #if defined(HAVE_RUBY_IO_H) # include #else # include #endif /* HAVE_RUBY_IO_H */ #define BIT(n) (1 << (n)) #if !defined(UNUSED) # define UNUSED(x) (void)(x) #endif /* UNUSED */ #define ARRAY_SIZE(a) (int)(sizeof(a) / sizeof((a)[0])) #if defined(F_DUPFD_CLOEXEC) # define HAVE_F_DUPFD_CLOEXEC 1 #endif /* F_DUPFD_CLOEXEC */ #if defined(O_CLOEXEC) # define HAVE_O_CLOEXEC 1 #endif /* O_CLOEXEC */ #if defined(POSIX_CLOSE_RESTART) # define HAVE_POSIX_CLOSE_RESTART 1 #endif /* POSIX_CLOSE_RESTART */ #define MAGIC_EXTENSION_SEPARATOR "/" #define MAGIC_CONTINUE_SEPARATOR "\n- " #if !defined(MAGIC_SYSTEM_LIBRARIES) # define MAGIC_STATUS_CHECK(x) x #else # define MAGIC_STATUS_CHECK(x) 1 #endif /* MAGIC_SYSTEM_LIBRARIES */ #if !defined(MAGIC_CUSTOM_CHECK_TYPE) # define MAGIC_CHECK_RUBY_TYPE(o, t) Check_Type((o), (t)) #else # define MAGIC_CHECK_RUBY_TYPE(o, t) magic_check_ruby_type((o), (t)) #endif /* MAGIC_CUSTOM_CHECK_TYPE */ #if !defined(MAGIC_NO_CHECK_CSV) # define MAGIC_NO_CHECK_CSV 0 #endif /* MAGIC_NO_CHECK_CSV */ #if !defined(MAGIC_NO_CHECK_JSON) # define MAGIC_NO_CHECK_JSON 0 #endif /* MAGIC_NO_CHECK_JSON */ #if !defined(MAGIC_NO_COMPRESS_FORK) # define MAGIC_NO_COMPRESS_FORK 0 #endif /* MAGIC_NO_COMPRESS_FORK */ #define DATA_P(x) (RB_TYPE_P((x), T_DATA)) #define BOOLEAN_P(x) (RB_TYPE_P((x), T_TRUE) || RB_TYPE_P((x), T_FALSE)) #define STRING_P(x) (RB_TYPE_P((x), T_STRING)) #define ARRAY_P(x) (RB_TYPE_P((x), T_ARRAY)) #define FILE_P(x) (RB_TYPE_P((x), T_FILE)) #define RVAL2CBOOL(b) (RTEST(b)) #define CBOOL2RVAL(b) ((b) ? Qtrue : Qfalse) #define RVAL2CSTR(s) (NIL_P(s) ? NULL : StringValueCStr(s)) #define CSTR2RVAL(s) ((s) == NULL ? Qnil : rb_str_new2((const char *)s)) #define RSTRING_EMPTY_P(s) (RSTRING_LEN(s) == 0) #define RARRAY_EMPTY rb_ary_new() #define RARRAY_EMPTY_P(a) (RARRAY_LEN(a) == 0) #define RARRAY_FIRST(a) (RARRAY_EMPTY_P(a) ? Qnil : rb_ary_entry((a), 0)) #if RUBY_API_VERSION_CODE > 20700 # define RVALUE_TYPE enum ruby_value_type #else # define RVALUE_TYPE int #endif /* RUBY_API_VERSION_CODE > 20700 */ #if RUBY_API_VERSION_CODE >= 20700 && \ HAVE_RB_GC_MARK_MOVABLE # define HAVE_RUBY_GC_COMPACT 1 # define MAGIC_GC_MARK(x) rb_gc_mark_movable((x)) #else # define MAGIC_GC_MARK(x) rb_gc_mark((x)) #endif /* * RUBY_API_VERSION_CODE >= 20700 * HAVE_RB_GC_MARK_MOVABLE */ #define CLASS_NAME(o) (NIL_P((o)) ? "nil" : rb_obj_classname((o))) #if !defined(T_INTEGER) # define T_INTEGER rb_cInteger #endif /* T_INTEGER */ #if !defined(HAVE_RB_IO_T) # define rb_io_t OpenFile #endif /* HAVE_RB_IO_T */ #if !defined(GetReadFile) # define FPTR_TO_FD(p) ((p)->fd) #else # define FPTR_TO_FD(p) (fileno(GetReadFile(p))) #endif /* GetReadFile */ #define NOGVL_FUNCTION (VALUE(*)(void *)) #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) && \ defined(HAVE_RUBY_THREAD_H) && HAVE_RUBY_THREAD_H # include # define NOGVL(f, d) \ rb_thread_call_without_gvl((f), (d), RUBY_UBF_IO, NULL) #elif defined(HAVE_RB_THREAD_BLOCKING_REGION) # define NOGVL(f, d) \ rb_thread_blocking_region(NOGVL_FUNCTION(f), (d), RUBY_UBF_IO, NULL) #else # include static inline VALUE fake_blocking_region(VALUE (*f)(ANYARGS), void *data) { VALUE rv; TRAP_BEG; rv = f(data); TRAP_END; return rv; } # define NOGVL(f, d) \ fake_blocking_region(NOGVL_FUNCTION(f), (d)) #endif /* * HAVE_RB_THREAD_CALL_WITHOUT_GVL * HAVE_RUBY_THREAD_H */ #if defined(__cplusplus) } #endif #endif /* _COMMON_H */ ruby-magic-0.6.0/ext/magic/extconf.rb000066400000000000000000000315631440414250500174360ustar00rootroot00000000000000# frozen_string_literal: true require 'find' require 'mkmf' require 'pathname' PACKAGE_ROOT_DIR = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')) # This version has to match the Gem definition. REQUIRED_MINI_PORTILE_VERSION = "~> 2.8" MAGIC_HELP_MESSAGE = <<~HELP USAGE: ruby #{$0} [options] Flags that are always valid: --use-system-libraries --enable-system-libraries Use system libraries instead of building and using the packaged libraries. --disable-system-libraries Use the packaged libraries, and ignore the system libraries. This is the default on most platforms, and overrides `--use-system-libraries` and the environment variable `MAGIC_USE_SYSTEM_LIBRARIES`. --disable-clean Do not clean out intermediate files after successful build. Flags only used when building and using the packaged libraries: --disable-static Do not statically link packaged libraries, instead use shared libraries. --enable-cross-build Enable cross-build mode. (You probably do not want to set this manually.) --with-magic-flags= Build libmagic with these configure flags (such as --disable-zstdlib) Flags only used when using system libraries: Related to libmagic: --with-magic-dir=DIRECTORY Look for libmagic headers and library in DIRECTORY. --with-magic-lib=DIRECTORY Look for libmagic library in DIRECTORY. --with-magic-include=DIRECTORY Look for libmagic headers in DIRECTORY. Environment variables used: CC Use this path to invoke the compiler instead of `RbConfig::CONFIG['CC']` CPPFLAGS If this string is accepted by the C preprocessor, add it to the flags passed to the C preprocessor CFLAGS If this string is accepted by the compiler, add it to the flags passed to the compiler LDFLAGS If this string is accepted by the linker, add it to the flags passed to the linker LIBS Add this string to the flags passed to the linker HELP def process_recipe(name, version, static_p, cross_p) require 'rubygems' gem('mini_portile2', REQUIRED_MINI_PORTILE_VERSION) require 'mini_portile2' message("Using mini_portile version #{MiniPortile::VERSION}\n") MiniPortile.new(name, version).tap do |recipe| # Prefer host_alias over host in order to use i586-mingw32msvc as # correct compiler prefix for cross build, but use host if not set. recipe.host = RbConfig::CONFIG["host_alias"].empty? ? RbConfig::CONFIG["host"] : RbConfig::CONFIG["host_alias"] recipe.target = File.join(PACKAGE_ROOT_DIR, "ports") recipe.patch_files = Dir[File.join(PACKAGE_ROOT_DIR, "patches", name, "*.patch")].sort recipe.configure_options << "--libdir=#{File.join(recipe.path, 'lib')}" yield recipe env = Hash.new do |hash, key| hash[key] = (ENV[key]).to_s end recipe.configure_options.flatten! recipe.configure_options.delete_if do |option| case option when /\A(\w+)=(.*)\z/ env[Regexp.last_match(1)] = if env.key?(Regexp.last_match(1)) concat_flags(env[Regexp.last_match(1)], Regexp.last_match(2)) else Regexp.last_match(2) end true else false end end configure_options = [ "--disable-silent-rules", "--disable-dependency-tracking", "--enable-fsect-man5" ] libmagic_flags = with_config('magic-flags') configure_options += libmagic_flags.split(' ') if libmagic_flags recipe.configure_options = configure_options if static_p recipe.configure_options += [ "--disable-shared", "--enable-static", ] env["CFLAGS"] = concat_flags(env["CFLAGS"], "-fPIC") else recipe.configure_options += [ "--enable-shared", "--disable-static", ] end if cross_p recipe.configure_options += [ "--target=#{recipe.host}", "--host=#{recipe.host}", ] end if RbConfig::CONFIG['target_cpu'] == 'universal' %w[CFLAGS LDFLAGS].each do |key| unless env[key].include?('-arch') env[key] = concat_flags(env[key], RbConfig::CONFIG['ARCH_FLAG']) end end end recipe.configure_options += env.map do |key, value| "#{key}=#{value.strip}" end checkpoint = "#{recipe.target}/#{recipe.name}-#{recipe.version}-#{recipe.host}.installed" if File.exist?(checkpoint) message("Building Ruby Magic with a packaged version of #{name}-#{version}.\n") else message(<<~EOM) ---------- IMPORTANT NOTICE ---------- Building Ruby Magic with a packaged version of #{name}-#{version}. Configuration options: #{recipe.configure_options.shelljoin} EOM unless recipe.patch_files.empty? message("The following patches are being applied:\n") recipe.patch_files.each do |patch| message(" - %s\n" % File.basename(patch)) end end recipe.cook FileUtils.touch(checkpoint) end recipe.activate end end # # utility functions # def config_clean? enable_config('clean', true) end def config_static? default_static = !truffle? enable_config("static", default_static) end def config_cross_build? enable_config("cross-build") end def config_system_libraries? enable_config("system-libraries", ENV.key?("MAGIC_USE_SYSTEM_LIBRARIES")) do |_, default| arg_config('--use-system-libraries', default) end end def darwin? RbConfig::CONFIG['target_os'] =~ /darwin/ end def windows? RbConfig::CONFIG['target_os'] =~ /mswin|mingw32|windows/ end def truffle? ::RUBY_ENGINE == 'truffleruby' end def concat_flags(*args) args.compact.join(" ") end def do_help print(MAGIC_HELP_MESSAGE) exit!(0) end def do_clean root = Pathname(PACKAGE_ROOT_DIR) pwd = Pathname(Dir.pwd) # Skip if this is a development work tree unless (root + '.git').exist? message("Cleaning files only used during build.\n") # (root + 'tmp') cannot be removed at this stage because # libmagic.so is yet to be copied to lib. # clean the ports build directory Pathname.glob(pwd.join('tmp', '*', 'ports')) do |dir| FileUtils.rm_rf(dir, verbose: true) end FileUtils.rm_rf(root + 'ports' + 'archives', verbose: true) # Remove everything but share/ directory remove_paths = %w[bin include] remove_paths << 'lib' if config_static? Pathname.glob(File.join(root, 'ports', '*', 'libmagic', '*')) do |dir| remove_paths.each do |path| remove_dir = File.join(dir, path) FileUtils.rm_rf(remove_dir, verbose: true) end end end exit!(0) end # # main # do_help if arg_config('--help') do_clean if arg_config('--clean') if ENV['CC'] RbConfig::CONFIG['CC'] = RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] end ENV['CC'] = RbConfig::CONFIG['CC'] append_cflags(ENV["CFLAGS"].split) if ENV["CFLAGS"] append_cppflags(ENV["CPPFLAGS"].split) if ENV["CPPFLAGS"] append_ldflags(ENV["LDFLAGS"].split) if ENV["LDFLAGS"] $LIBS = concat_flags($LIBS, ENV["LIBS"]) if ENV["LIBS"] if truffle? $CPPFLAGS += " -DMAGIC_CUSTOM_CHECK_TYPE" end if config_system_libraries? message "Building ruby-magic using system libraries.\n" $CPPFLAGS += " -DMAGIC_SYSTEM_LIBRARIES" dir_config('magic') else message "Building ruby-magic using packaged libraries.\n" require 'yaml' dependencies = YAML.load_file(File.join(PACKAGE_ROOT_DIR, "dependencies.yml")) static_p = config_static? message "Static linking is #{static_p ? 'enabled' : 'disabled'}.\n" cross_build_p = config_cross_build? message "Cross build is #{cross_build_p ? 'enabled' : 'disabled'}.\n" libmagic_recipe = process_recipe('libmagic', dependencies["libmagic"]["version"], static_p, cross_build_p) do |recipe| recipe.files = [{ url: "https://cdn.statically.io/gh/kwilczynski/ruby-magic/cdn/cdn/file-#{recipe.version}.tar.gz", sha256: dependencies["libmagic"]["sha256"], }] end $LIBPATH = [File.join(libmagic_recipe.path, 'lib')] $CFLAGS << " -I#{File.join(libmagic_recipe.path, 'include')} " $LDFLAGS += " -Wl,-rpath,#{libmagic_recipe.path}/lib" if static_p pkg_config_paths = [ "#{libmagic_recipe.path}/lib64/pkgconfig", "#{libmagic_recipe.path}/lib32/pkgconfig", "#{libmagic_recipe.path}/lib/pkgconfig" ].join(':') if ENV["PKG_CONFIG_PATH"] pkg_config_paths = "#{ENV['PKG_CONFIG_PATH']}:#{pkg_config_paths}" end ENV['PKG_CONFIG_PATH'] = pkg_config_paths pc_file = File.join(libmagic_recipe.path, "lib", "pkgconfig", "libmagic.pc") if pkg_config(pc_file) # See https://bugs.ruby-lang.org/issues/18490, broken in Ruby 3.1 but fixed in Ruby 3.2. flags = xpopen(["pkg-config", "--libs", "--static", pc_file], err: [:child, :out], &:read) flags.split.each { |flag| append_ldflags(flag) } if $?.success? else raise "Please install the `pkg-config` utility!" end end if cross_build_p # database files will be packaged up by the cross-compiling callback in the ExtensionTask to_path = File.join(PACKAGE_ROOT_DIR, "ext/magic/share") FileUtils.rm_rf(to_path, verbose: true) FileUtils.mkdir(to_path) FileUtils.cp_r(Dir[File.join(libmagic_recipe.path, 'share/misc/*.mgc')], to_path) end end $CFLAGS += ' -std=c99' if RbConfig::CONFIG['CC'] =~ /gcc/ $CFLAGS += ' -O3' unless $CFLAGS =~ /-O\d/ end %w[ -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Winline ].select do |flag| try_link('int main(void) { return 0; }', flag) end.each do |flag| $CFLAGS += " " + flag end unless darwin? $LDFLAGS += ' -Wl,--as-needed -Wl,--exclude-libs,ALL' end if windows? $LDFLAGS += ' -static-libgcc' end unless have_header('ruby.h') abort "\n" + (<<-EOS).gsub(/^[ ]{,3}/, '') + "\n" You appear to be missing Ruby development libraries and/or header files. You can install missing compile-time dependencies in one of the following ways: - Debian / Ubuntu apt-get install ruby-dev - Red Hat / CentOS / Fedora yum install ruby-devel or dnf install ruby-devel - Mac OS X (Darwin) brew install ruby (for Homebrew, see https://brew.sh) port install ruby2.6 (for MacPorts, see https://www.macports.org) - OpenBSD / NetBSD pkg_add ruby (for pkgsrc, see https://www.pkgsrc.org) - FreeBSD pkg install ruby (for FreeBSD Ports, see https://www.freebsd.org/ports) Alternatively, you can use either of the following Ruby version managers in order to install Ruby locally (for your user only) and/or system-wide: - Ruby Version Manager (for RVM, see https://rvm.io) - Ruby Environment (for rbenv, see https://github.com/sstephenson/rbenv) - Change Ruby (for chruby, see https://github.com/postmodern/chruby) More information about how to install Ruby on various platforms available at the following web site: https://www.ruby-lang.org/en/documentation/installation EOS end have_func('rb_thread_call_without_gvl') have_func('rb_thread_blocking_region') have_func('rb_gc_mark_movable') unless have_header('magic.h') abort "\n" + (<<-EOS).gsub(/^[ ]{,3}/, '') + "\n" You appear to be missing libmagic(3) library and/or necessary header files. You can install missing compile-time dependencies in one of the following ways: - Debian / Ubuntu apt-get install libmagic-dev - Red Hat / CentOS / Fedora yum install file-devel or dns install file-devel - Mac OS X (Darwin) brew install libmagic (for Homebrew, see https://brew.sh) port install libmagic (for MacPorts, see https://www.macports.org) - OpenBSD / NetBSD pkg_add file (for pkgsrc, see https://www.pkgsrc.org) - FreeBSD pkg install file (for FreeBSD Ports, see https://www.freebsd.org/ports) Alternatively, you can download recent release of the file(1) package from the following web site and attempt to compile libmagic(3) manually: https://www.darwinsys.com/file EOS end have_library('magic') unless have_func('magic_getpath') abort "\n" + (<<-EOS).gsub(/^[ ]{,3}/, '') + "\n" Your version of libmagic(3) appears to be too old. Please, consider upgrading to at least version 5.29 or newer, if possible. For more information about file(1) command and libmagic(3) please visit the following web site: https://www.darwinsys.com/file EOS end have_func('magic_getflags') %w[ utime.h sys/types.h sys/time.h ].each do |h| have_header(h) end %w[ utime utimes ].each do |f| have_func(f) end create_header create_makefile('magic/magic') if config_clean? # Do not clean if run in a development work tree. File.open('Makefile', 'at') do |mk| mk.print(<<~EOF) all: clean-ports clean-ports: $(DLLIB) \t-$(Q)$(RUBY) $(srcdir)/extconf.rb --clean --#{static_p ? 'enable' : 'disable'}-static EOF end end ruby-magic-0.6.0/ext/magic/functions.c000066400000000000000000000141761440414250500176200ustar00rootroot00000000000000#if defined(__cplusplus) extern "C" { #endif #include "functions.h" static int check_fd(int fd); static int safe_dup(int fd); static int safe_close(int fd); static int safe_cloexec(int fd); static int override_error_output(void *data); static int restore_error_output(void *data); static inline int check_fd(int fd) { errno = 0; if (fd < 0 || (fcntl(fd, F_GETFD) < 0 && errno == EBADF)) { errno = EBADF; return -EBADF; } return 0; } static int safe_dup(int fd) { int new_fd; int local_errno; int flags = F_DUPFD; #if defined(HAVE_F_DUPFD_CLOEXEC) flags = F_DUPFD_CLOEXEC; #endif new_fd = fcntl(fd, flags, fileno(stderr) + 1); if (new_fd < 0 && errno == EINVAL) { new_fd = dup(fd); if (new_fd < 0) { local_errno = errno; goto error; } } if (safe_cloexec(new_fd) < 0) { local_errno = errno; goto error; } return new_fd; error: errno = local_errno; return -1; } static int safe_close(int fd) { int rv; #if defined(HAVE_POSIX_CLOSE_RESTART) rv = posix_close(fd, 0); #else rv = close(fd); if (rv < 0 && errno == EINTR) errno = EINPROGRESS; #endif return rv; } static inline int safe_cloexec(int fd) { int local_errno; int flags = fcntl(fd, F_GETFD); if (flags < 0) { local_errno = errno; goto error; } if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { local_errno = errno; goto error; } return 0; error: errno = local_errno; return -1; } static int override_error_output(void *data) { int local_errno; int flags = O_WRONLY | O_APPEND; save_t *s = data; #if defined(HAVE_O_CLOEXEC) flags |= O_CLOEXEC; #endif assert(s != NULL && "Must be a valid pointer to `save_t' type"); s->file.old_fd = -1; s->file.new_fd = -1; s->status = -1; fflush(stderr); fgetpos(stderr, &s->file.position); s->file.old_fd = safe_dup(fileno(stderr)); if (s->file.old_fd < 0) { local_errno = errno; goto error; } s->file.new_fd = open("/dev/null", flags, 0222); if (s->file.new_fd < 0) { local_errno = errno; if (dup2(s->file.old_fd, fileno(stderr)) < 0) { local_errno = errno; goto error; } safe_close(s->file.old_fd); goto error; } if (safe_cloexec(s->file.new_fd) < 0) { local_errno = errno; goto error; } if (dup2(s->file.new_fd, fileno(stderr)) < 0) { local_errno = errno; goto error; } safe_close(s->file.new_fd); return 0; error: s->status = local_errno; errno = s->status; return -1; } static int restore_error_output(void *data) { int local_errno; save_t *s = data; assert(s != NULL && "Must be a valid pointer to `save_t' type"); if (s->file.old_fd < 0 && s->status != 0) return -1; fflush(stderr); if (dup2(s->file.old_fd, fileno(stderr)) < 0) { local_errno = errno; goto error; } safe_close(s->file.old_fd); clearerr(stderr); fsetpos(stderr, &s->file.position); if (setvbuf(stderr, NULL, _IONBF, 0) != 0) { local_errno = errno; goto error; } return 0; error: s->status = local_errno; errno = s->status; return -1; } inline magic_t magic_open_wrapper(int flags) { return magic_open(flags); } inline void magic_close_wrapper(magic_t magic) { magic_close(magic); } inline const char* magic_error_wrapper(magic_t magic) { return magic_error(magic); } inline int magic_errno_wrapper(magic_t magic) { return magic_errno(magic); } inline const char* magic_getpath_wrapper(void) { /* * The second argument translates to same value as the * FILE_LOAD constant, which when used results in this * function calling the get_default_magic() internally. * * N.B. magic_getpath() also honors the "MAGIC" * environment variable." */ return magic_getpath(NULL, 0); } inline int magic_getparam_wrapper(magic_t magic, int parameter, void *value) { return magic_getparam(magic, parameter, value); } inline int magic_setparam_wrapper(magic_t magic, int parameter, const void *value) { if (*(const int *)value < 0 || *(const size_t *)value > UINT_MAX) { errno = EOVERFLOW; return -EOVERFLOW; } if (parameter == MAGIC_PARAM_BYTES_MAX) return magic_setparam(magic, parameter, value); if (*(const size_t *)value > USHRT_MAX) { errno = EOVERFLOW; return -EOVERFLOW; } return magic_setparam(magic, parameter, value); } inline int magic_getflags_wrapper(magic_t magic) { #if defined(HAVE_MAGIC_GETFLAGS) return magic_getflags(magic); #else UNUSED(magic); errno = ENOSYS; return -ENOSYS; #endif } inline int magic_setflags_wrapper(magic_t magic, int flags) { if (flags < 0 || flags > 0xfffffff) { errno = EINVAL; return -EINVAL; } #if !defined(HAVE_UTIME) && !defined(HAVE_UTIMES) if (flags & MAGIC_PRESERVE_ATIME) { errno = ENOSYS; return -ENOSYS; } #endif return magic_setflags(magic, flags); } inline int magic_load_wrapper(magic_t magic, const char *magic_file, int flags) { int rv; MAGIC_FUNCTION(magic_load, rv, flags, magic, magic_file); return rv; } inline int magic_load_buffers_wrapper(magic_t magic, void **buffers, size_t *sizes, size_t count, int flags) { int rv; MAGIC_FUNCTION(magic_load_buffers, rv, flags, magic, buffers, sizes, count); return rv; } inline int magic_compile_wrapper(magic_t magic, const char *magic_file, int flags) { int rv; MAGIC_FUNCTION(magic_compile, rv, flags, magic, magic_file); return rv; } inline int magic_check_wrapper(magic_t magic, const char *magic_file, int flags) { int rv; MAGIC_FUNCTION(magic_check, rv, flags, magic, magic_file); return rv; } inline const char* magic_file_wrapper(magic_t magic, const char *filename, int flags) { const char *cstring; MAGIC_FUNCTION(magic_file, cstring, flags, magic, filename); return cstring; } inline const char* magic_buffer_wrapper(magic_t magic, const void *buffer, size_t size, int flags) { const char *cstring; MAGIC_FUNCTION(magic_buffer, cstring, flags, magic, buffer, size); return cstring; } inline const char* magic_descriptor_wrapper(magic_t magic, int fd, int flags) { int local_errno; const char *cstring; if (check_fd(fd) < 0) { local_errno = errno; goto error; } MAGIC_FUNCTION(magic_descriptor, cstring, flags, magic, fd); return cstring; error: errno = local_errno; return NULL; } inline int magic_version_wrapper(void) { return magic_version(); } #if defined(__cplusplus) } #endif ruby-magic-0.6.0/ext/magic/functions.h000066400000000000000000000035461440414250500176240ustar00rootroot00000000000000#if !defined(_FUNCTIONS_H) #define _FUNCTIONS_H 1 #if defined(__cplusplus) extern "C" { #endif #include "common.h" #define MAGIC_FUNCTION(f, r, x, ...) \ do { \ if ((x) & (MAGIC_DEBUG | MAGIC_CHECK)) \ r = f(__VA_ARGS__); \ else { \ save_t __##f; \ override_error_output(&(__##f)); \ r = f(__VA_ARGS__); \ restore_error_output(&(__##f)); \ } \ } while (0) typedef struct file_data { fpos_t position; int old_fd; int new_fd; } file_data_t; typedef struct save { file_data_t file; int status; } save_t; extern magic_t magic_open_wrapper(int flags); extern void magic_close_wrapper(magic_t magic); extern const char *magic_error_wrapper(magic_t magic); extern int magic_errno_wrapper(magic_t magic); extern const char *magic_getpath_wrapper(void); extern int magic_getparam_wrapper(magic_t magic, int parameter, void *value); extern int magic_setparam_wrapper(magic_t magic, int parameter, const void *value); extern int magic_getflags_wrapper(magic_t magic); extern int magic_setflags_wrapper(magic_t magic, int flags); extern int magic_load_wrapper(magic_t magic, const char *magic_file, int flags); extern int magic_load_buffers_wrapper(magic_t magic, void **buffers, size_t *sizes, size_t count, int flags); extern int magic_compile_wrapper(magic_t magic, const char *magic_file, int flags); extern int magic_check_wrapper(magic_t magic, const char *magic_file, int flags); extern const char *magic_file_wrapper(magic_t magic, const char *filename, int flags); extern const char *magic_buffer_wrapper(magic_t magic, const void *buffer, size_t size, int flags); extern const char *magic_descriptor_wrapper(magic_t magic, int fd, int flags); extern int magic_version_wrapper(void); #if defined(__cplusplus) } #endif #endif /* _FUNCTIONS_H */ ruby-magic-0.6.0/ext/magic/ruby-magic.c000066400000000000000000001211361440414250500176420ustar00rootroot00000000000000#if defined(__cplusplus) extern "C" { #endif #include "ruby-magic.h" static int rb_mgc_do_not_auto_load; static int rb_mgc_do_not_stop_on_error; static int rb_mgc_warning; static ID id_at_flags; static ID id_at_paths; static VALUE rb_cMagic; static VALUE rb_mgc_eError; static VALUE rb_mgc_eMagicError; static VALUE rb_mgc_eLibraryError; static VALUE rb_mgc_eNotImplementedError; static VALUE rb_mgc_eParameterError; static VALUE rb_mgc_eFlagsError; static const rb_data_type_t rb_mgc_type; static VALUE magic_get_parameter_internal(void *data); static VALUE magic_set_parameter_internal(void *data); static VALUE magic_get_flags_internal(void *data); static VALUE magic_set_flags_internal(void *data); static VALUE magic_load_internal(void *data); static VALUE magic_load_buffers_internal(void *data); static VALUE magic_compile_internal(void *data); static VALUE magic_check_internal(void *data); static VALUE magic_file_internal(void *data); static VALUE magic_buffer_internal(void *data); static VALUE magic_descriptor_internal(void *data); static VALUE magic_close_internal(void *data); static void *nogvl_magic_load(void *data); static void *nogvl_magic_compile(void *data); static void *nogvl_magic_check(void *data); static void *nogvl_magic_file(void *data); static void *nogvl_magic_descriptor(void *data); static void *magic_library_open(void); static void magic_library_close(void *data); static VALUE magic_allocate(VALUE klass); static void magic_mark(void *data); static void magic_free(void *data); static size_t magic_size(const void *data); #if defined(HAVE_RUBY_GC_COMPACT) static void magic_compact(void *data); #endif static VALUE magic_exception_wrapper(VALUE value); static VALUE magic_exception(void *data); static VALUE magic_library_error(VALUE klass, void *data); static VALUE magic_generic_error(VALUE klass, int magic_errno, const char *magic_error); static VALUE magic_lock(VALUE object, VALUE (*function)(ANYARGS), void *data); static VALUE magic_unlock(VALUE object); static VALUE magic_return(void *data); static int magic_get_flags(VALUE object); static void magic_set_flags(VALUE object, int flags); static VALUE magic_set_paths(VALUE object, VALUE value); /* * call-seq: * Magic.do_not_auto_load -> boolean * * Returns +true+ if the global +do_not_auto_load+ flag is set, or +false+ * otherwise. * * Example: * * Magic.do_not_auto_load #=> false * Magic.do_not_auto_load = true #=> true * Magic.do_not_auto_load #=> true * * See also: Magic::new, Magic#loaded?, Magic#load and Magic#load_buffers */ VALUE rb_mgc_get_do_not_auto_load_global(RB_UNUSED_VAR(VALUE object)) { return CBOOL2RVAL(rb_mgc_do_not_auto_load); } /* * call-seq: * Magic.do_not_auto_load= ( boolean ) -> boolean * * Sets the global +do_not_auto_load+ flag for the Magic object and each of the * Magic object instances. This flag can be used to disable automatic loading of * the Magic database files. * * Returns +true+ if the global +do_not_auto_load+ flag is set, or +false+ * otherwise. * * Example: * * Magic.do_not_auto_load #=> false * Magic.do_not_auto_load = true #=> true * Magic.do_not_auto_load #=> true * * Example: * * Magic.do_not_auto_load = true #=> true * magic = Magic.new * magic.loaded? #=> false * magic.load_buffers(File.read(magic.paths[0] + ".mgc")) #=> nil * magic.loaded? #=> true * * See also: Magic::new, Magic#loaded?, Magic#load and Magic#load_buffers */ VALUE rb_mgc_set_do_not_auto_load_global(RB_UNUSED_VAR(VALUE object), VALUE value) { rb_mgc_do_not_auto_load = RVAL2CBOOL(value); return value; } /* * call-seq: * Magic.do_not_stop_on_error -> boolean * * Returns +true+ if the global +do_not_stop_on_error+ flag is set, or +false+ * otherwise. * * Example: * * Magic.do_not_stop_on_error #=> false * Magic.do_not_stop_on_error = true #=> true * Magic.do_not_stop_on_error #=> true * * See also: Magic::new, Magic::open and Magic#do_not_stop_on_error */ VALUE rb_mgc_get_do_not_stop_on_error_global(RB_UNUSED_VAR(VALUE object)) { return CBOOL2RVAL(rb_mgc_do_not_stop_on_error); } /* * call-seq: * Magic.do_not_stop_on_error= (boolean) -> boolean * * Example: * * Magic.do_not_stop_on_error #=> false * Magic.do_not_stop_on_error = true #=> true * Magic.do_not_stop_on_error #=> true * * See also: Magic::new, Magic::open and Magic#do_not_stop_on_error */ VALUE rb_mgc_set_do_not_stop_on_error_global(RB_UNUSED_VAR(VALUE object), VALUE value) { rb_mgc_do_not_stop_on_error = RVAL2CBOOL(value); return value; } /* * call-seq: * Magic.new -> self * Magic.new( string, ... ) -> self * Magic.new( array ) -> self * * Opens the underlying _Magic_ database and returns a new _Magic_. * * Example: * * magic = Magic.new * magic.class #=> Magic * * See also: Magic::open, Magic::mime, Magic::type, Magic::encoding, Magic::compile and Magic::check */ VALUE rb_mgc_initialize(VALUE object, VALUE arguments) { rb_mgc_object_t *mgc; const char *klass = "Magic"; if (!NIL_P(object)) klass = rb_obj_classname(object); if (rb_block_given_p()) MAGIC_WARNING(0, "%s::new() does not take block; use %s::open() instead", klass, klass); if (RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_STOP_ON_ERROR']"))) rb_mgc_do_not_stop_on_error = 1; if (RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_AUTOLOAD']"))) rb_mgc_do_not_auto_load = 1; MAGIC_OBJECT(object, mgc); mgc->stop_on_errors = 1; if (rb_mgc_do_not_stop_on_error) mgc->stop_on_errors = 0; mgc->mutex = rb_class_new_instance(0, 0, rb_const_get(rb_cObject, rb_intern("Mutex"))); magic_set_flags(object, MAGIC_NONE); magic_set_paths(object, RARRAY_EMPTY); if (rb_mgc_do_not_auto_load) { if (!RARRAY_EMPTY_P(arguments)) MAGIC_WARNING(1, "%s::do_not_auto_load is set; using %s#new() to load " "Magic database from a file will have no effect", klass, klass); return object; } rb_mgc_load(object, arguments); return object; } /* * call-seq: * magic.do_not_stop_on_error -> boolean * * See also: Magic::new, Magic::open and Magic::do_not_stop_on_error */ VALUE rb_mgc_get_do_not_stop_on_error(VALUE object) { rb_mgc_object_t *mgc; MAGIC_CHECK_OPEN(object); MAGIC_OBJECT(object, mgc); return CBOOL2RVAL(!mgc->stop_on_errors); } /* * call-seq: * magic.do_not_stop_on_error= ( boolean ) -> boolean * * See also: Magic::new, Magic::open and Magic::do_not_stop_on_error */ VALUE rb_mgc_set_do_not_stop_on_error(VALUE object, VALUE value) { rb_mgc_object_t *mgc; MAGIC_CHECK_OPEN(object); MAGIC_OBJECT(object, mgc); mgc->stop_on_errors = !RVAL2CBOOL(value); return value; } /* * call-seq: * magic.open? -> true or false * * Returns +true+ if the underlying _Magic_ database is open, * or +false+ otherwise. * * Example: * * magic = Magic.new * magic.open? #=> true * magic.close #=> nil * magic.open? #=> false * * See also: Magic#close?, Magic#close and Magic#new */ VALUE rb_mgc_open_p(VALUE object) { return MAGIC_CLOSED_P(object) ? Qfalse : Qtrue; } /* * call-seq: * magic.close -> nil * * Closes the underlying _Magic_ database. * * Example: * * magic = Magic.new * magic.close #=> nil * * See also: Magic#closed?, Magic#open? and Magic#new */ VALUE rb_mgc_close(VALUE object) { rb_mgc_object_t *mgc; if (MAGIC_CLOSED_P(object)) return Qnil; MAGIC_OBJECT(object, mgc); if (mgc) { MAGIC_SYNCHRONIZED(magic_close_internal, mgc); if (DATA_P(object)) DATA_PTR(object) = NULL; } return Qnil; } /* * call-seq: * magic.closed? -> true or false * * Returns +true+ if the underlying _Magic_ database is closed, * or +false+ otherwise. * * Example: * * magic = Magic.new * magic.closed? #=> false * magic.close #=> nil * magic.closed? #=> true * * See also: Magic#close, Magic#open? and #Magic#new */ VALUE rb_mgc_close_p(VALUE object) { rb_mgc_object_t *mgc; magic_t cookie = NULL; MAGIC_OBJECT(object, mgc); if (mgc) cookie = mgc->cookie; if (DATA_P(object) && cookie) return Qfalse; return Qtrue; } /* * call-seq: * magic.paths -> array * * Example: * * magic = Magic.new * magic.paths #=> ["/etc/magic", "/usr/share/misc/magic"] * */ VALUE rb_mgc_get_paths(VALUE object) { const char *cstring = NULL; VALUE value = Qundef; MAGIC_CHECK_OPEN(object); value = rb_ivar_get(object, id_at_paths); if (!NIL_P(value) && !RARRAY_EMPTY_P(value)) return value; value = rb_funcall(rb_cMagic, rb_intern("default_paths"), 0); if (getenv("MAGIC") || NIL_P(value)) { cstring = magic_getpath_wrapper(); value = magic_split(CSTR2RVAL(cstring), CSTR2RVAL(":")); RB_GC_GUARD(value); } return magic_set_paths(object, value); } /* * call-seq: * magic.get_parameter( integer ) -> integer */ VALUE rb_mgc_get_parameter(VALUE object, VALUE tag) { int local_errno; rb_mgc_object_t *mgc; rb_mgc_arguments_t mga; MAGIC_CHECK_INTEGER_TYPE(tag); MAGIC_CHECK_OPEN(object); MAGIC_OBJECT(object, mgc); mga = (rb_mgc_arguments_t) { .magic_object = mgc, .parameter = { .tag = NUM2INT(tag), }, }; MAGIC_SYNCHRONIZED(magic_get_parameter_internal, &mga); local_errno = errno; if (mga.status < 0) { if (local_errno == EINVAL) MAGIC_GENERIC_ERROR(rb_mgc_eParameterError, local_errno, E_PARAM_INVALID_TYPE); MAGIC_LIBRARY_ERROR(mgc); } return SIZET2NUM(mga.parameter.value); } /* * call-seq: * magic.set_parameter( integer, integer ) -> nil */ VALUE rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value) { int local_errno; rb_mgc_object_t *mgc; rb_mgc_arguments_t mga; MAGIC_CHECK_INTEGER_TYPE(tag); MAGIC_CHECK_INTEGER_TYPE(value); MAGIC_CHECK_OPEN(object); MAGIC_OBJECT(object, mgc); mga = (rb_mgc_arguments_t) { .magic_object = mgc, .parameter = { .tag = NUM2INT(tag), .value = NUM2SIZET(value), }, }; MAGIC_SYNCHRONIZED(magic_set_parameter_internal, &mga); local_errno = errno; if (mga.status < 0) { switch (local_errno) { case EINVAL: MAGIC_GENERIC_ERROR(rb_mgc_eParameterError, local_errno, E_PARAM_INVALID_TYPE); case EOVERFLOW: MAGIC_GENERIC_ERROR(rb_mgc_eParameterError, local_errno, E_PARAM_INVALID_VALUE); } MAGIC_LIBRARY_ERROR(mgc); } return Qnil; } /* * call-seq: * magic.flags -> integer * * Example: * * magic = Magic.new * magic.flags #=> 0 * magic.flags = Magic::MIME #=> 1040 * magic.flags #=> 1040 * * See also: Magic#flags_to_a */ VALUE rb_mgc_get_flags(VALUE object) { int local_errno; rb_mgc_object_t *mgc; rb_mgc_arguments_t mga; MAGIC_CHECK_OPEN(object); MAGIC_OBJECT(object, mgc); mga = (rb_mgc_arguments_t) { .magic_object = mgc, }; MAGIC_SYNCHRONIZED(magic_get_flags_internal, &mga); local_errno = errno; if (mga.status < 0 && local_errno == ENOSYS) return rb_ivar_get(object, id_at_flags); return INT2NUM(mga.flags); } /* * call-seq: * magic.flags= ( integer ) -> integer * * Example: * * magic = Magic.new * magic.flags = Magic::MIME #=> 1040 * magic.flags = Magic::MIME_TYPE #=> 16 */ VALUE rb_mgc_set_flags(VALUE object, VALUE value) { int local_errno; rb_mgc_object_t *mgc; rb_mgc_arguments_t mga; const char *klass = NULL; const char *flag = NULL; MAGIC_CHECK_INTEGER_TYPE(value); MAGIC_CHECK_OPEN(object); MAGIC_OBJECT(object, mgc); mga = (rb_mgc_arguments_t) { .magic_object = mgc, .flags = NUM2INT(value), }; if (mga.flags < 0) MAGIC_GENERIC_ERROR(rb_mgc_eFlagsError, EINVAL, E_FLAG_INVALID_TYPE); if (mga.flags & MAGIC_DEBUG) flag = "DEBUG"; else if (mga.flags & MAGIC_CHECK) flag = "CHECK"; if (flag) { klass = "Magic"; if (!NIL_P(object)) klass = rb_obj_classname(object); MAGIC_WARNING(0, "%s::%s flag is set; verbose information will " "now be printed to the standard error output", klass, flag); } MAGIC_SYNCHRONIZED(magic_set_flags_internal, &mga); local_errno = errno; if (mga.status < 0) { switch (local_errno) { case EINVAL: MAGIC_GENERIC_ERROR(rb_mgc_eFlagsError, local_errno, E_FLAG_INVALID_TYPE); case ENOSYS: MAGIC_GENERIC_ERROR(rb_mgc_eNotImplementedError, local_errno, E_FLAG_NOT_IMPLEMENTED); } MAGIC_LIBRARY_ERROR(mgc); } return rb_ivar_set(object, id_at_flags, INT2NUM(mga.flags)); } /* * call-seq: * magic.load -> nil * magic.load( string, ... ) -> nil * magic.load( array ) -> nil * * Example: * * See also: Magic#check, Magic#compile, Magic::check and Magic::compile */ VALUE rb_mgc_load(VALUE object, VALUE arguments) { rb_mgc_object_t *mgc; rb_mgc_arguments_t mga; const char *klass = NULL; VALUE value = Qundef; if (ARRAY_P(RARRAY_FIRST(arguments))) arguments = magic_flatten(arguments); MAGIC_CHECK_ARRAY_OF_STRINGS(arguments); MAGIC_CHECK_OPEN(object); MAGIC_OBJECT(object, mgc); if (rb_mgc_do_not_auto_load) { klass = "Magic"; if (!NIL_P(object)) klass = rb_obj_classname(object); MAGIC_WARNING(2, "%s::do_not_auto_load is set; using %s#load " "will load Magic database from a file", klass, klass); } if (RARRAY_EMPTY_P(arguments)) arguments = rb_mgc_get_paths(object); value = magic_join(arguments, CSTR2RVAL(":")); RB_GC_GUARD(value); magic_set_paths(object, RARRAY_EMPTY); mga = (rb_mgc_arguments_t) { .magic_object = mgc, .file = { .path = RVAL2CSTR(value), }, .flags = magic_get_flags(object), }; MAGIC_SYNCHRONIZED(magic_load_internal, &mga); if (mga.status < 0) { mgc->database_loaded = 0; MAGIC_LIBRARY_ERROR(mgc); } mgc->database_loaded = 1; value = magic_split(CSTR2RVAL(mga.file.path), CSTR2RVAL(":")); RB_GC_GUARD(value); magic_set_paths(object, value); return Qnil; } /* * call-seq: * magic.load_buffers( string, ... ) -> nil * magic.load_buffers( array ) -> nil * * See also: Magic#load and Magic::do_not_auto_load */ VALUE rb_mgc_load_buffers(VALUE object, VALUE arguments) { size_t count; int local_errno; rb_mgc_object_t *mgc; rb_mgc_arguments_t mga; void **pointers = NULL; size_t *sizes = NULL; VALUE value = Qundef; count = (size_t)RARRAY_LEN(arguments); MAGIC_CHECK_ARGUMENT_MISSING(count, 1); if (ARRAY_P(RARRAY_FIRST(arguments))) { arguments = magic_flatten(arguments); count = (size_t)RARRAY_LEN(arguments); } MAGIC_CHECK_ARRAY_EMPTY(arguments); MAGIC_CHECK_ARRAY_OF_STRINGS(arguments); MAGIC_CHECK_OPEN(object); MAGIC_OBJECT(object, mgc); pointers = ALLOC_N(void *, count); if (!pointers) { local_errno = ENOMEM; goto error; } sizes = ALLOC_N(size_t, count); if (!sizes) { ruby_xfree(pointers); local_errno = ENOMEM; goto error; } for (size_t i = 0; i < count; i++) { value = RARRAY_AREF(arguments, (long)i); pointers[i] = (void *)RSTRING_PTR(value); sizes[i] = (size_t)RSTRING_LEN(value); } magic_set_paths(object, RARRAY_EMPTY); mga = (rb_mgc_arguments_t) { .magic_object = mgc, .buffers = { .count = count, .pointers = pointers, .sizes = sizes, }, .flags = magic_get_flags(object), }; MAGIC_SYNCHRONIZED(magic_load_buffers_internal, &mga); if (mga.status < 0) { local_errno = errno; ruby_xfree(pointers); ruby_xfree(sizes); goto error; } mgc->database_loaded = 1; ruby_xfree(pointers); ruby_xfree(sizes); return Qnil; error: mgc->database_loaded = 0; if (local_errno == ENOMEM) MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError, local_errno, E_NOT_ENOUGH_MEMORY); MAGIC_LIBRARY_ERROR(mgc); } /* * call-seq: * magic.loaded? -> true or false * * Returns +true+ if at least a single Magic database file had been loaded, or * +false+ otherwise. Magic database files can be loaded from a file or from an * in-memory buffer. * * Example: * * magic = Magic.new * magic.loaded? #=> true * * Example: * * Magic.do_not_auto_load = true #=> true * magic = Magic.new * magic.loaded? #=> false * * See also: Magic#load and Magic#load_buffers */ VALUE rb_mgc_load_p(VALUE object) { rb_mgc_object_t *mgc; MAGIC_CHECK_OPEN(object); MAGIC_OBJECT(object, mgc); return CBOOL2RVAL(mgc->database_loaded); } /* * call-seq: * magic.compile( string ) -> nil * magic.compile( array ) -> nil * * See also: Magic#check, Magic::check and Magic::compile */ VALUE rb_mgc_compile(VALUE object, VALUE value) { rb_mgc_object_t *mgc; rb_mgc_arguments_t mga; MAGIC_CHECK_STRING_TYPE(value); MAGIC_CHECK_OPEN(object); MAGIC_OBJECT(object, mgc); mga = (rb_mgc_arguments_t) { .magic_object = mgc, .file = { .path = RVAL2CSTR(value), }, .flags = magic_get_flags(object), }; MAGIC_SYNCHRONIZED(magic_compile_internal, &mga); if (mga.status < 0) MAGIC_LIBRARY_ERROR(mgc); return Qnil; } /* * call-seq: * magic.check( string ) -> true or false * magic.check( array ) -> true or false * * See also: Magic#compile, Magic::compile and Magic::check */ VALUE rb_mgc_check(VALUE object, VALUE value) { rb_mgc_object_t *mgc; rb_mgc_arguments_t mga; MAGIC_CHECK_STRING_TYPE(value); MAGIC_CHECK_OPEN(object); MAGIC_OBJECT(object, mgc); mga = (rb_mgc_arguments_t) { .magic_object = mgc, .file = { .path = RVAL2CSTR(value), }, .flags = magic_get_flags(object), }; MAGIC_SYNCHRONIZED(magic_check_internal, &mga); return mga.status < 0 ? Qfalse : Qtrue; } /* * call-seq: * magic.file( object ) -> string or array * magic.file( string ) -> string or array * * See also: Magic#buffer and Magic#descriptor */ VALUE rb_mgc_file(VALUE object, VALUE value) { rb_mgc_object_t *mgc; rb_mgc_arguments_t mga; const char *empty = "(null)"; UNUSED(empty); if (NIL_P(value)) goto error; MAGIC_CHECK_OPEN(object); MAGIC_CHECK_LOADED(object); MAGIC_OBJECT(object, mgc); if (rb_respond_to(value, rb_intern("to_io"))) return rb_mgc_descriptor(object, value); value = magic_path(value); if (NIL_P(value)) goto error; mga = (rb_mgc_arguments_t) { .magic_object = mgc, .file = { .path = RVAL2CSTR(value), }, .flags = magic_get_flags(object), }; MAGIC_SYNCHRONIZED(magic_file_internal, &mga); if (mga.status < 0 && !mga.result) { /* * Handle the case when the "ERROR" flag is set regardless of the * current version of the underlying Magic library. * * Prior to version 5.15 the correct behavior that concerns the * following IEEE 1003.1 standards was broken: * * http://pubs.opengroup.org/onlinepubs/007904975/utilities/file.html * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/file.html * * This is an attempt to mitigate the problem and correct it to achieve * the desired behavior as per the standards. */ if (mgc->stop_on_errors || (mga.flags & MAGIC_ERROR)) MAGIC_LIBRARY_ERROR(mgc); mga.result = magic_error_wrapper(mgc->cookie); } if (!mga.result) MAGIC_GENERIC_ERROR(rb_mgc_eMagicError, EINVAL, E_UNKNOWN); assert(mga.result != NULL && "Must be a valid pointer to `const char' type"); /* * Depending on the version of the underlying Magic library the magic_file() * function can fail and either yield no results or return the "(null)" * string instead. Often this would indicate that an older version of the * Magic library is in use. */ assert(strncmp(mga.result, empty, strlen(empty)) != 0 && "Empty or invalid result"); return magic_return(&mga); error: MAGIC_ARGUMENT_TYPE_ERROR(value, "String or IO-like object"); } /* * call-seq: * magic.buffer( string ) -> string or array * * See also: Magic#file and Magic#descriptor */ VALUE rb_mgc_buffer(VALUE object, VALUE value) { rb_mgc_object_t *mgc; rb_mgc_arguments_t mga; MAGIC_CHECK_STRING_TYPE(value); MAGIC_CHECK_OPEN(object); MAGIC_CHECK_LOADED(object); MAGIC_OBJECT(object, mgc); StringValue(value); mga = (rb_mgc_arguments_t) { .magic_object = mgc, .buffers = { .pointers = (void **)RSTRING_PTR(value), .sizes = (size_t *)RSTRING_LEN(value), }, .flags = magic_get_flags(object), }; MAGIC_SYNCHRONIZED(magic_buffer_internal, &mga); if (mga.status < 0) MAGIC_LIBRARY_ERROR(mgc); assert(mga.result != NULL && "Must be a valid pointer to `const char' type"); return magic_return(&mga); } /* * call-seq: * magic.descriptor( object ) -> string or array * magic.descriptor( integer ) -> string or array * * See also: Magic#file and Magic#buffer */ VALUE rb_mgc_descriptor(VALUE object, VALUE value) { int local_errno; rb_mgc_object_t *mgc; rb_mgc_arguments_t mga; if (rb_respond_to(value, rb_intern("to_io"))) value = INT2NUM(magic_fileno(value)); MAGIC_CHECK_INTEGER_TYPE(value); MAGIC_CHECK_OPEN(object); MAGIC_CHECK_LOADED(object); MAGIC_OBJECT(object, mgc); mga = (rb_mgc_arguments_t) { .magic_object = mgc, .file = { .fd = NUM2INT(value), }, .flags = magic_get_flags(object), }; MAGIC_SYNCHRONIZED(magic_descriptor_internal, &mga); local_errno = errno; if (mga.status < 0) { if (local_errno == EBADF) rb_raise(rb_eIOError, "Bad file descriptor"); MAGIC_LIBRARY_ERROR(mgc); } assert(mga.result != NULL && "Must be a valid pointer to `const char' type"); return magic_return(&mga); } /* * call-seq: * Magic.version -> integer * * Example: * * Magic.version #=> 517 * * See also: Magic::version_to_a and Magic::version_to_s */ VALUE rb_mgc_version(RB_UNUSED_VAR(VALUE object)) { return INT2NUM(magic_version_wrapper()); } static inline void* nogvl_magic_load(void *data) { rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; mga->status = magic_load_wrapper(cookie, mga->file.path, mga->flags); return NULL; } static inline void* nogvl_magic_compile(void *data) { rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; mga->status = magic_compile_wrapper(cookie, mga->file.path, mga->flags); return NULL; } static inline void* nogvl_magic_check(void *data) { rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; mga->status = magic_check_wrapper(cookie, mga->file.path, mga->flags); return NULL; } static inline void* nogvl_magic_file(void *data) { rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; mga->result = magic_file_wrapper(cookie, mga->file.path, mga->flags); mga->status = !mga->result ? -1 : 0; return NULL; } static inline void* nogvl_magic_descriptor(void *data) { rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; mga->result = magic_descriptor_wrapper(cookie, mga->file.fd, mga->flags); mga->status = !mga->result ? -1 : 0; return NULL; } static inline VALUE magic_get_parameter_internal(void *data) { size_t value; rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; mga->status = magic_getparam_wrapper(cookie, mga->parameter.tag, &value); mga->parameter.value = value; return (VALUE)NULL; } static inline VALUE magic_set_parameter_internal(void *data) { size_t value; rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; value = mga->parameter.value; mga->status = magic_setparam_wrapper(cookie, mga->parameter.tag, &value); return (VALUE)NULL; } static inline VALUE magic_get_flags_internal(void *data) { int flags; rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; mga->status = 0; flags = magic_getflags_wrapper(cookie); if (flags < 0) mga->status = -1; else mga->flags = flags; return (VALUE)NULL; } static inline VALUE magic_set_flags_internal(void *data) { rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; mga->status = magic_setflags_wrapper(cookie, mga->flags); return (VALUE)NULL; } static inline VALUE magic_close_internal(void *data) { magic_library_close(data); return Qnil; } static inline VALUE magic_load_internal(void *data) { rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; int old_flags = mga->flags; NOGVL(nogvl_magic_load, mga); if (MAGIC_STATUS_CHECK(mga->status < 0)) magic_setflags_wrapper(cookie, old_flags); return (VALUE)NULL; } static inline VALUE magic_load_buffers_internal(void *data) { rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; mga->status = magic_load_buffers_wrapper(cookie, mga->buffers.pointers, mga->buffers.sizes, mga->buffers.count, mga->flags); return (VALUE)NULL; } static inline VALUE magic_compile_internal(void *data) { rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; int old_flags = mga->flags; NOGVL(nogvl_magic_compile, mga); if (MAGIC_STATUS_CHECK(mga->status < 0)) magic_setflags_wrapper(cookie, old_flags); return (VALUE)NULL; } static inline VALUE magic_check_internal(void *data) { rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; int old_flags = mga->flags; NOGVL(nogvl_magic_check, mga); if (MAGIC_STATUS_CHECK(mga->status < 0)) magic_setflags_wrapper(cookie, old_flags); return (VALUE)NULL; } static VALUE magic_file_internal(void *data) { int local_errno; int restore_flags = 0; rb_mgc_arguments_t *mga = data; rb_mgc_object_t *mgc = mga->magic_object; magic_t cookie = mgc->cookie; int old_flags = mga->flags; if (mgc->stop_on_errors) mga->flags |= MAGIC_ERROR; if (mga->flags & MAGIC_CONTINUE) mga->flags |= MAGIC_RAW; if (old_flags != mga->flags) restore_flags = 1; if (restore_flags) magic_setflags_wrapper(cookie, mga->flags); NOGVL(nogvl_magic_file, mga); local_errno = errno; /* * The Magic library often does not correctly report errors, * especially when certain flags (such as e.g., MAGIC_EXTENSION, * etc.) are set. Attempt to obtain an error code first from the * Magic library itself, and if that does not work, then from * the saved errno value. */ if (magic_errno_wrapper(cookie) || local_errno) mga->status = -1; if (restore_flags) magic_setflags_wrapper(cookie, old_flags); return (VALUE)NULL; } static VALUE magic_buffer_internal(void *data) { int restore_flags = 0; rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; int old_flags = mga->flags; if (mga->flags & MAGIC_CONTINUE) mga->flags |= MAGIC_RAW; if (old_flags != mga->flags) restore_flags = 1; if (restore_flags) magic_setflags_wrapper(cookie, mga->flags); mga->result = magic_buffer_wrapper(cookie, (const void *)mga->buffers.pointers, (size_t)mga->buffers.sizes, mga->flags); mga->status = !mga->result ? -1 : 0; if (restore_flags) magic_setflags_wrapper(cookie, old_flags); return (VALUE)NULL; } static VALUE magic_descriptor_internal(void *data) { int restore_flags = 0; rb_mgc_arguments_t *mga = data; magic_t cookie = mga->magic_object->cookie; int old_flags = mga->flags; if (mga->flags & MAGIC_CONTINUE) mga->flags |= MAGIC_RAW; if (old_flags != mga->flags) restore_flags = 1; if (restore_flags) magic_setflags_wrapper(cookie, mga->flags); NOGVL(nogvl_magic_descriptor, mga); if (restore_flags) magic_setflags_wrapper(cookie, old_flags); return (VALUE)NULL; } static inline void* magic_library_open(void) { magic_t cookie; cookie = magic_open_wrapper(MAGIC_NONE); if (!cookie) { errno = ENOMEM; return NULL; } return cookie; } static inline void magic_library_close(void *data) { rb_mgc_object_t *mgc = data; assert(mgc != NULL && "Must be a valid pointer to `rb_mgc_object_t' type"); if (mgc->cookie) magic_close_wrapper(mgc->cookie); mgc->cookie = NULL; } static VALUE magic_allocate(VALUE klass) { int local_errno; rb_mgc_object_t *mgc; mgc = RB_ALLOC(rb_mgc_object_t); local_errno = ENOMEM; if (!mgc) { errno = local_errno; MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError, local_errno, E_NOT_ENOUGH_MEMORY); } assert(mgc != NULL && "Must be a valid pointer to `rb_mgc_object_t' type"); mgc->cookie = NULL; mgc->mutex = Qundef; mgc->database_loaded = 0; mgc->stop_on_errors = 0; mgc->cookie = magic_library_open(); local_errno = errno; if (!mgc->cookie) { ruby_xfree(mgc); mgc = NULL; errno = local_errno; MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError, local_errno, E_MAGIC_LIBRARY_INITIALIZE); } return TypedData_Wrap_Struct(klass, &rb_mgc_type, mgc); } static inline void magic_mark(void *data) { rb_mgc_object_t *mgc = data; assert(mgc != NULL && "Must be a valid pointer to `rb_mgc_object_t' type"); MAGIC_GC_MARK(mgc->mutex); } static inline void magic_free(void *data) { rb_mgc_object_t *mgc = data; assert(mgc != NULL && "Must be a valid pointer to `rb_mgc_object_t' type"); if (mgc->cookie) magic_library_close(data); mgc->cookie = NULL; mgc->mutex = Qundef; ruby_xfree(mgc); } static inline size_t magic_size(const void *data) { const rb_mgc_object_t *mgc = data; assert(mgc != NULL && "Must be a valid pointer to `rb_mgc_object_t' type"); return sizeof(*mgc); } #if defined(HAVE_RUBY_GC_COMPACT) static inline void magic_compact(void *data) { rb_mgc_object_t *mgc = data; assert(mgc != NULL && "Must be a valid pointer to `rb_mgc_object_t' type"); mgc->mutex = rb_gc_location(mgc->mutex); } #endif /* HAVE_RUBY_GC_COMPACT */ static inline VALUE magic_exception_wrapper(VALUE value) { rb_mgc_error_t *mge = (rb_mgc_error_t *)value; return rb_exc_new2(mge->klass, mge->magic_error); } static VALUE magic_exception(void *data) { int exception = 0; rb_mgc_error_t *mge = data; VALUE object = Qundef; assert(mge != NULL && "Must be a valid pointer to `rb_mgc_error_t' type"); object = rb_protect(magic_exception_wrapper, (VALUE)mge, &exception); if (exception) rb_jump_tag(exception); rb_iv_set(object, "@errno", INT2NUM(mge->magic_errno)); RB_GC_GUARD(object); return object; } static inline VALUE magic_generic_error(VALUE klass, int magic_errno, const char *magic_error) { rb_mgc_error_t mge; mge = (rb_mgc_error_t) { .klass = klass, .magic_errno = magic_errno, .magic_error = magic_error, }; return magic_exception(&mge); } static VALUE magic_library_error(VALUE klass, void *data) { rb_mgc_error_t mge; const char *message = NULL; const char *empty = "(null)"; magic_t cookie = data; UNUSED(empty); assert(cookie != NULL && "Must be a valid pointer to `magic_t' type"); mge = (rb_mgc_error_t) { .klass = klass, .magic_errno = -1, .magic_error = MAGIC_ERRORS(E_UNKNOWN), }; message = magic_error_wrapper(cookie); if (message) { mge.magic_errno = magic_errno_wrapper(cookie); mge.magic_error = message; } assert(strncmp(mge.magic_error, empty, strlen(empty)) != 0 && "Empty or invalid error message"); return magic_exception(&mge); } VALUE magic_lock(VALUE object, VALUE(*function)(ANYARGS), void *data) { rb_mgc_object_t *mgc; MAGIC_OBJECT(object, mgc); rb_funcall(mgc->mutex, rb_intern("lock"), 0); return rb_ensure(function, (VALUE)data, magic_unlock, object); } VALUE magic_unlock(VALUE object) { rb_mgc_object_t *mgc; MAGIC_OBJECT(object, mgc); rb_funcall(mgc->mutex, rb_intern("unlock"), 0); return Qnil; } static VALUE magic_return(void *data) { rb_mgc_arguments_t *mga = data; const char *unknown = NULL; VALUE separator = Qundef; VALUE array, string; string = CSTR2RVAL(mga->result); RB_GC_GUARD(string); /* * The value below is a field separator that can be used to split results * when the CONTINUE flag is set causing all valid matches found by the * Magic library to be returned. */ if (mga->flags & MAGIC_CONTINUE) separator = CSTR2RVAL(MAGIC_CONTINUE_SEPARATOR); if (mga->flags & MAGIC_EXTENSION) { /* * A possible I/O-related error has occurred, and there is very * little sense processing the results, so return string as-is. */ if (mga->status < 0) return string; /* * A number of Magic flags that support primarily files e.g., * MAGIC_EXTENSION, etc., would not return a meaningful value for * directories and special files, and such. Thus, it's better to * return an empty string, to indicate lack of results, rather * than a confusing string consisting of three questions marks. */ unknown = "???"; if (strncmp(mga->result, unknown, strlen(unknown)) == 0) return CSTR2RVAL(""); separator = CSTR2RVAL(MAGIC_EXTENSION_SEPARATOR); } RB_GC_GUARD(separator); if (mga->flags & (MAGIC_CONTINUE | MAGIC_EXTENSION)) { array = magic_split(string, separator); RB_GC_GUARD(array); if (RARRAY_LEN(array) > 1) return magic_strip_array(array); string = magic_shift(array); } return magic_strip(string); } static inline int magic_get_flags(VALUE object) { return NUM2INT(rb_ivar_get(object, id_at_flags)); } static inline void magic_set_flags(VALUE object, int flags) { rb_ivar_set(object, id_at_flags, INT2NUM(flags)); } static inline VALUE magic_set_paths(VALUE object, VALUE value) { return rb_ivar_set(object, id_at_paths, value); } static const rb_data_type_t rb_mgc_type = { .wrap_struct_name = "magic", .function = { .dmark = magic_mark, .dfree = magic_free, .dsize = magic_size, #if defined(HAVE_RUBY_GC_COMPACT) .dcompact = magic_compact, #endif /* HAVE_RUBY_GC_COMPACT */ }, #if defined(RUBY_TYPED_FREE_IMMEDIATELY) .flags = RUBY_TYPED_FREE_IMMEDIATELY, #endif /* RUBY_TYPED_FREE_IMMEDIATELY */ }; void Init_magic(void) { id_at_paths = rb_intern("@paths"); id_at_flags = rb_intern("@flags"); rb_cMagic = rb_define_class("Magic", rb_cObject); rb_define_alloc_func(rb_cMagic, magic_allocate); /* * Raised when _Magic_ encounters an error. */ rb_mgc_eError = rb_define_class_under(rb_cMagic, "Error", rb_eStandardError); /* * Stores current value of +errno+ */ rb_define_attr(rb_mgc_eError, "errno", 1, 0); /* * Raised when */ rb_mgc_eMagicError = rb_define_class_under(rb_cMagic, "MagicError", rb_mgc_eError); /* * Raised when */ rb_mgc_eLibraryError = rb_define_class_under(rb_cMagic, "LibraryError", rb_mgc_eError); /* * Raised when */ rb_mgc_eParameterError = rb_define_class_under(rb_cMagic, "ParameterError", rb_mgc_eError); /* * Raised when */ rb_mgc_eFlagsError = rb_define_class_under(rb_cMagic, "FlagsError", rb_mgc_eError); /* * Raised when */ rb_mgc_eNotImplementedError = rb_define_class_under(rb_cMagic, "NotImplementedError", rb_mgc_eError); rb_define_singleton_method(rb_cMagic, "do_not_auto_load", RUBY_METHOD_FUNC(rb_mgc_get_do_not_auto_load_global), 0); rb_define_singleton_method(rb_cMagic, "do_not_auto_load=", RUBY_METHOD_FUNC(rb_mgc_set_do_not_auto_load_global), 1); rb_define_singleton_method(rb_cMagic, "do_not_stop_on_error", RUBY_METHOD_FUNC(rb_mgc_get_do_not_stop_on_error_global), 0); rb_define_singleton_method(rb_cMagic, "do_not_stop_on_error=", RUBY_METHOD_FUNC(rb_mgc_set_do_not_stop_on_error_global), 1); rb_define_singleton_method(rb_cMagic, "version", RUBY_METHOD_FUNC(rb_mgc_version), 0); rb_define_method(rb_cMagic, "initialize", RUBY_METHOD_FUNC(rb_mgc_initialize), -2); rb_define_method(rb_cMagic, "do_not_stop_on_error", RUBY_METHOD_FUNC(rb_mgc_get_do_not_stop_on_error), 0); rb_define_method(rb_cMagic, "do_not_stop_on_error=", RUBY_METHOD_FUNC(rb_mgc_set_do_not_stop_on_error), 1); rb_define_method(rb_cMagic, "open?", RUBY_METHOD_FUNC(rb_mgc_open_p), 0); rb_define_method(rb_cMagic, "close", RUBY_METHOD_FUNC(rb_mgc_close), 0); rb_define_method(rb_cMagic, "closed?", RUBY_METHOD_FUNC(rb_mgc_close_p), 0); rb_define_method(rb_cMagic, "paths", RUBY_METHOD_FUNC(rb_mgc_get_paths), 0); rb_define_method(rb_cMagic, "get_parameter", RUBY_METHOD_FUNC(rb_mgc_get_parameter), 1); rb_define_method(rb_cMagic, "set_parameter", RUBY_METHOD_FUNC(rb_mgc_set_parameter), 2); rb_define_method(rb_cMagic, "flags", RUBY_METHOD_FUNC(rb_mgc_get_flags), 0); rb_define_method(rb_cMagic, "flags=", RUBY_METHOD_FUNC(rb_mgc_set_flags), 1); rb_define_method(rb_cMagic, "file", RUBY_METHOD_FUNC(rb_mgc_file), 1); rb_define_method(rb_cMagic, "buffer", RUBY_METHOD_FUNC(rb_mgc_buffer), 1); rb_define_method(rb_cMagic, "descriptor", RUBY_METHOD_FUNC(rb_mgc_descriptor), 1); rb_alias(rb_cMagic, rb_intern("fd"), rb_intern("descriptor")); rb_define_method(rb_cMagic, "load", RUBY_METHOD_FUNC(rb_mgc_load), -2); rb_define_method(rb_cMagic, "load_buffers", RUBY_METHOD_FUNC(rb_mgc_load_buffers), -2); rb_define_method(rb_cMagic, "loaded?", RUBY_METHOD_FUNC(rb_mgc_load_p), 0); rb_alias(rb_cMagic, rb_intern("load_files"), rb_intern("load")); rb_define_method(rb_cMagic, "compile", RUBY_METHOD_FUNC(rb_mgc_compile), 1); rb_define_method(rb_cMagic, "check", RUBY_METHOD_FUNC(rb_mgc_check), 1); rb_alias(rb_cMagic, rb_intern("valid?"), rb_intern("check")); /* * Controls how many levels of recursion will be followed for * indirect magic entries. */ MAGIC_DEFINE_PARAMETER(INDIR_MAX); /* * Controls the maximum number of calls for name or use magic. */ MAGIC_DEFINE_PARAMETER(NAME_MAX); /* * Controls how many ELF program sections will be processed. */ MAGIC_DEFINE_PARAMETER(ELF_PHNUM_MAX); /* * Controls how many ELF sections will be processed. */ MAGIC_DEFINE_PARAMETER(ELF_SHNUM_MAX); /* * Controls how many ELF notes will be processed. */ MAGIC_DEFINE_PARAMETER(ELF_NOTES_MAX); /* * Controls the length limit for regular expression searches. */ MAGIC_DEFINE_PARAMETER(REGEX_MAX); /* * Controls the maximum number of bytes to read from a file. */ MAGIC_DEFINE_PARAMETER(BYTES_MAX); /* * No special handling and/or flags specified. Default behavior. */ MAGIC_DEFINE_FLAG(NONE); /* * Print debugging messages to standard error output. */ MAGIC_DEFINE_FLAG(DEBUG); /* * If the file queried is a symbolic link, follow it. */ MAGIC_DEFINE_FLAG(SYMLINK); /* * If the file is compressed, unpack it and look at the contents. */ MAGIC_DEFINE_FLAG(COMPRESS); /* * If the file is a block or character special device, then open * the device and try to look at the contents. */ MAGIC_DEFINE_FLAG(DEVICES); /* * Return a MIME type string, instead of a textual description. */ MAGIC_DEFINE_FLAG(MIME_TYPE); /* * Return all matches, not just the first. */ MAGIC_DEFINE_FLAG(CONTINUE); /* * Check the Magic database for consistency and print warnings to * standard error output. */ MAGIC_DEFINE_FLAG(CHECK); /* * Attempt to preserve access time (atime, utime or utimes) of the * file queried on systems that support such system calls. */ MAGIC_DEFINE_FLAG(PRESERVE_ATIME); /* * Do not convert unprintable characters to an octal representation. */ MAGIC_DEFINE_FLAG(RAW); /* * Treat operating system errors while trying to open files and follow * symbolic links as first class errors, instead of storing them in the * Magic library error buffer for retrieval later. */ MAGIC_DEFINE_FLAG(ERROR); /* * Return a MIME encoding, instead of a textual description. */ MAGIC_DEFINE_FLAG(MIME_ENCODING); /* * A shorthand for using MIME_TYPE and MIME_ENCODING flags together. */ MAGIC_DEFINE_FLAG(MIME); /* * Return the Apple creator and type. */ MAGIC_DEFINE_FLAG(APPLE); /* * Do not look for, or inside compressed files. */ MAGIC_DEFINE_FLAG(NO_CHECK_COMPRESS); /* * Do not allow decompression that needs to fork. */ MAGIC_DEFINE_FLAG(NO_COMPRESS_FORK); /* * Do not look for, or inside tar archive files. */ MAGIC_DEFINE_FLAG(NO_CHECK_TAR); /* * Do not consult Magic files. */ MAGIC_DEFINE_FLAG(NO_CHECK_SOFT); /* * Check for EMX application type (only supported on EMX). */ MAGIC_DEFINE_FLAG(NO_CHECK_APPTYPE); /* * Do not check for ELF files (do not examine ELF file details). */ MAGIC_DEFINE_FLAG(NO_CHECK_ELF); /* * Do not check for various types of text files. */ MAGIC_DEFINE_FLAG(NO_CHECK_TEXT); /* * Do not check for CDF files. */ MAGIC_DEFINE_FLAG(NO_CHECK_CDF); /* * Do not check for CSV files. */ MAGIC_DEFINE_FLAG(NO_CHECK_CSV); /* * Do not look for known tokens inside ASCII files. */ MAGIC_DEFINE_FLAG(NO_CHECK_TOKENS); /* * Return a MIME encoding, instead of a textual description. */ MAGIC_DEFINE_FLAG(NO_CHECK_ENCODING); /* * Do not check for JSON files. */ MAGIC_DEFINE_FLAG(NO_CHECK_JSON); /* * Do not use built-in tests; only consult the Magic file. */ MAGIC_DEFINE_FLAG(NO_CHECK_BUILTIN); /* * Do not check for various types of text files, same as NO_CHECK_TEXT. */ MAGIC_DEFINE_FLAG(NO_CHECK_ASCII); /* * Do not look for Fortran sequences inside ASCII files. */ MAGIC_DEFINE_FLAG(NO_CHECK_FORTRAN); /* * Do not look for troff sequences inside ASCII files. */ MAGIC_DEFINE_FLAG(NO_CHECK_TROFF); /* * Return a slash-separated list of extensions for this file type. */ MAGIC_DEFINE_FLAG(EXTENSION); /* * Do not report on compression, only report about the uncompressed data. */ MAGIC_DEFINE_FLAG(COMPRESS_TRANSP); } #if defined(__cplusplus) } #endif ruby-magic-0.6.0/ext/magic/ruby-magic.h000066400000000000000000000227571440414250500176600ustar00rootroot00000000000000#if !defined(_RUBY_MAGIC_H) #define _RUBY_MAGIC_H 1 #if defined(__cplusplus) extern "C" { #endif #include "common.h" #include "functions.h" #define MAGIC_SYNCHRONIZED(f, d) magic_lock(object, (f), (d)) #define MAGIC_OBJECT(o, t) \ TypedData_Get_Struct((o), rb_mgc_object_t, &rb_mgc_type, (t)) #define MAGIC_CLOSED_P(o) RTEST(rb_mgc_close_p((o))) #define MAGIC_LOADED_P(o) RTEST(rb_mgc_load_p((o))) #define MAGIC_WARNING(i, ...) \ do { \ if (!(i) || !(rb_mgc_warning & BIT(i))) { \ rb_mgc_warning |= BIT(i); \ rb_warn(__VA_ARGS__); \ } \ } while (0) #define MAGIC_ERRORS(t) ruby_magic_errors[(t)] #define MAGIC_ARGUMENT_TYPE_ERROR(o, ...) \ rb_raise(rb_eTypeError, MAGIC_ERRORS(E_ARGUMENT_TYPE_INVALID), CLASS_NAME((o)), __VA_ARGS__) #define MAGIC_GENERIC_ERROR(k, e, m) \ rb_exc_raise(magic_generic_error((k), (e), MAGIC_ERRORS(m))) #define MAGIC_LIBRARY_ERROR(c) \ rb_exc_raise(magic_library_error(rb_mgc_eMagicError, (c)->cookie)) #define MAGIC_CHECK_INTEGER_TYPE(o) magic_check_type((o), T_FIXNUM) #define MAGIC_CHECK_STRING_TYPE(o) magic_check_type((o), T_STRING) #define MAGIC_CHECK_ARRAY_OF_STRINGS(o) \ magic_check_type_array_of_strings((o)) #define MAGIC_CHECK_ARGUMENT_MISSING(t, o) \ do { \ if ((t) < (o)) \ rb_raise(rb_eArgError, MAGIC_ERRORS(E_ARGUMENT_MISSING), (t), (o)); \ } while (0) #define MAGIC_CHECK_ARRAY_EMPTY(o) \ do { \ if (RARRAY_EMPTY_P(o)) \ rb_raise(rb_eArgError, "%s", MAGIC_ERRORS(E_ARGUMENT_TYPE_ARRAY_EMPTY)); \ } while (0) #define MAGIC_CHECK_OPEN(o) \ do { \ if (MAGIC_CLOSED_P(o)) \ MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError, EFAULT, \ E_MAGIC_LIBRARY_CLOSED); \ } while (0) #define MAGIC_CHECK_LOADED(o) \ do { \ if (!MAGIC_LOADED_P(o)) \ MAGIC_GENERIC_ERROR(rb_mgc_eMagicError, EFAULT, \ E_MAGIC_LIBRARY_NOT_LOADED); \ } while (0) #define MAGIC_STRINGIFY(s) #s #define MAGIC_DEFINE_FLAG(c) \ rb_define_const(rb_cMagic, MAGIC_STRINGIFY(c), INT2NUM(MAGIC_##c)) #define MAGIC_DEFINE_PARAMETER(c) \ rb_define_const(rb_cMagic, MAGIC_STRINGIFY(PARAM_##c), INT2NUM(MAGIC_PARAM_##c)) enum ruby_magic_error { E_UNKNOWN = 0, E_NOT_ENOUGH_MEMORY, E_ARGUMENT_MISSING, E_ARGUMENT_TYPE_INVALID, E_ARGUMENT_TYPE_UNKNOWN, E_ARGUMENT_TYPE_ARRAY_EMPTY, E_ARGUMENT_TYPE_ARRAY_STRINGS, E_MAGIC_LIBRARY_INITIALIZE, E_MAGIC_LIBRARY_CLOSED, E_MAGIC_LIBRARY_NOT_LOADED, E_PARAM_INVALID_TYPE, E_PARAM_INVALID_VALUE, E_FLAG_NOT_IMPLEMENTED, E_FLAG_INVALID_TYPE }; struct parameter { int tag; size_t value; }; union file { const char *path; int fd; }; struct buffers { size_t count; size_t *sizes; void **pointers; }; typedef struct magic_object { magic_t cookie; VALUE mutex; unsigned int database_loaded:1; unsigned int stop_on_errors:1; } rb_mgc_object_t; typedef struct magic_arguments { rb_mgc_object_t *magic_object; union { struct parameter parameter; union file file; struct buffers buffers; }; const char *result; int status; int flags; } rb_mgc_arguments_t; typedef struct magic_error { const char *magic_error; VALUE klass; int magic_errno; } rb_mgc_error_t; static const char * const ruby_magic_errors[] = { [E_UNKNOWN] = "an unknown error has occurred", [E_NOT_ENOUGH_MEMORY] = "cannot allocate memory", [E_ARGUMENT_MISSING] = "wrong number of arguments (given %d, expected %d)", [E_ARGUMENT_TYPE_INVALID] = "wrong argument type %s (expected %s)", [E_ARGUMENT_TYPE_UNKNOWN] = "unknown type 0x%x (0x%x given)", [E_ARGUMENT_TYPE_ARRAY_EMPTY] = "arguments list cannot be empty (expected array of String)", [E_ARGUMENT_TYPE_ARRAY_STRINGS] = "wrong argument type %s in arguments list (expected String)", [E_MAGIC_LIBRARY_INITIALIZE] = "failed to initialize Magic library", [E_MAGIC_LIBRARY_CLOSED] = "Magic library is not open", [E_MAGIC_LIBRARY_NOT_LOADED] = "Magic library not loaded", [E_PARAM_INVALID_TYPE] = "unknown or invalid parameter specified", [E_PARAM_INVALID_VALUE] = "invalid parameter value specified", [E_FLAG_NOT_IMPLEMENTED] = "flag is not implemented", [E_FLAG_INVALID_TYPE] = "unknown or invalid flag specified", NULL }; #if defined(MAGIC_CUSTOM_CHECK_TYPE) static const char * const magic_ruby_types[] = { "", /* Not an object */ [T_OBJECT] = "Object", [T_CLASS] = "Class", [T_MODULE] = "Module", [T_FLOAT] = "Float", [T_STRING] = "String", [T_REGEXP] = "Regexp", [T_ARRAY] = "Array", [T_HASH] = "Hash", [T_STRUCT] = "Struct", [T_BIGNUM] = "Integer", [T_FILE] = "File", "", /* Internal use */ [T_MATCH] = "MatchData", [T_COMPLEX] = "Complex", [T_RATIONAL] = "Rational", "", /* Internal use */ [T_NIL] = "nil", [T_TRUE] = "true", [T_FALSE] = "false", [T_SYMBOL] = "Symbol", [T_FIXNUM] = "Integer", "", /* Internal use */ NULL }; static const char * magic_ruby_type_name(int type) { const char *name; if (type >= ARRAY_SIZE(magic_ruby_types)) return NULL; name = magic_ruby_types[type]; if (name) return name; return NULL; } static const char * magic_ruby_class_name(VALUE object) { const char *name = NULL; if (NIL_P(object)) name = "nil"; else if (RB_TYPE_P(object, T_TRUE)) name = "true"; else if (RB_TYPE_P(object, T_FALSE)) name = "false"; else name = CLASS_NAME(object); return name; } void magic_check_ruby_type(VALUE object, int type) { const char *name; int object_type = TYPE(object); if (object == Qundef) rb_bug("invalid type leaked to the Ruby space"); if (object_type > T_MASK || object_type == T_DATA) goto error; if (object_type == type) return; name = magic_ruby_type_name(type); if (name) rb_raise(rb_eTypeError, MAGIC_ERRORS(E_ARGUMENT_TYPE_INVALID), magic_ruby_class_name(object), name); error: rb_raise(rb_eTypeError, MAGIC_ERRORS(E_ARGUMENT_TYPE_UNKNOWN), object_type, type); } #endif /* MAGIC_CUSTOM_CHECK_TYPE */ static inline VALUE magic_strip(VALUE v) { return (ARRAY_P(v) || STRING_P(v)) ? rb_funcall(v, rb_intern("strip"), 0) : Qnil; } static inline VALUE magic_shift(VALUE v) { return ARRAY_P(v) ? rb_funcall(v, rb_intern("shift"), 0) : Qnil; } static inline VALUE magic_split(VALUE a, VALUE b) { return (STRING_P(a) && STRING_P(b)) ? rb_funcall(a, rb_intern("split"), 1, b) : Qnil; } static inline VALUE magic_join(VALUE a, VALUE b) { return (ARRAY_P(a) && STRING_P(b)) ? rb_funcall(a, rb_intern("join"), 1, b) : Qnil; } static inline VALUE magic_flatten(VALUE v) { return ARRAY_P(v) ? rb_funcall(v, rb_intern("flatten"), 0) : Qnil; } static inline VALUE magic_strip_array(VALUE value) { VALUE entry; VALUE array = rb_ary_new(); for (int i = 0; i < RARRAY_LEN(value); i++) { entry = rb_ary_entry(value, i); if (NIL_P(entry)) continue; if (STRING_P(entry)) { if (RSTRING_EMPTY_P(entry)) continue; entry = magic_strip(entry); } rb_ary_push(array, entry); } return array; } static int magic_fileno(VALUE object) { int fd; rb_io_t *io; if (rb_respond_to(object, rb_intern("fileno"))) { object = rb_funcall(object, rb_intern("fileno"), 0); return NUM2INT(object); } if (!FILE_P(object)) object = rb_convert_type(object, T_FILE, "IO", "to_io"); GetOpenFile(object, io); fd = FPTR_TO_FD(io); if (fd < 0) rb_raise(rb_eIOError, "closed stream"); return fd; } static inline VALUE magic_path(VALUE object) { if (STRING_P(object)) return object; if (rb_respond_to(object, rb_intern("to_path"))) return rb_funcall(object, rb_intern("to_path"), 0); if (rb_respond_to(object, rb_intern("path"))) return rb_funcall(object, rb_intern("path"), 0); if (rb_respond_to(object, rb_intern("to_s"))) return rb_funcall(object, rb_intern("to_s"), 0); return Qnil; } static inline void magic_check_type(VALUE object, RVALUE_TYPE type) { VALUE boolean; boolean = rb_obj_is_kind_of(object, T_INTEGER); if (type == T_FIXNUM && !RVAL2CBOOL(boolean)) MAGIC_ARGUMENT_TYPE_ERROR(object, rb_class2name(T_INTEGER)); MAGIC_CHECK_RUBY_TYPE(object, type); } static inline void magic_check_type_array_of_strings(VALUE object) { VALUE value; for (int i = 0; i < RARRAY_LEN(object); i++) { value = RARRAY_AREF(object, (long)i); if (NIL_P(value) || !STRING_P(value)) rb_raise(rb_eTypeError, MAGIC_ERRORS(E_ARGUMENT_TYPE_ARRAY_STRINGS), CLASS_NAME(value)); } } void Init_magic(void); VALUE rb_mgc_get_do_not_auto_load_global(VALUE object); VALUE rb_mgc_set_do_not_auto_load_global(VALUE object, VALUE value); VALUE rb_mgc_get_do_not_stop_on_error_global(VALUE object); VALUE rb_mgc_set_do_not_stop_on_error_global(VALUE object, VALUE value); VALUE rb_mgc_initialize(VALUE object, VALUE arguments); VALUE rb_mgc_get_do_not_stop_on_error(VALUE object); VALUE rb_mgc_set_do_not_stop_on_error(VALUE object, VALUE value); VALUE rb_mgc_open_p(VALUE object); VALUE rb_mgc_close(VALUE object); VALUE rb_mgc_close_p(VALUE object); VALUE rb_mgc_get_paths(VALUE object); VALUE rb_mgc_get_parameter(VALUE object, VALUE tag); VALUE rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value); VALUE rb_mgc_get_flags(VALUE object); VALUE rb_mgc_set_flags(VALUE object, VALUE value); VALUE rb_mgc_load(VALUE object, VALUE arguments); VALUE rb_mgc_load_buffers(VALUE object, VALUE arguments); VALUE rb_mgc_load_p(VALUE object); VALUE rb_mgc_compile(VALUE object, VALUE arguments); VALUE rb_mgc_check(VALUE object, VALUE arguments); VALUE rb_mgc_file(VALUE object, VALUE value); VALUE rb_mgc_buffer(VALUE object, VALUE value); VALUE rb_mgc_descriptor(VALUE object, VALUE value); VALUE rb_mgc_version(VALUE object); #if defined(__cplusplus) } #endif #endif /* _RUBY_MAGIC_H */ ruby-magic-0.6.0/kwilczynski-public.pem000066400000000000000000000027251440414250500201210ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIEIDCCAoigAwIBAgIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDDBJrdy9E Qz1saW51eC9EQz1jb20wHhcNMjEwMTAxMDAwOTU0WhcNMjYwMTAxMDAwOTU0WjAd MRswGQYDVQQDDBJrdy9EQz1saW51eC9EQz1jb20wggGiMA0GCSqGSIb3DQEBAQUA A4IBjwAwggGKAoIBgQCv02+pOrAMVUipLY7qjNLx8OMfMjnVCBH21SsWn8gyIHE9 BtQ+tlsJU8nWNjlr++7SKIV5vQmyYsC2UY0cdcFASdoV0A3Lc2Z0makfvPgcIlpL 5THqQtP11tJfhjQ3MSFJYRG2D6m6GNqA+WTTsvJbPIxy5PHv5xb+79LLzcVxB9Op C0ervTOF8W6Ye4EDvhQ5tppOr/d26UQV+8zRuxjxx5uZSPfUrE9u/gIIdeROoB3T cnjAfzvjIzampLQppvhUnT4Vf5Rum2LohZ5GosKLy7tM65vr1eLyI2ndvS1MXWrU 05sFKm5CSqORD+TVkR1jd3z5HdPgO1KwadccxFixoI8kEIt/iixWTzbka2T2iJoq 5DeNMEMYYAZKuAGBzBcgvgPccCeAXFVF9AHjfaGRUMmYNHKK2HD6AdgNdhcE18V+ CJxFtggCJFYc1ygFOsHZPTbKo9+3ybSQhAswtDosWt26utUT1JOc2Bkj1sgQ0Yrk orANsdYz2ee3JFkzx08CAwEAAaNrMGkwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw HQYDVR0OBBYEFME41mMBb/XAHgjhlX4kE8xnXxewMBcGA1UdEQQQMA6BDGt3QGxp bnV4LmNvbTAXBgNVHRIEEDAOgQxrd0BsaW51eC5jb20wDQYJKoZIhvcNAQELBQAD ggGBAF/2ryrSgTpf0+wYG46Oi6V3p9A3uMxxbGsh0ZmlLQT1Z1ozclR+xzxzyIFC i7YWYyR085brDBnYNXgnUT9Nm4iAYx58MaPD28IFrcX0XA3DJE6Wkx4MmMV0chiJ kf5ASikfGtFtf9qDmpLQB4louB6HpKNq1MwsQo8zwY93t77HCiV5f0g43rcZfGTn wfBhpT7oOVWgfTLeBD811aS52VUCWclmnz+f01GdTeMwqsgc6oJaPSvg4JCMN94O wcBlxus69rhM8PeTJNhwLxzRCNnZ69t9k2cU+4lTmQQIB8gnEFJxY9gZdgQ6pej0 HXUIut+6pp5BRYF2mTZ3fnxhWyIZaeB7lla2gI6rV2GXDbp4kVplGEuQ975YklJw i4y7bz2Es4Hkly2Nc/J2L0+uMoBhMWMY3Xl0XDdkZYtBdnSB5g7NacChaAsukEkd Ozt6vfXxSzW/KfodB+0ELjlHWiFbI8w7c8Kt7/ceZGVsXTxD/f4tVWy8MmxFy3pY Cpe8Kg== -----END CERTIFICATE----- ruby-magic-0.6.0/kwilczynski.asc000066400000000000000000001757631440414250500166470ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- mQINBFnWkEoBEACzKJK53/bCbBhwCeDUBJp8J/VPtbKKaYFksMaBH7QAS32J2UI9 8/15JunhBwUwu17+95EXkUcnno0l44IwUSm3W4sYJXIQPwjtI7lIrLUavfky9D1m QYlef6x8UP68UgfA9tolpH7/g6n9M4gmEFyGJ8cPs/U0Efxawv/no08cX+HBgB/Y GrMj9pVyZpsUDpA1gxexhf7EoxhxHi9o2cZep0VPBL3B2mCz9M1kc7eoIe5SwyIx N9lFXjNMTiguGfUgShm7YkhrLO1tlZyyLpd+Oh7JYP6s07rjpWMn8mtZoatzoAQt VmodChQugH56b8kSkEgx35cUu5sn1rrPxYLt+C1sOCvtZ1tiKjvTFxxx233xDr61 2Q82KL7vhIiO+ZuhfGsnoyTchOjS8uHHVTpFCRzpJy1BsQCySuzGYHugYGfVd6is 9oQyZEjfPQiri3Zoo5K++YEr4FC+V4VI5VTwAnF2KJ+YsBIUAbgTBMpqFNlmDC2U 0IB2dVPaes36GjyXF0YIf0EBEUq/crHE7p+qrN25V+w0DiKT6OM+Dot3HlK/qdJK bnCVKTJsRZ3HxdHwewcJ/hcDpqy0EVRUq4RAPF4i6M+4rEsNUxXegK/OiqYqAI5F ut0160cA1nPqNzCLkT73jA6tBxQQ0Ideec9eq2/QDHdvTwcWIiISkiN51wARAQAB tCNLcnp5c3p0b2YgV2lsY3p5bnNraSA8a3dAbGludXguY29tPokDRwQTAQgBMQIb AwULAgkNAwQVCAkKBRYDAQIAAh4BAheAAhkBFiEEEtJ9XYyOm/GqvHx8fGR2jT3j NOcFAmOjb/ZdFIAAAAAAEABEcHJvb2ZAYXJpYWRuZS5pZGh0dHBzOi8vZ2lzdC5n aXRodWIuY29tL2t3aWxjenluc2tpLzU3ZDgxODBkNjgyZGVlOTM4OGNhYTEzN2Mz OTc5YThjOhSAAAAAABAAIXByb29mQGFyaWFkbmUuaWRpcmM6Ly9pcmMubGliZXJh LmNoYXQva3dpbGN6eW5za2kvFIAAAAAAEAAWcHJvb2ZAYXJpYWRuZS5pZGRuczph cmlha2UucGw/dHlwZT1UWFQtFIAAAAAAEAAUcHJvb2ZAYXJpYWRuZS5pZGRuczpm c2NrLmlvP3R5cGU9VFhUAAoJEHxkdo094zTnigEP/1HvFBlAg6EFHRE3w83FNlpI mKV2GcG0bpqnnn+zDvg3/tFAYpa5NVdaoPR5jpEGxIavIwMXoJ8QpNT0cmH/cW6N YgjU9B+V2g54hFzpjrh+qTtok+421SJdq/he38+OYCtNva7F3TaSAsL+v9C5nNvJ FhL7HobIZPkoKJZwA0fixkqTwPWR4SvgVfvdPHQ7x/2LUQMN4OV8cAPtMusMu8rv XSwiNiFfRqdbJoWUB6fGwPj7Un42p6cNuM0aGPww547Kj1QdbIxzH3JhNhqevYqQ nBKZKJBJWSb0+s2hnHvwt3f3I9mKHnzu8caVpRw8r/0dcoFLhjtOZLkXK0U2DPKP L++b4DsuEV8QkTnCj7+4x9BaLGGLHfXh8SCy01yoYdT9T3aHfMSIQhhTXH2lb7Hm lXC1IA0J0XB6B81NAOvy5yv9Gpkd2pUiVVzRvu3mLnj9pNtDI5s4P4x/I6iofexJ qkCvLH6YJf5b52yQPzLhM85oOjrHX7Be+OBLv8NKBXQ9BzHYg/C217S1CwbULW9Y NqQB9SPYuMZu/J+PIY+GXtREQ0aBxZzh7G6Dkck1xI7BXL9s1amS4rim/EjdzoDi 8MiuOn8gs987W64L4eFhtHXmgJNl4ovEDyX4qhn2ANsN59ju18G1/0dL9YF9k341 7Lm737l7gCKsMxDXXIrgiQIzBBABCgAdFiEEgMe7l+5h9hnxdsnuWYigwDrT+vwF AmN36hQACgkQWYigwDrT+vyRDQ/+JIzjQidhw7RkLm4w4yP7t4m9qehG/OU0WY7o 3fKCNsTKL3iBHJArO+z6Frm8xsAsGfW6mjfuVGatzJkZfaJRAUlQQLvcF0tbgTA3 yLSK7YT8JUxFwSIUEF54j8TkV53SLYqp9Qi3VNmzWfQhE5R5mg9yhg7TPf2ICwzb QKa40OUh3thtIvl5Fg0Oag59yphE8MH2XJUZEo5zW/g7PP4u85AkTr5j+lh4bMa8 7XeacOyuVi0weyL5qaafnlNnNxU3vYT0xlLk9KUyB9IjRYwFD+4U4236O1+8WMdX P632j0GYeNmxUWmeqxmqlw1xirVCXQb67hL7RFNqr1WZo5FSVIdmuzqlZ3CBMRiA Ht9eWDGh9mRVmOc5CMSNGAcOiGax4Xd114gTWlwOkyC5W7bufju2U31GD2TCMu8V wp8apLqW7z8dCs1xmZy8BOsqbfdo/CRCxjXRBsGyEOV+cI1DuoYDAAAXBEcY01iJ +B4qMaYfl3C38OBqEveKq3byhhpQqEBU4gYREgvlwPyxAinTHUhgBVEXDMLgtDEe pcGKG/CxhDsfN33hJVdNG/eTbRGz4A2z2QZswESiFAbMtPKo9cJ3/XIt8EABk2ZX Sj0uN4mnkeKHweR6erIa0+ilPu89GZPL9SMGWLhh/T0kYqQdgNXRShUBCtxeYq+c iF+lohiJAjMEEAEKAB0WIQSpQNQ0mSwujpkQPVAiT6fnzIKmZAUCY39SzQAKCRAi T6fnzIKmZCdQEADHolgvjB7DoDd8B5S7VodSqlurqLJPEJCO+idlulwUKCsU6uHR NpFIyb3PEySEClsn0OOcdx/j/+9ydfrZkkYFJtwLFaFzeigiZVrlBOFII8adOr2f I4Huw1hYx8SmXKR+5bW0XNeE2L/Hd1Lg2Lfm+WClsLhXIsSmhFX3lFjchn/peqyX yaAFGSy2bred2KFwzkIdEXtk50/Sy1zK2J/Q0b+1NSfWrGhqktjZtYmMTsS/aCb7 l7eyy9LlkxTbvQymKnyhQKRKqEPIoJ4Z1MvkjXQvSNe3ixNuj+eWwvYXiLTjNo7t hNGdWs7izzewLpP3U/ujLa5ONRjMUvhijtK6nv+jJt6/hDbTPkXZU/Hra2gg/JMq t2T+ytNlaGA8DQU5XByM5xBH/axiC/G9br3psDPf9lT58Gn4xwI6SHWx00t9rPZd 4rnNlwCnGMyRZVQPqOz2TjIoC1RfngzOkLQ+i0yTIddQegYMJiHFnowt7/zQSv24 1x/iZhBzjJSeKWsNSqvzQjM4eC9jUTomhtG3Hrr69uD+Hd9SYdThwwfj4grScczD gRIj2Cmc4xizTKjXchfD8+nf1nGSWO+Bgic7uXJzxCAJUfdezLtLGLnjzUU2igoz gX2YHC+PzHHiQ7hfMRMDIi5kalcLhHHzsv+MHdmMGbxzrL7s1rZjaHv+WYkCMwQQ AQoAHRYhBFcOYyuTRhMQc2p7b4KLOaai0TZ/BQJjgI4lAAoJEIKLOaai0TZ/eFcP +wW4bFG5MzgcxRjV7JA4sTOUG24cuC5Pra5p8rqn8Cb19vnwezt4lO3pDQ2BDb8G 50IpSabmGIxCD/AlYBiBQVM3Y3y72rMEr+t6DAjQS6kIOxwrFJ7wZVSW2U9LLJ9W yDEBPvBike7E9vQNzfQ+JrZVl2EQMhrY3pQ4AgDJm312lBfRY2al+KagB9Q7h/8M pz5gEkeiyj9R2xc9c3vQBqcIAkK99ZVGMplEgvgHmama5FxkswzZo7/ZXBufl2Wn 03O//jgWMSmoAjVuypqKgsKBCiDyHWcv9KEb+NbJATHu/+idhBKGiF9uM7ahnkzQ dsbImILCxMz40+Qcm0VP2/mJgCcgoJiq5R45jesqZC8/rC8ZGY9V6IZKxbmxFtnn uDDaxjzDH0M0LcxFsIvj9pL2Hc7i15iC0s5b5j76uEAtYAWmVIld4Xyfo1xv+127 ZUGICmnDwl9W+UYxS6nZKpp0jCBTNAzxJRJTi+PvMymfuC0tj2vGddKBkyReYXjq XAN0MZiHJPV7EVeDAY3hyUai0tS+lrYiSy1Kzg1/bDWWCPk8oB4TV3oCxO6MjG2s Z9TwSCKdnlpaahbljz//1x7CJo4BO3BTW8PJvaa0hwufs7fpcZeEMZWDOxrSEfS/ p3OFy881htf+IVv2aQbJbtTDOXSA/MZV7HgI5gUSG+cDiQIzBBABCgAdFiEEm9B+ DgxR+NWWd7dUG5NDfTtBYpsFAmOIe90ACgkQG5NDfTtBYpu00g/9G2eYKLTorpYY aR362eMj/a0t6/wSoDOLqY4yq/h7yzpHbJDvOZjPpT+PZ9SSBJdFrwT/JXUqdyvW BnH0k7nH700NfeSM58swPgrgI1wlpfLlW//UjR3GxX11D4p3rccHO3kgeWQRi/+1 m3alqALmYgmq8uKwAtn8m/qd3Eb2rofKX2hwMtCJLRpmXeEDw5cq94uhcbjj8vJi 82UojB1Zy26vAzrRtOQ36vWqBnasVOL4m/TBFpr8/jyTauhWbil9x1ue6UgZZPCZ aYE+Y7W4o4d6Tgy60N3OmQAm/Tu6tt2JD9yWSfdwN3PVPYQ5oVCVkyZAyG/T5mjy /dVO0sBCUXpZl6+3tUbtJzhHP6td++TplQH9catrP1PzbplAB1KbwkBTgSfq5+oP xW30LjDbUxaHFXeuzbmHc2L/FLD1n0GUr3jv0rb7mAtmhjOq+XgdBo39AJlLCbaN awwin7bX3VjknFp0juuln2fg5BwFt2EGx6NTG2AxI1rICVmWru81RiF82220Fgru taa3fWlQzt4eTYz7jyiFKb0jLZjn6PrRpOq2/4BF+0CnOSEL3bV3I2aYD597Nycm QLZJ3HtnZ2EGZ1asTvGdE6T/fGmjBSWP+DqdXW7+q1rTxUs2pcXTL3BwEQcPLD0y DUFbSXsn5sJiSELSR53pHCCUvGmYA7y0M0tyenlzenRvZiBXaWxjenluc2tpIDxr cnp5c3p0b2Yud2lsY3p5bnNraUBmc2NrLmlvPokCTQQTAQgANxYhBBLSfV2Mjpvx qrx8fHxkdo094zTnBQJZ1pDBAhsDBQsCCQ0DBBUICQoFFgMBAgACHgECF4AACgkQ fGR2jT3jNOdupxAAqT1z4DgdPIiZHaBMBwtH1663YVAZpluRBgZYcqGEQW7e9rcB oxJbnlQQOUfOujfT5ykwhZkhDFyACkumqVMunHg5YZYah56mFe24xVB2aTjIVnJS aU46Tr5xnC4eGRfhJtYy/qhpOtRTw5tqx3BP2Aca5z4RgwDYL6LZyLslydW2eEPJ aPdDbaQUcE/6sY2cCAxkqnFCI+kHYZClkro2h7PGBz5Y9KwGfny5I124NB+6OT+O 74nbqiwYopg8IE23xnZOtjv4wsFz+xeCHtGKabodIeXuiblnmoDyaplJ9Toggi9k AlY/uCduicSFH+tmfZ2cN5rOY6y3BOXwCOXSvkX48eJVuYvGMtO0eEWNYi0O8EMa rtcCl0B/g6qS2CMQ1DuT7ndHIEiieXH4hRrZcvCFWP6WYepgMWhMtN9Xf6a6uRHc NTI86XMSg2psj+CMf8eKPk/qc5CKm318MSXZD/TxYEDu1Ypke+k2EcAl6gLjFFL9 WqLJV4MHH20hymog29oRB4W/7FMhQs5CuVJsyoNdsdgwoxUCbKPU3mwSex+QG25A q3FxrZo/GWkoxxVEoMyc6AcJ8wNJncMAWUH3aKz63lejeMe0gIYTNMLHAU6jBlBm 1VOsgGLpgTVqqbBHAINh4r8hdngb48FfRCI7wdo6XjS0TGbJagY/TOSKPX2JAjME EAEKAB0WIQSAx7uX7mH2GfF2ye5ZiKDAOtP6/AUCY3fqHgAKCRBZiKDAOtP6/B7N EAC29ZOOoBAhFjiLAYuzxY93qAPv+yAy2jmJkTZ5bMZg1dBvmtVXv0hOIddeBDxt S+wXyoyJRtBuDm5+7d0Ja5jl84+tdx494sA9lOpP3TNBLdJyPKsVosEI/VbmCarO N6+v61xBnzzleZwjrJzMW/PGKR+iSvYTZxOrA7J0V9hQ9/FYO41n+m5xQeljsxx3 hYda2oE5QPY1F5fBgitw2nKo+oVHoPIrCatKyVEv6bVfApnOy7T+kPZacJqiRNv9 IgzHrh8w9BHzhPs1qSecTqNqASlYloRQ6uRVGPNwX76g0HSGlYOBI9926yjr2UlU /Ah2GR/C7HRK/LwQJUo9UjR+DqWl7M4rAyqXrbvu5DuEYxOsXSqI5GwIGtG7kf00 l1GalOJpgD56eNYlBJEIMMrk2bVUKbfETs2MSnJgPvy1TyRmhWnsXI0QYPhPF9ym xq7zjLqXgOAR47YTLEZMmPnDV+GZ0mNFuew/cm50mXV0IwhH/fTwJP2UKuny9qBr NusuvpcyVK7AwqiCnK6SOeu8JqomaMPMKP6n+i6OpnJzP25ZuqaaRWNvuHh04omP d7Vkoj533Bqs4SvKxzQ/pfGIrkPnSxbkF4wl26w27tAl5zINzTfxwX4hFvft2NyF o82sDHszc7y1E+3GCk4ggYpgES/3Dc0I6ToCf3S9G5fuVIkCMwQQAQoAHRYhBKlA 1DSZLC6OmRA9UCJPp+fMgqZkBQJjf1LVAAoJECJPp+fMgqZkWI4P/2w4Mr+BdYLa YBbBT77VLYK2gizlAPDPSeZ0HlrUZHQdreQM2xdTRuUQIZuhinRuzTcmWvoV69ko ++OYLc4kHzHKm+jgjYthYeT9AT7C8nk14WoPksa89zZ3zI6XIGOE1QsMu6bw/E8/ aqLs1Iu5rbvA5i10jZjYOfkqwDZUdgw4Eb/8yxYN+iZOuaLWwZy+MT9TNRea7p6c 16ffX4a9Wy8Oy09HJ2cgQT36Bmx9YLtOQR6fvYvIgzso4H2WlWFhBjpPZcri/ewW CHEexzE8n0VhyyZv30DzqU4sx8W5nfs05TcFT+lXpsiOTY13xIBezGlEl0PIr1iz 6fBn+mIkClX2bp0KLAEZnAgGLWF0Z2A4OsS2d++BP+7FOPhD9WVRftIabtqDUL7b 63Xt1BN5bqgGZrnlJdrG/AgNEUSL80+1nzszp6Dox7yTvkLkqCioBnvbXdrY0AU2 Jn3aUJw29ok0H1k12m5d/tN8zvf6d/yUoELF9nNpp3YxK6s6vLt6kJs2pyBhpoa1 izNbD+d4CMsylNOjkP98Sp4NFjVoW01xWONcMx43+n7zRxxougmeLZkMAagfBT6O dxdQGHqRjVl7HOkPTr6Yr4CZMdaB5E08OIRpNoQd+dTv5LvngaMHoKdTrEwVfwzr UOPHiNCJ3ewWUZgQrW0jfTLorILG37XpiQIzBBABCgAdFiEEVw5jK5NGExBzantv gos5pqLRNn8FAmOAji8ACgkQgos5pqLRNn+LZw/+MoWJDjQlg7+KoBzHvdBTpL3n nDGLRnYWw/Bq7cGu6BHIX1YShFAYGTn24DGfSbtmk6kdy0KII+SkRAP5xtvCBLCR Eh3CWNZOrzuT4d1Fvi5ZZ6PDEXPLyD/JwEAHbuDg/s9Zcb8Yda5GPRRizFdoJ1+e C1pVMzR2nNaMKkCJrjrw5g9w8c7uq2p1OfX8mU1hgQBsVOAeQc/wneTLeHeChO/I iuMnhSL78p6EhfRTazWMLVslaNGZa6MoSMzFWHeYA7HGG0Q79p6cVGeOh+NdXGnT NT34WVDRLgJETawnE7s9kT27oB+7aGaV4zcxz2A4fb2VA9N6DSoBgIQhPgpUIMVd Hfdd0+jTcTFWCvO+Hg+XXQMJ6vHosXk3KnNG9zh4fFnusXEdeUpsow8GQQITz8X6 4jvx4D0V7D9naFk6PLGgfES5+ssGj/Wcwk0FUUPP7zLvOax0blgE4HRzxXTGBuI5 eClonhiO1d759oDby49FhcV5jqKubWPVIwvXqkPEY76jW+cNN/L75ZXmJqn7yFhN 9oaWIXrob0l9y//cwMtdxMfSOPo9Y+T7GNYTUdwlZ/23VFVFsIsZSMwUHVNgCAEJ 0kFN0xhgTMbj8R5EGpXq8RI16rKZzJbUm2ZHUgJSPAWP3w6VKyuDldHZiaMg1rH3 oA22iObIFu3B6XnNaMiJAjMEEAEKAB0WIQSb0H4ODFH41ZZ3t1Qbk0N9O0FimwUC Y4h76QAKCRAbk0N9O0Fim3iKD/0RzNxe4uM/8/yTKj56lihhC3LzXrjiZmxxWWXy oozf90f6s8hCtqVMFcmVjXLi5iXLIg79y+oKCZ9EeJwbjm8erfYEIRpKyWQ8LRxe Xov4X1waEO+BBPtgyF9XX6yYKjxfsMvIyJVdeaRs/MbQCNTSk+IovW6vLbtl1vI7 63NeVm8HfSOM2a+B6smgMMeY0/KuxJIO2GW3b2YXRKl6hKLyhWgzy/0kOs9tQg+F B7KbCrSiJFI4N8v2E8cbaGA0C/76VbKKlVuMyWnz6P0GyQ4EDLoJzCzioD0lc8gz VL1xazSilE6URjhZKYmbabeHIc67fZupsAvFS7a+KS6JmDNrmm5GHRcRrj4jIf67 2F655qsSPMdNG61zDDWMIhP+mR7WTvcdgsmael1jlzAr0Ag2dIITBqUT43OH1uMj wATJyzSCl2Wuooz9vBRae4oWOOlsTfQYVmRLhqPq5dtBHRsJK/pnqEFb3nuVFx4o EWXc7ueqTk8C5kwPUbIzTsGc+SdZGs5d+p5SkiRkv94Cfbh6hHJjBNuhSUv7UVt0 7DDY3eA+7Zr+vRLrN99ykIpDDE7Ygk1Y0N6V5jxtHUpCafUxVdqxdj83c6kJsGuf D/GhK6SFoIe8pORN+m9d0KWYp4BPNTr/F9HgHxMEOo+ZCfWLd01M8Kdeu8rTHCx8 fIWkj7QhS3J6eXN6dG9mIFdpbGN6eW5za2kgPGt3QGZzY2suaW8+iQJNBBMBCAA3 FiEEEtJ9XYyOm/GqvHx8fGR2jT3jNOcFAlnWkM4CGwMFCwIJDQMEFQgJCgUWAwEC AAIeAQIXgAAKCRB8ZHaNPeM05/5QD/sETr3RWbycyhNsp0NOa+VXFUVl2p0aVTy2 fekeh9Xkg4OkQULa9/OrLUN1shPd8cd/ANHBeO6eGKkYzWTtzXU8FRrPLudo0Hvz u01HLly7YCyODDQCzcD5J9hd3UtWB4blPvWG6xWpHV3bNBi0LMdr7/rwhniYMpA2 D2KlWOP0PmbKfJNEMZwS9FruUBGBnIhodNua1wOB33vBPFaG7Rhd8Q495Vje2afO XjbS0zBZjpkZ5Mnh8uc20QwywtEUojwphGZ8ofCboOt2XnXJDUa6nC0q/4WeSH7x QEjU6R2fWmRgC1BagE1BQfzoQGRLmhHOjrnA6lnKZs30oSP6Ch7L3GBLwzqjD1kh DlryrnkfMBQ1r10yLZLNg/umnHPzs2PL2OmyAX2aR6RtJ6/MPKMZf+ZOfQxu0j4p gLOL8mHIpVdepn8pcCx/csu0rcJkV9zTirAIUX2R7Iwq7I3twtrX58dzbLUeXqpk rkdApDCfk/TE7lh6NK7XS81KnDW2L3UftERWHqZ2PDorgPfWrWpjWUVgSMCPQHwE kq01RI4bNA9n9PbiWuu+DRODqj63L/wA8NlDFfsWyHo2Oo11vsQwvlCraMZdlWeq dVcYid0OQblF+4poEkMzFABM+zLvVrkb1X5OU2q6US67XKI2WU5O5u0n21St2DHP yvVn69Vp3okCMwQQAQoAHRYhBIDHu5fuYfYZ8XbJ7lmIoMA60/r8BQJjd+odAAoJ EFmIoMA60/r8yGMP/2WGZc5sN3P0zHKkJH5X3fU40arUV/Zl5BByrFenAOb/8fuW um/LRlp8L+d4or0Bg+yyU2Fv+MtYAq11sOSp8TKklGIpgksuKpco8qa+rmsC5qyI csgrPX3SZr90jhz17Onge46OYOj3Brn8vcu1JQWl/EPWg7I/FMJXIL0Lj+Dg4gXL n1zT5EOPa1XdESlV60M7ItOXMOLPIOBVvLRkkqr/7oGQCVkkz4A90XnvjWX6vUD5 WcHXEr5k2BsDUBuiMneE5BriGT3Et4AK2S3uxUWD93ynYU2dj3CF4gBNoe8wr9uh 1BzzRQBuv9lUBHWtfC2AIk+FThkpfwLI5xBoHo/YR/WBjFGfjX2NcNT3CJj++BiF D/aES9bHSI/15DU+Xacbrq64ErcsVk1dElAyuICq7lNYw9Khi6lRaUNNB3QPy2Oy G/9YuorO5bFIIyZrCJ1DVT+02P8ueI5N9AmzBICsNspf6YxyVczxlKxavybOuVOP nGh+AhHkSTkE3kWoR6EKvDRhx0WpofuH0UxlNBhmvfVNOehLVge+XuWBT2kgnI6S Z1CRvHvHuvGlaTAh55xiCcjNMlMd8qqx1ooNqFXDQo1sBFksiob562WbXcffO0z1 wkyL43ZB392LrJDrbgaI56iiQaHwp4Mh9KD88H5MQtlb35j7qmhrC+OirngviQIz BBABCgAdFiEEqUDUNJksLo6ZED1QIk+n58yCpmQFAmN/UtUACgkQIk+n58yCpmSM gg//Y40XQ/E0FGCEAZs4My0qC3Qcxz1OkXyMVZ7viibVgHv8VG6p3tz9G0OPi/Ux c2OKntnk16iLxH/11EAY6lsrDTg1LbtAJDqzBnOCnY4reqtl7f9o33KggT+OT85+ frBZpkbLbcys60OixIox2P3W83lCoKRmEgWR66WRqTYgn+ZSMS0Fn35QLs6MVRpj Tw7e3tgDvU3RpLcmoHjKIOklUwAoeX351V7qvadjk1+k28BidjM+e/DCLFoZoQ/f TxOt7tmflzHgd/IsOYxt38ZZh6AK4NE5taI9NTflJQfhzkBPORrKHP4Epzn4YTTi UXFkNT0Y0beQGO2GkGRny36PGPCqeZ5xHSlTq/Yt8dplMBk4j9/wRjE50XxzXHsd lS+7T2DkA67vYV/nF/x3u6n13ewUyLVEFo/L1ke1jc8Htu9L06BoUHFNOyMw1guv DzLxqfGJmpwG+HKpXDEQ5zsEt4erE2Y+cv8ovoIDAGdCJuJz7uxzkw8QkMgdo8Bi HPsGaWtYcZx7EvZPfDeFYr6aqV6CeXebQsQn2H5PpWg8bU1rkGymyhKRyFwYe8/p Imzf95/iRCuCTzRZMVB52Rrv6WHpcbVXcYyFS3JKlYPna/tgCz7GzeVNgu8vDeVW pXVNdulk4NZbPwEuCWTO9gnK1fe0zGAno/b77oXTCV9yizOJAjMEEAEKAB0WIQRX DmMrk0YTEHNqe2+CizmmotE2fwUCY4COLgAKCRCCizmmotE2fxoND/0X4XeKhncS 8TzYsPx73MPuoCxi049rsksato2jiG243k5pWpydmQ8ZDQeBIFZ8eGAQpDTKNRdM LkrWdncsBnubf9z/lcH3QlMIwzty5XMbQmG5ObsHFHb+fHOijNeMW6HVg/2bX0mB EtRIvuDwiuqYpbQ4GIcVKzO5CO3Z+WWq4N3i3G4UOEuf6QEwa2XSKmVZmzbd63UW XMcbFB3pdQ3catWc6gN5kn6AFIZQdv6lwFHkVqdqsUMa9q/TW0jjFHr1lobfIAeR NBQQjKB1MfixjJbRYNAuUEpQKI0y/pptCK5Hs0Kv7lC7XsE9Os/0p0+dM6PAgr7Y nWCTyI9isBZtQe1XmHZiU2R8gTUlfELMQBzVJ6ikw2VFYZ+bZOXCah2RiAGzJfUh wvpOBc58WXszhyknY5u1ffkqsK75eGPTMeb3qEGmKi+qoKeJA24E+deKmuAlvlPG TzzW/Gq60xo8hLfpUb4k8Fr0og48yZVZZcgiuNhOqtbApxfzFpoNAboPX9Dz0xAI zIJK4Q/iljmPqbyFFosQyp0YGr89XxQ5RCf7KfpJ1QVZUTvYL3ClPA6+lcu4gEFA glyms3Jw1bQb4JTO1FiV9Ek8EEo4Hx3s/eunIhqPwUuRAgVjbGv/k66N1FULf5DU DUNn78T3L1MncjWyTbrjr4egKJ3UjFGEdIkCMwQQAQoAHRYhBJvQfg4MUfjVlne3 VBuTQ307QWKbBQJjiHvpAAoJEBuTQ307QWKbqRwP/0aafY8fRkSdUUcoH2BEi21y ERvpUtyfKVFANI61hi3xv7GpxMne4plla2s2I3LowQ/MaqmESm5cKPe7b1MqOsNK Wt6tFmdAcQ0G7n2+wFt7ambfEG9zH8qv87bvqJeNRdz2C0Dn9vhI1qqWFYM1K20B O1hAAc7W88i5KC6VvD+tNBRAvtCEwtVOj7Gg+jWSrw0bBUshFRjTzA6hTup+NlG8 71D/byYlmPUoQHldvMU9Rh8vxQ1G+y0dXeTdo/hEau+WR7GgT3hNxgHh4qoDTfSw AWMwQorrst12ql9vMYm/Ol9vzN6Ft66U5L2hh0E23NHYNEVbN30Of5xWfC+GCjq9 cHhuGdbSBHV2+6ULy/GicTgy4Hk9MTR7lbxEk3PlSQ++pWFF2SAaUnleYF4/rNv2 BziI/ESKDcA3hwH9NgXJRumCpdq+xjuBVfOT4Tu1LrrTnelvLU/bjr/iWLwcig5l E5qGS0wz4iKjSL4rlaqYo5h1i5thLq3boxw3GZn97136WzM9Uwc3dmozOS0b6qYO VQRxWv/05aC+peIK0UqU79nOU83NkszLSOTOnRXHBASYau0TtXgukE6d075coD83 Mkc7UB9pxXHluG6m7nnEJ1dVAhiAnqfO9bB2vsEJGLD6P+JPzg9oeQJIpFLjGfN7 q9d0qcxyuAq/tFzmD0JTtC9rZXliYXNlLmlvL2t3aWxjenluc2tpIDxrd2lsY3p5 bnNraUBrZXliYXNlLmlvPokCTQQTAQgANxYhBBLSfV2Mjpvxqrx8fHxkdo094zTn BQJZ1pDjAhsDBQsCCQ0DBBUICQoFFgMBAgACHgECF4AACgkQfGR2jT3jNOfGIQ/8 DLxIUCWPwHXMloHoIb9wBIVrkjwt9YooHHxsO/pcrI3r+T/teqsffRXMfbf2mwyz gY44gsXyXHKfXSOGvvgdThNl+WGUUv+ISZG/ks+NdXjlVrDsCJ6zo6Ma3c7axI6J lV0YqisagoX2nh05AMlJxBvMrlTlT00NOJD3GcjESfvK0K+IB+CfuQ4JYzxQGSX4 qH8NgQiBZAoG0MqcU5GDS35O7ImbS8iMRg2QGPiptoVbzkUhm/vDSIBO75AV8tl3 0ZP8NU2EHx1OUov5ug7boCN5day5hSKMGRkH1vDfrNcV4P4yaknAKwJm0StJ6maX 6Is2uj1EShMTG2aCYmuTUzh/xN3ZtjffEH3SpQwNECSM1tkZATX4vBzXu1T2aOYm uEg3/iCVCfA0hJ/41xVxU/Ep8pzLMvG+LjuAnc1R+A4gQfFq5P4NOadNyUych/QB M2YQ+dcR9aHrfx7oT7MPBqUeXbYpSBiI+cOt2JIRq2NZvmaXcmomdgfbRATrolAm 41itAnyNElKuOHnNvHIxQgxcaqsA3ST0SctzqUxpARmLyPj89i2OsaaDVvBWomjE O9YgdVy/9sBtpj1DMOGH9yDnbb9SKLpMfCERrMZrMifCl2+M1EVPNvE9oBugxR/a cf+9O+omGYBBCfJeZrD85vcGegGbcYZiL7B2eU7zjZiJAjMEEAEKAB0WIQSpQNQ0 mSwujpkQPVAiT6fnzIKmZAUCY39S1QAKCRAiT6fnzIKmZNwgD/9IkOBX6I5dVfb9 +0PFJiM4WzrNQXcNwdfOCHpYdxFpNdA9yRHeIvY+7eEFP8/Dr4zS6Oh4tKfXbdRA VA/HBwYrc0pfOxWwf5VtntdccaHRMYeA4vsjSyifM0U3pHrr3Ix8oslflABbWKg7 +xgRAB7iYF4fi4yUVW2uJRRpz2lADKcFSY1crS5t6Cvt4fZGTPN0M1kBe9h1CuI4 o6H/ZeceXIEDzRXq11u/UDoMeYvcXLUzROz9lcitPid9BuQDTCqYyBX+vWjoQFV8 16vpMwbq8Y9+EVtnAlhcpWZ5GmY/VU8CCbQqEuy7xdFh2ToSBFO8hNFpMXGr81HU 0QZ/1LK1DN1eZ5xnUL+H6qu9CmkWelrAw4b/bzbkM9kam6Ghghxham/YKDdCbyO+ V3en4VSEv4LRKbaBxcZObyxU2BZGfbfJsThPNQk3z9LcZb8NwohHoVvKn8vzWkBB /3lRSdhMnoz45VCOE9QLHyMJpbyudlSZ30QZCem7cK4ONu6CWD6vgsKz/5JHJ1ZX kgzTZ5SN+6toqvggIOGga6VO5r4JVuKV/dzl0MyO+BhiJvazFVHJuRGwANWn8zBH 3n/kF7hyQcCS90NmZl/NunAYfWiPB2CRdwfbb5AcKGIjdXFra9D1LgMvRXvpHvMR C48EcH/LwhpFp7nLGw/7KfOXUViR2IkCMwQQAQoAHRYhBJvQfg4MUfjVlne3VBuT Q307QWKbBQJjiHvpAAoJEBuTQ307QWKbdDIP/1j0OrFGrLfh1Khbj+ybujpTMzaB hs4CAtxZeEBV820hkcWZeC7t4TQ1bXtnVqpR9nsTJnfPCdJRWpELYJXjOozFTISw 2aqIZpv7KQG2oWGY4OG1+4DdbDAvxqXgiazk7ZlcgdZuww6Lxo3TjIUC7Wk/lCnN ncDPQcWHAkHlhC/NdWLmpLpGMQTSHXxaEajsZw6RqugSbakno8/hfZNRURT5+8lk GzhF2EiMxnTI7a09YYmbBjSvJxYM0IuaI+5dWMd27TDXVD7afJqD+vU9zhcRofjs Zfdi7/OnUjhb/lh7S5nApaTTlJOGxP6tg7mqjp8xiUkCq6PU9UwcSWbZB1csCexQ KEzjpQG51E059VCz77CvZ3qPbZ2bgiUtx3of3yUWX2KVuyjN4OP1HM1ng7U+D8PU lg5YDZOmuTD7FyxE7oQveGSYAhXgPDXCL93dzjVLyd7Sl3Xcnv9bdirli+8arFyK 7P7mq3fKruRsAzrQ+kjGG2XfvZCTCoxmK8NpW8i6VXgAUug1kFVX14Bp3Ts9kWbr R/2WZO4PDMkIJSkA/XGW5UIprW2cuGQYyY4BqEpK8YyRTXWMXv27vFcYAzvZOC/+ mfJpfA65x3KMQhVgz4nPWbjj7Wk6v86Jgyc+j6BTbzyyHPY9yqJ8jOgRKJ1Cczdq QxkunpOuJ5cfc/VttDVLcnp5c3p0b2YgV2lsY3p5bnNraSA8a3J6eXN6dG9mLndp bGN6eW5za2lAbGludXguY29tPokCTQQTAQgANwIbAwULAgkNAwQVCAkKBRYDAQIA Ah4BAheAFiEEEtJ9XYyOm/GqvHx8fGR2jT3jNOcFAlx99MIACgkQfGR2jT3jNOca mBAAql1GVmBthNP+sESFwNzUDP00l9taQZloZEnFjlH8llvnuu20tsHmTK5HcEXF igmdpn36Z3JEQEN8l/iAKJjNSrNur3n8qD+MprAOaTHNoXA2zqXZ/givtg+C6iFG bkgzWAv6T3iPm7zzeieBj/Y0GR+Iuhd9uJsPkssLwCmWCXT7yyKSlK8/h4e7wn0Z 02k3/BOOKXhKHgMs1jrjWrO0TbTBP8Mdvx+T10joJcnLHlMDM+GlzZFll83/XELM HU8MRs/w9vGByHaaUg+kK9vtk69XGua80lhN4fiLiW4bB2MMygUIbwLmdXXNzTJF lNGj6HQrpC/orfP2YNVA8bVWvehs+apqjlyBMTbe/whfSsGx+v9yoX3UdtWDagkO whktg0lH7Mz0SEe7h4zyWPjtKlopxUQS9MvCVTqhdglT9tX3cw7+B5MssvRpakA/ Wmauwwl5ruOANqKp1E/4sJKjKN15qmQ+SYknEdU3SS585QQbYQQ2eD0M5z4CRF13 kvYG0asDsOd5jNkpqXCSo4CpIue+wH56wPPis9oEveKOl0+AaNkJZrVRRxuqAP5g ItmcdxyoUBhIyTPLsmOQ+UjVS+9AFx82M2YSJl/lIv/1dxUIpavw5sz81qkX2N/V J2ipmBFOOTZBbE6eKCMl0NcS0Bt6JUIYXjegcqfQAlMWI7GJAjMEEAEKAB0WIQSA x7uX7mH2GfF2ye5ZiKDAOtP6/AUCY3fqHgAKCRBZiKDAOtP6/LvcD/47CGwBX589 DyXTptKhdA+21Niz+W+UlUlV71Z2q2bQobCpuRRjFhHHZDq2ATvOZKibvOg5mfaa gDqWsPlzvxpGSqb/G07EuJYr3/RKzP8iMscW54SGrfnVpXUl8u1Tyne4qcnmVMRe vGOXhdP8IfV0TkxAiuLWL79F6GPK+0r8Ol36xDtHrHi09tAHc7tHrOcfurevx0IG 5i2FQpOYx03cn8yfljFNNJbVmu/7WMx0ZNYi5lrqjCT7fsfOFbPYGeZZh1f8x1ZA YluD0m4p6OTzPv/418V9Hl/tlFRezBG8+BZKs2zRGb9EhSj1SSYI63Ng+CJidHeB O6uGDyJmgN5VoaTrrjVxIQRAao5yEegl6MnlrGjDT1kGfnA7aOoDOG/iXqxqlfNg oYkfO1O0DZS2w5BHW8iRdXnjMWvTB/brS1UijUQcAfuYVui4fMNC2BveY/Bv6EGm B3K8uaPWo7UFKllS5KkZaaQRGgBI92JM7FSmdqVPKoo5do4HPgBYevqPocLjZNvb jwi193prJDaFho4srZk9h7ahN+1TkuG0/Iy18gfexO3iQNHa7JY1NNPL5MGdWIrO dv98a3piBtIswJaUr9M6WeX50Y1LJtkHfdlmB5tpoAV3g96e9Qe5GCw6V0r2+l0s bHDuNCZnQKn6OdqmbmfwcrO7KLYDYo9oN4kCMwQQAQoAHRYhBKlA1DSZLC6OmRA9 UCJPp+fMgqZkBQJjf1LVAAoJECJPp+fMgqZkjZwQAIPUzgtSl/KCNU5y8Os5bPxp Cjo2qP0y9EN1GoeqZdByAFX2TYBGDRjx8mnXguM0iUfGQYqCZjZByxfoybgU1mVf 605yeUGAtZ28n1vyNpvBQtg+EydM/u4ixhDe1Q89dw+voqn0+PU+SKzcX7DNht7r Y99y27T/M9KwOcy4NtKeg5dHh766LWYUX4Kzq9MERAoDxpnZe8Nha4MBj4fgXbNY iyj1jWk5OTUfbgOLlcqzkFmCmbqMOGHdd5sO0Uyztn7jvVpIpXjpygviYEDq5kgt yiDtoHQ/9z/aLjr0kVUK4MP8dbeASbwH4uTCYHUxtsvgj9bZfzyhq1r5yiM0/Vwy iIuRA1Nah6XP0rZRRsd0V5j4EPng0oZXDesL3BEJb80n60SJa0a4RO0kA3JQcfo0 gtKtJraEUZt3Kaz6pMLPxaLkQH01hRn+iuChJQNQDts1OZNAbexnLe11Qn1lcEFa 15C02YqDsOe20I2yrLZRTMjuBwkOMW8sBur7x36lOlF4RJK6r+B5MbrMD8T2v1jR OwTjW4+n8M3TaZnL13XK9/U2VdAqeDD5MsPJZMee2mBGMM/8PJUqRtCa18kwRjLp IYPbnG0IRhao6+dTPRr6r5Ix3euCmbh4YCpWctm/yP3BksqCIOTKzGbBBtX9QV8k bYs+1T+Q/M7ZRiYR/7LqiQIzBBABCgAdFiEEVw5jK5NGExBzantvgos5pqLRNn8F AmOAji0ACgkQgos5pqLRNn9odRAAtv242//AFxgRTttxhQaMyde6J9Z4uoRBgtkE XMF+5SteaaqnmuyZC0ouHXRqk+EWtbuB/cl39/OCk7rSLQxO0VBcuIA54yb9Ip9D wMik6VXnr4Hj2EFlETsk+32F1gOOAy5X1IaoLLdiHoevlR6HFsZR1oB7S7WzdQvW 0KfDz5uthOAIjMyDNBZYCkkZLEIojldp5UH03GwroDIbGsu6nd37G6tc1lAz+TQ0 uzTrOBCOhHpS4zmuEBM8Epl+2fJJQkeEOBek3caN+Je347EILErNmfsNy5S1s3y9 jnfv7TORIiN9em6S9q6prESh0SjNF/lWahP7o5er55yZ/ESqw6e5jf1iCVsz5A5D JcjRk8PxsB86yPTDD3ETAXBSX0bzRgxtHYeMvIsHP5k8+gJWJLWMH+wW9ZHZvS3r Q46MTJwXgqmxb41o6LTgAi9y8MM6+m6yIRlEvbXppWRooaajH5C43AqN1EboXOhQ 1dqhXl4oX5cnWzVxFpA2NrNGfnp6yfg8CASwL+wmcU70JnT6f46Nl1k/qpLubdOu UZ0cc7SD+cHiL5psj1uMQRrLzlbCW5mipSDR0iP3CR2y6aV43dnF1CjZaMLin5YO vcUlTXtHpjRH/V0bbzOoSj4D/YEtDwtmqMffLiDLpFtKOtBZnoy+CByjOkAozYrJ lNlwqICJAjMEEAEKAB0WIQSb0H4ODFH41ZZ3t1Qbk0N9O0FimwUCY4h76QAKCRAb k0N9O0Fim6ctD/94WbkeawSEKYwtWeAjdDxCOL1XstkMQUPcbIBBwn93JxBm1q7D wCPc7be2pP3mjbivD0PE4VcPmI+1Hr1MNC3YqS8VXk059srTbCnVCZSy3EJZ33cK wm9JP/aBYGrO4RaiasyFtCT3DyyTss1k95qhuP9PsmJX3p5OUiDeLBqkeVjvBJ0u T/VoBNiOclYlOb8rc0Mh3jMovPWeaekZ3/+A3ZwLm58wLVdNRX2d6ZMKwiaybr+a FtMjuv0HDX/PfEpo6BoSqI5Aie5+m5Pi/YZjo6nGpiT9k6m0yVp7YSMwHGgwJ8MB RlHTqjAnGhQFzyAbrpHj88hHcAnFWM2RGzHzmzrkHbU1HbwBT4OMHqsSUZgoqUlB /s6yCCpoZB+1caVOUJhpr0egZrmZtPj7IcdlNT690sBpzah+IlS4Ejl2OHXh1Yb6 VA8Z6qR/mvWHJqP84HRerPOC0hEhKe0ktWjrcT015fWk+V4n/wLWABaB8P+Zpu7A pPWdWPy1xo9/JalL08XSDjr11jm+QEpHibFRtrmDiz1BDitnwzB8OnM8BpCCz13I q61DaeE8bkbUN+Uat+/yRiD1gnIFcvl1+Y9CUMkKiajkQl3aG1urNLkJ5u3tFfFH MJGOODrxEl4aBqEW86aFaESMwl/LUsihkZyddVyTYoTHk1IzRsQ+BgbnULQuS3J6 eXN6dG9mIFdpbGN6eW5za2kgPGt3aWxjenluc2tpQHRlbmFibGUuY29tPokCNgQw AQgAIBYhBBLSfV2Mjpvxqrx8fHxkdo094zTnBQJiEdugAh0gAAoJEHxkdo094zTn DDUP/R1x2d4qyOqWIRLHkDD8JI9nBgzfmJbVn48YaK0MDUN6/B7yn8ygo/RXX/+o ofp/Qs6GB7naeCZnjl5wuEZHAXwlho++1tBmY/tQ0/1rUIv3YT/k82fLsYYea9VB 54GJGz98njjjp6aLgW9GAMxBWl2HsqEkQU6W3RIiu9+ve3pKbDlYl8F+SIopZ0gU KHLmIeQpdG8pfEKWmuNeBC53ycOJICZIFnNCHC1MUe3NT24DWOkyUBSj3sm82hDk GUK9rSkZWTDjbCdMqPKRoJEgKqIGQSMSHAy0HR80+yubJqa9aRoVC2miireSmnqE HGPdH4KDl6mMwNjJjoQnJXKZmZTjVbRrCdWc6R46vrWr0AJSvn3jwunztiCpC4WN j0eKg359jCFDT4cw4VnGDRgl0B6QZ7xQqDKoUXgzLVUFVHFqbAh1QnHJQYfL0Njs 3/0wKLbIBpoV2hOre4FXR0KByub2vMnL1xRzbZrmxbXdaHMnDE33BuzfCBwucZN4 Y1VjE5l5DauJFZgnH7d96yjdpEvs7hqe1SMXBG0GQ5/SyoE6nU4ZKrzy7h4y/2mM BXboawJbE3WSc5xanaRt+gIYNP6JXG9u3kYgwU1BdhZT/DLIes9sl4Vj1FGwD1b5 lOy9hSSW1wzRFH+Z6JDC0P24lAEkpjwqOtLQ3vyDoGsNG5pWtCpLcnp5c3p0b2Yg V2lsY3p5bnNraSA8a3dpbGN6eW5za2lAb2x4LmNvbT6JAjYEMAEIACAWIQQS0n1d jI6b8aq8fHx8ZHaNPeM05wUCYhHb7wIdIAAKCRB8ZHaNPeM055g3D/4mbobE42xj FMZiYOKS94dKASMYk6dDbRe0zxQVUa4JkJm4A4LEzOykm2S7XKRn8RmenUcoCmBL 3xDkutBptw6UwcfFJ7DugbDgAo00vqz6BKtkgACMvF7VCQ0plLk0IisZhhf8Ot9e QLHQ73Y/RfPMJjveGmgtBzTNYANFsSkGp7GOG7yZudXOVk/O80E430RUEku5f5Ya JeNjZcASow4hfWOT19CuBLe5D0zx5yCXXcKWcCNS2+4Pz+1IGKXy3RyqZ968ruYe F6Yzx8bYDBC4ZsHukZm9UoakjhWu1YPg6+8vbwwcXq4cIXTD7aqMnLKLneOUbjq/ RUO5mvxgxH7lW6z2RAw9MCGhrq3RsBOIuPE7CGfr8ejoJCmOkuGIK+jc3bxzPa53 qN4n0PWe/pOy0Esmn3f2viLk4uanXD03Q8n5Nh6+33PK+1S2Hi7vpuswIxDXWB1S Ge0p6StQnS+M5BQbEMMxzpjZe3MlrgyGz80Tc/453gkZsKw0ITN/rX2NsEqBh+wV kRhkUNW9GHLVn9mOrDxCTdXc//jdyBxFRS0RuhXe2QjXBsr+t1L3SmgahNoj/IOw HzstR1nmIf1v7ZzcL8ecIVS3fbXcNEMl7soWhJP5mTHtFiEcp6th2AycXMEDfd34 nE++bwFRehtup80LR5nNTFqeZEZXbE5PUbQtS3J6eXN6dG9mIFdpbGN6eW5za2kg PGt3aWxjenluc2tpQGpveWVudC5jb20+iQI2BDABCAAgFiEEEtJ9XYyOm/GqvHx8 fGR2jT3jNOcFAmIR2+8CHSAACgkQfGR2jT3jNOcaCRAAk7QtPCAYE4uiPl9y1edO SnfztG4nN9SrjPk58gmqme6Soq1jhthrxJmC1p2ivLulXf2yiWw/XlI+yMIM5uif jQWOeGkiVCSZn0sUgq7qQ9XR7f7XFashDhSUs7z2BKvMJjmWuQoeeYOY6B3FbW/s ieTftq7BBqQDLjZNSvhbhFLQyW5X9lOoEkjYz6P7Wix0hEYfVkrFNXDBIhuf93I+ rIApXUttxphLaqOoOzmOCcAV+j0fBGkkFzqSCVch25s4NANOP9XgHWQbHFO5GpDt ezRjQtqyIUvd3NjbLpKqd7jlVlGlVfFP1+Z0eIPcbD6K0BjCrICjG6YZcAgfR+FG 9G47lNRcrBtbYc6NeIHIaIVCjTlopIM8a8uew7uXqSb/dQeyzOnYgpY/aAb7XyRQ zAXbEg6AXH/IGcd8lYJy9vPLMT9X/inHQTpbut42PE2e2Qyi7Ll9Dwpz0+yLNw65 piI33zkd1iTc0+mlBZuaiHdCfZZJvbt7oZDobfq+BtZh8HINjoOOTuSL6ku9T+HM Gfy0wrQFpEerxlBr0JkAvr4CqBMBj25SEUKRYJoOvjyR3rCX41/ny7i3WWZeQDfO SAkku/b1ZvVL3c61bTmN+EYIQSjp2++KFh8ZGF1aBcHXx5aIGfwbjGLGNNUFlxgW 0JhZsB040ShXG9dr9P1n4uK0M0tyenlzenRvZiBXaWxjenluc2tpIDxrcnp5c3p0 b2Yud2lsY3p5bnNraUBvbHguY29tPokCNgQwAQgAIBYhBBLSfV2Mjpvxqrx8fHxk do094zTnBQJiEdvvAh0gAAoJEHxkdo094zTnUcoP/3COc6IKAOWX4Z1JjngrGOUZ lZffyng+g1ETKrfJCsyGZRSMWciHxmHb4X9g9pk8dcuXBA+2rk9Z2Q+akJ9qXZoz GILast3RDlKF4ANAiSBFwvTpMQ4O+cnX76BQ+YbmQIBWjAzC+7oJl+i5fHhuHenx VladXG8j4hrtk9zr/i5ViqkzxoFh7/z0T+FEpT5QUa/gV1RUXMqj6qGSp+fkfDQd Ihl5YmDxah2zUu6Vf/THpn8zk3PARgprWndPxIxvSwkf9RHZcdGAQhQ8rEyLNDsI LkvzfFBpKNR9sRMi+/TFyOBmSXmVSv9O7l9ZoGTydm7U4KH6a3mP6oUneDax9zpd 8EDzv33S8j3dD/P+fBvPNr17nzlsUqRV0GoipvhvM0Rpm0GxgWUMwEGNqMNyPMt4 R6G1FycnTW5/YxrVgU3+z4UzWLETlFuc8s9tIKLtiR2WZdz7g+5lWyRkND8LN9ro jgXkvTvN23ezeg11VCyADbzXJw4xh/mRtRH3oQl3Za7z7z3Fix4A3G01eSrtx/qa gn681wTJIJoZ9pnrRG80P991AGtgLlTXuA3Zy3xcznc9lrkTzHE+NvoZjLZrFW0R T1k7YQ+gbUYd6Y/E1uCg5UBlB461m6der7R3vK3CwRwc9g5mRKB7GgIGJabn75kx T2h3pttLMWcS7WycDNRrtDZLcnp5c3p0b2YgV2lsY3p5bnNraSA8a3J6eXN6dG9m LndpbGN6eW5za2lAam95ZW50LmNvbT6JAjYEMAEIACAWIQQS0n1djI6b8aq8fHx8 ZHaNPeM05wUCYhHb7wIdIAAKCRB8ZHaNPeM051ZPD/91XCIpOhn74c5iBVNKQQPH VLO1+PQ0mpLStDjjTpKvY6eSNB1/oqI3nxuLcZ4QEtc2immfdxaR/ykcXsFvsmcS Jshe+LGtGl+jzfIQQv4xmId2rFrhNtPcNX65ou4W7E64/oMFOjHedoI5YcTNpmMU qGo0EAu0y0d4efQ/O0ARkgU7OJ7MgCipZ364OZ/FbYgIroO199mVE8tXBOZeU7TE YU3hXPBEm+DngQCKHz3/CPkoUgd7dqdOC7eBXh6GdQdvkyjK8LJ/+sh3cq1Ir5YM XNXeOIuQDHgK+FIrNwQ6GBNtJWgrD8T2mz2sO2mmR/3p5D07GUmIlcRxz8S8JSjK qQWkGFhH5m5CK8AWvfA+Q94Z2Ubc2ES6Kk7mJ+1zJM7ln7oHEl/UN7reehd+xLax kE10RQMhQpVnAtG6tBsImehtsweG+AZUpx5U+C7a8AcNijA8fsTWi+ZdPsv5/qRO KFblZJzrhsZ8AR2GFJtZAcFjSaArvYBe13m3+GqJgjsvXcWd/nsfVAU2LyWPpGkR klJ9cKT7r2mJgdCJxsRQFROEqM8Q24s4iyhxOTVwOFUEmW2WLEbshX7SYHIpstoo XBBq/ELxUN5G+2pgky8wYaLvJLTq7LunVzKkoD2ihwhTRDTlCgxdAn1+xvpG4C9K HEa57/vhxpTj7d88BajOVbQ2S3J6eXN6dG9mIFdpbGN6eW5za2kgPGtyenlzenRv Zi53aWxjenluc2tpQGVsYXN0aWMuY28+iQI2BDABCAAgFiEEEtJ9XYyOm/GqvHx8 fGR2jT3jNOcFAmIR2/ACHSAACgkQfGR2jT3jNOeqUA//ZmGpEVncavH+/se6y15M 2UtYKV0x9QjMftUcyrxUYps+vH+BsM0wdbt4tQD5E2C7lEc7H9Bfrt++CLioQ/wk Tz4w9Hf/uZ5dEWUdvdSIzvjaQxMIO/j9A8wXroT7TRU7KhfdQ9TzqZixYumPBZFG yKUSYcWIy/ioKspweLXJylI9LoFZP/lCd2dsRQfIpb2HMcERfVGdqVyJpyQGx5QY Voq30ZzldjyVciCS+GlY9g+6gdUwj7VP48AmcszUo9tgpMGJr/IlTBc2cd3S4vMk ZM1Nyk0K2vQeKWe+ZNO4ou6zF5qiQbm3fAOshL8mYBUaJcsncNhP1MRoYxJp1ykx cC6xxUqbTFzOvNd2ekR3Qm8/gMswbPgr0QW33Ej/LB1oaPaAn8slZxyULfY3TMkf TC0+cMtcAt0OiFoY/fupwgUs9CiaVMtknJ9LlrWPCm1p4ahAeKYG8VbJ+05jsTUg dV7lDhoov9Axb0wHEMfdciUQD7jZPqjFzd+4vRNVFBfucmKsLnh/jABjD6RZZlJ0 ukqIQfOFt71zndloSYqJVe2bPXA4YTC10ijZFhMYkbdP8s77XwlJhyIQQHnbUt8x 7ax3FmpnLf0zvDC15kW+g4VPafcTeFpPctTeA8XZn8PZ+lEz6/95YXTF76Say9vV Gvrvhuqo1S64qzDNmaig2JO0OUtyenlzenRvZiBXaWxjenluc2tpIDxrcnp5c3p0 b2Yud2lsY3p5bnNraUBub3JkY2xvdWQuY29tPokCNgQwAQgAIBYhBBLSfV2Mjpvx qrx8fHxkdo094zTnBQJiEdvwAh0gAAoJEHxkdo094zTnd8cQAJWbuCqBYCEVCRmO rpjQKwyLgqkhde91ijJWy9H8jH7LOICh+mQkJlnV2E1LeMHXJ/9s8aSpe2lyIQJr K1kKs3AUYVdUr+/X/6u9GeQNwUXOtHr+NBs2v7tUM5r+qoKD7a5QnIKJfSS88EpP eDJn4oUYrYLD1mBb+hbJ1vqkn8pLQFgibQl9XL4CvkY/Lerw2720aEqA67Q2ijKd AQgM+Nol/I3Yay5LLLrG5tcG95SsCPT1+7bgJ24F2twqTvAlSoQJOjFOMbo/2Tqz InEwp5hIA+cAv58J4O7zjk7YydquKRyJ0QzjfeLFHn7qqlbuXJWI6IO5L4LKv3UZ BVPtYn0wBazYbSei0DfbC9zv/jliIRulXG28G8ee7/pyb5njD9Osh0FonZdhQZqw zqoKb7UtD8by8v91xH/W8WRvUKEUISj4vFfLjza3N0cdfHls+MtLW9Aw/xtAyF4V 7D8WnR5gApb6+YfPSWIMxBz5M6KwM2GN4/QyOgUpDwBcjylZGOajaTCv96LskASZ rals+xWcD1lkldUEJserzu+pqGMGiuYgFvUHx0jiVTCvdLTm+ET8A9l6+LMalcLD 3KwacqGtBUsdUeNhCDeF0IzJdaAWr3pz93Qer1mXH8PITe5Nyv21aepcDmXOaw6c Jqc4hFDLXYcsFHplMghIgzIT/xNktDlLcnp5c3p0b2YgV2lsY3p5bnNraSA8a3J6 eXN6dG9mLndpbGN6eW5za2lAbGlnaHRiZW5kLmNvbT6JAjYEMAEIACAWIQQS0n1d jI6b8aq8fHx8ZHaNPeM05wUCYhHb8AIdIAAKCRB8ZHaNPeM05zP4EACN8opSzxl6 GLj9TjGbacxyBYwAWwvSJ7475Zmx7WTiNJ1WBJLwv0tl+eklPyOplaFdeXXZ/Unt zrmK0JHOWrFJoS4MLkGJ1BCfidRT2N3SZoZjlbx1zN+9cez9IpTSVKViG5ZZABNJ 91SxfF3CFxoAm8tmwTZek9sed6Wuu8VxFPYv9/2O6eYw05eS1XTvKuuJ1l5aSeJo 0koUHYsK4mJqLEUO1fsi4pmDX64mpLHf+6O1H1b2huE5mK4R91LHCr6S+4w5usEl /X0SWyxT+IaSumMEKa1NufeWEW47T2LdlofxBz/i9XBtADusgRrB6Rn7xzcgKUtv BMZR4yD1/iSpDE4nO2WgKHEajsSKDr4debzajbyZjxKqoWSkGQTzD6fjAIUPIQ4w Ck4pjdfZedPLqPvxP94Md+JGsK+elNhTQVLB799r/soLNcR6fIF3I5smz6FA2JLY mplXzme+BFA/frKvjxrbPp/GNsnyBr52Tbtj9oWCQPO7LwdAjXu24uZ8BVt6c/mL adfFExUAWFRPQhpCf5vaLmohMwtiUzHYIdbtxrsmx9lizJtc6XUS6y5IDsy+4Vd/ YSwwUL8umBslJZ2g3TTQ9caglYQKQtI8+bb6fX2m1VK+XREpFLYuLgcflHt0k1D8 LXa57GnNPTuIgVGgfTucLLVrEg+womGwebQnS3J6eXN6dG9mIFdpbGN6eW5za2kg PGt3QGxpZ2h0YmVuZC5jb20+iQI2BDABCAAgFiEEEtJ9XYyOm/GqvHx8fGR2jT3j NOcFAmIR2/ACHSAACgkQfGR2jT3jNOcaFg/+JT1dz9TaBhkogodKG27WNi1noixH tlUU9Q2YdoOfQMK2Ox1luI3mMcFzt9xZF9lZMKXC9Gx4OrBMT1bszqtdUbvWMEr7 0VYvvHvBwwDLqP50kXVgm0YvWr55POt3aQc5b6+MRjq3u9hqJe6eVaFRx8ic6Vl+ V69PhEiFynG8wVQ4Ar4okwuj2XF9+k9RkBIRXfkVnHiK8irU4gFU6dXzbbdwzwwL J9C8UBohCoWtwa3XhBZJeEwAPAw8M2DfGaen3NF3oUuA5SzaMMQW1/+yQgqkHpvD hf7VmfY6c1gCdqkndqAO3D/hElAAIukyMlNDXmKf+Fkrb4Q4aERJgZCDnzKNJoXT KntMZYsuPAYG9p5B/TYwsFzYOBVtkDQ8pDqqxEzVOiiXqjPjh1AJiPcX3iB6C0EB f+ReqQRUZyYAiVPHY6ebM6Erufbo8Ks04mIo3C+ScjWRlUI3qJ3P8lBh1XbXFit8 B8xPwk4fO4sKMirpxJBKLw57gY7ARXy4q4+tyxcB7iZ7IeJPd4UQiw7ru2gHuSCi v4Gxc/RrGuXh9jZnrNmiZNkjrtU51iPFPgvYgzSmjXsUH67fVqE1CHvJGB3wXRU+ 3h8kHuYNYTur0kXpJTQZTF+WXxF6qJAnehgx668XdNL1fx4gdrzrjUXQs2Mtszuf x2jVHVcivM04VUy0NUtyenlzenRvZiBXaWxjenluc2tpIDxrcnp5c3p0b2Yud2ls Y3p5bnNraUBub2JsOS5jb20+iQI2BDABCAAgFiEEEtJ9XYyOm/GqvHx8fGR2jT3j NOcFAmIR2/ACHSAACgkQfGR2jT3jNOeRAA//RO+1NcdRzcb8zSF3vOHkbgRrdRwt c5aHnwbyJ9zqsOy3z1T6lPx8jcXO6IuTeaVvL/BxnDu6IOoEbFZZRhqp9h80heTJ 2rsqTF0jMyyFt2+9ZrsudCz8v88Uv2Ms1UW7gGUj2HADyjjz40JgKdzh4k0Gvwv6 Kun4a0VVMBk62M/ezEoacJ0PhOK2UYHi5kRfvmmOnbDkI+ZWZnZHVlJOThL6QfsF z89BfEhbR0mn4uaQuoWhXV45TNMRMDcknI/C2MpRr4wWjgKBHfvntelFKpo5y4P9 pulGhcbBMaR2OYiUgZX0f87Zna6N7znSDMFGfIqGO0qGVr33ymYLaUJuw2b1N1wp IhvcPOZbPBYpvE5gWB/TKoyXQnMhYUaNo/q8uWC/foL/m4TSiH7YPGJW0IKBc+rL FCl4jNDZr3V+7svAJALHel77r8+nFyjkhTl9C21VJYCmk3DjRfIPic63e85PHlGi AVH248kvoa/sHFA2OnCrLRPS56XyCQf0baArskkB7jjNcSU3n4+lcoujq2dNqWGn 3TklKhKSHRFK3JCMwjcWzK0ro15XK7NpbcnDyD/Xw+8QRu+XbsO9cDnnbsJ4sWU1 BCj9nrYpWsAgv1Yj97HJPzbRHQCbuqpw6I6yKzNWW08Qesacwm9dhiebuLgvrM9X 6QXPqG5ooWnmeaK0I0tyenlzenRvZiBXaWxjenluc2tpIDxrd0Bub2JsOS5jb20+ iQI2BDABCAAgFiEEEtJ9XYyOm/GqvHx8fGR2jT3jNOcFAmIR2/ACHSAACgkQfGR2 jT3jNOexdg/+MYOcUtTAmo3uye/X7LZWgWyFCkMr94+LLBjwkAi+zVg/v4jE8fVS OOiv0I+LmzkjkoAboHUvoIHwRljOlZgJiWprny9sjD6TI7HmnuT8tM7GDXRHuWaV 9wRMw9ayh3Y4v+ZGRTQ311TXqLTV/Iu3mtmM3MQVDCF/GqM5H90Pe8Wt4WUOgL/T 8CikPxdb5wp3dyH2va+GMwy3z3J4/V41swe0hGd9ucOcm6wYWD8w4Et1mOQ2fu7Y 6pj9kbvW2yovYO8J5FjBJ4XdrC1pd4kQridyDG9te9itPPGwRBOJukDW2A39id9W UaVfGcn7a6mMR5Y/9wiaJa4/LEfnlC03f/To3e7KuETX4viLmzUCZXSF8M+qMkSs RV42zqbC8xo7mXLn4AYkcxFiWQFfOa9mqhPJ05cgBd7mMtC4sa9V4npKOMdcstHM Gbs0QXtGzxZkdcZubcUTDKPxthbrjWff7AoWRmDDCkUSfztEb/blyFHuFvA1TA9j cYISKDlrk3xd84vOm9lfv4k22YkHqIjIa4EttLLwQLoY0ju2Imydt9z8+FoC/NY9 j+dqC/6NIZKRuGxU91hXx98cE5hABEzgzpgUd9xSi/OxVT+s1jPxkt19uBNhzhTi 4gDU3Gu5iiQr1NfLA4H/7dC/503hR8jJWikXHdVs/JlzVW8y0BgiUiC0LUtyenlz enRvZiBXaWxjenluc2tpIDxrd2lsY3p5bnNraUBwYWNrZXQuY29tPokCNgQwAQgA IBYhBBLSfV2Mjpvxqrx8fHxkdo094zTnBQJiEdvwAh0gAAoJEHxkdo094zTnSKIQ AJ+o12oBIQv4sJmLGIcBvUgDhGV8PZKWgYyZrlwSZjNx700nyN1cAOn4KqEaAz6n M9pxFofZT99WQejHiEBQ22B5CRNpGHObWgELfqPnFlikkREwGIxPx3qX029POz1+ ZiIo20cOp9lx3FNt5h23UZj74u8Q6Nh6g5st6MEDqhiWTeWwAllhhciRq6tyqF80 R4LmgXiRbeSlgTlf7v6C6EBzwJ/ucbW1fiI/KQNmSQwUwymo+Dym3mtJ00+xUQFe I8EjmKfu4B00g807dcOmwNv1K0RLP+318RSFxrKtV9H45g9pxTLMAB6kiISbpMcT Zd/D6rJ92k/IQjJInG5yxxVKYAntvlvbi0NMP9Z7xlHoWI68GoiGSVgdmScv8WGC IFqXtuWDAwSj73FrOVIQMesd3087/bbzru1au0Y8pgXFLt9C36p+DaYkHj8n7WDR 61VOd2JhjPt8/p/2qu3uS4IwBogfzP12AMPUk4K3W4k3VWzinuO4NDd1qKOQB83t BtYN/N2rqwdS/9oXgyhJli8UAwkmNistcfJeyfkRutszt16bvJZGBCkZSbo3hjOI rD38aO5VUB5yjg0oElT1O3sryfjRg5Q8BPTAHqmnltVqS6PPF/rUPaMTZ/ZAJKGv 1pBpl4s1vLToueNG+A0Xj/9dXu2Ey3Hki6uK1J4WIYc9tDpLcnp5c3p0b2YgV2ls Y3p5bnNraSA8a3J6eXN6dG9mLndpbGN6eW5za2lAZXUuZXF1aW5peC5jb20+iQI2 BDABCAAgFiEEEtJ9XYyOm/GqvHx8fGR2jT3jNOcFAmIR2/ACHSAACgkQfGR2jT3j NOd+Ng//TU6LgCYsNdJ9UKDnYtHq2BUAxUwqp9hcytZElTUnYjUvj3YWHP4ICHes O+mnSNuOUlRCCMRJBheLm3taCLJumIX9C7sAITrxIrtl1DvnPyLLqT93ljrer+kj S8vgWAnNx5Jn0KcHITvbwHqPYy6Dx6xiy4JaI0Xg6I4EZoLQ1GbEEtKwFY0l3qBe IxijiS0jJR4496aTBcfrxUQ5z0ITSBlp6Yl7QMdwjhtdhcT1C7yKHWc4nq5BNJQm tpzchxWq2nbNpI7mVAWAM2JLXHEzwu63hPlqJe54TTfGjmM1X8HzMXOLlm5eJcex XYGRKOSeM/HtVspEg75s86Ysb5xLlloJAqkvvgcezDAWXw2mRaYmsknBKDuY7UtR ptA4yKZtUhcQQ2QRFWaH3jJrsuu7n7pOjpbQQa+CCq/Co3dlWp/leRO3nx25RDwy btSXEPFeK4vqJg/1acmLPRmQyeLS9/TM9HPJHPF2Vuy9xVBg0aYmdQWO/BVM09PY YtE7CzWKvWXcrBhUCYoRipooR6u06ewJNwE9QIDuFm27YgP1kk51SnmFgUjDH/Z2 1/pU8YpEjRSixVDoA+bgK81fscvHvvf5jmo1GnFFEIXl7M5+MlYnK4eIDKzP5jOU JfzpjyMDG1X3NBHNXvRHKxoTrNoF4HKWtFqf8FkK6sSfqOEvE/20I0tyenlzenRv ZiBXaWxjenluc2tpIDxrd0Bhcmlha2UucGw+iQJNBBMBCAA3FiEEEtJ9XYyOm/Gq vHx8fGR2jT3jNOcFAmCIztICGwMFCwIJDQMEFQgJCgUWAwECAAIeBQIXgAAKCRB8 ZHaNPeM051gzEACC4ptVJAye3VRKx/Y55bGeRtompVCA7TKaq27rbcwhA1C6dfH5 /tg4Jm5UQm0D/mkoyq0KjiR1VsTVAPqytYm8rOdYG45kjBXm+cJZQLzRbNtFDo/w +muvOAl7Bqp88jG55HtR+ruJd5mgIw7iQEZNXxNOKMkang1ap0q/CzzMCGYXpKQ1 Nhq3sRSyxkg+E27813CwWlffH8NHSLMWARG68jQxkV3kGqlDDmYSaqSuzoEMzPgQ msg3lwwA5MlFQuMpAyuQqMGRWqusyWlsNeyAUXooc+izr9EAnryatOoYeIYvyk0Y YaQ1e2KpqTqOmo3cviq2YHf/UPRXbIf4W+JCtkhvXpVvemelsm/ZUtzNIZ0PeHWS 5d/2gy4D95yomRsI/7iB1C80m4fArcIPDjRPuGTJ88/IfznWHYamQjOQnbXIn6tQ MXNt7qcxCCF/8Xv53TKi5awfnpjmJ9OJ+Yr44iIJROlrRSW5q/09Dqoyv4tCrg5M v5wbNZajytY2RLe/LOsX/LFkic/dVUk/p9Y3F0DrZHl4NzwC6T5JBGdSaQ+NnMqT NxGPpLTyCW13RJKgNiWXEtPRcJKLkl9AUFJyVnvXmIrFzo8iX/77Xb8h+IJ2/l0q xs/GACYlYAS4JnCtwdB0irLng/JesVEdeeuOQuVyGoG6+hhp9+qp9beHS4kCMwQQ AQoAHRYhBIDHu5fuYfYZ8XbJ7lmIoMA60/r8BQJjd+odAAoJEFmIoMA60/r8PtEP /2CANuLKYp/8hBRUt8Msma07JioEHAeyLML+yi76rWIY/L0Mcra+Bb7AKh1KlSn/ xpSVCWxmdYfMmAPWEyyiolyV7b8+zSnQnd3YsObAew2p5e08VJ3PpBe53e5+qKbv H9v56K5cUlv9dRZ4MSpIwf/sB9hRt1emXP5zDIxpmg2LLsqYNcrmZ4q5e55RSbIS sv9rbN+dsyWoLA4YrxrZyJW+4kdSExWVAO1WL62dz82XtRJ0PWwE8mWA3Bp6WYDW NJlg9yl7dxHoTF+JbPfaXc+v3TspypHe5MTYAcmjKS263tcTKRWRBnM3nDa9I3Fc ZXNGZeXrPgcNSOb5MvMlvR0j53wg6qz+BEOQOu5uTeseA/ho6bddIRZ8VK8v1GIf MaGjv34txevCTCTZziVMIfZmCqNI224ojGjKAE+NRHQBplLCN+AsTgl2jS/F4yGa FHhCmbJDPJgqcKNRgYFhjcRsZgc5KqvtBbIeMFxSfWVD0rsfeRKv3Wvvc2KqYaao lEJ/tclP68d1HoCXwC/ZPU96SR5NvtM7kk4p9KzQte8f0MfPRubUbIpeMWLQtm3g CxkLSUJkfvuJjKa5bGsJ6neDPu47u+lTiRWw2FP1ReEcTzdVC3JQBS5ewt2VKDPz qkp/N2S+cWm5cSkwBs5Ydlxh/Z9K0A7BHrXEqSJzLoFAiQIzBBABCgAdFiEEqUDU NJksLo6ZED1QIk+n58yCpmQFAmN/UtUACgkQIk+n58yCpmSIRQ//bSJrJeFWbXVy yOTGCpHeA/oSPK/1ZS95pQco9hGpLNUgdVYTmixTYxezQNA4roy2STiQg2x6OYkL jQmSg3ZglY72HRnrSl+Cp9OLpAlpZANlcmGBpkF85q+g1FXu8/ElKFWw0BU5V5FK SWMf0n4aUq1AWetz6RYccN1QyfnQ+fzYaT/eXwEUJaU/xe7JUEFCxNXm1OH4lX+r h3SBVcnBcfSaNaK75dd9l/I/1aBDZLx98QPhpCeL8Npvp8ObXX2rZPtdWQo4H0ql Bl0gtoau7aAiZYgGkFAywDvcxcYGFTicpJgb+9DT0Ha+gdzBlJxVtZMr0cy5XUmP y2XEqA93VSXGC651awBtRdwO9h7xLXs3Lj9mN9ZWznII2sNq1mHpxWX+r7cpwg9Z ZqIpWai6vtxwNxj5KFPQYtvl3RgNTGsmk5tcRuD70qXRDHd7Y8BRXEV+zgUsM4DC 1IDQhC5Pmr1hvFzdnbFnnTPG/c9DFu+Rw+BFleAvfVFTIjIFbKw9hc28+OBKVX/K sE/ii3C3FZJfKQ7dlGZwAYLjf7bdAA/Rnw1J4g2s1n+eMQoNofaOzWlU8sW3vcOD LbjqD4Xe7geBGiKDyxBT7wa75YatwUC2w6C5onDdTG5VHHwJzW6URQuwzMfSj01W 98CeYcoaZdzmFv6mSxdUwp8Bjv4UhZ+JAjMEEAEKAB0WIQRXDmMrk0YTEHNqe2+C izmmotE2fwUCY4COLgAKCRCCizmmotE2f3RKD/0TKAksrUT4sZD2xI2rpZKvNVT1 BJdROHs2c5M1HroI5XUuEhDC4bu58S7GhDNF1f3amrezz6zwMV9btA05H/QOmRGi WGMMuNTixvOWQ/kkY7J3S+HV5A1g03k4/gteI1KwsxzSvTFi87yY0Fdmr8A1MYMu pv2D+QhjxMndYEHiKmfFWj/zFR7oyMhOFgHTT0F8q2Nf+zcmtmNI6rEGqRiOj6JE IZ/HlHPlVydW09Ftqfzqq67SeqpoXg6oWV9RDRsZxGE69SAauZMDb3wfbpBYgavW AMcp8dx3IOvL3LUxHKmobmOxDgjsmE+K5I/vGYOlJZqTA7PyZlZ8U2GhPdRuK1O9 yIjnfojzygrNBP8N3h0dJ3ggCtuEab3zM1+HvBw6faZs8Kx5a+5MrkWqGOy5fdqG //rg/O4mICKHZi3ZHftcFujWXumRST6R/+VYZusoJJm+4KbP6ZuqxDEcYE9JsqYl MgKhPKV2cBwAOkkrTZJjMv/gU5qOuZKZ+xQnAg97hoaA8Yyhr5PYBj2lVBeBXkgA 7+AGpMrWMNDgARh5d8HkDyPam4hBn2BD6Pvxa+cX+Mhzf3J+Y/c0aMneIBdv7Hjq KoXHeHQM5lk9Mt7MywbwYMTKm0DD1AXX69cN2lfI6I6BhDwJL7ODHkL0I5JqQB0K ge1RA5CwDrYUjlCmUokCMwQQAQoAHRYhBJvQfg4MUfjVlne3VBuTQ307QWKbBQJj iHvpAAoJEBuTQ307QWKb4/kQAJVeI2dE1LnzynF2Mg1eQqAh6jOSR/+dIZPTUf8V ZGfWwf+TwhqPb31A01kRXhNHzuLkPPqN24ElkLNmGdLpgdnrv7n9CwGsWY913R7T Bt9/kmJOSqWO6SWFkfjsb/mV1hRcxBrOhP9rvOnBdIOugTBWI1hQFKm6dwsrZJE0 92HOPelww5q96Qz5lCR39Ut8PZ+WwAK5TfiImzolrVKbF5Hd+oJ7X9/qXlXwb7ND wvkHNtchAhZbUj3JkcRrZ9zo8Sgk71UVxkk2XxqYof7S0cTuxlFtZniEB52eQ5rN mz9C7SiqCUutncgQ2ynY8Hnlxl2ssUVBCHIL284j2CqwsTvGdQoqceXOWBV8HCI9 1es0cN7kN+/BuU5Lz69RMYwrWXEe1b2qdbld5W76YdFrAey4Ps8lbzfDCrEH2UkD ZU8InLKjeqGjrKI4bMYECL0cV0A4JNStE8OG79m5FvId16YbQW9mUFjOInZJogAg 4TbmF67RYCAiWidG7V5WqQed3CKMwHY2uTuaxSdSDJjsMTAM+5ojG3gZaM0ZOBDO rWqDSWOIzy5QGLnD5Q4v6Q6UXfF8v4yAhVfPRwr/ZtzjvcHsgGU4LTtf4n/oZzrH RwbYGjg1QuzvQ3wea1Bt9HIv+rxU0UGwsjOuCsDer1n3H7onRkLV/Knw3b0fgoMb ugPWtDVLcnp5c3p0b2YgV2lsY3p5bnNraSA8a3J6eXN6dG9mLndpbGN6eW5za2lA YXJpYWtlLnBsPokCTQQTAQgANxYhBBLSfV2Mjpvxqrx8fHxkdo094zTnBQJgiM7j AhsDBQsCCQ0DBBUICQoFFgMBAgACHgUCF4AACgkQfGR2jT3jNOdLhRAAsjSpGE64 bqrA2PWJvL5UDkz1H0NIx1fEi3oyZQs3Zz3x1TCJXQBw2H1NsIyajWvph35HTunP DXIxWO0F5ITvcbm4Bv8ZYtD08macMN9mOYanEQy0cvLSnvrGFc+YroqGSDCRhsGW f4owcVVETZpHhlmhent4xTgZPDpcsD4KBSKYP1b2DVY03jfpMMPi9W2UY7RXMyKi 5FG2iyKVMfxCw13w/Ly5ycsIXdm5UgIpXvx3gWL5sHmaJdzdljmASBu9j3UNftWd DvocrMge3W48CBZ1+k7iXcJutA5lqXE4M8hQmYnrH4fVvROTprlFJNdV2VeAdug4 4DCg5Jkvp4MXg76DFZHIZLnVUjC1Y9BpICIDLKX9hml/bo6O8pBmxikxV/I+z1QF sgZEF25Ix1YB1InsBRR+24fTtqaSAVPZf9Dfg+c/EyRCg6Js0FLoFc+KpIQd6Dyk qGFfRGmEANchs2UNWcSr0D0jQrbgymX29zBa48N52S7XNjJP+YsjQk4t4xJOI40F IChvUuapRt0M7G/yZi+h11EqiAiSNvQCpCyc9LkwdlKtEjRh2Ra7KjeZ8E5x1aHT ES327TMxwzczlZj3L74af1xhDDDTV5bQbMi1wGlY0cFuk0TCZKj9ic4pGxz7phfY mi5+hBoQEJS99ll9LY6Dn3ssDqOOzB0byfuJAjMEEAEKAB0WIQSAx7uX7mH2GfF2 ye5ZiKDAOtP6/AUCY3fqHgAKCRBZiKDAOtP6/LtsD/4j3GfBvH0WbnUtKKFvgNOo +iGQRWL+wUSy0WsUG6ApIqSbJOt1zxg/egz0sFDPLvHu/ebN2G6MEacY4OTuMVu6 IK2KFaG7dOoFHTYDemX7N0ty138jf4rOHMwH7tcwceiVuIx9WwQjDyxIkyoPSuVH kM1sXcwbymo84wOPP+YBVr1gnUXZXqc6sSYqGEPK84vZxSRHXNGjWlFMShKYfOWK oPRP5pcaHXHQdU/zn6uURr+0u7oHrzR7Bit4IorM2GfWPCtEw5jSwzuWWqvYoqxM XtGuQWujoEvkwzVc5x1YGsjv0VwcPwAls6VWwsNPBJBztk2Ow7QmDdrSmACK43hF X8QXHmlFtB8SP2C8FtXDhigP8nX5iGKko8AVgi+wDUn+HrMunZf9g1b5BPdqc3tx lVJ64DwMxfrxQp2GzsJ5qR6PE9OKZTJxaLwN0e1xW+mXS914oGwj1FdHaGuN3RjO Hr3wuYIODpPYWsOdxHQuiipeNdyWWVJSfgrDIQI27wsnpkg6fD/VJ2SDqItrXTcY t0Jst41WBh0r92P+wAEPob8ytypFNzzCYHjD1G1HKg94Laxc3tBggcGk6kmoI7T9 ujPmWdgFwC3Dq9ME64cJQ3wzmN+JEHrdNs/je4UVAHoD/ztOQ4dOV7s1u7bWAapB dBxTjQLF9B/0o33uPLhSe4kCMwQQAQoAHRYhBKlA1DSZLC6OmRA9UCJPp+fMgqZk BQJjf1LVAAoJECJPp+fMgqZkhhYP/iDfFAcduptAsDqgtF2vIWwghNW/NPdy8ktR Wa2iU832yljcqy9DRDv22jgSfEQn+40d2Ibxt+Mk4s1GYx0DXdyuIChWmbiHUZ+9 dzbFew9AOvi6AlUDtAfQKqrBk8mwpVA1O4H/2vnUm1eSEmIjgnHJYQO85CfxTaPj gLdd9OemxJ0XjTDCPZ1O0rd8twiUF3zn8SS4e75KSSLW8ULIXO0hGhA5bbe8cOXR XyKE9zLf8ObYfSJjCR9wvVAiapdGWbNXcp8YafNuF7afZXUYWEXi9w6uhujHMH4A zlsb4iB8EHeBeOJUst2ftzk0hpgvtXQAO7R1v7rp5ExFwYeS8Z8+mXreolIG3i89 mKOuLI6v7qK6yaHR4Z5953m7+vUYXppuRwsjKe/yjoswaNDWg77GFkZhi8h9iXFY UEr8myjEOY4q2T+wY6wf0RBxCnJWhVwvv5KGznxnVYf7mI3/c+b41uSwRoOBWVCz JhvEHi/ep5RwM/+APAixmUE9TQL4PtdguHRfksFNZp/Tr1/ekUunfDfIAKvIWLpj d1q2cEpNta7G7U0QP6QeUODBLlqtql1E58X/incjqyJAQzR5rrMOLFy52T6PDXHS xQybCGzm2uj6YQlq09ns4M6qmOHs9MepYU/4mj9khUGaios0NPZIWKG1NbewucBE 23qGSRP2iQIzBBABCgAdFiEEVw5jK5NGExBzantvgos5pqLRNn8FAmOAji4ACgkQ gos5pqLRNn9CUBAAqrv2dKFjT4RIWY3G4I6qE93fm8iXc+iwS09/fTtlA6VVfGxM nxEk3Zy6UAfmsr6PT2bIffBL0rpUg4QTIuWVbTep4+BDhV/w0/dZCEhrq9RcGkIr pN8Hodf3DQJVZESkQ737IehdeuHDN3fnaO/DnExG9GXGU08WBCNlKhvnlQiQ6V/J gGTAFC+NjpwJKFuHzQcQWUyRfnkfW7WZ1B+KvkIolJIvUrCVi+tA1II+a8wnjaDL +Tt9rse2peUckrXFL7yThMeAzcflf6dgfB6laUbe9RZlAoJCThbh8fG0HhkmAia9 iS/rBHVpE/HV9FCeHIGrSWGSb3fMLz78KBPLi+riqN43y5iZxHrlUj/S2HGMqHu7 KczrfD06XNzrJT3qzszKno3TxpKbQ9rc3Hs9iPvI8qEKgdIwmVdVX7y2CiyFkTA2 qz9cCOMQe0F79kH7BLHdjaelCLbGbtMkb012GWIm5UHG5EmBphSFJ6xixYbL/kQd BRTs6rubO+iDwnopC5ZWaDIQLd/21GHvHDs1u9+8ApC/82KMOursOVomTMBhehOy E+497LCcYkBgzrGgqkdnsfNqqqv095ttmAnrm5c0IZ1o/BppClmWnTIPLLDXsZ2p s/l2hFR7IyLM/mgx4HeXP3KOXpkMXqiK5BNB8zXVBFh4+dpi08sSUM7cQQqJAjME EAEKAB0WIQSb0H4ODFH41ZZ3t1Qbk0N9O0FimwUCY4h76QAKCRAbk0N9O0Fim3Pt D/wLEmQXgRES8QZexmQfCEgRu70EYaJvp77OJ5TbF8mNcFsMYZ1pW3kpnlFj/q+A mpceLpnZcsVu5mekDHXyi2nfQghnfJT6Trpa2EY3S7GSPWExYFsy80H6C8gBWT4Y a4sDxCzFOIPdScrlGSHIs1J7+m42zwqb4hf6MbKZCKaWti+aLsushbO0UAynDQjL D8qDYmQPsOlLcdA9o8B2iX6XvuJ2vGpDdG7Ir2NHqgCkdUVDl4lqgpRqZExg8x3q PUMszDykfxFeeIl3ucHH7K2yfzqeV6BjoAXDuPeQZS40I6IBzMpcrdyP1gdzVfPL DD63rNXVBW+EjU5GyXwgDbnF2NPtHkHdMSeSmEOzOWNxUSEq4Uz31XMsMjZQXt/s +hyDpXkiTp1T/EkDw6g0sLg6I+5cVU4xl1YtV/yqAKzDh6PrukTQ/S6rEgXsX5nC Zn1cmWyh2AfyC6769AXM+ZNssjRwtZovgN5aHmFN8hH/Elzp/R4wIWRCdZI7g+dm a7yGdNoWc12pWZK3jmXAp464EpELgnLHDOnGaMGbk8BWlHBZcnDmKWOYSpYHni/n ZEDuwmQTfCZZPSe3YNT+ZvX4gG3r5659prTFxdObUESBPSO6k3cMQzCqryitd3c4 HTSKLokwQRBnDNCUkCKW+wI7+24izYuQw5/bLs0TRjmvebQ7S3J6eXN6dG9mIFdp bGN6eW5za2kgPGV4dC1rcnp5c3p0b2Yud2lsY3p5bnNraUBnb2ZsaW5rLmNvbT6J AjYEMAEIACAWIQQS0n1djI6b8aq8fHx8ZHaNPeM05wUCYhHb8AIdIAAKCRB8ZHaN PeM058XPD/9+0WKWBcQPm0lR9dPQ7U7XLFkl2zSwzOxDv6Cf8+DNndaJXIsmkgPW qOFRJxrm3cIfHB89jzCLAwR5jkZ5LLv6yUqSC6qjGxC+q78eY2kOJvfiOeBbtdra QF4lWWgkdFQrUxcX88A7lNr3AuXVDDxHyccH7O+LyByIb8GkGZ19dImWB7ssyZ3G hRwi0jbgH/XJDU06QNowB5P2SIzWfXLu+HlJNeCNUAP35HM8nr1hAFgi3DIhPLUT TGIhG4ekVETb3C5KSTFY01bPirB+RiIqMb0MvmzdZMB6Y++UIfqgoCm75tEvgz2i XtXWELbidxuls96e+8za26TmCgomjSDIPw4T7VrUoh8qEPR8f1neWJu9pB6FHmJu KN3fg+Fji2jMDQuZnWKM5iw6oZQg+FhTR2Hd9qgPUjWQgD3G1krWydAqJUkbyEDW l8iFx+go6QdKfp4m0Jt95P1fKPbhLoRMJrxWmW+v46diyb36u2YPvEOM68hmoTns fChThxGvpVuvTgZ4JeCNO/zpWpaLXXMzIBMlhN4U/ZCgz211rIPdikR+lWpmz14t FMHM8m1dE3xQWoDefCEqhIUxM3JfK8qXaZtxODs5Q3rOjHvY9woC0e6JjJ8lUT3E 7CkfxVIT1ag5n7040lk6eTQ33TpbceROXYB0Q/VXypNMhqjgnoqkBdHSvdK7ARAA AQEAAAAAAAAAAAAAAAD/2P/gABBKRklGAAEBAQBIAEgAAP/bAEMAFA4PEg8NFBIQ EhcVFBgeMiEeHBwePSwuJDJJQExLR0BGRVBac2JQVW1WRUZkiGVtd3uBgoFOYI2X jH2Wc36BfP/bAEMBFRcXHhoeOyEhO3xTRlN8fHx8fHx8fHx8fHx8fHx8fHx8fHx8 fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fP/AABEIASAA2AMBIgACEQEDEQH/ xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUE BAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZ GiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOE hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX 2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQID BAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIy gQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpT VFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeo qaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/ 2gAMAwEAAhEDEQA/ANHFGKdijFZGg3FIRTqSgBhFQzdKnaq83SgBY+IQTVS4uFEZ QcsadcTbYUjU8nk1R6tRYY0g9utOSB2PAq7bWbSfMwxmtOG0Ve1DlYpRMiOwdqtJ prela6QgdBUoSo5mOyMcaaR2qRdPA6itYR07ZRcRlfYB6Uv2IDtWpspCo70rsLmL NYZGV4NUZYnhb5hXSNHUMtusikMM1SYWMSG5kgcOhz6j1rbtL6O4XI+U9xWVdWJi yU+7/KqUUrxPlTg/zqtyWdeDTgay9NvhMNjHketaSmpESUtNFOpAFFFFMQUUUUAZ FFLRVAJSGlpDQAxqoXcwTjqavSnapJ7VhTyGRyx6UIYjPuOT1rQsbPdh5B9BVbT7 bzZN7DKit+GMAUpMtIdFEAOlWFWhVqQCoG2JtpyilxSgUE3ExS0uKMUCEopaKAGk ZFRstTU0imCZXeMMMEVh6lZ+UfMQcd66Eiq9xEJEKkUJlHNRSMjBlOGHeuj0+6Fx GM/eHUVzs8RgmKHp1HvVizuDBOjA4U8GrepJ1ANPFRIwYAjpUgqSRaKKKAFopKKA MmiiiqASkNLSUAUtRcrDtHVjisxl3OEX6Va1OT9+F/uim2Me+UMe1BSNO0hEcYUC tCNaggWraisnqaD1FPpq06gzYtApKWmIWikzSZoAWjNJmigYtIaKDQA2o3qQ0w9K CkY+rQblDgcissZ210V1HvjIrBcAMRVxYmbejXPnQFGOWTj8K0xXLaROYb5VJ+Vu DXUih7kjqKBRSAWiiigRkUUtJVAFJS0lAHP3bF7p/rV/TkwpPrWbcHbcSf72K1dO H7oGiWxcTUh6VZWq0dTqayLZKKXNNBp1MgKSnUYoEJSU7FGKAuJilAoooAKDRTSa AEJppoLUmaCkMcZBFc/ep5c5966I1k6tFhRIO3WnHcGZSZWdWFdhC++FG9VBrkMj APcGursDmyh/3RVsgsiigUVIC0UUUAZNJRRmqEFJS0hoA5y+G24f/eNbVku2FPpW Tqa4uvY1rxfKi+wpS2NIltGqdWFZhulBxmg3RHQk/SosXc1ww9afvHY1hG6k9GpV u5B2YUWJ0NzfTg1ZMV7n7xx9auRzBhnNAWLe6gnFRA5pHcKMsQB7mgmw4yVBLdpH 1NVp7teiHdVKVy5+Y4+lNIrQuvqa9AKb9v3d8Vn7oVPzbR7mpke1OP3g/DFOwrlv 7WO7D86ct2CfvD86h2QEDax/Ok8lG6MaLBqXkkDjgg1FdxebbuvqKqfZmz8jD8sV G808BKszA+h5osK5l8+Ww9K6yy+W0hB/uD+VcuF3M2e5wa6mLhFA7AVTJLINLUat UgqQFFFJRQBk0UU0mqEBOKjkkWNSzkADvSsarXkZngKKQDkEZoGUrvbcyqy5AX26 1aSGVx87ED0NQ2fyy4ccjitRQGFJstFZLdB1yakJhj+8F/GiY7QcVS2NI+TzUrUZ NLe26fwZ+gqAX0TsAI8fhT761bCyKMqBg4HSq0EEk7qvXB9OlWkiW2WjNGSMAihn IXKMR7jipbiBd429h2FQyr5cR9e4pXHYjivphwXdvxo+0PJMN24fWtDTbRNpLDOP Wn6laKYt0agMOmKLq4WKpGEGOWIqFoJHbGTgdantpAwU4GRwRVlbcHJBPXOM0XBG Ze2YiEZxkY59zVZEDFQse0jjr1rofKDJtYZHvTI7KONtyKAaFKwONzPurdoihjzk jkUtvKwOG61pNFnljmoHtgTkcGlzXHYkjkqC/OUB79qtQxYHNQX6/vIIh1ZqE9RM qxWf7/axHHettazpl/0zHTODWgOlMlkqmplPFVlPNToaRI+iiigZkGmMacTUbGqA axphNKTTCaAIBhbwZ6OP1rTRMDisq6+4GHVTkVr2komgVx3qZdy4leaMsaWK3C1b KBnp4iAqLlEAQgY7UojwOAB+FWAgApdtFx3RWaPAzWbdgNOiZxk5b6VrzssUZZyA BWPDmeVpWH3jx9KaFua9ooVMCpZ1DIQaZBgLUr8ikD3MbcsF4PlwrjBz2NacacVV vLYSoRUVtfmBPLukbK8BwMg1W4tjRMdJ5dRrqNo3/LZR9aX7da/890/OlZhckEdL 5dQHUrVf+WoP0pjanG3EUckh9loswuW1TFZ+ftGq5HKwr+tPJvrkYVRAh7k81Ytr RLWMhSWZuWY96ewtytKM3qD2q7VYj/TF+hqzTQpCipkqEdalSmQTCigUUhmKajan tUbVQDCaYxpzVGxoAZJyh+lSW0E8ShrWQAHko3SomPFXbM/IKUiojhcXiEb7YMf9 lqk+23B/5c2/76FTbc0ojzUXNLEH2q7b7tqB/vPSM98/V4ox7DJq2IR607ylouLQ zHtNx3TSPMfc4H5U+JAHx0q5PhU4qvGPnouUi2i8Cpe1JGOKkIGKRDZWkX2qDYCe lXGFV3WmMT7KjDO1T9VFH2OP+4n/AHyKkjfipgaAZAtuq9FUfQU8IRUtIaBXGilP Sig9KAKZP+lD6GrFVc5uhVoVSIkOFSpUQqVKZJMKKBRSGYbVG1PY1G1UBGxqMmnt UZoAa1XLFspj0qkasWLYcilLYqJprUy9KhWpl6VmaDxS0gozQSV7iqrXCREFjirz qG6iqctrk5GKEWieK5VlyDxUpmGKorbuv3ePpUgjk70xNDpbhgPlGTUMc8rtggfh UwgJ61IkSr0FAhY1IHNSA0lFIZIDSmmA04UEhTJGwpp56VXuG+XFMCtC265q4Ko2 o/fn6VeFWiJDxUi1EKlWgkmXpRSL0opDMM1G1PamNVARNTDT2NRmmA00tu22Ye9N NIpwwNJjW5uRMGUVMtULWXKir6HIrJmo+lpKhlmCNigRKajdgOtQm4LDIqJnLtz0 osMtRtuqXFV4iFHzGpxKh/iFMGDdKgZyrEVJJOi8daqyXEZPeiwE4kpsk2FyKrea zHCIT9aQxzfxgD6UWEX4nDqGFTCqVgCMg5q8eBSBjGbAqpO/BqSaTPAqpMc00IfZ DJZquCq9qMR59asCrM2OFSrUQqRaBEy0ULRSGYRqNqeajbpVARGmGntUZNMBrU2l JptAFm2l2961baUEYrFVSjhscGr1vJj2rNo1TNYc1n3QZpcDvVuGTcKc0QY5NSGx QWB34yQKd9jcfxtV8DHSjFFxlD7K394n8aUWpP8AER+NXttRyDAyKdx3IBbKDzz9 aeLcGnRnJ5qcCi4rjI4lToKeyhhyKcBS0EkccYTOO9R3EmOBUrMFGTVaX5iGNAET McZqvKflOakZutULyfCkZ5PAppAzZhKtEpXpiniqmmNuhA9audDVmYoqVaiHWpVp CJlooXpRSGYBNRuacTUTHNUA1jUZqXYx6A0LBI7Yxj3pgVzTvLcjIQ4+laMVskfb J9TUhXNDAohCyY74oibaxU9RV1owg5qv5YmjLAYOeDUlJlm2faevFXkYMM1hJMY2 2MeRV6C5U8A1DRZoUtRK+e9SA1IDgKZKuVOKeDS0xFeIdKsAcUgUA06mDYUmaKjk cKM0AR3ThR1qs03yj2qtd3O99oPSoHlLYANNICWSTJwvJJrIuzIJCHXAFbttb4/e N17D0qlqMYzmqT1Jepb0Jt8HPbitRxg57VmaAm2Fj6tWxjPFUyCEdalWmbME4p69 akCZelFItFIZzyRPJ0HHrU6wKnJ5NXY1VPlxgCq07DzcL0qgIQpkfA6VOFCjAFEY 8tST1NOQFiSaYAnT3p8aZOT0FOwAMelP3KFwOtIClfPsgY9+1EEW23Ud8U29+eSK P1bJq5grH7UDMGbnUNh6FaQl4H9qfdjGoRt61ceESpyOaTKRDBqHIDGtOOYNjmuf kgKScCp4Llozik0NM6FXFKZABWZHdAjr0609rkc4NTYZc8/mpA+RWV9oy2M08Xi7 eKLAaDSgVn3t0AvBqGa54GOpqllpiMZNNITEUl345JrRtLUKN0gy38qZZ2nl/M/3 q0VAptkiYwKzL/k4rUfgVmOvm3Kr6mkhmppsPlWiDvjJq33psS4XFO71ZmxG4Ofz pKJONvucUiHK+4oAcr4opOtFKwFNmPJ/KmJF/G9TFQPwqJ2LHApjEwZH9qnC4GBS RrtX3p1ACVGCTLjsBTmbsOtCpjJoAqnL6gB2VavPtCYz19TVKL5Z5pSM4FVJ1aSe KR2Jy35UWAiv1K3MZx2NaFuQ0YNU9aOxYnx3qXT5QyYzSktCkyW4tRIuR1rKmjeN sHIroVGRUctukgwwqU7FGGkgUHn2pwmHJzirk2nL/DVVrMDjBzT0ERNLlPlPNHmh QADnFSLZseiGrEenkHLAU7oCsA9wcKOMVoW1qE5x2qzDbhVAA4qyseKlsCJUxTwP apNtBGBSAqXL7VxVWzTfcbvSpLx8tT7FN0LFThs9apA9jTUYWk71TtbtvOaGYjOc KfWrferMxJzhU/3xSqMMw96bP0j/AN8VIOuaAFAAoprt2ooAqyHtTUTvSkZanjgU hgTTGfsOtDvjgdaI07nrQA6NMcmndvrS9BTJDjFAEXl4WT3OaqXK7IkP+2KukgYJ 6McGopojI6oemf6U0IfcWouICjAE9Vz61z9rK9pcGKT5SDiuihZti5PIrN8QWuQt 0g56NikuwzRt5BIgIqxjisDSr35gjnmt9G3DNZtWLTuIYwajMAJzVnFGKQyuIQKe IxUu0UuKAGhMUuMU4cUYoENNQzNtQ1MxxWVqd8kK4By/pTSuFyrfXCxjJ6noKvaL uaw3t1Zia5mWVpXLOcmus0gAabCR6VraxDdypqCGGeKX1atZTnBqjqnNvvPVWBq7 H9wH2piEn5aEf7X9KkPSoJz/AKRAv1P6VYpAMNFKRxRQBXpGbaM07pzUDku+B0pD FjG9txqekVcKBS0AB6VDOcMBUxHNV5zmQChAF58tiT6CnowaSP125NLOAbcBhxxm oYMm6aQ9CABTEWFThsdjUdynn2ksR6lamziQj+8KGXLZpDOKUsknoRW9puqBgI5T g9j61X1PSvK3TQZKdWHpWUCRVNKSEnY7dWDDIORTga5e01SaAAE7l9604tbiI+dS KzcGi0zWFLWb/a9tjOT+VMbW4AOAx/ClysdzVzTJJkjXLEACsObXHYERoB7ms6e6 lnOXcmqUGTdGnfav1SD86xZHLksxyTQTQR61okkS3cirrdEO7TUHpmuUNdLoDZsM ejGkwJtR+aAKO7Cr0Iyi49KqECa7IP3UXH41YgJQGM9v5UmBHcH/AE+Ef7JqzVSb /kIRf7pq3QACiiigCpK2FqOAZbJpbg80sH3aXQZNQKKCcCgA75qm/wA0/wCNWz90 mqkfM9AFm4OIwKjjX5MiluvuinxgeUPpT6CHHnDU5DkmmrzHSxd6Qx0icex4Ncde xfZ7uSPsG4+ldmea5fXh/wATA/7oqoiKAHpS00cU4GqEFKKBS5oAOaMUZopgAoPA paaBuNIBu0sQFBJPSuk0WPyIWjPX7xqjYWmxfOkHJ+6PStC1yC57FcVLYy3ar99+ 7MTT5FYkMnDD9adCu2MCn9qAKjNvvEbpgYq4KpkYnFXBSADRRRQBnTnL1NGMKKhx uk/GrI6Uhi0hOTQTQKQCSHCGq1sMzVPN9yobTlmNMB9yeRUsX3AKhnOWFTR/cFAC p3FEfBIpF4c89aUf6w0ASVzOun/iYH/dFdN0FcvrZzqL/QU47iKIoxQKdWghKWig UALRRRQAjHtVqyg82Tn7q8mqme9dDptiRCpbgHk+9SwHJG03C9BVtI9rhR91f1NW FiCL8oAph/1lSMkHSlPSgdaD0oAqH/XVcFUz/r6tjoKAFooNFAH/2YkCTQQTAQgA NxYhBBLSfV2Mjpvxqrx8fHxkdo094zTnBQJiEeXxAhsDBQsCCQ0DBBUICQoFFgMB AgACHgUCF4AACgkQfGR2jT3jNOdZQA/+No5+3jB1w8O6+Eh+n4si3DH/xxPZT88s rIIAyJWsjTS2UueQ0GTMo51Qfd2Ju7q5rfocqD/bRtZWmVga13Iz0xEM06u3j+4U ALnBU2v+7l0IE2zO8LZBBaKORQ74QBDmGrAox4H89aO/nCeWpJmBrgyfwxaFDxe2 Nd8R8+cSpSgfnI9rS/vCpYfiKrBCzrZewjhdjQmixMkZfaazFiLVytJPyBsDJf76 VYIHEE79iUQgYH3tEtcsjhvXFmDaCvyfpGsaWcU8HduAgeiLZ8y0+mKYpQSHBv1a xJq0TTaAbPzfXzus1BbW7EcIrwUxYlEVgPvzfEodibiJp3n08OgzAy6t/S7aPOuX GXajLOBVJR4TO61clktxRMviQ70RXqDokCfvYqvZ8zpfsWV7eVUmw5ahvtAzlayo 4DN9YzP4xe7kmXKbo2ODX0PUND5M0Gbu033A3hwKirS7eQjHNRDZ4nCoxGaZNUVS iRo8CV+X6myrbjZBsVHFQ7xiFy6zNHWolAji3dWrVqZgUiOQPboF5luv/ZoART98 bzro2XXdcMfUB31wI2fcMQx6S9WLxJdy6uoD4H4wPJlgiXSdQs4bZ3LXEoo76gA4 8FHQRVtt5KZoVi3Yd67flbWBdWk3WeB8xYlt57vTKmvbnCYjOqkTHDqFcHUtVosw q1yTXf5MXzGJAjMEEAEKAB0WIQSAx7uX7mH2GfF2ye5ZiKDAOtP6/AUCY3fqHwAK CRBZiKDAOtP6/PvvEACAJYnAtVHlC/+fRjK+iOIHGDBJPbfjYMWInQOnxu1GurRb Kwb0A1DGxriTy95LcUeWrW83t76s4jkXhWfoWQUDcsumwRl8svgeVCMTRjnR2pdx HzHjfqJsS+u2ZY8CdxqcgKcMbu0Ei915yulUN43tbqxxD5ZxHCgBqkm67cB20f7f NPHAga87x/jr3M1IxLAEIa1jcYRABOJUCL1OOVNm0BBXq0QeNmUI1p+fIOCvYR5p T4tTuo/g/EOFOiBsRXwsT94VrBLOw8/tbf3kZgzl0oRb73gk7aTXheAW2EJWRZTr 83lCH6QAym15DFCuAyNz8ObvpaC0AU32BYK6+THBIzYJTjXKVc+3OCTMK16SPXSw XSp4M8h0rr07IoMMyG+gGN7I3gcPSjKtTQM5ZTnIIgAryjESP7giPBlOvx7mbLOl SExfeUVnaifJBUi2rIFnAO+LdCA61R/Rhfj78yPvNY83NVN3K3Cqxy8ZhlGtHdh0 aspzy9SDmKfxvHNxMTGQsAIhE/G5cTYQE97NBxzLLfIN0mxw0slEPh7LHN2ABwtH tjXia7+nqul7qAgrT+67ZpxrvzHKZLHCEAJ7ey/FlUO7Snk0m1ygh2VjjI5DeFIS JHuni0N5VG2DMYpOlfg1HCT5RhTHJacKHg+JDW7+Fpvl8ZsM9cpCoS/6/5jQYokC MwQQAQoAHRYhBKlA1DSZLC6OmRA9UCJPp+fMgqZkBQJjf1LVAAoJECJPp+fMgqZk IJAQAI1S21TAEjlBZCwaT1O35f1S8yKLT/T/tMNNORK4vXq4ExT+zwPnup2x+sxg 1u9l/EBUVNUf+HK4iWigFvkxIPTHQ87Oy1qPblqAhJwuSwu1IIT+ofJpRbiRxCnl CDyXy/ICzYPc5dManJy3WPn6jZvBgq0j0go7i8TSoL8lBJb9lqgGC48vmhyXjDFg 01WGZX+3uG5mektaUCDLasDBt7KlFOpA9sdy6aFkZ//+MhlklLwyBRn2LeYX7wjf nQiZaFOauuswV/+oqn8A3LEBX1CAVpTQ35gMElECPQpEBHMhNpth6s1SNW15635B rQOmq6Vi1gU4Pf+/0vd15LnIUI3EgPPG72g+7VZ8zzYWazmgzZMHtd/OOLuzAwE+ SgSIR2sv5ui3aVpDFQoAl9HY7eN/6cu89j6ox+st9XnzuWEDlS6kVc989M+SnJwS +Zd1lsi4rYuPDFFR+3VZ+/EYBgX+JfIt3y0ffcLHiGxZmOXzRpGGK3xMmuVksJw4 4ZJ8OUVIqkVT7L8hvTFmtaER6wqC8SedhhYWRo7bivSnwvMrq/wpu0rGHtjp/g4N 5zyFs/SSa4tRnnt6c0R7rBDgpxFEj1SkKhyOHomwWJ9P03gQn/JYhjNok7dl0NhG CfBu38r6KL2cXONFIWnkjBYDN9aEmvDNN9VPzYB6ipL8NMJ0iQIzBBABCgAdFiEE Vw5jK5NGExBzantvgos5pqLRNn8FAmOAji8ACgkQgos5pqLRNn/TCQ/7BlEGQ9jQ qpeZ69+lZ3FhSXQm9n3qAuoEbQHYw4joirBYKW+4FWX/zI57WDUHByiZkLVfqUQZ KOMw5NAZTQMmfq7GfeWKH2uuQu+Z1RG6wLQAX2Ap6xUd9jT11VhZhI22TfA2oAUk MkZSM9iZdfZcIdh/s4vmOWeGuM3P83Y03o8Kk5oMXHzC/T6rbsivgnC0xYoBswdY XcVI6NUkIf0wTFDj6Dtk3WZNSnlLL73RVs/ebA3/ngpVM+4w/jNx6ALXpw2u8Qvd FBNjRixvdIqlszNpaBl104sotulmwS1JTxzkG76KJ8IY4TIDq0+/ay1gwFm9SmJd O7FVJshJwmhZZK4nyVrDSvSixTiVt7IdjRXj7Fp9zoUmU/pG5waMuu5x71zy5GXc rm2iivOMU+KrZWbG5XZqrLtbtDRi6iX+kFkmmQCZQKBi6mMfW6/7pSyskowPsrhM SHR0htnKj9ZyjkgZxekvOWY+Wlc6ierxSQLRhf9riVyfXoRHmLs3aiUCbv3BTNEb 1n5oHyZBAcX4DfzIB2wUth7HgYn1QCFkApyO6dkvIDDe1x4B5NgTiSXfmOjIGVlw 12IC+r4/w1MYsk6NPSKUEOe6CYDOwcCDRW3pWI6Fa0gIXaBe8PS3yTmfZBnQvfZM rrAAT+9W+M6dWIgLHU5+uUIWOoNc+J4+odqJAjMEEAEKAB0WIQSb0H4ODFH41ZZ3 t1Qbk0N9O0FimwUCY4h76QAKCRAbk0N9O0Fim4y5D/4n8cYIe9w/4cNKDfM9gahf qKlzwHMIhRICWFJP+0JSkhGfhryORF9MexyIVVP9QvMP7BBFGwTZ+i2WFlDrTMwx oN6uxD7Pml2Br1BCu30vvxxcmkG2nkQaOe9JwSGjG5Ozx+rm+Int03asgggtKiIR ZdFIVKRVTjBIifSzvVgTT/OtWmTVUIKY3cTKi2JYNB+DsGvALzaG9987x3ojkI1g tBxYMSJFuGw4pUrzm6nXDK3pdDHcDCcvkv6odX2X59Rfoi7jviFc8IYct6qHyjUB Dnl3Rif6KmT5bxZeFBcTyAa9XkGXWdQZm5fxcfodxvFJsxky2KLVRWlhkFj/8pRr OFlm7/r4dnqqENBhPLJknbNhlZpGn+AFv/p+O8M9tp8eT6dtWIcPk2dTzkCOTxpS Rb4n4daYHyeWhmBZWlT+RDD7zzWWaSPlIVuEn7nzQD5hWRA5ERPP328A3jjMK9dy rsMS3d5IroZKLnzM5mvMV3Qf9KNIFy53gCtc5MmnWz7+ZjkSFuIdEBv1Nnwyetcl FRRnjIXIcykP5ZJADOQhXJRLAabCKs6o3uIiWF4xC6uCyTWTB00Qh9HlzSa8Y+9+ 4+wUCIvoqcEu9c1BMVfAfm0cvZEW1hQZ9iWbNQEeQ1ZRxRjpiMkCOoXflZZu0FO0 g7ctprB6TIL95VXPdQTG8bQuS3J6eXN6dG9mIFdpbGN6ecWEc2tpIDxrd2lsY3p5 bnNraUBnaXRsYWIuY29tPokCNgQwAQgAIBYhBBLSfV2Mjpvxqrx8fHxkdo094zTn BQJjGh6yAh0gAAoJEHxkdo094zTnpZEP/2y+Uf4zhs7701Y13Onqb3reJvKa8wTF bhOe38KNUsRIXfy33tOAYyGWHufkc0llw6zHZC7hFEbSwGFdlDqxykqfeSHx3NNB U8xxprl4d2c7c+/70EdNnsW4W/Ia1ZpVYQ0jpC3f/feLdg7Vs4IXnxZ24NFN18lL 5qyqJn1py22LchO+JR9nrGa5vYaiNT6zjU/RekBBt5HNttjvwocrRC/M+J1/zp68 yh25DX7C0pFAmpQTrWnuVQYRoYlCAhJidGRiiRlyWzj/aGmT1Ix6LwnZQL08hgvW U5XFLKnLXRa+UJHvLCwSoR/1GHVvIK1lglE9U4ElKklbm+SBR5pFsfSxIsep9IkX 5YHdzkNezrJ8Z+TY55RqVDMg35Y7dhKXeSnUpp4EMVOESOb1pR6DEssBL0b4iJug EJcH+SJaVsS0VpJCg3Xswz43xz5YpXWchcEyLdqhiRktYyfRpHjueHQBOFFnPul1 H6vOwHPn/l2Aa0nAJhUeEHgpXXFH/Wo4H/S818ijFwyj3oBszQ9sNnG9Y96uaN+a tVrTi1pRKl0FlEyDRTYcUMtWfiMzq9jlSkAY+wFiikuzi0/QZJMkD4K7OTL/hdla LkiUOYLNgoQAaU9BQGbI/HHb5ADKpx/sDQsFUx92ZPs5d4ZU9G2PBLy3aaOp/2qe 4JPuUUAlL/sbtCtLcnp5c3p0b2YgV2lsY3p5xYRza2kgPGt3aWxjenluQHJlZGhh dC5jb20+iQJNBBMBCAA3FiEEEtJ9XYyOm/GqvHx8fGR2jT3jNOcFAmMqp8MCGwMF CwIJDQMEFQgJCgUWAwECAAIeBQIXgAAKCRB8ZHaNPeM05+rvD/9Ok4euSID+L4uF xxtadWhLBVUFjRlBYf/LIMYjcP89m1H0jT3ysybECiQ/PmrlTJf0JOXC6nseZ+qw gfgYjHLhrUYFM+n2iSq3XtBxOMUw/cvRf3qa+Je1554LYdYwDlhy2hzk15sIKjGU cC4yFxnJmhBg4Y9zp0T5OO8Ruia9ZDXS3WfQKAV/OrAge+7Irgs1RL6tYFlrIdWO XMQnQCyOx2KREmf4rVtW3IXlmcuDpY+Le6xVHc/2K0YxsBFTOCAF2Bgc+jgYMI2s 1K9HGQEgMci4LPlR5DrU4eHGPf9pbSqQ6R+FfxMtuB4ss1y8XHnu4BGtzb4SDlv4 XoTpLcgmNXhqJgpY9boOILxlID7JzPOrH5ggK4sO3vxhgV1PNmkr1jLuewu4FuhB +lbGnNhD4NhLTuFb0pr9jM192po2PANNuudjBnh5CtOqcS159Hw7+zpdymtbch6F sJu7BP08obrGE6JA302kO6Z2aMso/yZRFZ/emvOGXU03ViCPWKuqpNHCZm0oTBcx GvFB60y73NPqoeQCXKlnAiiNH3wgvHFAOnYkcTRpzltw8p8NLbS4QydFGKFBSCYg bhKOrqfcUMFR4ZRe7Nftg4BiQbvwFkg3FX9bBWrW3xJvUV2grW0G1KNOPNoNJcR/ UHnyoJr2Xme5WIcdOssNHdDyGOasPIkCMwQQAQoAHRYhBIDHu5fuYfYZ8XbJ7lmI oMA60/r8BQJjd+odAAoJEFmIoMA60/r8RWwQAJySS87+am6DqOUntFQO2uqcqsqP Q6ViB9yscn7M0M9juYZkabJUVxPA+E2nukoqpOda0RCzFXXc6Ixaih8k65hbFeTZ J01QSBgydL6LlN5E4RRVEjyVO+gkttCCrt1biOoO2vXZAUiqqpMxmJfEAvyupMGT 17d1r4jez0ocvwukWe2kfQc8BVQrqqbIr+fX329quzHv5QbPchMxrn901rEzlxuy Hv9HTlC5M+9j2Lvew8tR1IO/Av28T2FCtSoguPl42VUljNd4XxaVDLOoHRsNTeR3 5YLZz7jPAl/OxVAHNjslMM2WAVKRYxtgLMIBkIkDLcBGriedh6GIzr+HMD2UHWLh T5kB0SPw6vjn2oNzLtvgmw5nlfdLaXqGW9qGtsLZehxNtrzK+6bOC496ONyx+F2d YkzIhgsJ/eRpylLppxKYqHTIa41iPoNHJZE5MvJflKjlD2MlRR58AGrI5ZfUM7ju Tu+ZcOhUvimTD37n1pfqAtuvP8MbwXkH7zdgA5lSK9A+rM3iLLLg91XDAavBer8s FitrCkzLOMSAvH3lgknDghsl5IvkDuVfHf0Viy+9nrq1O+uFbIvV/H2J/wjytCGL bUloETrL7PvlUXf5Z4aiqetgnMdCElHWDRtdUVGV3suQE1nkdAHbFBM+Uh2s/95O Slg1pMXJCu7UYthYiQIzBBABCgAdFiEEqUDUNJksLo6ZED1QIk+n58yCpmQFAmN/ UtYACgkQIk+n58yCpmTKrQ/8ChJBkkc/Wqc6M+pmwtFSfdM+gZleytPd1M7JOoJ3 rYjkoUVVnglDng+PPUXGObsi6hmWrx4YpUniFlZlsw4xlqdotggulBJ3CZEua85U RMOOe9SJclYMKLW+ozR5a+Bke393os3AX58Y84VypI/vvXgOV0cXSNVvYLibK6B/ HTiwV8kSyG4VOx+0Vuqg6rs7o/AvgwwwfhtuHqm34Bf05UbdlSgK3PhAqQ3RghAI EFYTrx3r/xBmTgg5HzS0e6OuPvI7qYkSizHb7lh8ByuJDrtpofbMHkApFKnagZvV KCcyYY6e80DpF69gCvGxcnYtYGlIjCzFkJzORbehDAaYlOHU101o0nEl88nNJfZk 7IwvfSoexTQFbTYrCEkcGq2jHZmewZG3geovtOjvibFHyjnahCcbQEIKTe46GDg2 feJkScYwICeLl4ZbKMH+Kp+uT1e7kyWH+z5StA2HOjmGUc8HalBApaEyhJuOGaME +4llci62G0dvpF2IyveErhx3MaE5nLd4rXeZkFEwsldcDVOdhudAznFmNuUHnh6x 0bnf8ga8vfYORzawB0v0HXiPwLJqXexNHbqOr9kvdIDglSqivpgBJPAuiVxApApv nK8TmA2Mwy4zulwYLclBM/dmwimDZxgI4xcXnKBeUjzSmIMTXgq7/3dupv23UINB yBqJAjMEEAEKAB0WIQRXDmMrk0YTEHNqe2+CizmmotE2fwUCY4COMAAKCRCCizmm otE2fzOLD/4jkJi5yZNZS2b+EggVomsSQr3vmTX5NJlbdqFnJKwHrzad9F861hAM /xhOudYxGsgSE4kIbxdaBTC4tL8ZqAbnWuMFRVxffm0tu9YwG797fxPBQiU9vhI4 t1dm+x2De5sdZBz2TI9soI+tWKwB9swb1iZ/43Zkj2fmc2zYOyBLPhjT41QYwzB0 dBUqMlvJBPEg2/qh97H0qSET29xXucYNLSQaN+Briv0JcASXNBr2WEyTSH8baLYI GUc71IvKBvvL3JIrx/eRlRV3+UDnsxucoch+aJT2c5CikYl3uhN3ARrv3SkFWKzi OHkH9tNrqP3hpYoVPcJju2EwkcHv9S5nUT9ok/B74aNI8l6vW3K9UDCVwsnO6pKZ FjFCJ3YLmTIaAFClvfRtgTFPuzeROSlaUHrDFEUmbShXvNndt9gPu/PrfGoTcw7t 2mZVs7aXWz7uHktqR0jC/2vvBnWicJiyI9DlCmVIjlH1Y5K7Gg4mNsWqRinSThuj 3/o1mB9c6yTSvXg5wqtX+vTYL4B1ZmAVz37n1/BbHXWFIboyXLDyjMdgxeR2QkBZ bNQj9ShxGSRuKYRXWXWXIQ8AVSGqo/r136S0XRpTkzq3eSmkNQoXZoueXC+ibKvI 8sgx7Xv8JUcfVkp0wEm5EVsjVlXI6Xz3jnzNyR65WZ1/81iNo/PkwIkCMwQQAQoA HRYhBJvQfg4MUfjVlne3VBuTQ307QWKbBQJjiHvpAAoJEBuTQ307QWKb32UP/0mG P0/iH80jH4kzccAH3KKR/6zs14qK4w66JJXhjPvLf1rW6aJRtf+e53Px7MA5d5ER Y5bA1QOdsnxxoloyNDLc5VkOfctXygnCH8No5IRhin+b/l7rC/BPX0q437ilcxAS 6vTmKqr+kpZJ2qZjNFDRm6Ow0hCe50wssbVaKwhivjJ6FVw2ncWgbj1ZAS8XQwsx W+jfKhdWYdszdYMXAzisME16kMHFkZ/I4hsuSk/ewU5BT7189Lf8ln4ETl3HqaKc Seh/hV6Szvvz26Ykv8391KlHusrtqwOtRCpbIugiyjRDMOHaw1W6rvIET8qoFfUP CyakAZ5lRBAYg6tX2cxgy1jhdysB4umkb+vSp5Mw1izbnrhqb+KjfyJjZjUaEs3L XxH6FDJJSnn95mkP15LIPWcfqFizsskEt9tpei57AlxQZlJ+BIcxWrsq2+Holz6j mgRm/7ckLzlxf7PGnTKX/5oas8zPboi2AkO/ocU3P0MbwzvZiAvFcHvIDS3VbiKw Y6dVr2LTQSDDkdK+++PIcojx6rpsjDAIhHR/6hDsF3UQjVKoQ+IoTIF+MqGC7n0X faGE2Vm/KaopqYA8yERStliVaFqgUvx0p3s/krYPwW7xWveTBJc69dlA70Kb2UNY QpW8IzylsrpJ6C46Hnj16OgOJn8UMtxUNJ57V+dqtC5Lcnp5c3p0b2YgV2lsY3p5 xYRza2kgPGt3aWxjenluc2tpQHJlZGhhdC5jb20+iQJNBBMBCAA3FiEEEtJ9XYyO m/GqvHx8fGR2jT3jNOcFAmMrDTUCGwMFCwIJDQMEFQgJCgUWAwECAAIeBQIXgAAK CRB8ZHaNPeM056+sD/4xuIyIM4v008E+9ES6qTLCjC5AYOwI23NLGtFMOD7ge76r 7q/m4O0pyg3vjG7WO6z7uYMuQ4QUpMVny71Lyw1D4P69LbWca/P6a8iCO/nHkpnc vxnD37HBfm+ULHkK0ITT0azEsKlId0CzYrp4NYtr3ry2IqOOfAIw+2TPXUnHsN3q YkEIbgmOm+sK6ob8vM+q1qe3HGDHOP2QwmGp1pEzaegc3CSU6OKx03coKkdpsmF7 W6YkvAifannh+OeojswNfQ+uRLK86YneA+7Xd21txLCwrdJJxiComq9jXsSf7gPR RQciOk0XyYSdTJRprmnBclibPMQLKA8U8cN0jQ0NrJw2aspOjo+wQfwqexRhdbJC QgckUc/oUYTJ6LeWXIo5nOJK1AkoUo+AbANQcF9Y4ntPJmU1XnOwqvam4bQlsRUP dXqv5a/kh5aDsTqvVolS4iSGZL7tBjdsWRSxf3iRVqbfq4aPzZ/SzRe9exPUsdhs hp8+Utre0sbAT2s2PvhrjY6iYak4WjMJOQMGsX1hxvFORSxtu6msr8Rjx6NVKZ8P JnMmq9YKKSlGA3/cez5/elg43nw5fzrdV6ZdHA1TIZ0njDCE8KCYwCR0V72l7mS7 GY7kR3JemVifGYiMkIl4j5ldZgU3mlOBSpUk7b/46gfLX+fJWojFBAiI8U/C5YkC MwQQAQoAHRYhBIDHu5fuYfYZ8XbJ7lmIoMA60/r8BQJjd+oeAAoJEFmIoMA60/r8 P3sP/0mBVbaqVSuum/F9Ct2oKBAzCJPNn4NJF4oBEW9IE17DEOHUt3IyL2E7Xu+N EaVnPBKL1CWsnqEsE2HhSNjlmLGekF/8U4CtZNqjuZW/MOYqOe0cSlZkLfn3/5sX V5DmcTLtGjKvG4Ij0c3j+Ukp0NLRt9PmMF3EavfPBpy9+GrY2H0Avmj/Xba73sV0 XswbaHfsv1Lzgh3IcGMyKcsYcS26u9pfCLm/uffWxRSPv+FegCjbw+woVWZ5Hscw 7+BUZ86DDB7eMhlG7OGhkpZPBeWNIRPpT64daHA0MWLdhSC1vyuX4mXtp9/q5RvU LvRgU2KEnAmCPcVZTPAWYYKjVd1I0LWhn1zR70AvPS5IYZVXhJl0E+R/E63iqjsU youc+7hCSZqSVoAqDE5t+UaQKmqgbS1qznY2WagSFMh0wTiVilhONOJR38+LTpVp 6skSr8Xs0iJYasb1GEaToauL+lP6jyMtz7972aeBmFPGMOmLWe1vzMQe141JgwXY L7rj2W91iwRDbDMlO3v7j93otMF4F9EMlyiNbjrd28B27rj3W6hpMBXuBSqGuwvE k4XceB1huXge54RA/U0smDneKOEGSpN6969qhMKhy6QKtB6UOD00ZLudiSgEZSWF vD8Ik0RgtfY1Sx9CODIJBEl2ARKs4HjWjA2Dtt/4U+f8mxC1iQIzBBABCgAdFiEE qUDUNJksLo6ZED1QIk+n58yCpmQFAmN/UtYACgkQIk+n58yCpmR2UxAAoYjM/Kah z+xo+aZ3uCj+MCc5wYh2yJ3Ll97wv0aYXHlFUY3VksD0kS3DXKqIQ1HqU+jN7zdx /GaW37y0dTLtruYhfqMcbqgLhlAetv9QG8S7FXVzifBzzSSAcr8NT41Ppi4oCkOZ w/y6W6D0I0KJFHe43IpjgFfUpcr5qideJonTsBCMu0fjBJjlC3ZCokmF6iRfcRqN XAfcgJtaNIeC1Utq7pRbAeKkMAJ6RLtuVp6MHfTgLghNBMG+GEWI1Q8jOSt9MCxe 8iKPUCJjBbrY8PUh59uDIpYNSHQb85yz1WJ3jsKEcxD9YaVHXn6mcT3tQrlQ1VM9 OMsKuQ/l09n1YS758JAxddlslTs153TQnu0TDHbl7sh7ZIAEfauivIDb+dHYsSD5 Pm+tPXOfgKLgilyBKWZ+0gQ2EyyD5QkPZ9l7sEBJVohAC2ly64GRW48kPln2R4Zz UYq0agXcQVMHHm0F0j+F86TEXTBviCTLaF+jKTMYUQtWY0qolLQPUi5Tojkj0gJl XWfiCryU+SSLGGkHIpc0FepIidKNz0hsIcC3bHvxgjw5jdCGlWGhes+waihm9ElT MzO+3iBAVjnqO9lBdaZigdTs33HcwLmCXPXtCYXASiP3Trct/FNbxgl4x2PEKxbE fYf9N6NQY4kzLu6GrfT8ZKzAgkO7V66VoCSJAjMEEAEKAB0WIQRXDmMrk0YTEHNq e2+CizmmotE2fwUCY4COMAAKCRCCizmmotE2f/bdEACz+wFDNGuH4Wia5/1m5FRE omThGp1GyoZ/hG4ndgYkxY70NcgM6vFURv67P/4wQee7mPM8c9f7RTZGJ1+LkuNj Zs932JwLpjM5g4ZCX5aopE1mUT77vQLAfrn5UWkQG4xffOxkGQeBMSPSSxEGcmQo kVHF4/Nr3GIaQKD35VligIQ5+AsuhuPBhTJBHDw0eTA+G22tOX1tvhI96wtsQiZq kut9xhqa/OXPiUk1nPsM9Z8aCIcs+u/gEMrXCGkOJbQHV6ZyMKHOf/U6Psl9q56w WVoE3fzhqGzvVrn4FOTq7vvdC2fZ5KZz8UIad5kXTfIy8EX6YnXorphyL5xLRxsw 7PqkvIKs8q0WlKME5Xb7xJHEplXodsn2JahWCqEVT/SkDI+0M6wW/V38G8U4YeME 1Ff23k73KEVY1im+8vgiPxTWy0YPZkK3n49o0Il7ymPoH2NtURjD0BE4BfUnsGnt iU+pgY4ys5vvKZHgNj5fu2W6FMjN/fBPmBPRV/0+m4VoNisdvrD1FO4O5SAue9Kf VoteGyy8rvlAneeiNG3mwGEMV+Hp8ksJjW0g7WW94HzGzBr30yfjtqmgu03YFfEI u6MYf3N9XtYy2ZYvsV0Oh35lHxbeNLWMxAqIYRyO+6pxG2MdDtoYNLGxh/BS7x08 UbB5rg39LGcuNCx5G3+LXokCMwQQAQoAHRYhBJvQfg4MUfjVlne3VBuTQ307QWKb BQJjiHvqAAoJEBuTQ307QWKb0FMP/ifmFzE6Q60f4UaILJFjaGTcs8R6Kn4Tc3Gh zVc1JR1wnfE6I4Um7U1f91WqR5rXlQrvf6nxGfT7orrXjkrkRVbldveGfRERBc7L 9GBG/QKvsy1km5b+n40+JQ34ySwvkvy2iQ8kdfloJsSwRNqhX2DW96xz3PGn3zzB VG8MjpatnLpmmxF8iereQGbO3XaPogVL6dKg/T0IbUqVO0XMshnMA+F1luG7bNIG WaBVb+/JeLOltUkuyZAIbywJp9cI8fFWeTqGpISYDKFiOHss3wRlBt7J6PFslSNN yOoqF3Yrt53ykWpcozNE2td3iNHSmTKkjqnSuclIO7fham1y9RCibvSfBJv901+7 YGdUTVb9ZujLe9iwTOJoeQEVwYREgBNycD0Nta2T3hKHtgXiIo6N5u8Bra/5eMoQ 4eekyuanZSDjU7IvmWsLFRNYiAPvu++YwHp4bUmdj6KzK6bXinCtOCDI3jdh/H19 caL8BA63hdjQVb6gFIjLLYQd/D04Ss/f9248ipkjsKMdwb150mDtGJA62NElp+BH jJN9x0z60DPGo9usArV8DSfJuqxfFgX4aFpcv5UdOaiF7zzqHZMdwWZfvsBFY5Gf nsqfroHOgcvCKQ+gdnAIuIwg37BT/UZu+g0YHHAsBVU/xCGJb7czBbWtdM5x+Gm+ l/XZFrcLtDdLcnp5c3p0b2YgV2lsY3p5xYRza2kgPGtyenlzenRvZi53aWxjenlu c2tpQHJlZGhhdC5jb20+iQJNBBMBCAA3FiEEEtJ9XYyOm/GqvHx8fGR2jT3jNOcF AmMrDUgCGwMFCwIJDQMEFQgJCgUWAwECAAIeBQIXgAAKCRB8ZHaNPeM05+eMD/4q Sexwc5Cck/RbtKAs7+NGpEhXgCEQ+zBZmMmpsNUcKJ3h5H9OSmy1kpRc7nYgnUJS OGN5stNOli5HW6hIVC6I/3F7cpuacK5vj8MybiYSZyvsfT2xZRN/M0J2e2+hSLzo 9k2H2hkrz8XUIfbxMrFh0yuL4DX9BgA9glowgnrS5BgQ3y+10894mJfLbC+K7JSJ MukOOXUmiFre3j/mT9NjALMxckvjX2Yf1Td8W2sZTuQg0TkS3f2AFrqkywgYKrJt 6k3IAWlSHgcfVL/kHBYKcwXg+g3gvsR+8ToEBfWgEDL/nuHUe0jb6z9ajhwIIkFk gkB5Bl1qjVb6eg+8poP+j/K4RqhKFGl5uUNgjDV4bICARq5vi+avfve01zo9FtUQ fW9o9A2vwaXrhVopEqh2K0vMBO+xDhfNfVvr8b+xN+YqoVX0xKhJdHhwD3rduUr9 WJ2q9y7hDl/4p9M6lKhW8bGpWtP2OEoOwUnzSdgIECz1AJW5X+YjlPiQjyMbAzOh i0lm3Ub4Ej2ReraGLBAxgZpZ7cRVQtMJhh1KXaVxCYPT5su9Sc+kT7QyO+c5mGPM QWEKLMPRRC6Pnjdz8ErteIuRfh5VYtY13YIOzxCVAVC819b5y5wx9pY+XJ7EQZ30 h6dYYxwEeQjWJYYWAa7bRycg9U++459xJSWEjRPMzokCMwQQAQoAHRYhBIDHu5fu YfYZ8XbJ7lmIoMA60/r8BQJjd+oeAAoJEFmIoMA60/r8drcP/0sNUA+hvurTRXJI 9UhP7l2dRaqh+3M7zYMNQGooUbEPM1Uk/FgeIr5o7SaYMcRbISM5abSrl6ykSVDj t1VbGMr/+nwfYGmwqE0dcthi8d2gtCxZ1iNZGOQMD+ku6kzzlpPrAuY27rJ62Mho WfYAgN44xBV1tEr2ZmZw8JFBPCFmnpGemibVqCCha/lP5q7bcHqn59w2p1wyP41B HH3U5NLuaIdEjgwY9gkns6VM40/YfG+lpm1Wp97rFbyNGhXAFdXWBNjD6GwY1cKH /mavuDoLanE/hoG+4SbSo73Q/s9eAeAPPMi9Zkg5udhymjg8oe0JjiX5sfnXMtF6 HTmR6FMvQbLMa9v0QlKsP4ymKCPzpwtkGmZCExrepB71JK/2vdKrQNvfBvj7dtTu x1BwhtIT69r0r/U0tU7mJUfD1VIl1tWc2K5iTIJWhoF/Ge2iL2UQL5BdFj3aP2GR 4T3gVg2cmI/sgw3dUcaDvkncWYbTBvg8NO8DGMWV+c2sJJ5h7U3Kj64WCf9W5jCk iyS3H3JvgsVMFG6KX98N+K0a2fn0e1y4ubuWXsNTTB1ae0wf2CKlGTm+Zh9/JgBd uAZfHFSXS3t+3LTQMC5K6Xs8n5LWkq60u1HP0XRf6e369DcAwSgqYZH00xyDBxvn H1j5Zt4eXvBgeeBfJgO508/EKXl0iQIzBBABCgAdFiEEqUDUNJksLo6ZED1QIk+n 58yCpmQFAmN/UtYACgkQIk+n58yCpmSQbQ/+LIl3ntD8Vr63oVa4+u411FndMOIL y4hWNYTyVnqwPuwBriABgweGjguS/Q0dQEdr6yDA+CyrJdtocj66XayHqlQ3Xnbs ql0hUQQNjLXc6/tIe2MPjjPp1Wjac/HdaizKUtlXEnm5jXUrXuMmrCc3RgjiuW7/ wd9HQify5jI/B+P12QYiSVLIwSPRFQ/ozKFSRAeN+wvor4UULbkWODY5PdmVhNPn 6cbqzHOqVYmW1iVivRye2XNoFD6RGk/ynnRfgYvJcv4cnZ1eH/xUwlfQH5MlScH6 z+nf0+Qagyklbb91bfUVkKdmrEZ58/Rp3YolnSw0d5Vn0IcCMiGakrOJionQ2PrZ s6qlqnLsM9e7/gUL6VGF2Q32BOGhwulppHyWAm0rGfLbLs5U36T4BkWO4WNSSCAq ob9pcFhDFU06fXzOhtfK+cWyIxQ9ZmxA6BzvE72i9SuATJI5fggTirgPEQrPjufP 0Y7a8MPinlt7A0HnUk4ld5yliVDhh2whPh3lUGxrnCVOLPOZSMoCGQhe/hCon3DQ kSQWR7J1RnrwnQ11mDQTugmhvhyA9Ro52IuQ5KrbYxAU823dZaTPcn6xXhM4iiE4 MP1cfQDGX4IcYcp0c50ypszbfEtDXy0USKYTVIQDx6ksh9HK5b57P0bMCZ2+1xb8 p4QBoAfLNpALxCuJAjMEEAEKAB0WIQRXDmMrk0YTEHNqe2+CizmmotE2fwUCY4CO MAAKCRCCizmmotE2f5SuEACuBpv0+yG68eop6ukXv4/KF3oPjtCzDSj3DBfjD7uu 178uyIxJHFarcpuOZ/MS8wIti+EGQ6dh1fLhagOgPx0GyAMsQK59dajQzJNAdEs7 OxduC4BDd0rmYTJurGLlT+skIaU26YbLQBeWUWtU4uflx8bdJMWXB3JJCzGa5FRa AioNCUL8AABXIijm9JqnO4TzF17GzzjI9kpStvO2DXhxwNd1Ek+7xbQegic5gqPS HCuY+veGZVhcA77jbJd9z1sZm/9E9mYvMjFSJufEKH0TCJE69kG9ytjJPSjSvCoc huqB4OsdHdNbfkXZ4zoCnjRNF1UcRGjudOMpP+zCy15enCQMKARBdQdTKXGSjCkG 5IyFQxLP4x4rMc9DV8V0zGsx/NKExBKHCr7G7IVCdBVfxQpbkafHkziHsZycqTVD RoAuN1wh93SwYqDEnRzxYHiyv6+zrsFH+6j7UpoymGQp0Qx/mh6H+V8AnTJ8B39a z2wfDMaklYOf+xuAS+dWenXyQzQnG1dUf/WljSFo95GI9ewsDTfyFIBu93RgyspA WNm1kH2/C+kjIoaDVh4A37jMWnX/x8OZU2P9MZAuydHHj2eLx8U0MOgb42ZRCMPp 0dwnd6DIklw8jwXmUXhkGMQpMsKjf9lZDa2UhAHGEZDn4mK4QEonUfI3Q931+Zbx 54kCMwQQAQoAHRYhBJvQfg4MUfjVlne3VBuTQ307QWKbBQJjiHvqAAoJEBuTQ307 QWKbiuUQAJNOYlDm2TDNVnQmv64OC6wVjy45yIYaa7uOIh5eReTKNlFJ9WCvutdx ahyVNrVdDR4lnfmVTnWeMHyeXQTwfxJwzHILr0TI6QIzdjtGSxiukyGgSR6a4jsk zuo1NoGusg6qIqgITocADNDcwVMxMST/ES4wL+A9R7zsTwklv4L5qZetNBoWc8Zt uVSsAMGsS2gMRNBzxccEciaQADKzvFYIqDVY7qjShG9Vx6dhIvPROKAu3K77WGjR 7FwLjz7gs/XL3lFcGkxvL438gt76BCNKvu4/lPNtmE4bNfjO0LvW5qNtTmZ+FxKa VUGu4gDPNIGpvgTnPpnMCyXnrht7SY2X8rI6cGHDi+vkQ4fj5Cqqmc8mJSW1afrd bpo9Ljkq31iRQLSteDIL7GQkTnTBKd2ohrzjFc3ZquDXLfNAxO5e/ZnXVRT3t2ZF poPQFByqY8ToCKeHjRIlv4hIiWb9BI+3ljZU8AJ3js/LWqi2Fji/JJLPKhIrrOoD ijjh+znOa6zOA2JdECxqeM/a3kYfshfv0edS7yzp/xJPf2n1sXAnmesnhBQsoi8d +qtFLXagG3KgdCu4UwgXNN7HJzTAl87YNAB73hteScaBGxqnApX7rfvPjJ+aQ8B9 12HKlShLfc6ZXowq2oV93yK6RMQYEKhTReZxhIhHQiUgVhT+bLNItC5Lcnp5c3p0 b2YgV2lsY3p5xYRza2kgPGt3aWxjenluc2tpQGtlcm5lbC5vcmc+iQJOBBMBCAA4 FiEEEtJ9XYyOm/GqvHx8fGR2jT3jNOcFAmOjX2MCGwMGCwkIAg0DBBUKCQgFFgMC AQACHgUCF4AACgkQfGR2jT3jNOeboRAAhTkr8LR3b/dnYZRBY/2QXFSy4vlD4/p/ FGacMhcZa6itKURW1bRVZkzWlK0Gmo+pWSDls/+0s7ajpjNe6Y8rd/irwy2Dk5jj XG6EWpbfg7Fcu+1tIURodNmnvLmn2xRiV5vj6mCQQwRUKom9dqzBWp1FA0ofVO6u hOq3ZBhPfIYhb66WkukfRIElgXzv+5BfMJHcdCGfE51f4WM75HOgP8EwvNpHXLMy I1AMi1JopHza2f8RHJUt66bu4HgZ1pKxCSSyZ4ugvF6p9cu1hYQjT6BU48x0D7DE nEYkMe4du6OQkXO+r9u0C90w0CSPC/QQZjiSeisDM94i7MgoIP9TMLA1YrypYXSn HAqKLCCpqWr7cB7Z5ybWHD8c9TFdZM6pvaCZG3ld5sNfN+VfVBjZgwSXHtz9pdLi nwz5F2Z0RQqNCDWYnoRODfTCcX4duHN38zAQMsQsAdp5EHOeNHO/qoGKnpxvp/qY ElnjeKYINdOC8ECvtwsPVcdo9ge2ABaHsIwJepC+xv2YMI6Ois9ZrygiYuwYkA14 NKknEoJt3l5ywHx6z7ZTiyqWPyCCHDuiOafhkENtBEFgCevJ5+vbXZRnFcA2ZXC7 ec6iUatcVgucrB0ZB7uQKovVadOPJfxM+LLO+FmckyzHxh7ipPy3dbNu6XbWCm7x 7SvApt7p+vG5Ag0EWdaQSgEQAK4u09rJ4icyar0CJD+w2oVKHqT2oYXfPmybRAzm jrdFCKseNe2ACwvi007GzgMk2sRNBnclPle1Pc1aZ1eDNCNaRX99cVXAWHJXRRBz SReIMFLzzvCxcsAIcYlrzusiFEL0LuRKz1+iwGHPk3A0Gl9F9KmOwAKK4S3R8bnN rp9HaL8Xt1X1dwz0Gx495xiVWHOD5f1GHZdcUFOJi08NyijtJ62daisV2H5EMkVi uWtCQ7acaO9kBrOwS0KZGSWj13XquQD686x3y5uVuz5cRlcQ281Uy5Kw3CwumAJA mB6gWe4tsJPAElEJ3jfOBMeeItRw+UyiS44gk0Vbgxc5V6B19M+ysy31rmlbJahZ DkWaBaQkeCcv/esHsMsyyC48MNVFngy3zwYxB+LC4ryIY3RXV0Std4RDNrqhjSUj zHJQ2CzZtweIo19C0oKkagOUmJ4pncx8BAi416j4h5XwxMZSc/SqRnu56cptA2cJ eu1ijvxXqArg2CydREvlNbQpk2FzVVUBGyTZV7EtaCwk+NtpLXm15q3CRXxV4ikB ngqh3W9g4Bv6rYYfrUGitJWkSEwci20xuBJ1jh2R68dugnYJ9++Th3seN9MQ5K8w MCnQQuFBYFE8WUxnnNugIf2hdMlCqmC2NXLuRWz6J8Bi8rx5i8PO8XCF6hFou+lB Ad+7ABEBAAGJAjYEGAEIACAWIQQS0n1djI6b8aq8fHx8ZHaNPeM05wUCWdaQSgIb DAAKCRB8ZHaNPeM05//OD/4uqiMKCg+dx5NnW1KQnXDr5/iAh/FjRLdACCO4Ud8v sbEkug0pe/Ob8QwlZ2znBFdaosFCN35ZjgMcCTS4X7uCiZWryIcfm8PL94LKcjYm SbFMn3YbYsLu/NFNkjVlIEkE78AuaDedYRHOPT9Ucpi3cfWBrQDOeEZOj/na3h2t OZrNKBjYnFJ2kg0Wsop1MRo/OlSlO9QFenqpGzYvFYd+aEeN3vYoTbgAE8FsBOhF RoekBUpmxS7/vFSDEkQv4KK7UpUKCW44Ddz42Go4BXYa61LBHuV1HRXS3bixL0FL WbTb9XZ7+il1H3bCa3P7rAuWM/We8+I2CSihFAmxJu3uDt00/5yPQ+sViIgTriBP a5GELs0gHpvnq9MKYF5BI5ZqVVqM5f96OThilSysquJ3LbRhnFh1NipSQ3AWgERj J7MnJOm9FKXeRzHX6SgV58BYeWTQyH+BJyvHy669g6vNoauQ06HquR4ZDsv96egS DfQqGxtF+Ieg5yEnxlCe6raWeCDopUU7F0pCxHIBDbRag1xBXibvJtn7bx8HNU6h mIIVZQZk3Hkm6307fXuJDWzgHIHhclYvp7/GR6cE0TRLeTDy+EoTSDTD+w5Y5yQ1 jwsx6lM63PvlIXrFXeg1hoq5/CUk/yhTWrodsptusdr7l+KGVLzNwMHdCzROzy25 lA== =YR6r -----END PGP PUBLIC KEY BLOCK----- ruby-magic-0.6.0/lib/000077500000000000000000000000001440414250500143215ustar00rootroot00000000000000ruby-magic-0.6.0/lib/magic.rb000066400000000000000000000123601440414250500157300ustar00rootroot00000000000000# frozen_string_literal: true begin ::RUBY_VERSION =~ /(\d+\.\d+)/ require_relative "magic/#{Regexp.last_match(1)}/magic" rescue LoadError # use "require" instead of "require_relative" because non-native gems will place C extension files # in Gem::BasicSpecification#extension_dir after compilation (during normal installation), which # is in $LOAD_PATH but not necessarily relative to this file (see #21 and nokogiri#2300) require 'magic/magic' end require_relative 'magic/version' require_relative 'magic/core/file' require_relative 'magic/core/string' # # File _Magic_ in Ruby. # # Simple interface to _libmagic_ for Ruby Programming Language. # class Magic # # call-seq: # magic.inspect -> string # # Example: # # magic = Magic.new # magic.inspect #=> "#" # magic.close # magic.inspect #=> "#" # def inspect super.insert(-2, self.closed? ? ' (closed)' : '') end # # call-seq: # magic.flags_list( boolean ) -> array # # See also: Magic#flags and Magic#flags_names # def flags_list(names = false) raise LibraryError, 'Magic library is not open' if closed? return [names ? 'NONE' : 0] if @flags.zero? n, i = 0, @flags flags = [] @@flags_map ||= flags_as_map if names while i > 0 n = 2 ** (Math.log(i) / Math.log(2)).to_i i = i - n flags.insert(0, names ? @@flags_map[n] : n) end flags end alias_method :flags_to_a, :flags_list # call-seq: # magic.flags_names -> array # # See also: Magic#flags and Magic#flags_list # def flags_names flags_list(true) end class << self # # call-seq: # Magic.open( integer ) -> self # Magic.open( integer ) {|magic| block } -> string or array # # See also: Magic::mime, Magic::type, Magic::encoding, Magic::compile and Magic::check # def open(flags = Magic::NONE) magic = Magic.new magic.flags = flags if block_given? begin yield magic ensure magic.close end else magic end end # # call-seq: # Magic.mime -> self # Magic.mime {|magic| block } -> string or array # # See also: Magic::open, Magic::type, Magic::encoding, Magic::compile and Magic::check # def mime(&block) open(Magic::MIME, &block) end alias_method :mime_type, :mime # # call-seq: # Magic.type -> self # Magic.type {|magic| block } -> string or array # # See also: Magic::open, Magic::mime, Magic::encoding, Magic::compile and Magic::check # def type(&block) open(Magic::MIME_TYPE, &block) end # # call-seq: # Magic.encoding -> self # Magic.encoding {|magic| block } -> string or array # # See also: Magic::open, Magic::mime, Magic::type, Magic::compile and Magic::check # def encoding(&block) open(Magic::MIME_ENCODING, &block) end # # call-seq: # Magic.compile( string, ... ) -> true # Magic.compile( array ) -> true # # See also: Magic::open, Magic::mime, Magic::type, Magic::encoding, and Magic::check # def compile(*paths) open {|m| m.compile(paths) } end # # call-seq: # Magic.check( string, ... ) -> true or false # Magic.check( array ) -> true or false # # See also: Magic::open, Magic::mime, Magic::type, Magic::encoding and Magic::compile # def check(*paths) open {|m| m.check(paths) } end # # call-seq: # Magic.file( object ) -> string or array # Magic.file( string ) -> string or array # Magic.file( string, integer ) -> string or array # # See also: # def file(path, flags = Magic::MIME) open(flags).file(path) end # # call-seq: # Magic.buffer( string ) -> string or array # Magic.buffer( string, integer ) -> string or array # # See also: # def buffer(buffer, flags = Magic::MIME) open(flags).buffer(buffer) end # # call-seq: # Magic.descriptor( object ) -> string or array # Magic.descriptor( integer ) -> string or array # Magic.descriptor( integer, integer ) -> string or array # # See also: # def descriptor(fd, flags = Magic::MIME) open(flags).descriptor(fd) end alias_method :fd, :descriptor private def default_paths paths = Dir.glob(File.expand_path(File.join(File.dirname(__FILE__), "../ext/magic/share/*.mgc"))) paths.empty? ? nil : paths end end private def power_of_two?(number) number > 0 && Math.log2(number) % 1 == 0 end def flags_as_map klass = self.class klass.constants.each_with_object({}) do |constant, flags| constant = constant.to_s next if constant.start_with?('PARAM_') value = klass.const_get(constant) if value.is_a?(Integer) && power_of_two?(value) flags[value] = constant end end end end FileMagic = Magic ruby-magic-0.6.0/lib/magic/000077500000000000000000000000001440414250500154015ustar00rootroot00000000000000ruby-magic-0.6.0/lib/magic/core/000077500000000000000000000000001440414250500163315ustar00rootroot00000000000000ruby-magic-0.6.0/lib/magic/core/file.rb000066400000000000000000000021751440414250500176020ustar00rootroot00000000000000# frozen_string_literal: true class File class << self # # call-seq: # File.magic( object ) -> string or array # File.magic( string ) -> string or array # # See also: File::mime and File::type # def magic(path, flags = Magic::NONE) Magic.open(flags) {|mgc| mgc.file(path) } end # # call-seq: # File.mime( string ) -> string or array # # See also: File::magic and File::type # def mime(path) magic(path, Magic::MIME) end # # call-seq: # File.type( string ) -> string or array # # See also: File::magic and File::mime # def type(path) magic(path, Magic::MIME_TYPE) end end # # call-seq: # File.magic -> string or array # # See also: File#mime and File#type # def magic self.class.magic(self) end # # call-seq: # File.mime -> string or array # # See also: File#magic and File#type # def mime self.class.mime(self) end # # call-seq: # File.type -> string or array # # See also: File#magic and File#mime # def type self.class.type(self) end end ruby-magic-0.6.0/lib/magic/core/string.rb000066400000000000000000000010371440414250500201650ustar00rootroot00000000000000# frozen_string_literal: true class String # # call-seq: # string.magic -> string or array # # See also: String#mime and String#type # def magic(flags = Magic::NONE) Magic.open(flags) {|mgc| mgc.buffer(self) } end # # call-seq: # string.mime -> string or array # # See also: String#magic and String#type # def mime magic(Magic::MIME) end # # call-seq: # string.type -> string or array # # See also: String#magic and String#mime # def type magic(Magic::MIME_TYPE) end end ruby-magic-0.6.0/lib/magic/version.rb000066400000000000000000000014071440414250500174150ustar00rootroot00000000000000# frozen_string_literal: true class Magic # # Current version of _Magic_. # VERSION = '0.6.0'.freeze class << self # # call-seq: # Magic.version_array -> array # # Example: # # Magic.version_array #=> [5, 42] # # See also: Magic::version and Magic::version_string # def version_array [self.version / 100, self.version % 100] end alias_method :version_to_a, :version_array # # call-seq: # Magic.version_string -> string # # Example: # # Magic.version_string #=> "5.42" # # See also: Magic::version and Magic::version_array # def version_string '%d.%02d' % self.version_array end alias_method :version_to_s, :version_string end end ruby-magic-0.6.0/lib/ruby-magic.rb000066400000000000000000000000701440414250500167020ustar00rootroot00000000000000# frozen_string_literal: true require_relative 'magic' ruby-magic-0.6.0/patches/000077500000000000000000000000001440414250500152025ustar00rootroot00000000000000ruby-magic-0.6.0/patches/libmagic/000077500000000000000000000000001440414250500167515ustar00rootroot000000000000000001-Don-t-attempt-to-build-tests-documentation-and-Python-bindings.patch000066400000000000000000000025261440414250500342710ustar00rootroot00000000000000ruby-magic-0.6.0/patches/libmagicFrom 7bc0237df1b0d3faeef59fea933f51941100b15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Tue, 19 Jul 2022 23:50:48 +0900 Subject: [PATCH] Don't attempt to build tests, documentation and Python bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Wilczyński --- Makefile.am | 2 +- Makefile.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index e816779..980cafa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = MAINT RELEASE-PROCEDURE README.DEVELOPER README.md \ m4/visibility.m4 -SUBDIRS = src magic tests doc python +SUBDIRS = src magic # This variable must have 'exec' in its name, in order to be installed # by 'install-exec' target (instead of default 'install-data') diff --git a/Makefile.in b/Makefile.in index e2f0673..2f02b82 100644 --- a/Makefile.in +++ b/Makefile.in @@ -361,7 +361,7 @@ ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = MAINT RELEASE-PROCEDURE README.DEVELOPER README.md \ m4/visibility.m4 -SUBDIRS = src magic tests doc python +SUBDIRS = src magic # This variable must have 'exec' in its name, in order to be installed # by 'install-exec' target (instead of default 'install-data') -- 2.37.1 ruby-magic-0.6.0/ruby-magic.gemspec000066400000000000000000000036171440414250500171660ustar00rootroot00000000000000signing_key = File.expand_path('~/.gem/kwilczynski-private.pem') require 'yaml' dependencies = YAML.load_file(File.join(File.dirname(__FILE__), "dependencies.yml")) Gem::Specification.new do |s| s.name = 'ruby-magic' s.summary = 'File Magic in Ruby' s.description = (<<-EOS).gsub(/^[ ]+/, '') File Magic in Ruby. Simple interface to libmagic for Ruby Programming Language. EOS s.post_install_message = (<<-EOS).gsub(/^[ ]+/, '') Thank you for installing! EOS s.platform = Gem::Platform::RUBY s.version = File.read('VERSION').strip s.license = 'Apache-2.0' s.author = 'Krzysztof Wilczyński' s.email = 'kw@linux.com' s.homepage = 'https://github.com/kwilczynski/ruby-magic' s.required_ruby_version = '>= 2.6.0' s.metadata = { 'bug_tracker_uri' => 'https://github.com/kwilczynski/ruby-magic/issues', 'changelog_uri' => 'https://github.com/kwilczynski/ruby-magic/blob/master/CHANGELOG.md', 'documentation_uri' => 'https://www.rubydoc.info/gems/ruby-magic', 'source_code_uri' => 'https://github.com/kwilczynski/ruby-magic', 'rubygems_mfa_required' => 'true' } s.files = Dir['ext/**/*.{c,h,rb}'] + Dir['lib/**/*.rb'] + %w( AUTHORS CHANGELOG.md CONTRIBUTORS.md COPYRIGHT LICENSE NOTICE README.md dependencies.yml kwilczynski-public.pem ) s.extra_rdoc_files = Dir['ext/**/*.c'] + %w( README.md ) s.rdoc_options = ['--main', 'README.md', '--line-numbers'] s.require_paths << 'lib' s.extensions << 'ext/magic/extconf.rb' if File.exist?(signing_key) s.cert_chain = ['kwilczynski-public.pem'] s.signing_key = signing_key end s.add_runtime_dependency("mini_portile2", "~> 2.8") # keep version in sync with extconf.rb end ruby-magic-0.6.0/test/000077500000000000000000000000001440414250500145325ustar00rootroot00000000000000ruby-magic-0.6.0/test/fixtures/000077500000000000000000000000001440414250500164035ustar00rootroot00000000000000ruby-magic-0.6.0/test/fixtures/invalid.magic000066400000000000000000000000301440414250500210240ustar00rootroot00000000000000Not a valid Magic file! ruby-magic-0.6.0/test/fixtures/png-broken.magic000066400000000000000000000004661440414250500214550ustar00rootroot00000000000000>0 string \x89PNG\x0d\x0a\x1a\x0a PNG image data !:mime image/png >16 belong x \b, %d x >20 belong x %d, >24 byte x %d-bit >25 byte 0 grayscale, >25 byte 2 \b/color RGB, >25 byte 3 colormap, >25 byte 4 gray+alpha, >25 byte 6 \b/color RGBA, >28 byte 0 non-interlaced >28 byte 1 interlaced ruby-magic-0.6.0/test/fixtures/png-fake.magic000066400000000000000000000004741440414250500211020ustar00rootroot000000000000000 string \x89PNG\x0d\x0a\x1a\x0a Ruby Gem image !:mime image/x-ruby-gem >16 belong x \b, %d x >20 belong x %d, >24 byte x %d-bit >25 byte 0 grayscale, >25 byte 2 \b/color RGB, >25 byte 3 colormap, >25 byte 4 gray+alpha, >25 byte 6 \b/color RGBA, >28 byte 0 non-interlaced >28 byte 1 interlaced ruby-magic-0.6.0/test/fixtures/png.magic000066400000000000000000000004651440414250500201760ustar00rootroot000000000000000 string \x89PNG\x0d\x0a\x1a\x0a PNG image data !:mime image/png >16 belong x \b, %d x >20 belong x %d, >24 byte x %d-bit >25 byte 0 grayscale, >25 byte 2 \b/color RGB, >25 byte 3 colormap, >25 byte 4 gray+alpha, >25 byte 6 \b/color RGBA, >28 byte 0 non-interlaced >28 byte 1 interlaced ruby-magic-0.6.0/test/fixtures/ruby.jpg000066400000000000000000001013401440414250500200650ustar00rootroot00000000000000JFIFC   %# , #&')*)-0-(0%()(C   (((((((((((((((((((((((((((((((((((((((((((((((((((" @G#Z3a6ai\lw}װodo:;CK{SC:7t,xnwl|t>>O=_Gqt;;X{+~?Ioap6Z9||:5̣,e#Z\0`\PAg+>'z<6r!_3kеWK2eX-V"[ٺ-^_ę6.77G a3cf`"%.0a8^к7//UX-*ԥBl-n5}'y,y<{{r]uG-Be%.!q 1v.B޻غ`|.z&/zp lĶQ-JTl-wc~h_7EƶŚ8-YXY[o mr۴JJlKn4jXV؋ay_cmqL{Ow넠Xa oQs.wp|^{ @@(iBԱRAl-_׼{O>j׷ڱu|Xmﻯ )~]XXb =[gG_c,X(@((UrAl}7<\,qÍ&[ӌtӊ-X}i%b" q8n TQԠ( RJ,TݧWg~ LІ ,QԠ(-JT{_U]S};ŶՐTAR&R * \xӕ!ZHux 'ƹݣO`( ,QԠ(-Mj?=qF2U!PYHT!RHJjÑo.Gy篿}/(V X,@B*P^g>#7B +TR ,v;9OWaWi>0L@ (Yܳ<K߼۱l #&"A,DĤĤȱRl~л2H<y?lsz"[`YV %X(PP`HjQ_ֺ|:p:׏~>_cXT%`EEB),@DoOF4t\vtO>2ؖ-m@T'No);zE8y5WoBAB `,,@,,@ =<׺| |'|ÛԷж amؖؖ( @PS=; c-p<9Ʋ%$%%XM=Oͽ'g z~mNjߩfVe qlE-ĶDT(jw|G_2q&yn$^[\E#{fLlX@bX"Ug͆|<|3GvަXjUb[qlEն%% %P}:|. 8N3 /&qq伇hߥ@+$@XR$ ھP3ͻGZa 7~XjUb[qn6-ƭۍ[b( @rףR9[S5۱miZ٨mjzw/3@ER A* ݾqaəyG~ohviv o㥞jXVZ-[qR~G NzckP6 P P]q9A E g1/ʀ<aӯ~c \4 xJTRJ,[Z[qۍ*Y@_n}~mr~&L E5 P6Cl>H,  J! GaNz^ho ӆ2N\ta7UbZjXKRS2vz|:ynnO&[֡mᵨfmᵨ^;   m7`;_TuuuG;Fx:y1~t^Xv:p6aa)RJ*ԱRNpy~4:|x8)rb2TA`TAx\4 !@@ V m {8Ǘ񾆬sy9^~wp4a\7Fopӆ.:f,%*XVC}w_O_G'tptsề <a\N :f.2Wt?NW˔=lOf**  * Nug ` L][-* o^'w/:~?6s?Tx3gG;F:90юv7qu5̴a ӆn<|{Gu枃r=-Yy!j , * * ~Ae2B]DNCkoIz|~Z;tis>}}Sݫ7ecV+q8Ҽ~_֬6\KL5.HZ q11AP][03" * l-2UOuxo>п_.C@2.+ʜ\f\Ēg*q1*qqrn6taۘ$;.H,P ,̥,*͒aXCwzwg1iɎ'q7Ë.V<\f\x̹S%ceʜ\eceʜ\WLXqr/lӁIQɈ RZXYBdxl (2d vCql*۽7=(zOowdů..Xe:yXoKNj&\xNj&\x̹Sx^F:#-[7r( e-Eז9&@5՞\ I dG|ۚ-޺pK;czsCo}NnfS~~K0 zvNƸ&l˛\]l˛\6|2"Y *P $ B,X;f;e@ ٯ%ZöZ_b|^WqߑWz2 "}_Zmr65vL!YvMeͮ& ݸ!  $  le-FHم%W w2S/yR,`|I^y1Lb1LFL m{7kK(&0H( e`d6*Z V-4Ѭ]` n^>zD@ He>Ӊճ9r`L9b2ѳ㍸"X`%J@ͶUtKlO;M@'~sӖ=?op}(LA@g\21cLLaF_?3H"X ,ia@`CezUURUT%SO뺸+2@2?a{OaOq^O9( [Gq=#,xXRI:r&0,rH"X b 6l͹\rUYKVURT%U-%XՋIh,KjN7.z?{l]}?V<]ғW#C H$K@Le,HN n=}97|7pn>/=˕p]¹.9y>'=K,,cu?Uk7}>*/?w..;:Ǜ<Ψ|=pǞʺ/?yqnO1y>y#.=3ڗ p(/@P 0!"1#$23%4`55[|urAey>,}Xܱc%K}>(}P7kQf ۨt `‚ ޅ)1ۉqj}Y+u+uN7BIޙqqqy'l$3e\gir{݈{U&A^∌.z)>>Wl+u/Owe u^2W+Q\Iӣ},In#nO[ѥ ґ/KVݐ5#ݨ礓{]q-S8\1cچI{k^ TZWҥjP7✹--j7pԯ]FZau<Ej':ZQتl/O{'RNĸ1U.C-%jT9cQq\ZsIV+~_/ @v,zu ߦ`}[V/N4ROеQs%P".d졆v|,ލO/Kyl4B`d2 CT7iSՓm͐RR#]C!d+H-(c;$pJ^Gd2 촭8+IO#2"M Sd2 C!# /R{8%/bLh)fd2 C!VrtZޟQiPeS%@sd2 C!d&q4Vx5+RȬS\\\~‹p"ƕ^7FwKߤi5{I~B}ߥ.'/+ Gb.DUw g~^UpITIF Q%5[[QX)~5T˃˒[P*K[|}I,^5 \ m>n|_...//G}@NUo̓ d JZC-ɐNn___/)iSƭh dvK:MFKrSo7QU7T/ d 79N "5mJw t'P d =2-!Jz!6}˛ci"/n d 2@$WM5Viu:_4mc0w2@ d =ӨKp0l7ҭT(ȟM}0x8d 2@ ~}*D"Xz$J9cF@ d 2@ O1ƱVǀVi$f3sbCX( d 2@za84"UOX<1R_bO4h3 d 2@ ea)Eo*wd/ͤJfGy+ d 2@tb%B46#\j\_zROZ?€LZdaq  mKLHPM fYqqqd2 Y;UӴ SݙC!d2 C!f?sڗ 9U:zC!d2 C!d2 C!=h%J>B+3 C!d2 C!d2 C!Us/cq}w?J2T)?S!d2 C!d2 C!dR[KuzCt , C!d2 C!d2 C!PrԿ^\?gbFdq3d2 C!d2./GL}u!s֖!d2\:\_7?v/(д$c%x\\_Q ε㱚#)?pS y2۞<֯R󊼚QΗR+JR;錼\?ǝG`aYVH>w_^-?ҞYNww_>;E2֐W+^;<I1](Ezg}l:ER}/xNN3}m?H*M.p´jY< lԜep Jj>ERr%-|4WU7{-i4cP|5 ]g=fW#D^N/ߠ[[/8ƾf.u&?#XȜy7IA%dq8xp32Rɿi7Z' I4JWKMN•F31FiĸmCOR=8I)=_63Pw;;C@ dZKKGzkT߫B~.j3P8>+T`HIhwYiu/U^dji~I&a1PL j 0$ L0Zu8``` " A d$ÌM  DCW] paJPM.ig* łӉ ӱP!*$JA0b $oRgPX'tMbHP*l 0T9-8-6A:u?hp&i 3).5I%$g:(f,i3q%-:N0Zu? M6ĎM\Dt9A:AZ~@:tYTGT) OHV N'OGAA4h$ aEH&[H"4 !01@A#2BQ"Raq3Cb?Dֵ5MCچxX~м$`^/ p`N}9ҤX9 =3L,&8NѸwvRh7EBSJiM):veWGoD8IfwzkFbl͵h݆}SJiM*,NΖ4zBGo<<\x{HʊPI=\-5 \x/…9| Q}.>xlu>6T*<[h]4QXVgEMppP,cq͌4Z(:IelMI}TpXV+?Nx<Ś$&ɋEjZVmUWmsxHtr؛s2c(lBQQQS1yɍ8AcR֪*******p3vV`q8øsPSrdmZEL訨hƑ İWNjy&0QTTTTT81F<)9I+crb.,?Ҁ G᳞8L\ A lkY{W,YMCyieF(P@P9LIJ.jlKeI;li3G敪X&U&̩qQŽgI҇2у?WGky&btZ{8I)'OQTVU UrygіR0=8V+bXٹW6垓>o@kGubXV+baپ+À|(&#nN)콖XV+j0Pqo(x`zsKMq8-,|?9ल_MJk@=~CqZXh˭em5 *w[uK?[Y/Wj#ۣc\Vk ^Zϕ{~UdOeH:.*ϡG^Zxr~W)'U+!01@ 2QA"Ba3PR?IRU^}]]]]}]}]}B\P$ Ӻz]CxMHvaQGI-6w!ZӺvD^Xd&8TEtSx}w>J (Jo?jTU4 T1=J_H+v8ܞ)IʩV z/W&) 㤯WxL g ).9۝ ;7@; ).2x3sTuΝ$0@̧Š˝+?A|4*Ի.56XUsŞuƠ7'—G⵷@@j…j vOuxԩ0(PTϛ/qpo('*9`e\g>dpX;.[9~|OgoQd(PVUAP|Co1 ]|]|_+cma-ԏ8Vc.ۗi˲Wd!vZM]pM6h]+Z~+vv%v kd.WmV_> !1PQ "02@Aaq#BR`b3r4Cc?⿴V=H{F$1+Ohc?ochhk4ZAtJ >qn=WΦςѾM)7ju)c|Cn+2uGo> ~TeiFI(pqH;&XiZn\RH4D3Ξʩ:'7bw xc=ٿҁ&7U:GLݑ@φg l @fXigt+MN(WKp*X5fh'&,e+:$}sIyhZc'W'D,7 J05*$u5VrN״S22ea+ABa.uPسKueJ߭miҾ0_5`uz72U؝!{+p[ qHBvAZ'[[N2U`L?*Q$]`Řtn6t]yNv$Vc/%'1˲yѱPPRX:Vg-5(O-& QR`7bEKaXn~) BR+& rimUq{o m1ة4H1(Y#5r5" *s0)'|t*RL|zmZRdد90wќW7(k).neBQp;2uĔR?"!kMV9bL3Sb8q[jMwX9Y8f P^o)$^uBĜ}ev4f4&O0053''uA^(էg$>dsPٺVa 0#i:Omӟ̲zce-~y;5:R4eL)&Zqs.ˎy )L6_>Ȇk?a*3ZM$MiBQBNh|{hI4ѳ cr?EjH Y3W{;4zUbZVp (fS) Qٙt6&$'͒L' 4 6g hYi>f m2S@REndح3JuUEԣ96X Tq$R:S;oRsMYrO$=(0QJ94׺ qtDId;QD4rAX2~런ґlOj(&ϝ2a0lt*=Ty l6PJ-f`4Pvq`oU`bv5J@@vQ26& f0ΦFȽcޫ6pckWK3$m~_iѠ@T_L1KUQX-"Ay11ڄGBRoۙeyz"V.PM*4*{E /4&c-ĎYZѴgVpG'1;u}3Oόۗut6w$4&#gr#F+#C*ѥ$89H(4ݛ/8 -(e$1uyH⨤=QKxʔ&)/)[4V}Q'LQ&o2XhzDP,H&Xb *hYw~2B)Ǫ)uR&2 Le:>SQ"( zbpA`JyvMQ3͔bЅ(~L|r#Ehʔ$Sh}Qx?NN4Y(.1;` Q7Pcmh5:>Qˇb3L~^dGHE%߱O"+>&(7,4="(JGLe!4dc"P|/6}Ϫ>~x3qPy]h{T>Ie LR)> TcȊ$}1p+ !1AQaq0@P`?!O|| }0>b?@DI*fFsCK?|zY#k7^c>M{Š ((&^ ~?2+luy$38tdy:?~r=YϘ?F   >sbr;.seu9$NE {z sAADZd,J/Wuf=C}q"R|tn߱&QEADt2W|46iSX#n>}1{Xm4pCk䚻Ebi or3tҖ FM#YZ6^۵bY㗱;[!mZgV3in_,KE|v&Svȵ͒/(d24b&[lč51[m2E1sK*wvkiclO-T!ary u/"ϜfT&-YXԒIgm=.~]Z[!#[/gM-;E xx}8PA28| h!v;(EUWCn-\h"Zt\WY}\0Y+vy*&k^čb'] PQ#T45u_ ٦M݊|9" ̒-Uwp\ DYQPR4d.&?ϓdXO ,'s:ꫫBhб0COR瘑nibkg7mVVUB m'/.wQvfٶmkoY݌6u%aJg9'df{nv^劋%- tHaԆ4LZbXE_ʲW*HG_$y0tHhv c+HvX2+IheBaTI$]<ی!$^y7D&dz1eC#BsJ: x.݃ϋ%&ÞңSJNb'fvď~.g/ץ)d%!rm&G+O \KoN\'l}n\_JKWy˽/ wi [yeeod^JRLIb#6CTm-kQ,v1.O>cP=.&^K^8%zH_O{kHO6.ȍKWq>vIw1hs_,u~!t;~s#ЂMns% ?R_<`ǂE6K]))4[˒H4ЯkOC+c'?oۥfZq'~lp1؛>khyNE-oL?k_ff0[LN7j<kش{tֻ%&aLDŽ,5UĞ tvAklB܄0`[YeY1ZW.hhk! !+B'nmhTB3SUdwYv$bPI&ВI&|: ]7 t;SF6iV:"I4$I$К幣U"X_畮>SV`$lc4W;I$M Xv-! eXQ{XB["zAjm5=?j &PM &͌0q:&|VJ sMGV$@R[zZ`Mp&BhDw.z[ZlkZ/Aw׺:Kc/g$I$ВII4$IY ,,wRʿ?MK:@nXHӺ.I4&M $hM &ENoUJ݉! lߐ+,-X7]ܤM $M &I$I$ E`ҵT#nb_q&2[$"]`F-I$I$/w6nT444444445W>]j ywZsIb|˜ hhhhhhhhk884;2a9O5Gjhhhhhhhhk`I)lw-ѧ.ڞ xojsNg,=bS޶E f~UVvdE J _1m3j-dXjE{pꨁm۞{:MJS&P\uY?YL]# r̶4pᡡ"Oݜ{ANE%Qڸ>sf|SXX)|>hhhhi$w$Bϑ["I VQ6 w.d$x7 !adC%2D1Q)AM>EPձXZG#J!Fɬ|Jm\,G->EKƫO5$Vd%Ţp&_1s;x_l1i{jשa(;<,PȜ5JRgUTVq?a0kZkC\`? TْMK2F4@"^(̊j1O⇐mè:t@asuA/\Uz>qB͞T1X1(u *GT@u@mː]U]1SMKX.G&0 :t :"R<;Xsjwgܱ\))OՓu@ :$H3 02}I25K3B5gt :S$I$I$nϦӹֿJn:Ϛ"keDI$I$I$I$e{Pi"΄ORedɡV$I$I$I$I$wFr| 5Wlv$I$I$I&IS DxvHPI_V6)$I$I$I$DGJDZIpD2QRBO 3'I$I$I$I$4UF:f{KlI$I$DI$9+:*Hdr ;MuM5UhI$4I$4HS@0$&$I&e8{.+ǣL ꟯sćx\I$hGU3Zv35%ōI$I$I n,/p5GdXl,q̒I&&\TԄpEd!T=Ô)$I$I#s m`-02UYA$I$Hй!(搑i yV?ѿ~X^ߺ/nI4MWsE4pOYЎ(GI$$L.~{*0b^b]ޠ_c!bv8DӹQ")7*Wom{d FLiFʗy( 7w$F:~ ,9%ٴ~z)ٸd^<<̍Q|Fn~)Fn<,5a1z'lqwb'< а4Q|k~^h`N1<7 mGu%).vߥ;%|h*t8Oo5<es瘶T۷n,?9BKr=_<< y ٦u.V'z'\D{{<<@)vx[ȼ|J[ѡr=<-druaOOs *̉R}L\_jJ6' Лp*S9ATڀKy҇|z ܷzV_hPS7ydgP0vg*fwvu'!b:DJN;ts 6*w\x0+9MrT+*c+Cw<,Gc] =uݕF~,.6Fm6%gYT5!OcLbn|/5[C%\\KkmmccDSkjeZZ6ưlvnSr7F:@@Bʃmx?h+lÿ)F]YJ%DRD+ckrV]qH&RGe[>N:g]IHh߬(B3 ݱ@S$H^wW#W5L7?+mn(ڪ1J"D27&L5~Hd(moVWXqvm_Ω$H6օYF=&KHtkk%LJ&6$H"^[wHˆІʲV9ӹbd}HkI\ϤTojRe nPz|@z뙃s8 8JU~`M ᡿kp#rYU!6"AI֭>L?}mu*@/PbV.sce f;7U2o*z\+ |_;\7dJPpUy cҏ{+Y'NpӥpP 8X-Ak쒥#pkybn6Rp7=:  hloU23AW[2R pvݲB jJ  `;& e#< W#`W`e=GNe!- UXeXD k2#8)Q+Ts9GY\ԔY[FksGG(@ѝk lv 7Peu u7uřXo pm" UA4od[CaneAͼzř=/;X7[AZfR7r({tl,cg],FqJL>m;^vXšc.Sb'*)݃mr/{k++rnSiIEag]=Ćzyŕ&M klְ;e%nq?!ĕz&X%fdj>BU:`R;p*%IYYYYLDH2c=O1=OG!}19bȽYYYlb s sfO>Wшd=>Gs4'=u:/s9o`8眾|cYudz r}OGXHzEj99) !01AQ@aqP?'t}#O>O'IkjK4?7 &1&6v4g Qn:kJlNr!'j37o Kah1bρLZ?6n\yzsu"abȂoDEy@#©>ٿմNʡzL/n VXt־l?h/VC@[(؁y濗UixCGǯ:&eqY vbTyK߷(d9u|tK[5n܎ߊ!)'ΪRiyixt-oOn/O}Q7VjaQkTXƴz B6 sKD;/ _ZCMr 2k@Z.RRCMl8D~ .!ox0`𺘣B;tև=q!kFؔA`778Z* pxjTG\(M݃EU=H#0:nHm wQJJ\ ~cb7XJ2 K.oD܉+|oYc /Է5@%%rⰧ%#C 3A訏\CN,=a n˭1u2V`awJ ĸwY.\\nև.)u"i\+>r,v.\gYihdxXn7]&MJZi82KMbfτu_h/dR>ybku{AIeJ*T(u]NRo\%#w?YQ6  Qttut2RCpE(?-Wr]rV%2+%J}i߿-J]A4 [%߯V;.«UA- %zw{uݛ;wk1"gH,kQDxG|^__YAv+{-E^v6?6X?_q}N߈sr¥gU. jQc-R*&vnwvn釻 1"D6"XB8q UyDBOs/F7ݪRO_y57be&S/Of&L,nߥyLz3~poI7 P$H&v\F81䭥̤xβ(nƍo;D[=ޣ:\Qj%0r^[7:vPOޮBo7`0]ZAb(4v_׼ -^KZh'n9%ovW[zyu=:Ϙԏq7tn7j #ww1;1}L[l].'e&g= L=[? j۫zA G_iE*96'yҝHev^x";9Z˄02 /kUr ?1 r."%jBGO_ia81cCw5ilZomQտgR[; = `n{Mi( [=Ji~wXqqpuwlĠWDRgO& hrM<Μ`C!`C  ``2vO7b޾;%->`K{O,ptc} yԝ:YdSus!-˃pp>BR#RnOӴJQ= 9TmUYygv^.c_cc059}f.@黃W^@(Lx2W'pOJTIws #^8;S)`BCazeRZ)tk. %UoZWZ\AeԋQ{K2pp8\sMn{fu'Vڦr>uZTWa׼/ ]ߴ&z{e $101!0%hݍg<眳wY=dPvrE4hl?q=)``8 OP~X: cn$n)g. B?qV}GOoL@s^G |ŗ:č[|*ּ.x˄uo 9orvcWť(躝D=LpdzwcQ-Wuz\y̤10!~&Vg>1]e8)9g,圳r&=!=FӨuȤ Kɚ7nB LH5hR}ϳ>-NX9qq{X(:,NeKc#mPjd@Wiz x\.\u4b]/i[lGV\+,1p@N#6M^mYGF/~d=! ! :ziq@HYrǛ;ǜ\\yb\eI.<`tGXp7~Fݣ%YuP2N[8u_yHeŋ.Զ\OloB9\ы;;ZV{wuۼ^SԹpe0Ⱥg][?bt`T,.\r˗.\r.,.v\/%᣷_ތ+uwuzobjeB򞁒`K}'Fcˋ/ŗ.Yr˗..ZbW8>w64yh6jH=s&Xi߈BiL~5sw0}k u@6wGCIC=[_=zKRҝ+yNV v-{̻;z+PFu< ^d\03@}x+= Ѷ`N {3e}7ԋr'&tJ89/ y2hvݝݎ55e_cYYTR8>Fi`z;FN^&ƆBeA?z.KأC|uX )~4 ed=g\\ppp톕_sZgC]VBz[= [,s:=T^WUJ@YR+tmdXV..G)Vj|6-'Qt ^7//-K^!QOe*<)NVЬ @t21B\a{e{C# 3,h\EQgJ|Mv:xS< 2Ϲ~r88;::gzz-)x2!/!^S7X=w3uW#KӡQ<((D)ϲ~ 7`h]CA+ΆԆ5V?NpƾV\8G  {c@(~A)vLyO(8O(: ~;ظjo*71&Vm^`8znCڿy}N7 *j"m()QQe_ߦwKC+ v5h<ۓZ} |ёH`9C 6 Ut@ Hש珘jǔyGQ5`BA0 W3fד+CHn[T>)P`˄x\!.\rpr^`*h :Πtubja"z 'oh8 Ǹ {缮ks.LB VW`gಽ=*dHBa-Ⱥ4  Wwaܯn3@v7S|2C9zWBoʵ#IFӋ4TqC C)f=S`;ؠ6Ժ,9?"-z)CGp'gɾ]}GXHns![(yCD(* `pe˃Id=臑].ݍUz{J7 8 t㭾[.SuYr˗5.\r&L.^.\rYqץy6@њ{<hPu7ewI7pihcT`C (xJ߰}`k~=:[L^rY,.\rd˗.\/'\\|ݕ %C{<>rD@vm24WY@!j^m%d\r˗/*dr Gl_@n[%0 k(+*uE0荌7MѭOfȰ R3 nxn%$3qN *hv&.a;xu+]T"Q(f͇*n)P.\r+-r^K.]˗.\is谛PP%@:y3sKF|¦^缰XS䗕Ը?[QڿЏ_,xzsC&UVeBFq[K9m:`k̹rˊr˗.\r˚9 Z@H)+oqRZڶ JSH)SrM rNH(NӒ_dm{cAFX/ˤY,K.\rbzsoe@*2TOt 67 :߈=5ݏ8((򜓒<$yGyNH#G]%J+5]uwktj9LϷ* P"߶ٍV_qeV&՞+@GqS=S<0X rKc>ŚՖ[ EyuT Nȋj,qcUbx1S<dd5.\YxM |=،@įL߹rv Soc,˧ǸZ .G3Xllp+gUˤ`@*/n|.\[ Fk,lvH,.땓c```qqs8 Q+\@%k39ŸPal]Y^:?,˄,y؏;u._I\\Q*TB@q}7"R>dcR \;e V[.1ds\.t"FU]>ί97E_#7rDi5!^Fw /0)88tp_Ch@!+Q^; ֡Տw50\$ \&\G3&Cm*BT u#s+ W-47EqwcQY{u탃G;r^\%BQJT'fsH&~LR^kb8 \]q3]7}ݠJT Jkϗttu<~D ?ƤT)-W\pqGGx9]0s\rP[*  @*T3D@D~ae?&o%˗JG6i* W!*WTN6eB_EďԨGPt#QikJԹtrb˖XEղ(4J @* CnVGҰv 2ݕQ ?@!\0#;+AlL @P0 `@JϲVu;>r~M?PVo }[j_MO!Wۼ3 @%@@ P J:vp 4m!j'!J ѽc g/˗hxC z{N J%@ @T@//==}#Y*Y4Oպ}K9 ,vOy~SI{*[ !>?+9 uܲ:S7? lAi襘 2?Q~/`{~򄬦0W;OAS|)nF}_((^~VP]?J.?0~qQ}ܨ>DwZFyh@ B G Pw`:j9s@Tq@ s ȷSܭa?GE9@ |d@ \ACM[[^q@  rCW wѾ4GΝ4SS/Cug9r_@2@ Ƅ|w?hu%.ʸ[9rB d@Ul:d\]cB d@  o!wQA]$^_ G0dL7%ҽ*"BZO G⼔<۲8}UI^zcZgqZR7>Fk#*X>(S'Psc͝f1Xsf;X46r#9ag58!QDK$f|=LJ+ˣ^qC jq@ jvCq?wuM7"R^ M"LD爠jq&\N&36DL9eSliy1~mDqȸ֮dCwX^d7]o.f9q[ !w%9"]DKquBL y 2k5ZDbYʧtLD/$ |VȸH;_ooBIƥܓ+AuFw!j.׊ȹpC%ɦTQGu<{+!_u^On-܌F^َ˭[ xCGmA 8# 8|*"Kizo3@unIxkpnIʧ5-/u|8.{?xnQ8P@2@ @NLx$qAy T3yTzBx֍g  yp y?b-Soshy d@ 9 [5 7 Y Y­'ͨ:zNndy>$"H:x&_Dƥܓ+/8L'%h5r/*.EZxWG q@ jD:W!۾yy&hGG!=FRQGu\;rW28fja__Eݥ=wc7~Y G "^\.#vE$* ~g{={:Dƥܓ+YTu|IF;(nǣvRrO^ &$]:ߏHkC3q@ J WR4$舚$aj9㨎rw2;nk!d|^# ׎eB Z8.l/#"\-wGk?~QCSĄd@ tC'yu[+7t ࠄAZKAqTljf'N=ɸ2EPnщvшg &,Kme_uUD\ݚCq@ P 8Թ7t pCԊ%ṝb"8lgZ+"B^cbg[n@F8 z\]Wxz8]Wް}pD@2@ 5[7JvfIp{D:8rO2gqzf3aܐ2'2mg^+7{o}!& G BBE7k[6O ɚM ](X>x/oР[a>ncy㨎k ;ڕcCc'u|I`tUL4Q'v/Բ"2.ʠ8ɽùk!jq@ Hu[ٮh n:Ӛ c ?2;%D>?.I.8"ηl?h)QBڣ[$PGu1n_y67ICu̾;rW2#EܝFsD1{9(Uپ11Olwt($8P( rޗmcjn@_LӺ& 4 UQp2ѸM9o3.){JnƤ,Q$2ηA= .)ႀ7c".w-yJYp+k%ePmUEGZHqTǥR(UyqeYIt< 60%ݢ. mS>̑sAɓpY+*x3d<yx\x%p%;-ގ" -溎8RkBIƕLR A x̎`zZ7inχ*tx\-7nb2@2@ }xWqC/[(uCpU[Q6$diA϶r>\OTh캞*<3Hz E8WSe\&f^ש)Ļ3o,-`i)ȹDܛt >.N&qTk83NGqDIx'7)*.kפګu:2+♶NNz7n}J3 H/> Wd.泩|H(l+aBAĔ t?y"Hćc-"ZE 'N)7r6<\)O JR'++r>G>/p[uQGu\|'j93Ox-cـFc1Qǥݞ*e&2+e׏~+Umt5A(@2@ L5LWLI?|6%!C;9#ڒM 7#,qAsB>*2uE m*AJ$.pM礓b$4du\^ެ!ERj9M ΕqB./q".+$oC)pE-wwC:j΍Hgя:NY2kEs&\KޫirRqQ1Ryz*L5UK:@3,$X(UpݾK^C4t /!u䛻G8')|!l)uyOzNtni6)j4=U<{TU]ŶcKѐs)ț7Z1ogSRwJW|&|u-[(蜼3/,$q"㨎HH:Ou~ d#8847i{Uq^eNdUNn;[ޏ A#bAP ^M/x"%72כfAElF{=zG@\feI]rD=\ iڂP.ȸv tGQB':BnhHPm# rsu=[FN#@vPBW$=C \GdpdZ:FQUjøġ'Yķ D{T;&U<헗s~|΁q@-*O zn*8ʻc[%ڽnB閕mJ\  s2*<"z:|#݁($πBT[ɾ A#?\(\)O2wSgd9',NHqi_M]m>H:긁{qe<.6 셽x)zRUqyd__>̪ro;eв@2@ B7\]LqCWϳsz- ތ|C#Sur.戋]Vܥ58ȕa Z*ɒhTs 2!$7C9!IPB R.GSANFuLf [Ez8ZWyO5r\0X)cqEmkWrowd@ sn趶D/ʻ2*Uq+͔?|GmT)彔QԣTNd~w%&KfFsuK1|I!B_KHa lˈ8v ꠪M`y/T8-8Z88 zbvPUn33Wr厪87fhʷhF;O}y):$y1o%j9#l.9']q GXjZ~)wp]'=KO""qT>hmHzz!8 "U\'>;IWtwXWSŕx*pdžrKNL{v&H1hTp[W.omyݾ^7tNtdW*<%{ f\"䜌Aڄz 4͉P]dSBn=p疃::pAʛG%$ω:(p]רI}$Aul+!ٍhFݸZsqn'c2wDU"_ WU\!60)>(J6o&[#G sVͻz ˑ=zB..<[nF9%7M9".Gc|1tfZG^;.>_/yLD>H#ɿ΀t`A$|L$4=Vk6o,BGju8O惨y [9첓މD|r̎fxI%]lZpuK>ǠTٗi>m_ {fԸio0m+޶ݽE*تj^o*\MHx57t)[pFy6N㨻;. 4Y$2FeedRǾT>صrhIpB ?t`e-YfM|'m}x㨎+L0&S ) FfMn6*Tqn*w81EgyIT&Hl win*(Mj8urP_@yO*:BCNnxÖ,n{Ҽnf9X^z,~WSQ!}np𝡟mH?Ӏ=#|XM|c}HJ5ג%{,T bq ݥVXa6*tUTIBQ2վ;]4.GɇJ mGO/ld@ (& ^E7t H"[t;v; [oss//?F"$u2}"p|s9H/Y'xSZ /eQGhcM{hk^5C!LQTFB~-8V1G) IDAT'F%R)=z"-ke6TRRG\8;ý˓z؟GwG5m_g/I2^GSdH ȷRЎy@_M%.dPZ  7({!'!Q3넳,Z5_đ؟SB @Tmp"1LUQB,SǢ9Dr_GHkpT &o{N߉GKm!bv*wqmmZҲemsQ }'<7,Knݟݐ# K0Ij^ 7W:M* lxq?ϒpA2]ʌ-OȕLgrRS9W=$^lD|(^Ru]I.$+k:]ECun4"g;v8\L$8[Uey6uޢO A?ʒU[Vo:;!MH%Brxpe}h"UbI2JvT{\RH1 z1w7:*Z<:D@EHD(Q%CnڡLzG|:&T &t^c_$|c@5{rUଊ5EUUqz#/OGx@2@ n255,X2pCh"uљZs%<%VvMOH^Jn:\6 ~q푐Cg7ap|]J!Ha&@a-!|l>_"/:ѱȰWkpr,rfVTkW/To~#/އ¬d@ 8jZ\GƉƖnR~ |O .悋h該IwS. Wthr CB>)zy"@2!#E=L'Q $? {ImT &CAw06[q[%==#֕KZ73UUL{5vMKv -#ńЋqyK NDNpģS]i 2f &Hx{.OI8ϛ}%pH'iu(!BH7$rHPqq0[\&7>;NLGu|q :=.ţ|<'*n#÷\UqKK ??{ѥWf g0 &nAH1_I7tX:GĨqAD}n;Kd=% Brj\9C=U:iWeB tUʘ4 !?#+_-#>]M^7R:@DEgIo$|$8#c7PdpCH{`^Hr]axI @P!y,uud>ǖc6P׏LG(Y ٖq4>[Z\}TX}+r[$O@u|F8\ӽj̔pg` Ԩ@uҭ#6 Լk9!$:_@8@,8&n#&rO4yn/ ɚx9$$ [OȶKFj4o9ۊ(oU\=69A~s~aъ#*@ pPmED5HJlR:(Re[ۉ⽓UY`6i2Y-qEg*l<#!/_ǂrÎpI8sORdI9%?ŗַ%;Y2<_M TvPwCD%} aj>.b]AmJN{ї.gVi P{z!#ĂA3܅n'$S  BkKe\ѷu\DGg[ ;i4ti2f^a6VM&ɵpCua ڗb9\V!o J"mHgocy?H+/)邠:TW{9k/y`'|/g\KAw¾K+h?gWȹ`GFޟ\_z/oqLd@ *x2^)] |9c"('ᡈ.zg'xwsȹM.xn%!϶s%uއgVOVHpXs<՛GU,_w=s[?$vǭ#n﮴g!cQT>)1>*N?_j<69y]^7xCOS]LHbd܅tp?$y$n3%\&RD'礀l3Aل+ %}&G6Mj_wj#e=:\CJ"N w͈8)h'%uri {_<}+q?u<Չ3Qwݚ~X| @۔iukTqz>ncW[~~-d@ ^Dm6TpCtA}g@p}/ 6J瀏4$<=P](BsE%{׾ WBkxx(x$JIM'tI/ڔ}w| GurA'v-8 S}ˋzU=MUUivQ,gVeLU\>ɋ=_fGHb`V|)O<4}7MϤiϒ2 g{9WtdJ8F;S ^/֜rW{#X}XB,0!7NIw%Ҡ) P<|$gY'޽_%; <pu|%>^{[/LKgro_+͵U ďiV&$1CHM귍 %$!sCH8({d ޑJ̖ %KyB擐J.>$L$և\3)ǘjEIa@6}{e |rPԃF!#g 'z +W?>Oi| :NyaS&kWP>R[c<-"fl|zy?_}מ8QTkq+`/U˨V+~S[SrˍdzAPT歊Kt,=Z~G=#TbP]zld ැI ȁz]mg4>¹.慳bp\QM6qV y4i} P2I:r"(hoB\拃kzLBPėWhZ& .uO2(g.'AQ!xރ>0{V+ fW/ +S:ݽG'81-0G\5j|<tCe@ E %~I4$roDD]Crla]4jrX,_r•Zn26UPm0&U<.6u-أW]i|~tȴ8@Ljx M 7DDOTT vydd>xv:d΢:᠄lNs]W!WU#žK`l}P] 7uyt6O 9L׈$UWnUDeD07@ןҹ rw?wMr7{]r?mnHwE֋ hQ .5@"@(./ cCyZgSdNQ7\7=:=:@L"$vs5M#:exf$U`o.gkgN+e%}@eWCtDěrFk=Am.Yd޵Zj߽}t|0xFZuʈ@>V3 p7uJZv`n*g}Oc>6cdHfWGiԵ͕k^nm0.1{}arNN@e@ &5ܤrIa9 0}e;Uﭱ%-Yƕq%ԣ.[mB=I\p Szl?WX!ڔF!}hb>|~r7CsLhv2@ 5BCīE^h"ΛiG#{i`6P"X 9&g㼕pSy yD yU~#ijS::琫Ue|2砿FOAT䂿s[v4A?*M+k,V@ןdtUd#Xox'a/#i0M{TUM֨@u5njW]_BU\>I[n#4 & T&p"2}PhGtJLe .[L%{üpLԩd2y2n([Քp0*z@+rD*ۊ yQI!!{طy<BGLUN8,$m'K*q:SG$"nn{C{n5с|66noOl*^נ;f*R{۹*.patnj;;7%&"nAOs4=vBeF%$\C`6F !NO>gb3Ip6Fwel?›z*Cuo}ZQr9(\Gl]/!3^닷;z⮾tRgPӱZdǏ|=?}Z; u#͓n?>frcrVQ֕Tq]~u]˙9ܱ,|O|j7M@ *0? ݶM4$K ] Fs٤%Ʈ蔘SrΖ)~37vP;V[[ 8>4.jb㪸ݫ.>}خ^ıX)!?zQf-wUT8|4gtCI;jMsɥd 7кhDvՌ+'u"O@)bԸ́DLc2-gVҢFco:*Q6%\C7K$qC ]mYtzNd2HpP9%WJ 7ފ1tBvWQF!׍.vLeeXk}er*ĔV+K|:䠎7VJ\ #WǿOG_GS͆S~ y/+[aI/4&bxqZf*_i>ceM@ Jg-$!$sr4.<0Si˓% 燒e2e#\M&LmdsHFBG!2RB`V9>r;n [kgHiuEue}}UI%E]iƇ?HF uR(Yځ k%ȩ{&Ȩ5W(1|V*w~\Oyl{LG&s4jLnU5RHwl(pܦ\Ν>k6p)XA=|A$0w1Tu _:I;qΝ# 6Tno6'$)%8#g.Q7fB"J W@@֚U/G9~Jܧ[9B΂%˜522Vrg$XQ$a@Uu|k{p4WyysWC^{UTeϛmLZTq[]Ro*Jӂ~ϱ@2@ P[\+4^6/|Ч$z' Vx%]ʋ!0wH_{\5/ȐwsQO=!un$!p+pT~93 c_1U9O \k|:4# D\%:5\ip! gkӵO*I~: &)@l .urmz`'ނևor@裆B.ĭDp 4w\M`Q7܍_ 8)>wٓiQ-O'rVk謊KERmekok8xo.kq(@ E\#~?) st #NPJ|!>HI& o2 ad"ڇ}3!w}x!"3"}xa.B^W@a03u kcu+,tdkIoͩ?w-~f#;`R*4]ګOUg{ߗp%%UB˜Tq=qU^:~6yg7',/q ipLIz=JM]UR} vYgBs3cY}1֌tyf2G;,X[BWIT]=]5͵Cd17'NJ}sg+o*~poC-Tq)h 6˾t05)k4HF1o G $"^D$\I"i]pI%nm$D _\^#88;:%v-$PAЕٺH{H3X2.ҟ)vSȍ/> v\ll]Ρ|8$1_src8(U}-UǙJבֱc >Ơ$flTY*L}^1]fE]T95,%s\CL%`/w6kWu!}ͯGppρtUnc|!4]2Siv)UsJv~m/Н38+t(Pűz|Œ#D\UC[I>;HQ҅K:- bp%)%} G /X2\G%rӯQsxt*JA/~]:'Yjv\#}@[Ņ )GBmy2_Y#Mek0 yW=>uk1(QРdA-k u##F 0ox~<n^Aӽ4l׶J3\ًc0즫zߘ:>1jPִ|i4I @ ID| ib8S7-/˓2h˖(|ǜve~ܱc)"F /5} Yն `#Z[{>lh~tcsь>:nUs_g/ߢKqc1OhpM}~sn9{{o0w^0 $ubҤעE:lUTzʧ׼Q<Ө,gVbLUUqVweL\vk[)TāWU43(({ ސ]OSKi>7,;\e\Bn*3zc r(:j>gQt_*̴~~{=](k:Waj8O~J c@(mz\AUO9Kv\L}U{-֔elZneb=f̬}r.722%d@h8qj~ۈhcQϑj |pFxH|^8(T٠l#j xۯm=pr1*nڷsPSϡ.B.D ߦ򾉐Q!_}8rJYtm(O[Wc/ JP-ljq^aLK墊\Mǚγ *.ƛr>MF88ptM7p~r6AYZ႐Ξʆ8GUB^E Wce yw{„q>\ sYrJK@_E "!ו,H[ތ&,ovH",ۼWq뮻oWνjQY@愢3džOFm?>fҪw]{*.yfi:cAM6˾t Go|;T(17nH W牋/=}`dâ l[2mgsY7^>FG3Hw,}[j \9m1Nt93 X Ɣ'e_:{;j;88Pq_5D[>шt^8K ޗAbJm+qI&@ȋlv:w`Afc]|n&[حJ}LZNg:(x0啹7n_whw_5dA8Ud4.h변rM%]#Q'WDT@ǙlcTvrw/[$뢦*MLy$X6P%t/:NA%%˕ F[jj5PdP&ඇ*SfS|%uf5YpoR2焐Y7!/_;oj%~4y]}j^W."Q4aWRg9QSo|ݺgUWwQmSWB A-ebL-g2LG@;{Z9[)@"#=B􄩎lpp5]A\d#cuK&Aoyeʞw;߾ >iV *P!4,}ZB3'CȁG~ٕ.W_K:W\_JG`o3g?2ݽdkN Roԓ>U嶻e۫u|ЦJd\l/;4.zZvL:VqD]=*ppQO xoޡ @dty{MGӣ8hre;;crM`l₈ ~-UF'Q3Tԃ@wžɘcG2+=?!܇Ůw~}{Id4?!/|qr̈́kth4d^4C`C؇4{0%[^=|y&Ȏx0y锨 Q-+vL6> 4u5n|TXJĉAl^B|(EoNe(qRÔETľ'׹z6֘re{,@[t{g8 Najf^$PooWȫ*YutQ]!הWFEluPsk5-uŤ}}UsushjҺR{:IO'y[t$zqI Lp; BE+q!4% y %2k7:ya9r !/_+!rnă5>g nky%Aq~es;;zZ"V:&56ۏ,; "A'Lrfs˔Uq]]w2&Ky# ' G98ؗDe^.j(?ipXpJ$|%= .hs@UB.~ˑÔ/)S^j>妇@Iz[\#NYTTg琹&Lƶ!!/*7B4[l2P!z:MG(?-l7ڗtc=0\ QdI#1Kٷu(+ADt9=n1n0UUq-,Y5\U\4yѯMe- WjHu."}3IƘY6pIe5Id̺ᔄún XeP™~Kؿ_=.6bC6t޴]ٞK>  SBKߙ h)9k*msȍ۷9jڏ0 8-_9  z^x<ۏ n0Swb%RC H~j;gUsPu̗A?D Deth.)$Q'NA b wC,՟gioX ;sqo٦ZKqݏi9zxC>A*w/}W7f_^, WSGn8[vq/qUI%IIYn; Ęx ?.!= z(YKݝEyBTN,?~>n^*( ї8FmY{x^*%vl'P^ *L߾`PDž.qMuF!++׾>1  LjzhqE%甤ǭ6J ֲFmr7ZYTf+7h<Ŧ4htn1жOuqH8g@,< DuH/WɄﰹng$(!ASppKS툇}CY@hrUP2eޙzM=e֪VSwQ/{>\u=?gmm~.Z \bK~Zk;B0gasmeS,]җ=|u?..RPR&Z -@oUT:uߜ2K2V1Z"+c .cʔ;@;{@ D\%ELzpnfvn8'ۙupX 憃JNBn3R Ί\̺`>8 g}g}}x} ƥ"eگq )r /$K.'+FW]C:4-yu]}>{n+EYi %(cXkecy i]Ƥ*ͮc̴ Nl.}G@n @,,dBK_OOts+놧ـ5Õmy=K[3"}U 2.v:M> Md3؟ [zrz>gN۬ǃD(Ҙp6~l]0̺:u=OS.LKw^6bx\ߐv‹[z&9ߑHĂB!6UD!,M?qnop 5D H= !W߮W&䱑N QbR<> VQ?z>v;FA3ZɦDA&D\w+M}&A?%"G!K@[Du{g>sǃ'/xp¢EFXa ?w[X:ݏ5‮\8/Ko2s@ċai#pnx ]~jcҌ˧FucVn=[OH8$bAuj8l;4&M/5|+QS-7|L"CDqz\4(\ժ7/&ަrwB.WUFK.VȮ:Z :_$\&3[ ?)edYw2P=.3f|T؇Lǖw,%}x*}:')ut(unkd{R PԇlK_/5}7jc}cCg_nr2)l=q6_=R󵹒8yQ$[ K^{Ip'FcvB9"o1̅5*Т/Y MͣAYUWYy>!]guq15@M6w h0H\ѹS{''-Sġ ҇n|i7%IlJ`gUo9y۵Щ¾*Nmem|&(:{~/' ׍GYW=_wBmzlSqїOB!"WuI$2.s=-?8D}U7y4]lt>2Wso˽i 4)^4&cY 4Ho|O@TwKWn4j\b2\ g8=FUUc6hұTkbwc`kU.*JpWsvN!ٴ}Ol/.l}T my~WMq0iwi_z9\u-Mא4]0Һr:B g?|MYqa|Hꠠc^(2?g][S ׍ISno庱~g|Ozrinb q\7inHi:α,H۹}k#ゞ,cv3 vn8=ꄼ~itk+)ZTA6;UrC52]3rzTv+óW ;2Vyp͘f}nlMkPǹvpn~kOpo`Bw?3@@Uݕ@%A#zO*Aש@I*&Ğ覎@ "A'Jӟ:89u[ݜ&&ҙ+Љ}i1]GSex}X.׾!~\b%yxlI}Ul? l+۴\s@ۍsL/8ʹ{co>1ط7ղNR$c"d<'k^YqPD!߈} K}=h hė[?B _"fEwYgP_xE]}H}k[$bn` Uڈ4,+qqF̽ <.rN!"d.레 ܻP4Ij#F!䆱)!"2@V$d#P3CF΄\$vl؇ AټpF%B擗yp04Wzǧ_Iw`;' л MDK)9#t[&U.$d~ª@Dg1##@MD4jSpX|3q~SN G>]ߊ*96¤iKUv}Jm.ci8:'ZuF߿;C5Jt_#}q>6Wt!׾\}kIc7u f~ݕ|_YtY1i"m)+YJ j 0Z k+O_֬W.=8H!!.r[tMLZ^ @a7l1\'eS.,+5qQ#%!Eʩr[Ty%%aCރ06ol[x}b'D]wDsͥ>}q^[+S<ΧiYP\W-7g=ìxf<\'9&)x~2u| Fr)$覎@ f EI7k{Mo&5q憃[ɇ-ă O-Kq"dCY lZS`ҍAreٱgby!L-9oi^!WUDMZK dN9*LۇʶɅUeHf᫯8tX ewgRD\g$:pc\봃4]H4]B!<ԭI[[|% o&k|zK3$bfq!)"zSMA6Z,@#|Oy6f˵(I]IAŶ/ 7u+ )l{&DCmK5ӵ$!'gt _,eKI>WRk#)C]wfyԇ. } ߃ r#c7?4wwOoDC *N ce5J-m2uJ/(Q?By5ԳIr͏WԮwNEJ j%h-]i?}SO6Yt+>&Ѡ_܉'!7hۥ܉5Xd$^ L}m=ط!9]"Ry)sl砻.(DSb:ށU]m5gyj [o~4t<=BIcG7ug\WZ^a?!DQ֕Dm܈Ș;<(YВ%ZIz[ތ@C#Fwq1uHDܶ-]$īfvM ^8%ݺ mCzL&s)]a[4| }Cw-kgy奁ڈP~hL-1܌}רbF+C a_ ojpqRb>y8C{o;2WLGUڧh#ח~ϾFz=1! uqW/o"QM*KmmƓ=a0 7<=JcxN} q1Uh5ݤDCoc$w'ҷli6 Rt( #JGm{=yKWjZ^nHy]z})Y'!@ v&䖱fSy!'v:#!g[`>΅к0P>N\'5_SonY+ Hs/hE #[JY0"|[Q3@ z3wUﭤ"AڀT9Ŝp Cdn8A(q8;7'IM>F\D˾eCsFo:.R/-}[[?EDZGfuM0Ĕ|+e&n s] m Gȑo~yY1_b93_D| @ĕk_$.Mcq\۩(&G8> GQ|0/ h:Bˠ~ 3 µKlm#qp 4=@Hjf&H[qP4` $/><{) mezґp.* &#>q!esp5܇Hz]\Go\Kr{/=An{#_@Jc"v"Ζ.s ?d};>A%h Ԃ|}|SMl7t.]Œc]S۵0ֹ^-sqY7VIh9dj9?/!gk2}>2#1 0h7|g/uW^?oWMyh9 . ک v;^L?aWbʷ#A"j6"~Iuˆ4jF!Da8 \i$i}bAYB^3 wE3P|j&K`"JUe l/k+Z \cLb:ʖ<ЌWo Hb`V0n nf1f1={fzϸmϙC9>v vi``v%v0 [꽪jU7'"3#oddyoުw3c[y?<,%ȭR]8n7? ~uKGpw(c8AZv@ܚ&*3aQDiE KǂUx?k7|g O>MսËa<\ċvgT/m#2ku3-<צN2¤A¦)R* ٵՁ"TM!WܥËڮ: >i595D%Jp@&rA/@u\| 簾,Uym5E*$$P wAnVf TT li: [9`a 2Zc{3n ]GҀl~@^3%x໪C:z׼_yxsS{DWB>q="C# 2CQD#bbmz"~n#'<~m:C;Ȇ7$Hr"p|M\/ Hy H[@IorL* {[m$knMfhs],,-.#B?v?gaCˬ7@:Ag}w#ͮaZ``N-SM'1w͋^rw>;Dqot8_AܮC kvx.0ïL9QD '*ۼC,`e{vEogW3X_[)!|(RP%.ݽp 5O8TNR啺jLkJInX٠n[JrWTϫ lr9b,6뭥~+  5y:^^{]=qu1|ǽo~tLt kaS L@'a͐-x(Qˆ&ƀ?7U1,]/&VE],Ζ.΋,^}O,Ҧv( SMTkʫAim- W˜OֲBw} ?cP=L~G= CL(Q4 cKy%?x1,=pPr~măPu ^ő ѳ6;-ۭ6wUavGPd藹2p[ I:0S9ո~Pl'T:U>qMAX[mH/x଀D^O)Csk󽕅C}Qb7+tVg6dN%XDxvlzf3 GwL7N#S]A\]#!*%J3q#Δ7!@׋[',v*< TamD؈$w01y]6l_JSOjnXb[GxY7bl cgP;A\$3 t]=P8,.鞟gC(;f.8Of<,W8}th6߻  `Gemwy=A;bX3­]%q=S@xCлz|%JoQ@4Oq)׼a[TWaoWog򠇱(S)]qaiyTG4ƣD%WE Ox}k"lx9O\[M5xU6u ww3/eQB: VS Ů* dS7(J(eqCy~~;ٶebXzZz*zrt Pyvz| ='?X>^ ?j&}.24鱇lH?(6!_ 6*JDR)bTS91 #ŗه\v5{UlN|^p6{Cdi`y՞r6nvX{%a1cfOvsO)+:|K SU楈^GeݣEx(QPĥ,x>~m^^xeh:ɰJ02x?Pn L9Zt@Mj ,=E TϩwNfI 6aRϔ3^=~do(sچ9R'r^6<]S-Ph|ur^ӃoOϽ|tU|-mz= n+ `/Є8aT}&3>,'|wȹ,:Tu_ӵ:e"A^ƒEN(Q#qf~?Ϗ+HŶeٮ.ph6Vn}QAháD{i@!'M^r6>3dN~KCECqEPEx7\xyfPqfrSr*'e^7_rU3XqNa"dX(QTDq}67\|bm;lwc#_Mx%|Cэp1,msX萮Ék;uzt y6& l.0 Ă /, 1'S\CGsƛH;`Lyy:V!=K9:\|ͣ^_o>,JkAV& ^ӆv 文@\H ƣDR`tӵ?ΏChb~?|l ƕsX[mjXMU1l@tT\!Zz/*7ArU% )FirZycIR3.W76|y ފ~7/^~O~;Z_\⵰@ )q{Qz4yaYD0]Xx0%mq aB#?]P xSk+ËM wvr7l>-f-Gq5!-5>WNB9g9. LjKr:vsǁ\wQg,Ƴ!${[~/̻oӳNEAI_ 6q+qp -4m IU#x(Q .Eq)/?%֮?| j[)VJ?}ێ]z,t5 ͰDj= Ple  !\Wܭjc@$dO #Cȥ-`lg9O9_Cήmȹ^1zkzhS/;?ZȢm A2 {1z A\oXMAm=|JGscmBm6a髧+o:~2s/6 d$=  mD#=ș #HwUrSx!+>'`-ͤW77hk?!PYڅoK]}K/yW>+YN.8z`X)[_&`T s/4TN롆&X(Q.ޘ?4/Զ6 }Pb1P_WO~ MIDØTHrw8( ~u.46*xs\V<^nͽ39Vq瞞lՕ"]4ggÅ_ԋ?~޽3YL@2wu8=z=€1Lӫy(Q4q)3~<eSY?0l3u~;@\aure<ı] c- 0uu1 L <y> ހy:ʥC7d>@.o3h75mO9W1 9!=3g)3 ޓ~߸g|?eK8(Km{yPH߿/~:E%:2NB 2/$x(A .K^~\)" w1]l~jbwá" Z H{,x4 ܌@h`bNȡp_ %DQ @rJ>_xťg<{>K:| eJp O{{7vۋxq0> >rkdDhQ#W9Jy1Dh`"0rSr#'wK:4rH6r+kr}~]M۟,'gmȋ}}d?ޔ9; P^ Gqyo8rGxy# n/@=cDe'@(قkl6^ %gssxPFBrD]s/h1a%W@ˉ@ 귔.l6\ ! Nbͬ+g[s%W{#0C΁1wZE uZLyCˇ^7nq> {CQP; 5j;qs˷2ln80ƣDoRBmx7?.B̶ + w?7Zͳ =P$ac߄GL0K-r@<H]M2 ȥ4Kl S5m ȋPC֭y$b.xZ/.\"n\c8oೳWm\ρ?>{v )tx5S(ɀ=6|0%>˞ğ0[ ϼ\|tLܖd68ݳ2?1CRYv 8AirU:6jL? o!380.@|nnrA7a+pr^+vjcr^$VNp\-_Sλ~w*ﲲ/䠀84a24$M/ƣD'U//3~)?Ċ鼃U_n]V ˅x٩uoLՉP7bO&owsz᭫c@aC@.ȡ +VE5E´\rsL v/!犞1·x5Oz˞y5?Ek_Sxȕ`AD|@ zX!8^@\\ X\FeH )?~-LՅڊ!K^.Wj3v-kJۨ xvȱ nҏnek+F(^pO!c`f\7B3w =*,I@!s\{3.0s?etQ>HC=vOg|K}t ; nA!{ƣDbQjSA\o D1;~f * !b2b|6ၜ &v7ѐf LM^4p~uj8cD(ɮ',R!o+k~>:,q+ ku詆B}ްLZDe.(W?iOY1],Җ?uҸbz<^+:$F[JVp~OrW9tFK@nszYo륂G_d0-g- .WQ/ Ƈl>rnݵ!8%PK.|OCbj9CgX[q0/EB8/EF$zƣD6 BX÷sj[xXm>4=u4R@N6a46 >F &u1Gqv+4JzUjyd rx>W|!+gqT9";9Zoכd'Gvw^:" 4M1A7ԁZ{QqA<QL( npN{<[1hJ*+7[ȑfיb:NNCs x۔P6ȩ6 &X6%3ȱQPlO1@I ϸgCy#quu!qȹ>{cC7^'^&,m3lz|p!oal.x(S H"??Wl]#@\Ym4<][1]r>Cn# BA x1Z1cpbˆv\an9%ܑ@Os4r1.og@^Ӻ۹{>r_C]{t֗d .f ;@ nY2;aK_|;8`+wb;9 -_xywnW1Jq{ #W/U x(]qZMx˞jxeS'FgC!Y⹚ nyp~_7B)9*C0 hm ǂ FT]j)@nr1_\li&+ 8m}G S9;9Ǖ G~I{Wo;3)z=€X>x lc#GQqf8u.{byP[VW\΁\%wb9 Q `A\M6|ɨS   x(|@r\XX,`N\-a;viy=rrggOz{vv4 {CQP; ERA<+_:axtjks6j&6CH7|AQ[lPuD Ger/5Q 䦗P8daN<[\ E/n[T<E z)@[Gίg9lez1_(C9/6nj ]D@9D= 1_|]834|7zF)q3}cw#{2O0a]$AVV|n$i\M=JIypn?d̏=@\,Զ{m4(Yerq:j>+t=e@M` i(xMbAi.96_诽QtS wAi_:@3K`3Ϩ Trd*I~cczyW<)nK$s@#A|.{?伖&ۼs2tM #S3/NO(Q ~?m%[_5]lq&:{{;zJgIZMC'ˏ,U>7JC o !ܤ 0k;[o[ ݃PCm$Q/lb񶅅|qqsJ?C΅sSZZ;^+򃕳/! !m%a;1, AZh@RN~)a{,"G2F ?~eO, CG\e[ &uZܨ<|(w❗e Fuٞ4c@-L- L?]r{,~U=f y2;[{%Ӈ/=`pC+J8nЉˮs;oęF6k:pzVMߎVAp/"G2&A8S ]~eOlC&g . S'F[ġ3{ık/I);NM hS ir[A[ĝL_4ZW6\ Q+g0^xrZͿ+e)qoԅ+-ayn]+qp-,xqA< ܋-Fe Rp=v~e/lqGԉJX ;$2ț8TVoxME?YEچP`iN!W6mEjAPGLmbzYW4K<拟F #{ 9wnsZ9rN=CAցӣPA^$qk(Q 03|dz]T ^]ɽr(P\9-&]@ '*h G%~.N}3zɻEԏ]  ̣x\SqwXE]C9 x<]VZ#Y@W8uS-R.MJ 'NJ'3St ѷ _]a|`BNr1 2l~+!|8|6_o !u۵8$|!5z%UGxb7^ƿe<Ӳ@SpX3CH7|[ 0qUj(QPWx˦< mx0.Y͆ǽ꧝;%E<)^gU*U|M@\MX/<"[3ubψ6 f]/6=ca9Qelllls*mH[ 76b̺YCimoU%s?{hﮝ$OuM[ ^ 8h L@GOv@y/X(Q M eswc=qu.VPhX9]5.҇q5 ?6qf 7R`uS&/14)~]2Lmp-T oOa;z*fgt(;ʅۈCj'ros}$|C>C_sxg i#tM^/dk@mE%x\ IC/?G\ MWN('y=rj "׭'$ffYonxhKφgieao  crnj6$e=ҋ]kxPV)A _+ƣDi( S71֏`ǁZqc.G|f@ܖ1tM_N8آ@"W0y os:aR!ݟ^[r/]Q. Ul#*m6N=<>ʬ{gC'E6q93 lȹG+}Z|_>a nġ[3m L Z2% B n~8}j;z:4'Qq5_Or@N) .V4R#}Λh _*ȅǜ2DqCt2#!!A$2PF@ }G#4 uu]V)2fâfG>a9I?W[e+[^luoc{gNǐZ>!= MK5_ϜAz[0`zYxxճկJ c:" ސݶ$y;ȑEjJVzrhr=aPm 6SX!=OG"mu.rzq|9ƆC]z}qzsթ$A*vqv%|J@\SƣD:3VK_.Ý#!^ WRtXV^^Fj)Tp !q/$y;C,-rbPIHXfNm9Y7[\ Q0~hqI}w3CkqHC1:j{蘻bi g7}w}Uq8Wo씀x'qz(&! %x7?9.戯]¸^.v: ^:߭ݨKc?G1z\fBܸ!\rNrFFS:6ۄI@L<ȓLY+^ Q'ϰtoYs~=UGfg~1z_Ix5S@|S m5ko̐a0+==M@,_@Gq9C^.ܖ-XQ>!bsM 9;9g#oWp /waa@S [rAr-~7SƣD)qbm&~\Yq}h`r*[5] M@\ ȩ 1%k Nmr}F` oj@nT㡟Ym4V`qy  9Eֿ0!f-wrh .@N 9r) Q~1D]xUs_>\ SϽb;@{gW>9;9 Vй?KFIquRI3;ƣh8X.{Lۯ$?umw $U>. )OA SD~ם/ Zip]&Kɚ"8z1} 00Hv D-8Zŕ-e!)6伖CL]cK+wm0}Kڴ> XA=ŀ8 @hx,-㙗-x+yվV-h5X>}j4G\ݶ, ĥ(Ol'Ԙacx`I H?붥 >@XK^6uW\INQcr=Y5zq]"ەt^z6D}1C _b slmi6NCmz: ޵NC={ p@[(* k/rlz,ZV%dAU/\@ 5赥! 7?;-ۘ )"G908ftƅ&?ބ0vsg` Ι#Q/L`Ab=PgNtcySo!~rL}DwBvFl{y }^*d żpP+.r;3B>X' zg!uvw-ӿ(0zO{8D-W"xqfLNQ @\rp7;xhbmp gsj@0mj^Dfpä73إiz 2vMW,y5Y&(}rMb/<\Wntqȹ HArʉN/aW^tozgX6-lq{ u(C #^}ϏD++gs7kCӱSi5!o8zlK%^6:*Wv{8#²-ͱyC\˽ʽ~?.vZrXG-68ܜ69ۃwݷ9 RA] G jl){@|FEq̪6?ď?Ǐ `'roНoav/RwNQ <`Bxe]& 멦xÅ;;&=Ƽe o4(M\ f} ]J8,{Tå lT@Sng.&zp~oXk{{wrf[Kf^KnscJ~yuqSZT3v0eߊ'0.8?OAVkc@T]10|fĥuh G6+ze^@.!9trB~) ۶9FT b+.Y7< O߾r^ @prV~kK3>]pv=>ۥ+W͵o M(;n Qf=a<ʾı{חx,Ʈ[lڐ ^։UnJ dT)m )/7I^D•GR!h%Z(i-UV=I@eGA"y,S /eWA|pu淿Ŷ_p8伹8ܜ08|K}±ؾiswӐ q=eq`A<0eI*lñį0ݡlguCw]:LՍyp2njgm(OTm7qD*۰E I^/2pdpޔ9TTX.k^ox3~hr9D2qwĕ4I=]]fx9NftQLs Od9) }RYS\ IDATnOOg?;ЅLdI4-etN)M9ʠ@>N{93gA%l9C/!m@ο"336F=+.ψU+C牮vvm~뎼zMoήwrLGg{/}sc~]QAQ7u n clSiD x?( Qf97p0Hbw7qSqBAu:& -.ד0Iz*+$i G&x^KpTg X&bRȪά O/3+o ޟtW^cW*^őfyGVE>QEuP՟ן^l%@MRIHpYf5,)f< G.KDh^ n*;h+SW}˔0CFH- LxvH%J67yğϏ?jrj1<#r~rPN`WMpJқe~@\O k⾺)mk\&uCjPe$t[fqLpClPuI0qESrF$ n#P 닅2?C#\\˹=e-[E}O+!x]zx5ӿ(PCV}%E|ᅋ}~/Wl7+X/ca6Ҵ? EX3eEY5]=[ y?@\#~RY9]Y1}aAOqV4QyA2^j>lbuMC>IO8$4=FrpD/~|DЅEm#h_|xΏ#p`4[WX7{ ;@:U!ۤZ*fX#/[-gMdpjkqY|ba=rFͪxl ^o+\5SYlŒ^e iH]ٔ2bqR_v% .@|[۶L¹KOHymz+eR=-Z7!ؼ= !6>p?iy\ 56YK**+$i G&H=NRY ȃMm~?Lk.ܶU_!txU]b1mŷ axH=i5WInC6#n c*`BzRs*z85"8"F){PGx>е.z .^=gi e 1SXI遇MHZ^7`ʰY7=z7A@ڶ~/= .hRfw&6 ȍ]US ^W\g uuZG8ic7^Fuwz\9 NlD|ok2Owj-˂OIR'./$$EM'i= y]5JUĵڂgdu0QNCm^q?Fc;gV9lma&>աbhj}Xୢk [(-+J/S+ ZҚP>ۀ| \Ͼos=ғ*+$k K&H=!79A1e# '6,$LCU3΁*{gٙ!Ɯ>䜮* 3=vݤG@ae_9qX[&̰t ] =,}|hlq.-lP~5. OLּʏ$Iu"p.iH>r. SAI2ԆJ8׌Sۙ-@|Y]A]3z'pk˙^o<8Wy+mlDӻy HA:7cͽb{2kA\+'2AX[18A+ du3ej#&\ˏ ? +'.戯f;g<5@AI}C^ҼYS ![G#\^0߃䭵MAOv{Od=ñZ0l#uxخ^lrl=30֣^"ޞmb / ~X=Yk"dRҿrn5Gz~ks~}qVS& `ڞ"y2M#.&нQ@|8d9m~Ŗeٜ-xM㚔ْN5 .O)L BGCu 5|>V& 鱇"}mmcߧl# hb_q3\q~lg&<3^w\.9og7T tMrviȹah/ >Z} LEOXA_SmeX!ġH{uJkM!ɖzf,c0e*oUx.&= OU,*O3l 퓔 !TOI^*q)"C0C% B# Bsj[q&$~. nAa:c,p(6oFr͍@W<7g3 M j٬ w{79vn:E{Y\FԤIrG:K>p]aJ(7H2ZP0٫^k mUGaG&!WE^_Ff?lavROd1]?~MH\{B3]FڥچUmM5rWe5tlzR<r0qlF5%ϼ |q?r,aCʅ|3-7pDn{YTi\ElD{W# m׃+^U.VsKph.%czi%\6A\Yתncl =KLxg#G2@q?C[ͻą;-V/qާjĤXLI]lPx h3߂P6PzpSkOI6EL-, =pD3e߉#=٦o+>spe&^q65hg9Ni-G%/[5 93|&my4řW?|~<䌞ŤfQO1d &[|vCF{yT 51g|:.bΘ?s-?Ï 3w⫧۶y0u<>7clSi7ơ >}b;x]צ.=6Bs$] k KHOjxbilDɼvfrxbK3 ԓYrEo .h/=X͞{=V8E1a U#)_;EIda$|ёvxC-ܹ^ 2N €x}gvflC^Gx 0<a!#Nl61|K[m/v:.Qz%1VT R&OPoSz5$]#n%W{X9[(Spߖ\ _!Q,C֭\^#м|kqHtutz(d=@L6X6z:P抃:XmFx%!ő#ߝ;!v!Kdݝ G> 4?vnSA^/POשUIvVEf:%ԣ1y#G8VP7ŏ$ > aܾL+^ S/Aq! _Lp)mY`ZVv.BaD Ht%p=%  }8^6}KO"\q(\-psœssw݁L=8ܜs:S1!ۤsn|CflbeS6=9M=VV-|`=)F ZH3E'հQ(6T»y ήۗ!>ogA}pjbʃCa@\=m@NlY)t<g:#An%dI:!im=pD QR-1W?gf3b;3 \ }R*7_ ݪyԜX[&]e|hWT`<2"\ǏWQ3ѐ[yzYB< ~SRKCq]?$yZO{/Cyx} 5s+$]C.mUC)K³9`zQv bX_,6sh6O|fYniQo2W\ȩRj9JUB#y/Jj8& 1ߛP0{Yp@%RB >BO/]Cj5?{{޳xq ^<: n=Ys<^4.bz!yxl%3^7TPxgB=UVO}fOGWqnABf N!i-m("gæzŧ+ΏdƿֿC\߾lH5YsnD-6ɓ- /d[|L?IO  4`"'aQ.!b1_)jI)g ~*L{Ͱv@ܔ֮ġ$do{3IP`d,g^PuqjmF[@zLXcaPñ#rL?\qC˹GԗYo~QGpwϝTT?/#|z.隩* _0h/ˈCέz|ސsclt,gl&aa9dJT *5L&[ֺ`=QynQV.4{;ۙ;~'\zp}9Մ$&WU5MA\OJFٓ=>ԧA@^|W]k d积mLܦs{K+OMBN}u~BRC?0VIjw5Hzp박H6ŧbm^^jNs(5Hc(?hִ2c(㕹0xa*ǧq 扏3x7[ZD0q5TL)ߡ2&CC:#~5i!9@N7#<r+.϶6 nm ۽޸oUvi7BAdaao[[5=1s3-52nOM4iWִ2c(( {Z( 0paOxRY[z%[e3kٜr64malʧGL4gD-4DqEimA?<"8ӆ LJ-&%7$Cޚ E!-z`9Zgl䩨aC6Wq !b躘+>;K(y]V> 3FK }?=JaSg?`R`v[y6u)iEC{<`D?JO2R!PB|@z7DP6PDb2 rhz s+|\F ,Ys!2Y!  mm ?ۚђ},Q?{OYb>I>'U/LҤz*i7$G0d=&'D25Zo_蓹K\Jru9 /QL" b:b2qs #j9 !iMO?g00]ϙHWRsY+xp[ gnζ5px h-z$ ?xʥo5Nc[}&y v3ѢF^z̏ͣFDt3*[ڐhxXQQOqqx.ƏΝ*{ W .>9yټrJؤ;|J`MAcc,U6*M4>*$%d{9v=~ѩ"/7T0MCDQ^ +.dtK,(vC.+~zR 1I-:#mMmcrj{|U'3a~}| n*cA0(xN#=fkbNx9<]9b7j7U>NN]TQ/xq6YARG| 5]+<~y.y"0q+9Ƣ_[s!r6#Ԛs=5?.^H u5o W3OldM8=Y BD ~='6#0{]zfKAv~MpŢ2uCB0J +!!-S.8Fo `0qr8/:WW|i)_=~=sMvYO SH5Ys &n=!$O:1$ԃ̈ql{O޹3x_YKwp@5YޒYnǭ)spSU:n_v2/AC@Ԡ0xߡ! HjA BKHF]n~(]d oF XǼ&zQKBٹѾ7HP^ӟX^T;@&\!uɪ<8h/ˈ4|j_[ķ>b^"1֞&ZT=ϭlc}c7Ϟ'ɗ+ :LE^k%4dQRW ڻl3΍I#Y+Y6zEC&ZFt_ψ 2i [(QbAk X~IkanTEHF]+$= exM*֏KŴԙvfsW3d&l­cgUtKH4 &{4FȔfHL(:q4OZMFjҩ ym*l9Q&)_?sMu wvr_] M/1+„G<Œ'nk|&"Z{S 4-@맂3Tު1o0҅9!u9 U!rey>yr/g^ Yǘi If'˂l]8WvA&<@ =j6y^wo&+/ӌ[ja<ʤkw b UzX9}g;Lj`75Rem⺪W.@-_sHS&r-T!(v!Q\ Oj4 佹#.s?:lFro>0j:e)է=%IJ|ۘ^E{_mgAXH>V$KUF8L=J!Ϗe@\]9]/W+ooU ?2hAT؂B|Q^ nIƓR.Q7eè'YHmmi4%,$:x72+g}+>S.= V>|HQLkWآ,H5Y!  mm ?ۚђ}sKێ]^ԧ-&-&=!@|7e0ߴ?e'MigzhMFԤa1p}q^s>6ql?ZJZder<)3z Xd^2[նA1\~dut~yٶ}H9\ ֚7&=XȠ5|g6ɫE3Fyo,}bR6z"M!׽6G+Z3XO>MX!˶)+2Sm;<[+.sv):<؞˺ݷ-͢bE," xb&B1#LxbG_HHb,XF z{u*fevrv[u2+nU}k(q]FM!犌E[-swXɋ_5^9n=;yl̓|3LyT;[,ʑnj 3x ת)̄ӭ3?c0#{Cy5 ΗbvL[(!eH$yC!eKsTv}n[ Mz fu6[/^" W@8~/r~Y(smlE΍k[\{bxx]l2hjֵ;.N~<}m3f{}&xR< ~O?4X~ K/C!4^8~zp[:rwE`6^q .nq=hPm?dR;CP}@ي!x1v,_vP$ԫ}'T} ^2 nc?|BW2B?T]NbR2vRzC!e;Xp%rcۗ}TS{&xi:|.|+z>DRȹ*vu )T]rޮ%D9Q7=؃f}+'ON=:{Ͽ#ٱE'Pg0{99-~p!Tzǯ_aGN˱̓)24⼍ U?\'oX^}pZΚ6bYN`939V|@@rWR'dղVUt*36zz=kzx'~VdQNJ >c62 66E/9Ԗ.=xg0O*'9+~%1::@Q~2$ Vض9VӶ[rn[Y|P@B& 7I@X\\B .B9NX̯IVNeyř7֬-׳f,YWCf;i \hiwm|6L~!< /m5 'FO ah~r\n4?j7*m*5 O7S>M7ēOx}Luq"`BV8 O-UݔuF>׷S'k32)_*sSMwS`yȧʪ`J7Y5}mŜFߧN5lϨng{ڱLv·]fvi~>粡 [柨bK'kqmr2%c|=wƓg;q n6ɦS.z~t} 9eC͗K?l2Pf;|m"d062׻mGot##z}r'wpwYq`<) '#-'~V tel=WMc ` !=<6c `?ThM0Sȯb.?yxa~̐ x "kr US.^*uq>ܲ)u%PO'{43 j+Kzñ·Lu7M볧{)VR[|w=gI.byMA`mmG0dWtΦï#[˭O)!&B' 79@.Sl W68t'붫}%0g@n+._?Ntkn6u].Әmc*3ѓX q̚ Mh÷MǶmekٛ/.<EK'R痋?P9`[~~qssCxd~xʰ .ڷRULS S 3gL6 'D:' 7I@Bmly{Ȼ'.)/J[d\MwNeq8:LyK|$?[ f;v9G fRl !s{;se(=wۆ^wNțv'_}$NګGmnIbk߸ M۬˰x$]@\mT=#yAKn.;J!F[6cҾᅬi=>٩FP?GӘ]T^t+Ẇ?L˅a&+Ƣ.Q_]"AUn3ڶEcVI3?6i.Dj~6Q; elWe ʾhDŏo;X@lmelJ#ͺ,bx4\ ,+ʾWPfߥ }@vt–!-7!Ծcv1d{[?x]Pek^PڊA  E!0_8=}9z60x,\F~#)ao ]VuTg;|FuNKMh=\e+6a##rZۘr+ֲK﹖t^?ltnIAm72<] <7v݀mr_ oKtіUl=wq]}􁖌\L+YrQI^UJ@>63o8ө"zşȇ4J"<^։05T0d6 WBέl/Kٛ Emy9%x<S{=~08x=h[?2ċ|uƩGM؉&L=O2ځ7O8Uxލzx6,~61򠎵Žkvp^eH_ xho#Զ.v0/#}Vma7ڷ|Y;}TfK8ƌ Q^Z̧>#>QgGU5zYV`{kkxM\uRo: ߻}9L}aoCoKkiJN P@/>IlqzJ ~bh: OKO;`->yfh_GSLqL4vu~lAy]aoیJ;C[c'"<]UFT[ nMeV>pi9xŷI6x?J\R qcXfL(P{wricc_9%wՂ9?*ԓ\9U/O/@i̮C?=:z նӵGcw.Ppr L p!dF 0@;,< }ë<_TdTT a6:ٹz8 `Ne5Ԋmx߫(;!; >c62 66W-oGnϵ]MwÂ9./ Q&OЯ=[F^ FL?xn?l0#4THJϢu~ P֛k4uФMEcSVCrVCFd' eg fdS}+nnohdO{mb[ad*.}uvpG9GȎTӇ&.ß^/_ܮw.W$<6O OVz >dsAܪ`pe@s==/Oo W <*^f>BW cl*TtlA.|VvA3-C(Ʈ,!|R@mgS[?1rrWQBwuig $7ŎN6n>7 [ \|u7kmj$xA Ɠt5s~jj#6 gry]^b_rMb-xcCKJ|Z >CCrL`Tp8Y>Lk ڶ[)Y:t.1Țdʓ !w 9 e_1%O}bN=; IDAT~7hv?0ޟ'I??=OwP WH4͵r; flrt^Kl*s&vȽJ1w*.ͷ*@;zyin_2<*leQ&=]+@|g 0X[.rTfmcz`{N:𭭖۹F7 |NM 's}GnuP`0#m{5h[9nж yhO/?֮dʒbRC <vf!~Kݲ94h%_o}qA5c~0KaI8y#ş׹np ΅׃]+GN?۸~lb"*Ay[[>]qbB6*/}w^.T[9 )̸mk[XO}}FJ)O.}!!dno7nN!r#o0%b>E{mnbFġsݞ߫[vI,!~jGoڮ]VִceOBԔ7P{\S NisTfTfyaޣL˅ʅ.nh|Ƽ(lDz]4"8-Q&8BUC2S n\D8; eh~ Ivv y+&tJ_߯FQʓg< _(]6l'^ VyƙW ^X!_fua@\j76pmS V@= ޱKm%yCM <]Om9ŅYorж_~/nrβNugTD)@խ]8f 9o\ضь_5%w攐gz3/*.=xR%@^?<\ycyF\RƖ'y:M0dvLۺg).)Φ3.mK5vR=.Ϊw 9OՃU?ϓkhz ]} !Ǻ ϸ<-NO8-ƬrOB*XVz5}%o!:[Kr0`jSY텧X[!^* ڏL~hQ> uvM_T^Z q`\;08@2<_LGPgk>YGS_䷗+!hrÁw7l͆!~Kݲ{{JVA.7u+J0~U8WataW&@>O\NЯ'׀X|̐PE3j@>tzUy!pMDu49wv_\%vwk=]Ol'QV Ѻy$x?wJ3nGI0$W0bӘp:8s0u%6VmZrڎ[\h vUPS9u8 "TsW!|"4 戴|^X7JPF;oy -| [ޫ!JG^=|qf `rLcvrk~ʌ aO#x W>0.iM~/bwKBQ!](3c&tJ@ns=Beek+Y޺=4F],_B_k/|iμAֶwz O=^9z[nB6|vla{ Ɠd/ 7i3oժ8'^; ؜9 buuEoڷ Y8v;Skp;`5r[I(BE (>볍W\gkg#<~緔g;q ^o!+7w\4V]򲼜yc8RԓAPCB9LQVW}ï̊4q | erNjw*!w 04 y\M[tPF@[}C?/f2>1\^Ѯ/Ux O%Φ2mll"K k'oZʗرBjq[ V 9OZUm@~qxAO9?[7ye8f{O|o~xjq:2 W:yG@H~:6 OnKQ+tH9`t<XuPU}#x1a:"rrFU.e61MjVq0m&Q=z:?h[=r:?zgnyB^v;[aN!r \`A;sBH92'ƨFF?QG8_/SRP,0+ A$W\f'xSpFaVC! _uȽҮi}KH翣`禝I4<}cx9h~r*3Or,%$( C7;FnnG3 Itה͂?S,G 6DTzҔ'HgoclBx1LcQ~RMcF^mƬ̹V9?V`.@ -[نGCi4mA1=2 +Pۺf\Qo߻M@ƅÅ+kx:}@ynH" >cl7’347 ߂wl֗BΓƠek#sB%7 7\ְ%[OX Gg>Jۡbqu !wh9wQЀ]6^-Aܦ5R6sB$#6bxz5u?:qmk[~CP_z\O3 M3o-"jBΓ脔Q/(yV?:,#)ڡo0kΰrYd+o̟<ð<ܧ8ݵ0T9:w#Ikh"[̋ Og#@mŲ~X8qmҶoCf{hB^{^ﶝ^o} Мp7!|5|gjR_pzi wMRm$jq^q"bٵ]Mcv̦1e?qi$PpVn⍸'UxxeɾA:[+|=u )[ߺʌb2N.J%aītӫ̆:)WOQ·Zx )+c@ٍxb֪27ܼp_JUdtYYH9Qתҫ>l>qqn3lZWܢ\}=yׅFW9K$Cq1nTti~}Q<2ڀh_%Or44=}MgHx:uS{> Bvr.{|d _OMke[s( dQ|+3@\B_Y,o*1ӹ~o Oc pZ`D&zi6U>?Ckh7 7Uq,Si' N+ģJۺ @y}ͭz38`@A~G?2B3`9Czó qNRHj4biIs_@gև^y;]Iņm9,<.|hrT74f@ΟV +c 6m}P"\lQyml +5p ڠm;ĎbjWc˪(ʪqu<ٹK8WәqSMwz#GwTSՅo-;'aͫP15,ZlաPcORMX^cSY_񫒾4<]>e-O{Aj#+gԍHlsr[E@J@K=]@o S >%R!ڱlr9V-0[FPTx: ]O!V6wl֗@{8ןfR >&j `؁G CAyѫ~ ^q}ĭ}} <n1=+/& -~v#V&/qvl=AA7 ] vLc}%jȲϱZFcL3Jdy锆ls^Bԇӿ!EblFXqf!;m&.j3:q1r]1@ Y:?&d _3?Oac"<?+(d{#~#`IKE!pdS=QX O1 ƘBf+q=!k[KwmYvywě-0;\\3a8+ht9n! C7:j!~v/ gPyhy]?Q j>>u^u6iq&N[r و\h:CMcJiÂ4Ɏ* O$@6'c-!ye C?X . F̎H<r FW;~qL]-B~Z൴x ߱[_Y 9y&PvMHl/ dw ؾ!ꠃdmR.<Bӹx\xSv ҰQ;ڗkO¾äd5D m/YQe xbzU6lRewKN^P!46%M&dYNcVyY?q]żg]_zLA #<)/ e CUNc'W(`| WH~⇕7|>C?}8=ml .ʭTvCD!!S$C^lm>T뼌4=(h˾cm@Aw}}UA|d­i9Ws}sԃ>D=[mB ݯÄU9_H>SpΛsg ߮ XܺBveq{D*DXy':cRc/*n,=ƍ8 Ol[Ϊ jɯ/C!_W E|Ao kh[=xc1.@9D}G7%MG4;mo .lp &\.gKo58olږҹPZ#Uvj!x;r{ PyjYHdU X ;c{߲I%ch2DԿd kK`7lжWvȯ\ӒP%M0#[_p D[V9ȧ~_yhmd@1\2"Am^,oS[ w\rݱ]%k#]xzŽvc'M&dU_~lжbC O#Ƨ8sp(=Ɛvw\=Ԧ|!ui IDATc" yu/!"<Y2<=¬3^~rkz) 62A:Q>xr1!ie| rACremh|6@tH2}M,ӿ)Co'nc]IF&8q6n~r*ɦS[˝[om{seYpy%0*u8aLa,h,@2 :l^[ҬR1HrXxz]-mG0zQ{{Eri #Ke]~m ;xz#]1$ 7E[td_6'kco{,lI1;wez .Lc6t Q5PCȹDˠUSˆmwC Ƨ[һܟ473|@Ͷoz9[uZ#sH P>f U[e2 kO>/B -Q*(KS [AlSo*G O ooKX g/ў笽H,5q}hBq./eq Bg!ːp\A\:;B\B4fӘU FSx4f[Jԇ?ȭQ@>̀OtRt@=-H*Jw~u@  f&Ѣ -&zX ȝw`2by(Bb3v g[aam,Eid:%kzt tfU?shNc @V5͛/!l^oFڣck_U 6p~1he WrIW萜7Bz]Qװ%**ւ=\>$y2.&!ֹG$ vlkCض% o[C|◹|ć?%Ƴ{;sҀn^i_Av6c/(.Bs( ٶech ]_`@YB3>EWLWʨ]=ur Uz*OJ[D~u&&XL^vU,&JtBա.]\Cc}utn1\*<{m4͢,h?jK˩ˮQ>4fx>ygӵvh3Ih7ztmZfq vmxARM~Sx0*ċ.'v}_5zq#D()x2Z XvaNۥGnj.q6zqӱ(ncg>W%VSJVGL-<2tϧw0-#POrbۆ!]W[!@T/Sɤ'~Wh3Q{?PkrXL{+;$7ٵ_W(XP%M7ıM@=La ϊ$CW4Ոeʄlb ]0=Sc~u6rteuSY?lmy7E9o7ܡ<h[mgȱ)v-A wO2E!eHqgV'Ә]+^9 OdkW:{[4W74 m7|}1 1.b! EB 4D]7]Ӛz$EV5(>TfSP>Tft38OC[+/yӖZ\~!AzLSH  !w f}Ő\Z])D`|‚8ֽXޤlNj6g,<wsGg;7X 9^aw`2?@*Znb^Ƿ{&Iw{Y%擅ijh4f;tAږaꥧ|lezsw:sa2|M^BWw)qi`k4 vi!ΣX2F}jHm!(e0!b6^" O1c}9@ t-nM`ܬ^SC,UEyy z(E>s,<ygȇTFxҰ 7`+d/tNg R3a6X8;5޾wUuIZB b7G[vSmz@e^LS! Wz3W<+.K#)oT>ӏm/ Owr ֮ωC*<pO,`o ^Jr絬m=3>U^qkueԃݼKnO#k@su=9|J7"l<#}-ɟ<myLehU4|dK,Wrli'>)7SOFO_~⢞}?`uxB7!W7v nSn.mLH wz2Z%ޗ/b_g4H2+.bJ)9_ vįqaQdGPt2<=W˳x-m^RP#"@,ĵveu}4-J{ /60xu?q:|lb0vѨ^s~*A< w&4ۀlײlc1}߼ۏ##D0a+κ%\y$_[~ {{d^)N7S" t9/BOl\ DY'f޾U+;0Uר^lS\V^cʋu|k.67b5 EOb YM^|:- ..m҆}Ϲ!`R Br<`{{I>lܫ2}ݼYua5z:n^t" eJH7l#!^@ʾ@Ta)qeohK}*dݦ|@˞AOOza@"ϊqˆ侭yP>T1 Cck.]pGC|}]kk?n,8hru&~był~wpsCx:+G'h7-8*>ȃ\l:Gȕ%x+lar ✀|G ]Lqgw\<<.llX?wE6ztc3` ׳r4/{E n ]|ۼضw로g& X/Fo}*Qh`|x@@.Vim{tp7 5U]Uɐa*ur݋CTn)cD@Eviu*;X袛2'[NaƇ38gX?qQ&ke;r R@|@Pyy ȱѐX$mǁ7m D}#ⵎSzr+Q/mU/3+ߤӝs? uT!{ŏkÞaQ;u JkR{um+w7q?T!<#nMf/iT *;wrmۥmtiX ǖccp9 coZߊ訦$粼^U,ߥ2>?4+J0އ*8Hz>-^8?pu)^qaж~zNH^w{s}&dh:/y&u(h W+G 2LOH]Dx/kV`G| fk:H~랋](k *2=2Lu#oo|> W;nk7:, eDu@p9=I7+ >+~cWZy􊟜8= Vz̅*v&CIWm(GPK Y7+ywho7C Zx0H՟/^^z/Q`ċ<ڻ/8ͯ)GWhH֓] ڠeXz}V'~lSh| ϖaӊyyf\lV1BxV__u n[Y9KSu'Tf6rbAN̨WXAި٠m'WhmQf4~dm/j}XX=ywn Ǒe[S?Qںxz_+@|E2c,TRO| 䭽>;CKY ߝmm87 15cc[>T3޽|_ .l*:Td,NӐrg[y;ua%\>J_xۼvtCJ4I]H]' ruUtNò>zjAږ$$]LH;KӋq ~Ӽ=ɯO@̀i1QWSVh,]`=lm08, ضXA6rvjxF.5UUVj^ mnzA A<]ǥ+~tX/\h1=&؍,R>^!Ɣ۪GNԶ䦔.ڪ\<7/% ﶌܧP۪<ձ{Uy+ul[Cӯܱ_^'Ijo~`>2K Eq0a.icQCi޼+ҺR7\wy( 8*T7g)2{`9eau 5+t-{i6&' Cr*3պ(WJ7Z:hu:WҨW,^]ʹjzZ!/7GSWޫ^Y-2M~'vPuma߁>b:]<]d,w0Gmup g6 ~R=H[ wsl[렘ϛOw/n.NN+$/"cK>2DUIr.ژNw>pU0hѤqߡ;TOTeez/=ՔfWƈ<9wr3>0!}О Ɏ$Q2 y`鳌rdu 2dy zI/Հmj6GM|EhoUuH{}Mk#b\0P n 䶒mo.kGn[?U!ɐӞpRz 2ɠ奲0*:N,oWꢨm$5 \`cd pd{<k_B/T[tѦ]xM CA\eשUe<N eB;Ӛ]D[*"aऄK-Iu[rAob6-LǾ؀aPo|KCPCc76^ES%'mCY+·(ա8̰p%ĩrM~rp }A.v|]!} 1ycxmˍ%e+vT龚p a紟8_*٨otQt Ѿ ׋~ ) mۤdAEgiҾ +W[e0u*8ĉ}| [%_Q 6IȲX 3ow>|%gJC>eiMԖ"XW]!〬ԌbCBNe`+P ;mq9qpsmFA S__$k*.tyqU/8 lmz#?_f'zwcMPiڮj nl譞 Wxqx7+.bE 4Borw+~6YHicY^ tVKj`vtVS!WB!wWɾU.9aa-ͻ:m@#8ۦS*.p m+hZ}ɋ=x]ǿԻds>w PPK?GQ_/.+Haa%7srEf^yټ44 S?FO^Ҟod)HX.vy<`^o[U&?xԥّ,Vy` o %K '[zԟ#*=kːk]k9}]X!@8zOr@8]pNa栠}72Q&8)e[NyuqOߑ8A>a6{{t|D37dYf~Umo* @exE]1h,S)T]BEm f>uSaAǶ-i!D/+dŒ!^A8/^WFYC۷K ,p{j_l:}& ZJv^-Ŏ꧆K}eH.8t:qqPqA ns U@0:x'zs*LW\Q,7WY׬aNYOjUXx  Ȼ՘U!b<4{1vD[u.y|oc9J׫36rz@m[h߷u"IpqV.Iά99O=`\.'9xAI9YK|_qA۸FVA+%؆%@]6tM|XnW_ve^xQsSBoBcжo=lP9 ؑI]k0\ 8Ӎr \Uqi?n٤^pa!Z*o_a%F6~ת thIJC¼}_##W\%') x9xWÃ+%Zhl S(ϳ `)ܶK-Z W%$c@\gGU',`;XY lk+^{ŹQԋt:rZ0Pb_LBV'.g]_lھdtZﳠtlC'x @\LgzY G+3~5:̇IBS12-k & i6m`g:Ɏ]u5oj[&rQmPA+o#S5CkpŽsqU>!$ۺ]yK_M&OŽ ``^..g bL+ D}V404,2#}^Y,.X}+~Xg}a)K _ֽ? zv2Us=eI*AG#r!!*}&1ٷnZK#wuyn2eHf'[V]@eqnNq޵7m;on8P/;>S0\ ug}leI +Sz@\ 2^q:z:xYx:9xa^qߺE''x$f`j]lD/H3/KU};qBmml Vrw؇o%qeɎ l y{AIW5I /o:`t=mm9_Zj{F7ql {:I$jŇ,bF}R.Wݨ'n覇Y& X3Aq+k BP/FA gM-8չ6TE|Y1(?N9 v~g l703Oၿ!#ݠs[v23 pjyΓb=)L]y`[6 :h*Umj6KWax+,7緹^DHlP-73gƙoK|HJc%%Yc }Ň0u7)eq|oW0WS rL$,擂A.~u+ճ riZvEI@ uJY;o&]j'_pl0׶oPO9r6~]%_T>UAyq<}K$"hڸ ]~-r|g2F,g1CrKi/b\Z$ϸT X'3FP/o.7\_q eiJokG@73iʐxEٙg]ŗ CӴz_l&d=rZvڇ)fԡuhzᬏFf ?cȕDt~r-Ȳ/y (pL*S7t`'z%񊫦3%-_P !|?qXn^fC L[\];]^(d4xlw(U 7CS@6UvBh`2dMmժkj' ض5xv)ptMWo\B_ ͭ0P~x@hqC5X [~^|WG_]ܓߜ5,b{ZiP_JNq'>>ۈ^lv+qFy\+@|V:7X[#D/]#w5ɓ'XXa9[O=ua%x3}\kQ/,һJB,>d~UUh?+Vd2^s ^rx8\'uߦufk15 `жv?%G|n6\! ['dž@V/+mce+v]-+tV=DMr20h ,gu&F1J֪-<.u~2;" FWA_mc+V3w|gc¯,/98@y_ cc=F}yw-g\-Cx:w\byHUxO*8?p+_-=;քrT~,\֓zy 4 'J;|E*.)9 mvx]@OSvLj ge ^nӾ.%> qCLu۾ϲ3sW+t vG ۡy鶒CzYp v`l&J2m ~QWxŏonIO}u24Wd֓Ϲ=AjM.ܩ/D\ׁʾô5+Io xl'@58#h/CgS/zL-"rEh4mV[w[O>0'iG _ׅ%=ZJb ;8h7\Lp~bGYNqs<98XNgrnu?rd z5vľu"u !2T8L* ~TH;e(-*J0i#@| Hx/ӹ;?AH^k(~9]KޡkH>/TW|cәq2pY+ "X,BWAzu_[tF_q4dvrKP8]<4Y^[BBS򯌗\AuI`ӑq7W?ܹz"k'6lҕeHz Հm ~LUcE3OS8DH/7޿0C&_+zP {uۘWc0+n'.z/*)nڵWWW}ŏIx^0 xϫBI{pGA"rn}:ىXסB crL]M ofa֠n yXh)on tdftfǿDGMd8X[ܺteY}xzIBU(q%2Bwi_|RT/[BA+2c ,:iH^5M 4D]YZ@cdN\&L ȹ+ l=ѕ߃L8mHV3>뎛k(8^,zqevŏgIf"L SBzm|#za IDAT+& |:Uw\6{߲/u}}ԥ2]`ρ#*8q2B9by 9=<})3[ G>/=0Ұ3 DUB1< Z[<̍/d(z[iȊ{=H@'It> E` QCzؙҏ?9o;g C(/ u!ˁuSPWCs_Un_ ùPq&Exl6Ct3V@nUMgV vyEƭ5x#~IQ;kP(&gB]m !<6Rq>_˴-sy~ؿ@^UH&7} ]HG{Ap6D7xW E9ղ^- C.5v #@l{D!,7$ )4'oSFP^!}qz*~hh:ܐu*9l.5F [ 2ÆB4" =׼HAC刡 ] 6V eA_Е{'Ci( k \&(7z+N|oӜ⼂AHdȁॠ 'f3Fԩ E~׺?y ^92ʗ!&krOaGxsʲj(ϊZ-&Ƽ f;/ͦOOU(]0m*nŵ>!{C;CѪ[1{AnOxabZmyM{~|DN(ә̠xpiW W QO6؇vzf ŢlYTmJ`6w3^x_کAMW}ihz0z4/}{Au Qh9O rb؀<4cHF"<[b5-[#:5c3vxa*4O!C WVnf BCAn@p$mD[ U7v'[T^5UǪqxr ;i6WrqI?8p3 /|DnpuP DQM@nuzQaޑrUz;x3v8h,K.alby@8M=%C_2Lz5S!nȽz%2tqӧߴm~W PM_$5$ 7QA ̚ ļPfL gPM>,>_)A|v:}?D>xaCu_߽]7.j 8XXoy^~W8Cj -&pFNqx̎(pS/8WzssC:۲YLF ZEЁyuICr87j@.W[Wk Gņ@za6~t^Ay92;OHsVJ&˺oml:ۢ@ɛu]C87yW >vN~R}.ټ⼲^q(ab*3gvMm*sqzB-}&nV+LyȥE' Ga O}yȉElm% /B-O2 >w0Nh?jw ~r &N: 1Omvx/ ƻ6|i&_=@ WI^.+};0n9|Kct:㪯x /1_?<$f+ݎCLȤso/^>4YuU5k"*;zjP(Y] +m! !AXn@Nx\]w70c}a.X ~'ɭ?hk}h[aRx2C+yt<@<1YiS╼o+@3rTX9pA9-~_Oiqe=/X^N)1Ђt~MXLeG֭+d @Su买E ͫ91[U_)"3  S(QO93$F+hyyKw0Wɛmu9H6i[4ku6Xc͑{+= bg20LUFnUzÏ+V9tf̊cy^9> 9~@nv#r.\+cp>ە7Ffhd]?yǡxoPYÿKcю nom~d+QCP G]MzH@X@?K};~8L@ g˶)9=:,=Wb.U rx^m"1 CΪ]^xbА' .ᦺH (C9ayV[ӽqnz2n"_/~Lar'q%F+hmvy=vG{RW]:u}ȴI,(Xu >|͊xš]s^qMP.[mʥ^q?qC_'KZ#r׾ ]b*nEg.L]Be˿&Kr#:8!鷖tfŽtQu5xM=$K׻@b2򓋷^F% _7% 3#k׭nIH0 33dz33x0-`a-f *V mZz}U9y##"##"#"ofFV啲z7nfUeƽm ͅE[{ e[@\ sTT q^l&gkœ >%-\7G[Rg]io}k+S1U/OO#esE(]5y_8Cъ:y-Kz?-wy ?okZ#:&-LY'\{͡dm9&K[KyTr9l~g{"φSmd CgZqGcr_yOiRqG F,k<8 Dcx#jЬqeGv1M{>JCX+ HfU kw(efpӷ8=֊f n^qy9?fDY w3GWetl1Lփ6}n$Xۃo@N׈ @|&@yG y\_&gNzv`3k=vG.A46A\Hv^r䮿#~.qa?[+Y 31mthd{6dW|<ˤ~+˨e΢s2h/X[/H~]*YWlrU틍D7Jq'[E (Cr6 tȲ kWɵ7,_,\Dc >ӧW7%:q8'CƮۭ*yAn(e_4:uC&7-JnC!㽏JMͭr.lMcJ_b9ς0t9> .M1@lg:dׇߙqHVG+گYܺC`C4mw/Ⱥʘl-7By7\uԑ.QX{s˽Ƞ.ʥuqkmla3)m4a˦C:_+~*3Ӂt$Dc^+qQN4@iI:k:ۂZd8# 7IWT`a*O8 J۹giu ߷t'󌟜rn9C#@N]Mjnx$PSߤ'<>-΁ ta8oG|s O_"Y`.=D;Khw=gyX#c`uk7MBwS^UFE:} EI `aI$m:/+g퓭fdҵG,z % 99/Xay6^Abs{y~ȃXz{? bJ4xX@Ea ӯAlhHO}.@<[. oiuS"&@vW#_ 1R:H0μp2BOymdN늳ml"qAd!y9^s#2GbY҅n'Xy .ρqي |{V፭<Ŭ;dYA=$C7Ox'!lCL7

cT|t#Xb{.2O@["O=soC bA >Sk[7.K(ݩ n#:5 &@.@cmn(c^q& LtIt r/uxq> NkL7 B֏(ØQr~._5nŬ Ȫ iG'uc0ȉf >uĐXkkg,q9rZ|A< \%VʬdmϽS!OZh eV.+F&oTbS:l5/;&)KbU_f1lhBFs~ V1Ms'ɶi=rxI3 Um~tLu`w QN }fe!yU;A0Q%͡%th`+r}ZSn3(&Umsz E':xp~K?8$#l?;#WG>\>hUC:pp0Կ:iS:蘒AMAC%W&.8"Uxd g\:ϸvP;\X/a1o]O V7=E<- }%@f{_<: '|ncR!Dӏt7FFVoqpdij<qGkđA>?ENza="vpO>C~+c Et }NH <[>U@ p7vVx8qRff}-)<of@g[CM@^!te q.C:*ѣe\.,x8kY>|@|\߸N#g?[zQJ~ʮ7с6O "*]oȓoP }Q 햶™vpa{Cr̥[rz=fj8XzQ?\kIU8'=S8xqdӅDz1$TPMՅi[Nm0 'w~cV1t8^o2|:!t'xx,uvUĀxA. !2\X m@y Г=`\Ǭ}ؒ!ã~ֺ?XG 1rՏ_=U*6Xn h1::*GĽ6y]pUwۆdkW4웭?wrR ^mIqq A,lTMI0A?;]ED|Kv`10Ey:&&]?ut#g3&i "RmU'g8qm$pjAr+򲎦\Z;VUlnNdϩVsh. ainޡVϪ'/@_f/,9UK?CU _ztYġ|&_76C@4Brw}ZdX7FBqi~xmac|S0m;uYt1yH+0 O7 űK< Bpؘg?9HwHWRd W#-Սt(@^.B IDATh3@lWƫ-*y[1Ż⡂(vB]7 >Ɂ8 IάxB- ~/\P^hw $썧w[/0S 1lk.UBtd(mR4ν4H 0mYԝ$a%mK.XFu gMcR;!B^g9.V cz +>hj] \n7͑L~3=5=qn/ uٚ 8#?=ܯz|2Dcڶ>9lwV !i?XH 7cRNl[1o_'n&@!*^@:@μ'$mK׋<.r : C^DZ]ש\l=\&cx5CJa|%ecd%r0L/p/mO+ L@+% |0~r%oK328?#'49yr W #E4O u%@Mx,|@^V .uS t8]tp<^:a#aeK >oWRC K]wgn10 1or:co}WLVfkg0u)i u^pݿ˼laYԡ8y ~F;#(9s=]YDЀБcynɒtjcZȅ)2bN=7>xݼ8skytE=k)c5?'Ga>t!tfqz|wtHc6.+uϥ8]{]T&NTu?0Q.8\۔3adcDEt45H@LʽuG݀f@Z94?mkA]axfd"o{fSo8a'{aTyv - \CN }mc@2r]%:|{DnjqQ#*|>/9, k@ڃ6RN,X &4? k+ΤqpzaeQ!L2-., 5@BXncwPJ\֘'uu9NboCn(c@ܯ+srCN}uDiFB=3Gȓ?Cч.8۴mKN4RA\:lk 儤pM& E/gaXS8Ƞq|3^k$eK׋0NA{ǓI0BR4d Wk{|Х왰:Pl?W 7BB }0E ?Z \xlXKyAMׂS uq `ϐ'~SODž =D{)CTkc:-aLc0 py C7. ur.bz&mdEO~T2GҿMkƿ"ټ DY6+!ꧧtM8ȝ6PүS=8Znyi&Til = Y\Hih gǒ/+UzTmm-C8[6+7y0@F6;bmr .q >G|R$kꊫ&t{a}N(h, ,m}ʞbȇ=fUa2!1+0<\jmH`ZuC;94Jݙ8/KQG>F$[7w{U<']Plq [ {>"j8>]Urҫh,{k)I2)g&T/M⧧Yt!' zqik#Epײg>juEW]@{Fù0D@Nzb&[;K:Q@ȭW<"Uu6R?%je29OO@a}'_E[+j.Lۺʌ{/qDF19*ĵFMͣ뇌u&xk1ƺ|Utr[ɥiX$T8H0Ƞn?WiҶ#z#^ʙrRBtW\p9Bj)TlUH% ib)@P=A2)qYX=nᚘ8Nׁ_Z7Ϟν?%ϰ{IF#̛䩟}}rŽ!GUtŊobv؈'ў%ïoVC5hw}A CG@& =5 ׮:Ս_O/]#k#ᯜݪ j kcv4yOy7=e(Lxx`6 '<}*s[VBD7݄(Q54͘NAơ:ē?zrG_ў Wt_҈o h65ojt%QVBt>< Qq+ Uwd;(-t=8/ka􄆭,ČGr9 Y:s,M!c.U_@DJ@.\/M8TGz4g.S;KE R D d} pAˑMr%KKx2c (&W=D{+!]x6{qiR%@4{$o:[U"-K^xu 3nf(Vz3NO2o aC6^r5ȋ7r#8TG[wqqN[<1}:ރ*v:?aF϶3U8^szlZQD/6덃.2L=ueOih:%q/9Pu0sONki ij"3kšƁGÒ"_U .{V ^_xeg6cBa5O@KG3Cru:]ګum9_6cKI06Կa8D(k֌lfQ?K<闒5伝9q[CgYnnp}9:=9r,]r͹xr<> pDA.\T,wj=@<+U& _&kK@|wO:}!7 jWQUmĶKϿy:+ !em7MFk(kR IT^q=3a 6RO6V,)֒!|[ޱE üD :ox_ZMurx9U]m MVK \ q=6E{]@<9 W s ;+]3 Yx:Mv%mеXroG.k  ڕ*DT]vT;y5rPb?֘P@F6:I69D[Et+_vOu\MBqm*qۗ%^6B&O׋gka0&G+ȋrH Ū}H=f]3/T U9Ac>8;Gzh|lD͊uA/փ [id5i(^' [)7eNCUiu O6 Y5lrPi=6 t8oIl$0u+JVE}Iٚq5N-%#6N!j(%$[!^s:P'H@N^9X@03adY4& 5epO[uM*Y {% s؜?1Z=K,^CB ޢW1xmf# <3?|D݃._zvWUyxʣwQ[)tLɠxS󬒭pb:cO;C5_5t+ 3.{U^2/8 v8_/l)Lb&g &L䅤n Y/};{Zc5S7 '91|\@p6>< vsZ'2 X&=xc29-]@5x)t .gP̛Dzϩ;;]zvW՝wީ񕃸@FB9hBC]l m/ !i7$m3?5ɒeN׋S?'äQ6XImJ/0g9ͲN⿽Rusth@nI5hMvꉅ*k0϶zTĪO9A~[A )dBe,3z ׉_'tNg/;U.AW5e=D{*DTh{w*֍Wh4.VPl, CRLV繩˻}xLl=>3K->;֊g R ʬ됳t1hy7 Y,gmH&G. c.9s~plu 59DxWo~e=?No*tQU="m՛Ng?֍!yNBӶ kW]X^2%L]i3V}f ,D1 OzjO WGI*F3֧Y@,]y)ӾЍ, ,:PzI;s m G~fpXiWQ<~뻜#;% o/ׅm8.C!!h/A> O\֯/0&$ocVYF-j Xzdtl^q'YL@,,]|56֋/m<:lQrcEq@= 2+mrr]4M`HG_ 76>(TS5Y1?\*yKUzM^g̓~gF~15!cXLK 5KAİ_]SAIў UDcɥ;.=x0m1TG@KGmP.c8[~/2~eB'd k7\q$]//B򶅘 :rϲ Z=葦yکkk)H֧هw46s:+E\\rtyN-m.s>cou= R2 ךד] ~ IDATka x.yŌ7D7o_{Qhe(j_|%}t6&UG "J(V!;kyrumߍCҶ%qd3ym6WW3_/P;ʚ0uᴮmNCreR]oM䅇rk]J.@ۈn ȵ`,MPի?)+%K[jzN5B|oUsW{IkeId.]v~Yw~ 9y A)U&pC*]>[;-v6 %[1e({X^S퓶y+ۆqWI#v<Ήd$KOׁ.,Cgl.E/]vз]( U O ˶._aLH aks i ʡnK@3R ~eE2_eR8]'׊q= 9Ƙ$.#7u, YcԒA Ze ]9@*UpoK+k}lϑռΑy@My41M&x~Qq^l2ECϨg\=%\aΫupE:otH@yB<:L> X=}I|%)y'smOKzy6u;N7cv+hdwWO;e46\ULgPs.0U 䰹$JSu‹ЀūA9MSv̵>P|}N dt}8 Mu3E8d<<Ô#~ @@ =D{ Ӷ2omn:`ScJPyBPX. ߐmz$ $Lewmv@6B׌Y,K(u  kl;RsغcC,*uT䆝c+L|luGHXwyhsTU'h@׆Mj>?\PC<'Nmm.  '!S]D9 ?8؏gh  9Y70]7[q%Jou/qU=B \=]$izRg-OK0 Z=!Tmrqcȋq.: Gu;%[9uu'cOS҃[{s^䱮Ԭqzh- E8}x1ӌ ӌNJ.p}%X !]@YÃ<H@1hj*1> m0߻@6k)z'F5%^,ZZ[>/5*z@zne3q@a7~Rl+@eu[ k%.~O uZݙM'VV Z[rVgϫ~;>lr_=;͘OE*i[]ALס RuaC*φmSXcP#szA:x01 2OS7[s鲮 }6X3)^zǿ&p9yvLi:%"}JohV%SgR8W@n#%u+ѥ-WF\epK핁'\ns+u))jȇ)1.%j[x.Q[2@Dmg>C>-D>!S!03~vwn<(,E=OHڎ=&(a9t6j=cS7'RjGҔC$J u ^ҹ݀\W\|I =Fu 9gi8:#:m Glćzb]Gܚ98pZTYVQ@eXC3GBubu +c:Bqƪ{oe<ēmTbh1eK Bzbos.ߗKaH\WW qX~}  Η`k _Zs2 @_NT,IH U>T5y0y ;@nҩդ&ִ)| Fx0J؞ +eF7l8DmB 0eJr䣯r4ƒP.U*\\qTd2' 'ҎU?AqРɹg&=u_SZq| :,SP;zYM r="WQ|XL/1a~۵U CUzh)(d]zr."5듨 T`n~{}ez+γ'ҿtKABb@xeאdHxK{9o 'R r|hyl{Ƞ?ZRN N9jXzN`n\+KubҶ 9C?!|?W TUC걫{/d~xc1 bkS7qM~a\F?v{xm fZaJ̀8xãBSϸ^ ^am/C3l `1 *g5rt3O#QȓoEȏࠡ+LPzPDUUӵ5^ytLa;# o!(!S!U9A=0/fL@ n#@%ڃ谑YR  SbwwqBRf[[+ewmDрw׵?y$\$<77 3g0! ,vW8kX\ :с.6bQ\ ![x8PU"9uTLh` F^إیw~&lƻ\$o~@߽ɔ&]@Xame28tاP;# {ziwzvW,U׼m;[{$@c3nt`e5&#sf/J^U]Z=RN7˙mg6 WTt@ s-zQ,W`Xy-?݃=U#ùrql"vlds9l r6RstʉR r/Aw(Ϙ;[.dNϒ5>Ur+ܺ^BWQUzC.˻řQX\70]%[R{?ۣaD&,N᾽&d{` [a,87[7Ay(orZր{/bZЧ@r ϡ\x'r a`l ^+9S؂sG7rxE ֐;s|0&Rgå  ׹>UcU $`<t/cQSv˸:BPiꡁ\w~cbXOZ/y^.8yWzs;H{^rz} Uu.=4w镛/VUPlmꡁP>dH+Ѷ>z#i Ʒ5R'ٚqXK ,qg@.{L5@q\!`όݣ8iԞv!en#X4-H_jވu>8(s}},u#laWꉄvP<IצBp11erC$' W~{QeHǩkwscbxaR6A T6谑80"pJ< 5'o)q N%f%Zeag6 u@B92v̨>4#}uM9!j E7*W)*9tQY /uCxޮxa_&"fkgç\¹\|߾ TPM" Ruڶ&lj~wg 6#8X59W(`6 d<Y6+̫zbh:4OܾLZ2y umU<⤅tg@^\ 'XXr]r /w( t bϺ2 S{*&!%NcMVyé;Vv|@ =a>so8p1W 2Op([Vp'~H*mMs!E]blxjߒ~c$mDV1ӣ˛+q0m~dX+NG<딳6zSs@2[˒qӈ IDATeq!ȍ8~a6kak Yξ8 e@"YU/gY鴧9{plH޽. gD'*4y}l:t ਝ /&^T`l> 9x' TlXLLFG|oe\A \q.s8 Q<_+:،[50mxCk.yj "3Mx:E_ެv^3LPn0uNG)u3(<>6 υ'Tj֐@q 'Ey y ƀky8zV? Ul飍M uJOƛ#HC?7&7NN_\>_&xt =5}7 \zx2 ca#3K ?zz}C R! }x`֐@';۫9wT86k_=* U .k3#ȪoeSW@ F#2҅ʝFP&YYi⿵t*ڰ.@l6 րgóllm^mS{2rr]姠h?!G0Jۙ_dm1~1XBa#f@\3OR e޶g\čgK2׷^ WfkY|t[7 ab6[ /rx; 'D[\F/{ue@w ЧkwMR&t\ @f>GmЍBUt*l?CG>cef2t l}xa ]#~@e]Mў ʼvJzuy }uyyLUƇ^gD/\i,5%e!y j`7ZY-FPތIYfȴn ] q<2(~3xMt-7dJ1wPD DCqG] ז JaY6q8K>TwX:W(xJC.}! ӮT]xtYhrP 8u{L3tQZʳPx%ƙ*`ݤ"2@ /g3`[鲲g2 'tpj0`m~7A ejrA9}S8IJ@K 3oˀ\]gYvKl'}% !>cבsDʏ/73Rum򂷭JȺ$~[rhבC[I{Lm]\ sĚ$[京@rBTd" v:XJɀ=Gipj2[mv ysldX:wGhzE'=DIG5_~r4g J`caE˛r 3. r_VS6uϙAx& |Vр1\\C^]gY֑}b1m 4]x󈅡T;̈ƴŻ+PE>L1"@>2>7c̪kn Y;8F8\\vm%iۣ ҵ#.8/a6÷Kso{˿Ȏ^C{a"7! L sn@͑X &zt@cq,* FN{ V0imv@$m 'W'#>]z`rMOLv`I^50b=p ī3InG#tQ`/oV*:/rBO ƥPu" SOc=3"f7v#SX~ hvu3_ A/Z@%Xn#cpv{hp%6Ix2"30 &irC}/\wh? ( ѪR֍}`n`n 沚dmIYu!^HY3_8]7Z# ŜG7'@Հ<i:rkbG% 'Z :1)@ȩ.źsA.Qw7㨫+@ކ>Xgksp|m8qu߽/sb7ꊇA쁜DlE Lp$m6|2g}!07u(YF6../VCz`rM0bq5g#0 eJ( n#I HM,_f罋F֋8øEkq#1[7Jnzi93 )l7osr\"sO5:;X9p{UeLzo²U==sr]NB\>c'HӶroxszytŰ7'iKoK h? ( *&ottA|4[zh`;.$/3Bxz3ܗ7[J5O$zXq\6 #N׊Z0^=sxW ?.@N= (@>b(/yǁNsh@޴3bpq%xR6.OC:8sKQݾka>6Gɟd+} %[1tvXI>_B_] eR)--Cvʅy©W<!oj@߁yTrIW~8:4p7\)=I(Y&coyrfLaʚpR Q$Lk\%E"$ӸirkɈ`=K=ZL٪K/Æq)T]o6jp]@R%gt*9٤!syݶro lː )g%odG𷾊.=D/C p'72SvV,ں9̓8:Ax/׮'o( ;LxKqy3NXx:ͦ>LC=;΁|sS : ge*"ȉ0^ 9p*isyo~@^y6K 䅫~Ul ȕa=šq6<o8$h+<7WSCtq=D{I .iA虴n V L&j8%Y#C IWkxO#! NU5hC)AnqC>5>Z<^u{䲇<^3uds#9Q'Vf[.N.&ic=Bҗ0.x÷[o?#DaRV1 ָ)Uz6V L:PlŚjA|thNWYK.BxEKhsaeUƩ "lYfuxGGz /1ap;uh'Vs"q|@Nԝ ukG}蹐t)?)Cɲ{ڶ7U7_wJaZ$X㺊p-Kh;uա޸͸Uu{h`+(4k9kg(ׅ@x}]WgDR5'pK$L_g!=8;>+HDZcb=rJOA ލFd4H3e5g*!xAN| >ܼ5nSznW1&NbuC[]p.SĐvrz. IW=HXUW{B[4yoX7k84\=doȅorZ!9!7⿌`j<]r՚pC^N{ZOpN Lo) XɲlmAlBֆs9z!W%Ak\p^Ct|`4.'/0ctlښ1PxGa<"7epkNFrz([iuxݶAt^.y)NҰuCA9 N 2@B. , 0+Văgl,kjMn =@na h&׋x|6tw7k~dm" u{^RxAp^CtR'D#nwUPt49Os=D1 ]7~A)W I/W!&%o ㎉_3Eq2@>[.o@NFm<ۇy"űc 5%GY !9f0+?I%up"`m6/ '@r,uȱllν<]dcC\߻ѵ,%=D+Z;>b_~zu45OqUu4QK\oNn\ ? $o$݂qAb᯸mzq>k—q6:i0;,봌:9H,9mkEp}$prDQ,yT=vɲn8cBܴOv^l@.]>cA7 0֎7 y<jUzە5h,>4h̞@\d ^N8yě˦N׌Gi:zGC 3E KQ MD1#+x\ CY,>Yl_W0{l%chIetzy. 4iЅ!_AP`!T} cR{uJ׏$nQ:4}m%7+s=PHSgLWug 9Si*90\/+ͼ3 IDAT2o8+oxohp~ߓ7X a =D+=D.XmMFɱۃU.=4ɹlUC[1I񢇺ZHzqǫg;bqԩ@tVl(grEU/5<ճA\^ra@onyD9XRTo;#>f`z^s9tʄDK,@p2 _G>F_{ˏ,=D+=D.!(^,Y=4j %c 7AIhtp/E][YihzoA ѢUrL\Qls"Z@>W=N91reӽ7<I2o8+ך壯npfKJѭKh%! L\6cIr6A,cV4f@P^i:Wڌ"T~čy!DgS};rx5_rGD;"/r,cԓMmIX218 Q@g^\?ЄABݺ*Dcd0xd;1S N.o֍uz}hY8W\7vO4-$L=>.%0NC\C_q:yڥ(̋ =CJFh\3 V]lҚ˕My2nMOY6Ȓ>JO!@{ɕ7|pJѭK>wۓuݸ̡i(6v\( n#X'OAZ7ޥu&O; W;m x<mYq S0ʘH@<} 4KdBuVloo'jCC&hr~:yC/=^!u!Gڅh,nn6\t&4pAjcxoib]r5 6AdD⾸y&g%|jyCuGVAbL4(:Tu# @.Oא@nD *ۙ7эqZ ftsPqL~:\xirr5LՓ9F-J׀ 6B6lqr˨|7(on]\?%{-e&{CtDcJut*k.yZqN|6IBF p_2JdC dgYGνa82[r܄/NOPu*䬌YZ φcSPS9WtHҺ⊹cuħ*`4$Ct۲%;Ѱx4yzh`+tĻ$>ak.\DTgXD{%k|J׮ѥ;dCR7xr'|4fY"s$Wr9T ߎMp!Tv6PsQrTh! zyS&|!=.c!\$nی趥vE4kK  }l։w+3Tlօ:D gfsB rSEYg#%7&9u3_vsDs.&8I݆ M]}Ms: 8GI D%L7<t]8+e&*ZH:k~{+!Gzn[znW2+' ƻ{`9@Y7h.d[d%+#KY&VDe;Te>$8$UrWIXeÝeF ggw}{Nst8v7psU eCd'>AxP"ӛeIo сКpiym{WPO`` kūS!TNpu7 !и:@ssųE#{{p<).ҍCwG8M>EĦ{@Cҽ|U=_߶,MUTJzP߃1A!]4D+E¨MJ^ԱCȖ/VX2++g|=Tݚ N)2aoۂq-s Ft6n\0`ffmcR7֏wbqUeu+!:l@?y;Nt7Լ|qCy^xa ߆Di.[˕r%otÖqtzVɛ]&Y/"@4ډQV  Fp=lk'o|wn ihj]+ -MZkd I V eS%2a>Y3B0>G,@jY|;du:}c!܌Nk,;a0u=''c@~49LRXUrBo2_XZުB:rAxU ҍ>OӘɔr\iʃhY{`b~+~-0Guè#Y [o8ߣVr(;8Mm 8=C7Z[ )G)-ȗmEc8c?$݃69~G[up?<; lUIXCtRtX4DKՇhY¼qvu?a^ Z @\"[y{{- ߾%5g#gPGgX) s;9No Xg*e;xȫ sk w. 5ڮ'| #oxsy±8פ8[PoF,UZѡ):,W% yg7ǖ U*U-U@t측6P 5o[?p|Q[E_p2;7 |7= -=|p֘ s]4?]Us+rgym|#L%E 4[05h?^:vp:07wrȷ+g<+wj?A|>!` 'A8 oN}/TZ4DIK魔4a۸|yV^؏ 8z]'' U7hGyW`^xqBZ\Ufqɐn+|(éntC& >l䏻}IrD<4=\UmRՁ|9sKB8zNa5^\m0- #ὡpO_"/ֶ89Z_k]'iN.Rsh6͛]4KO MxہۚwLӛ/+jg{{OdǶo_Eq#;cex/!3>Z&roYҹȫ q}DIm7u=}>dPp톤Ftd?ݫMQ@Gx1o:Ƭ>]'iN.g7՛-Æ* ."c076ĵW<(+}8GڣԨ73*'P=&/|z~ot[=^uK@W!xk  ya绫"m_An] IDAT,+h-x_zICtr) <c4oj u<8lnl__j}L`;wiizi+b}: ~/D n=YtmS=g]x.r c.88Kg{!Nr*pwrwt| #'}nW?x˗Rz+y9*W%gon"w* .m6Wm4ZuӴ6[Mn.w |aE S=YSΥ\yu.r>q#7@fAWHGƼ a~ wBi\o #o)t$_8Jm!:|jUM70342)I .cnX6mB_Mo:'pOY_xw:ݛW'd 7>?c:qLRS+l9u2t99{ߙ,U9;mֆ{;]&/oz :p/O+rE݆~<'<>|Ì:2 i+}4D'[ـSQjD-L'ME~\ +kݽt"7> . 09À#_&mO~ F?Slyygg9E^e _I8yÁOKN=0‡N^=.oyn%ٚ<= GN9-.S.1vviN.rՐ}lxIxs؈.ئA\T6)/O5G!Sz3cb߆w:yqY6q9l8kӛ50/< =9gέ=v6B3M{7uuB冬,'}v_ '<@yMM+h{ѶV@};^r8ij SȷniV(z»Ct{ 7${n6*Fn炛g^S>O8>b`vpޗ;&c.S7z Gl@JrՐ)2%qCL ӈ$CQ eSd_2"dum} ̽7/?F533d`ֹ^q;N Ƭsק-ea>V -@y XD =}7/|^p=^8z|{.{`Vw W>"a`>a`G>[|H m\i]287S hYlQ%ovAB.Vg=pݒ6*/|½w' {D혛 {VW_k@m+N' 8 [??09Džk GTr7zq^pv6#!y`~o{{n\p E8-8Uv'x&֌-vw6s n, ]287S*Ѳy-7t3mHW*P?8 !ZMqO 2' <ń utϿE@cK٧?woE&usx!aE BhGޛ9S/l@V<y$n8]{.{ؘjcρܜp/@}s-3=Xz3z7ˣg/~"(M1e%CZot݄`.MUCfT!Z1 U7Ƚ,em#{Pu.cB6Ag4֬Ů#SxDiu6iyh͇i HSHCtb) p  d)0o$&Q*˲ m`A/C] oz3oyyBΨy:6Ő'QNO~L.n?Yei7Ⱦdj+ uת(WܓeP nYG!0%5vj|@sb g_O_n:q9ss^֐?A%mϗPG P!$alG _ny)@e8s}O0wvj^7t}#t##ho ypnB|܉XWr rf`_-kЅ .ZWE011FJ\C>?YjRbTfB)2mUWxG{&`=zrRoϸmӽLw!;AGpqOK/Se[N9&i;0n{UӅ9B/@+k,C7=t,Flҽ2yǍooCV*6{(]};v\jmu Vd) pꂗT)RCFVf ӸyT [ǣ{MeX%_07mTGQ9IzTD[ʽV=_"r^r6{sc B99Gv+Sn;YE=p-Lq_K7%d ֫t=WAtُ8# ЃqB*G svv.1ÖcRK4*ĭAfE׫6$%^0TmGa/|8"lOZtO(WH{d+٢_<-X\{MK&1ĒSnaQ7 Coq G`#r_/PT^_U`z)ySw.sɁI^gȩ%ćl+ p-ڳnA5ƿ-"/)CM'HV g K'kz25ޮD9*US؛ío<gsiD{U{\P3[p8'Cefո , ѥJCtѲ \:أJ^"*b $6rinݔ+ PG!衪g0'V-l؟|pǯFH)nsj3 [*S89Yx ,dv1qr9;E8D#,ίs*侊vޏ Xl~*M| ߡ'~C˙"!?"'{mWgpo^l/? JUn6} ǪԢ;DYƁ`>Vs2FodBb!TiNB,0o o"4,8户b(7"1/\<)#܁J@v%'x\zAe6^{#\=MΟ##x!<8u %;y]/摒g U͝\o8609<{MV$GnV37o<{n@ Y÷Tuڽo?mkBe㓘5Hv2†;cnePF9*\-K"pkb*"l`tE0 IWcc]\aXy٢L_|f#rRikY-} ӝ[vVrU^`b8o;a2./9۬x8'u'kyݿhW[r ;fU5{Mm&Sůn+* @9q̩=fc&1f  %^Vf؍IƋN"9Vr6h|zm;#uSTl)?Q]yFe-_-Wss//zԽ)k6{PwrSN}8 [n8!aXh:~;nząpnW@u>p{+^5UK876}.RyUnV.9qNG RP\i.[y~C.QKen*xEVN[GY!6]0ub{UlQ<0;pLxȹ.|31| ^.].ڶ{SQܿA>{n%t+c0< v+(w9/\=ꆳ|nғ$ 9ٔQ6~BZAGdK۳ \t bZfWI7HCtRXǿ)W%HG1.viOr W =`Ի:GhI-[pH7A.皸pmh -󄻰Η!+OΧOs!|3}{cBӝo «/ruASMX׽kmڶ|ޖ+CggΦEz/`6VQY03d12H[y2iK#!Ÿ\QrCCVϴ\ Y} rzRy[i֦7PqnMz{$I`ze`< <@8 񄯦1Fi;D_lsՁ;ͪ@wTW>6B`=V3BĔtAxaa I\I)pBl) ȕC5,x>/zUNZœSZՋG|aQS, 7睮MqB_qn*pv!ŵp6$xoMsJ渒/4: |Tr' WMa!p]T/b.$6^wƿ(X1qG3N1U&d.-8̧ߟvtU%#*Yl]ܗm.ʽܒOVS IDAT}'=; 0©F79IO@rmt},5@\"@\D dz2T ޫ8؊'_N?~:yc-u~qhVS.;]LˮIvr*e+n{o^V]+`j@m4J+6 a O2V[+\j,^އf”s:$S_5JD2uG4WYi־Kh' lZڷmIZg{t'=g`~f8$eܐ;6 KݡѲwNmfkJQp\d_&(JOn7CUo73move5 ގ&xg+Zʒw;:9sWѯUBp!rv_&rq bEׄ︆bhݢEVf(\ RCtRwh(ZYċ/uLEA^x0TOjY 6 gWE|p1hIcBU,65t˵p _ _7s׽b5włŀ||ؓ˗Czi򪁸P?_fI-m {8W[6MHz |cL^4RS/0\o7E :Э;y2i׎^WXm-X`Y2TeH>)év$`mZ iG.о} @[e6r:^ω]1^ys}omf_{$/E0);4 RQ+ )ܕȮuDS efoq SA{"{a3&}zDqY 8dr'[/=VN~HTR];COS0zi -F7b!ZzG_51ufuQսǿOoVǼ SYg.sS'=;נyyoКr';͋p!ϒ*YKs_PMՑ!ـΎ3es&H"u!NCtTM>#w*,E%Ơkm⪺W .aCU _R.~֩7GIMOeCvӣ}+a@5joNlSCwB '=݄҅UmmJ?;ccgʴ.!tdh ]/5e 51cT4K@\D~ݶIzU:H|fꪅKpٵtD#ՃlQib R˝6E'^ěgB?s]M6 S8 C [!^c,axPUq+z&UNGU+lsf_s *z#|o{m_i/wv̺/ n=h#=2M~Ryywbq0 u.H M4DUC,f 8](/"$߿<fUWē = dr5rq|eBӿ;GoeEi/wvkY!ϒ*}Ka Dyn 3 {3^0 ?r[79(T%{b5¥C88֑wYOA*qO7|<o;YŁ;ݍal|!p2$p-:O HXUvp.T_ UkkfC^Z>va#2![y4s_8yk˵;q:CRRA9? D#,p,vQNz:︊iƔXYrʷ<[ޙStDz6=0a]o ^DNa:k>Ycf#QI٢:Wa~:G0삷v];Y:vۼwTl_E︊НVETR:zzcdvzx%SKHGʙ¬W ӜOo[Uoͻ3Idƫ٢#~#pB)8LY!0Oe ;n?|MɒujӜuKͷ."7<6.Yp `n`ҪʽFHD+uSOaVu(a_Y~L oX?ϙ;АXMURK"ڞtICUm<<) !-30( 0F4kA=d4ZUqcM?x]qk I/W&GXD. dhΠbm_~{?î*6ڟg^^7FSY];Z8rxd㬅l 9Ov|`p1a[tQ8 efOROcQV {ۓMqkO^z~~ِXqVj_jWa`䆛n /֪AwYM{8]sYd:U] ^Aq3\Uq-(/< \}k؋Ha b: Cл~wץ4p?`hWc>]\xf_IUW^EBy^r@Xo48WeU b @\D~Q?\uf,أ%4.5$=o_Ch=ㄒȁ*d5|으W鿫$*XIm6Nwx.2dj#;ɂs]-rۼBYڰh[I5[S+/<+/e{a ![TG ya=Dݯ W>?ݷ4t'Yc"vz6:BxR;;>Cq# g֋rz-z1{~Lbwz44 춌ӗ4fTu4r*q}z# ZMcv-7e._?{~/1b.;]-EټJ%dq;!7 7&kWZ.]^aeO&9VRa`N [C̵RTxPuq:ݶsko>xì?' SWEut 3DyQW[#/hioWc}[/m/Fygu+ &֟.z˳@yʹss霝g=]\ZyQ8Uq%ke'&[ucs>Y:*煋۴I6cۻˆ&"emApOv;~+6k}\?ETsѮЭԾ ̋v@h;-xe2x]xkw0;I6MA[6)ñnsaGhC?Wki%7-+X1}kKko{!V;{ p6d-ʅlmƅ{z_' o10є\+'7 oAܐB+k 9VT1$] 6Km|ԁnzlgQ|?O{z5ICЪX9w"@\DyxGQ. MU؞+nf8dGΟ$HN?W"mP›Qxj:˝b, U[}Yp!_ou;idB0;W;xĀh"p`@6|@\vr',BuG:y+iwci3Xendg<0uO;?3rb];LN޺Qp,vo -o)yP\tL=EoSpE#0ƮI¼qvL\XTq 1#^S̝% et/r)";N(0ucl8[ͪCR˗م6f"U=*^¨qHCy i<\vغlexM}t?dW{p\ c]10zm e\u9\ӛu`jZ~ڌ0u↩TlQ'0G{ܶDz_ <3?$*GwbU4t ۼǪplY+^ڽ[.ڣw<Ž߃1bDa #"@\DIa2ߑuTkݦzEzPuGɱmƿCس)ErT ) e{1,}S(W .P!/\/U0b62fm w/`j,_ܯ7͟½@0# )[iNlS8z䋯K,w\eeH(%/ȋcJ#S{H) G˼|3GexehD2Sr5{D|^ ݐj؜ ԁlY616mJAߺ O~^IVTn ܉m˃쭋xƭ]͊i @^w<7;R!{Au%p}]=ym5XυxJe8N]6SqAUWx^ͪiRRϸ &PIo G޷c9Xt&LOsCi0`U;4ꜷ^Blx9<Ih ;Rx E]Kz.zi@`STqm(FV,z I5%r l= (0SE4cp06Lukp3pRЭ;<;jcM.5aPr죮әQR1LJW .C|RpWEtx1"`"$3#?ݍQЭ;e6;o¨#ie7uTVON6*^D_EYϻvcN0?kQjmN$y@\\@\oj\us3IjHzo4$L,'Qe@lfTf~&ʀO|?RՁ{K#Usqq;nŪ4w3 tb`~o]zn+{lM("o<2@1O\Muux+9&hg[dGǭ)FF6g<| _ hu;V5p'Yy.a7΃7G]UxU,r"U E/v0Sx7&103 c>Ʒ|X1=z 2[.*1&hCf, eS8OqiS2mz( =ex'>XҟvU;|.G,vș,w|ە.˶%r}iGKspA]c?I3Un8D"9q.|Ps%o9`3w5$4w_ƄSؓ{($lQO~K|_/Bl1z֟n5@wnʆ*>R[$#7ܳGzEpvT2 ч,>zwNlA[}{ |@<` oMzrze8j DG*II3\EM6]󊣶لphu:lCա"gsixPE)w\Kiԙ{ ɮ(& b 婮^x^ByaܧhHθM [4" 5؂M{S0Ʋ<;jFzNj#_x҂y(/s7U0-۔2mop~]JA_N9B|·T5{0g^x^ɶwԳ}Wy1_,[a Sq~ =P:J@wŁ;j|燧Q m X0UX+\$eRpuUBћuF#<2`{-hû+ssMAΪWUu5t[ЩY+煯_f(0n{E8a7WwmJ#1hb4t'*Э;㫷zj;ϲ'wx)IfexcB]Zuk.7^pgy&q#,^-fa*zE|+O~ GaTiYS;jk^ 5xy0I%Wθ^Vծ'~%m}߫~|a, ݶ NޅUTAL|U f Iu䧇lQK,l9e/B"c]ן>#@*ojNL{-+ ʎnE* N ݔo?ﲎ0 TU*j\yL6o'0cަp $o\뷁a郮^q1Kf YkOr%+VS'c<Y '3y^Tc[ïn<;b:l B`Z²a7ʎ6 Ƿy3 \'m']kZZ2DGgBQ1ڎy.a–m9jÂmZTuxA\\=)Ws&z[hh0vZCexPW-i/ewܲXxQv6)mzR-X[*YVr=E{WNFˬ\xKqӀQ! O*E$0b Jݼ{!aĢ{^+EVǂmGힴ$"5JF3q֎^ 㛷nJMi薻L8^xU[-f#ַ)wܯ$P^ds Z*c2ixQNe!n7}y1/ƃ7:;v,Dȓ:?)سOQ|^x؝NC` ٢ڿI2dI7w K<a ]7C`tkVb,UѵuJ%ozo_yVP/*[ki/Grl@%r" eiOm0HUY(g=!R+/|sE'n<\S,&5d߉wy pa HCe3E%XkyÔHk]`-ŠZs@0o{>{݆fSj[xPKg,fjoni1Y1!![l:Jr:g@ȻU2^):_^K|:[ys:X_O&ȅ3it{uQvhmrCSvMG0ǜ]vw>4xa^]_98:ӄ.`dt"|F!(a(~Yd 5:竫<m/g˪N)挻,mAY]99VT~~0?c}yV`^Lݞ;>ٲ!k CN.uTYHg0%fnP'/<mJsBȂ!z7m^ ;\|iN p(ӡBjb7ixng_nÂ=0.\ aVו]f^qWTG 0愩@#sC%٢& Smx^Fuu`t/ IUdliQxy掷|Ïe"Ke^;wst[)렪{ūuA a;Jv4 E4c~:g[lazz@!tYǙÖMΧp~rsROD~8@qA9*{?ݿ R}Ga$b ~DŽnhW ^ &/c֣vCrƿ  Hu@dbb%LDi~@8AVd,ʌ7[W?f䭮7/ؕui-9ǁ>~p=t]0g;.gG!yq|xTux>>@0`xᆲ}A 0G5v[k%UսUӛ-,:F3<5+#d-ݚ.'Ki2;(k6}}j.pr4l1_Y:oGUڵ+q{P>(xPsb,̇<s{o%?zEu@+Eg qMޚwJ Sˎhzz}hT ttdۅ YRƗT#EE@>>>[X+ulw O0xT0AW?0>(¾>Ȯ_};kԄ[] gSսUq @:*yQv64g;lTg#fZ?(pu*Нl<]Oof+ס6p2*6 c~C qɵ  s#W O#>OoV~^x((%JOkX+g6ә!z,&Z*gΎKR+0KLwau&\?ڎhVj e(D pU7 -ݏW&E 78OML5U+A<&k0.//\&/Qϸ dT;HTi2_pC d.Н|Y< Ɠa}av^}V'ÛZDy.c~aH}V8$x/wN 80n{ūZY4yJg\shP801~aQ(K*zt}5{3 ܅-SiΎǸBEV?BJPM$mS,{y Qe!i䂸1y>sL%#2 ^ixMU%/<BɵQiӨL8*l2;0>:AiT3 rUaGpjUDz(Sw%m p.{XP)ixuwGVYf^xl?64ij|r~:yսĵօsj@x\_Fx.񣹅@^:Nm/&pt&~][]2=ˎKMyYZN+1fH(^q961Qn҂K#(M^xު39~ǂ #G+VW0P^xx_lQNigɴ`7?{okIyխ[յWW/͞E["mKI6`C^  E ֓ ,ÀiZHGi(ңi 3^vrLgXȌȓ_v̈-c?W|ʎO ߼.ydn*?qy`vx݊VRFimM4L,&ai7&˕bhǮi}$;n\4k (N+gG]\ik"n#=b{8Fg  xO1llpZN~!~?g;9ܼkBn*} Et<<耶sXQבeD|7k6IKDe?o.0 Q`AjDeqK$|%<'0Bƣq '\vyԫ 8>ZIr~#N1NHeSlskDThs_b]Ⱦ>x2FμpL[ Hw"C]2Njj^8/O{!"5av_uUxއW  z-Lr'<̲g\,g]Vԗ oj|gN% IDATͯ%\l貏b8-Լ 3KBpzCoתw+2vyp  2ppu6x}^DÝ,O _VM#CʨxJj72hnk…DūYb'm3/gD|HmF½>=uxtx IA '2q#[ab%uf7>yt@w2_9-J;x~Jg2N&] DW񪷤)lZWPOp`]Β} A@dD|!6#KgV!`1zԅGis : SmE>3U謤·}^OEiIqPgsYu]\}nݢv:>(*&.EoJ=F>Qd6Bćt#yG0k[B>upQvdެy|[K՜ QCleVDx߼Ip/e-J;<8NkqݧrE\tE"InD7E\'ʭhm3 B_͈xT" E}d>$[xZ=I\o$30Cƃ`m|Kpŝ#jd]Mpvr CUX>47tOQJP̑]tmEõHěK؂+3e*>r"~5C٘#BZbO2B~TAȻJĻGEXnopZ$MΩ&{sW/G=Gty,\O½LrǗn;D%[vLEO%n:.5"DTtԵaMޣ$ٟdW{ťy(wnǣ=jTDj{"~%æ4g<^!۟DŽ;I ؛-M! /ΓY ?{­Vg15D]IbCvzKSjeuZ%oSD\MuADk::Fr(Wsq4'ьըxWxQUd{o+:pQd< k`𣹛sWX8np6g?xܾ^S݂/NExƬczKX u$|Ka:Detle-3"zJYd/.JĻGe@oDHR%QK tWR>oBf(wiVDi낞.xzeuU֣ᜓMq E`W6 PkAñ0yb4INE::~Z.6 iFd

  • Z-+FD)N~W $ .WZePW}0#pMa^H;Obb݌/ErW$ãVw\( zx+&Yeʖ/߄_lȠy[@ZXq>O>upVFL@xs8ݻDPet!M:jڑq";Ҳg>cxՍIIY{!ݸU9זvLW::jU.5Iaʎ u_lQq1H+QFķ DIxU{ > ٭;t=*.k64!᫓ۚB ߟӛF+|O?~/ܾQGHp/JyuM_ )KFv]*} dt{߬&|qFS:lڷqKl>?r򽐎2B)]͡Q:^MlDWyጭ+E[0P!Q{A THy'­+)kOf[U'{i?L |.՞Wp#:5uAܺjg QFx9ØG;:/\&_! >af`N*:jM7#ha^@. DƯ\SxGQq*G}!EM =VMp/T:'3TdZ e´]feuH|.dhMwJ^&0y>vdOaQN]t=*.'t#Z5"QmC(<& 3o8=LGчXPٓn~ߤi<<3}wY&Ykt] mEMs)Rmʎ =}T1ZdhĠ8J*K!9ބwSA{ˡQq^" SZW+ێEw=݇G`xq۬=Mt9O7vT&Zh2F4\6DܔW"M&3 WBV$鑀ۼpQv8ޞ$!OTkdwuWxסVSijbz^8kF%;Y/^q$ EIO<{nL[9MGUݟc8;eF+Kd׍2Bw17Yg"6 CVK'_v96/ N٥y!?8@e3WmpټN]!umBUT+񻤁 $SL`Nnm̎CVr+2ļp,_-'2]ID,2A]#4>9\-\ƞpʡltg1dS_sPSt>}ovPw/#a8$|)ܼrzكaN N E.FŻNmyE" ej~yJ~d]t4O`dm!Cҋ z͗CS"<=/_[6 [xr:8I9D'7t՘ҿW&7 g6aKl KxBC}"O\!!߇c8ըx׉mEnfH8-?+XMvyA8w —op}o^+6 N<Lnuk d_`Il>~6AAnҎ 4ocb5 b ~^@N^r Waރ);l.JĻZտodFsdInqvyna^qe\x|89 lm}'yj:וtq"Vfd̻Kv-S׶M;=oGO4AfhQ硟.1K‹Gdl£N)Tm}փQqy5>pV GN$lF=؅?J\r/ "M`X|O<_A>@j;_z\Y7m[w <|!}۰NIwEᎎgdu[FYbs$V^ȳI]MqeWc7 .l]6?.ѬrS$z !&p\}"!'dz /`X^ۆr^?Na?e6ߣn~q8n4&Z#2gKf"yܩ8mmp$::z-Ht^;ĉuۮ;D'E}k$V^Q.q&De˲D(o '\.pʮƐtT_١ ?8vP[rQx%1YKRpS$;0LC~r=*&wūfM IgΆWC EƣpiLnqTimB#΍Ξpx*I\JJzKwٹ㌜ۈE".D\ێtnb y!NpJ 'PC1:$xF0Qwc_'>|'nB|vklo&#Jy|qZ ósEVP/dz g9N`gsDOtG1OU%XCMtR'ÕGM3]jjԉdhO<OL?/\P;-!b˃`oɁ^i}giۛaVş$ 5L$M?vDf|'4Ht!=֐ӳ*<: 4VvQ~/*:S.$\E'vt5Yl]Aφ#Lld$SrH8"#Ce4W!;d/7=N{_S:M0xۛ:dݰ^Em!t_Q|OrHhuw y6$\6OmSӔX(pke􆚛l-!d'XEh09To ߉P+_s1Mgp=(; _Y<L9"h xJ~ _UPnDH' lpޜ;{͎Ut\d.pml2j=m=x]=Xr DxWH8S1fZ\c gP!#MYz.66ڬݗvFq5ɷ>98{gnt+Iupc掏d\ 2^u[OG=IxGFud)b5{MqY$!܏Ɨtyᩌ\!F!.;Tn=l|S=*&ϑyc2:;/}t'irLv-ܝw)ӄO:uS\KDu[OG]لѺeBFEao~Oqӝ(Š鵇riM9LQ[zQ|-#9jpi&B]bN݄ެ$|{VS` >p"UJ'=TN釛cz_f6/fԼI6z]#M딉A._Fr e$>)q-Q|Op?܂q;/{IdN=_Ifd< D_\Eb\jk0 )n<'rbӅĂCdu{UxHj^mu;7)=AV{4X g2zd-ռp$|)LL`x|]=/7 ۛiDu{EƓ4j ՝X^4>98t9I}۔&7fh UZ\'tԃ8:VOH L2f@$Q#ypQ +\ FVt#'gq7SHtF _lYd< Yխ!mD𥡪 ܿy0~GMltRg q@MAȮ o.xueo5F "ޢ-mb`xx=uSUҋ⋢G-2[2B~ ^}ngj+X}7gjT!`Po9q)pm#GMtpc'~8˜I ho߈xl DS4AVLPX1W#>)q-8aJsߣYrĶ= jIFƻLdq1ܼrkst "cRz][Jo* # #AVLub^$V,GL@O\jH8cxnz40wx] 7dt}ՓwC j32N#y{jyO0=q+>U&R$%EJӉ!abK\)W( ->\"`ujW>y7Ȫ귡[&N>摅)]|DSI顔 IDATQ4qU%L-CEH4\CTh D9*W_ė7p/G.| ۛ]K0u =Na5Lڼ=u2sQaqN4+sݣܪCԫ9Р;ޜf@i+cܛmJD\0km DbK DXMGbyHgX'8h7jnn}'W-͚yd\n ǧpF\ne_< ' _\__OK7UWm&lF'@OěSL |Aac?/\uJƳCetGEgms]%,"ۋ}c_*D],NlDWk5L/'ds^1SPiG^ZO5=V $zNbÏK g,7=ؗՇhu] T^8Ѥn¼pH8fDrP 6, AaNӌð+ ֔CՃl|'<<=­35ne.nLiLEV\VdHOY#s8c7iM"nϞM'h /WKv> g}*ҌP L/eu~#&x穽e*7y Uq<_adY2[ }:tȸLĝ"qgr] B}> 0} f|nn>j|$[3>Q y@n7N`6a4Pܓn_u " qjpoܲCL`KLI]=W/Զi*4R/j;H8uJ&aDrfQ)&|{$|C9qUDIWPյN{z4{{8i=VY2[Iݹ`}ZMDԻ{՛ ulB>pw1-p|j^$gu4BYg7a8#Q D/ۛ] /&-@[I$o[7j ܹ[GutgOv痲emIZO ==fTi#[4\6[>jF j7 [煳ʝ ԉ. '(d/Y! "ۛsEۛ!8\x='nE o+&9H7E E~>7:\_]oqRFmu9' 4ȇڼpH8_cǢ"87/0 /{m(5Ikb7v^$:NȸQ2%;} 0gעS]Ew 8G'!KC=6Iv%݌VR1[&sh*m umDU{Iet^,j g嚌֋@@H8%T绕/>Hv^=\dVlh82}˕ j(Dɺ}*>|g9LjT w{nzJc&Rzz/τwQ5w|u%:aFi +Svf Wz8?9 ߘ=3{wYūխ/&[O6MRudVSImطwe0*.2yc>+5_xSc#4oBV^mDkK%hړ[NnE#N=r tcy ElCc{Qq.`QB[^{Ed/.o+ef`^׳)I5?q *pltVjLS_ YBdu/^QVG kM[UU,9mG"N+#i"\KO&l[ $xA _'R./Y%?_)[u 꿴D0׆t {%hz"'L*)mgtÄ.^lǥ˾9B1)GyrhjxE v9kF%o&<#nʏ&lUo:l,q&A^ /9%NR`Tu:jF>d럵U%tTP@~G='Ʒ۳g8 e9dKŭ'Ŵ t\;(M"V4Nlj8ODcx!i_<|.p樟.s3vلL|gnjı[>q8dp:_a0uۺGoMO22_hrTIh*YkTh5+~)r xue+Zm;pI8Noû82W](%ZQ_I81lstN>?>Qދ/'+nsszWɚG4 |a(^6J+/ B͒p"IrUQ $-94G]m4sgr0;HD#e럵U̥Y/BR:&_M"gR ~y\Q 4Z4x:B ,I OOgTj.$殓+R |wȴ W 7z8Iy.p̖(>RVG- f5pc^z0?5 t!LJ_.7~Wdڻ*]{2>7Ȅց S7.D<#7w6YVJBSMnY= `i^7Cz"f䜎۲+ WkoJ!j~6eϑz$Ӽp$t`NEy?9(q[qu?޳2~݃= ڞ_^y v&k}AO|TnNO P'w0{l'z uu 勃 M~^Ԗ$W>pYQ܅?8OSW2eFޒqI @<>0+H?Sɉ8oFE5ud{% zINBgd%u|`5^ߔ-9AdUyvJʨUä}NYM͌H6ؖ$ث_<*IcKhxPlQ?rPE젶#i%ݔb|CPE2B^rJ'r ~dr]$^\|{xn]u_qVS'U*RyT?>ladv CSY-yzij}Q.]7(S(FTby"F=u\~-YQ俍!#Mr}[ >@=S!2Jo7狛oH9e掋d]QW%m$\v"ܶlFAy: wS'y6^o\}%> ]"E=~+p)-Be:k* ޔ-HDñ|{ebuj wU }d R"0u#6} q[N[UdE?/\`K'E ᔘȳVD@ m¯E4"w~}u=ϘsU+HoCp{[I'90np bIf<9ّq45#ub䜐UqMFUemFU !d8F>u~^-H8eWlb}ZœK{$p|_?sD9Ʒ~J;!U$*0u#[|Tוx}<_G37zIha/JmD%}ˡ5q E57}O@Mqw@.g@gwj^[$~!;^n]qv[2!زh+X'}XJ`~?(GC[ši^||+*n=z>܊6AXj!*Yz?MoUDqa!EGY3ggp{{B*NIJgguR!E=~0Q[*FePH5[EMjNr:/ƗAmE0.BSC}Zsh^\3!=OO!m`ipUNEyYh/-煫@4;'2t ojJyv>ZsDt/zibKZ ᅑqFxo|w|Ji؄0Rɝ_$P<~ $W>pꈺ=؂?0^.|lT0nf$|!Ljc:G x/3 $gV,G 6b S3J|^Hs}% @} Imב3SCD\!8-m_9=T\Y6] pRorګ |1$0+e+f/é}F(/'rVcgR|{ |a| 4P{}EgK(޳{ fMQ2~oX _McNX6a\zNDٜ5'K'\(im&1(>&ބ:] +E*Y^tݽh/7WgɝIXsI-^F#(!\y~]SQ 4U\Q%2trRb6Mn#η[D6"6]no6S&B"|yĭaM?=gd|]U-_azg$.]7msfGkXN˜GN0 Bxiqw ٜ΋1v*HH)ڋ2π}Cb*Ψ~2SZT|cJ#|ݸΦJ(js6Eg+c0(FNz9= лz/+mMj 2[@GΛXW;F |F[\".am*%hiَr]6I-ßH,^H/Z/n}2[ڃE!2^_!8uDP^:al765z­]*e.`ɮe6t(Budו܈Fp0zKVYr G1𥜽Htb }"h7#KG3/ۚXں(7_+|t.[C)"],P1`Hv]*=yS:l7Mi`cj~Q(?N`7H\G=" Ht @¹~\툒ʰ^jnF1R2pǢ)oO9,Xڈ=Fޓqм[M_`aٜײH^vN1.~!,eM2 _l6ul e8 *m |p/8_8+suFgq0>NlTƲ-Hone\*y{ŵԋ.dWq Yd.XE_lF|g.կ,\J{ዳ9~k3.8}Ap5ze|!^vNע܈RavldBLkIRH_:$t15F}Gmwc]g lIMHJFY[\JG ee` I[ Htd#gbqp;g}xY[v.O1$ 0a섡Gƭk-V=}ھ$l|@7ˍJa1T_,EedeCWj(71 IDATc7ct0B'Yq#1u)$]e9ڟ@Q/_}YQ/Q[/K|~_.ެX!SHYDq[ KYI[ǪkÌޘL*V'jK]rbllTd\Û]7dNh'~oC%PJo56Z; 98P;-!EB@O^rՇ G2ݺ>UV-Fp`S!Lu kG=ʿXdx6ғnU<dZdd2@]BBj˯ ʻr"N?$\$Pw)> g2*ʘ%ZCҝ >gy᪫zlC臨[jh[Ͱ5;0EE&%4r2> X8ml)%cER]/Z [O5:#\$cy &݊} lɒ'8kxA(]/Np[jk^ |.L|K.+3DC _88^c[#^GXOt$jW/wu AwysɮX:jtTQq4.աkWhOPՎnYL&F[9_~UXs]eҀnɅp}e.flQY~?(2(*AӘ\5$Z5.}ޗ2"Pλ/ o|+y Xn:߶ d8KT:\"r1MuG6Nȿ^lNׂduF@5 o'z;S: Mhq "NioI<#SM—WFN' z-NRNm+~(no=wi&ד*VfS:s=_|e0fs6ⶽ ܸ6Hbh6՗vLnÅ%Vtَp 7#j#~-Fْ%O|qn$'yTVGH[QpF_8 _=~>[Tka,WT&~z%~5AE]1^˜1 }˯7\*~8]r:~TGgలZzqCYnYCe^M Tmcٲf#M ˬpVw.V yJ8iL]Cсyd>^9x^ܗT6ًv-}u>}^P+#RH׳dFz#JSg"gq0~"\!u!:0I va>,} "5iJчpC~vCuld_YzC ҁHrT٣ze b|~>t' }q.{_%TN# 'AFm2\F#ͣqHy_n \nj{ypK[&Hj7.,8E:z.,FWk­pԖ&yԋ$ #'|ո>F^GTSC&l܂pU}?ϓE7$ԓq$MH8" F'rs5ŀ69K=.OlÅ5YQ+ 'j/6hFQ}S4 [F_[_/`wun/r׆AG;wXt' .߸3i_ٽ9ݔ@zh>b]˭ yEG˕V'ȮU3Q.uK&A]]?Udǁ Iuq޼py|}%un$αUWg7܁*yp<]\U"ŊFyd;&~[୦7 ZlbU>mVJ,N…fT\RO=/}]k*[וQSɻ} YshfAчp:L{?/\?uKGpn>z(o"[k߅x&jn¼qA$M:~45k:Ke8dM% 1LB O6 0%Xq#o*$o#l! WOwc4I8P;-M$> t#l$&Glp}"ÿ9|8 W`~ʩdƹ㞌#~ i Cm7phIHMEegqHm5xQ|&utI!:*7(߮l~w֋!O|q'H8kK< e$AH8bqyFgv_9zޟ ف/퇣y_W;Aƭ'ᳬڄ-_Pߨ@J}!m/`^8':,!$ KzD'iCVM Tc&hDy^8+suԼp<[TZZN)})A\y$Sv\tO0p$r}{B{QFY[\ϊP})PŤUDd|A>tvQތ&"nNZ}nNS\F)C`p7_>nL<nhdKvձchO ,8%R;.MkIx\U%ssGIOC G-pf}uzsv׎޷ .Nx e֌12N8GMٔBwyM]^ZM:r$Z }H @٣z4ɓPI2 I>pܷuzur6!7ْ />Ygש ~% _jf*86跪?<% wEL'B<\ ؤj7-?^2~#z V$/Nْ%O|qn$P^ *?Eի;fUF;箿q=8Mt';"AH/Ӥ3dVlҞ'\& ,D\wA6|TgI^RLFƟV:X nxs:zx?>pC]m>T j=gF芈<}D٘rXT$ÿz9x͑J\5$Zhb9gcd=ug㕃{_ԋ@y[&=Xbo ~uQ>$Hd5$WiGƵ{d&q{0xQW>wp=]--ZeQqݍV^& ړ NɨEe}&ĽH,įR\E!2l TVmd럵U̥O,xQY>狣^?h?C߅SD.Rs\Q "O Y4r͛_iҦix昨߼)m'DPuF2۸I>DZeĥvQ|BBz"בm_bt*dk&ާF)΍smQG2~6K҆Q}Õ#d(FbE]/W +#Yz/hi]5 # %w}OՊ8ZC^K So42NUf_oڮlo Tu,z=Ib)ʭL0Óצq/Em^ڷOxXy#E鲧Y:h:N@f{4؀pټgؒ]X7WoK^#y5_|7OZ}h*|bgE_ ]fϳbNKdDZ?L]['3$X{[%# ['Z'~B8$ eLߤ,-$Z8AXCeB@5;WqaTK!oB_po0η.kae# vI8O#Շ]/ Q  ᬜ /&M'犯yE{mvo s}$Ag6kt:/ 87T]uSy\|s<4iah0wEs#:PUʕ YKH঄jN29w ~0mL^mÃ!gp\璫xdh(v١݀I)>:MP^zaeD9*G~M :PIRLŤ) I6[᧮D}wχ(V ~ A&_k6@m>0s IߓXmiM5$LVM\$!Gm&d].07CoB;1܎˶R!|:A XP;-HAMDL(Îdʁ6[CP^|H ҡJc=/[{2nt`o|݋*abc2.b_Gm_!\t}i-瓚eezdba] ,^&qޖt ukZNGӑrL&s+/x:Gq.0Kseʠmµpq'$Pw/KyH8%4I ~p.`?/܌??SWEޥ8۷~|R.(~ Y-'>mM9N*-~Qe3q) (åhx?"t5- ^tܝ؜&Cy^$+6h>$-grE\b%O$|7rB~@ '(ooVɐ:'hGAqNƽ'߹npGiB5rrsDIV &܅z1 Ghrl1, tcڵH8u'(]/Lp̖WSe ԋ@ $|)'0WVoo>:a]o|㷳 z[sWk7.1Y*p&BnOX̾\ "?RtIIE\*t=qc:z܎Vqۅ;c }˚ #xc |+:{2Wg<|Nˉ4ţe[7J8~R|*]jl^tp=aEtr2O\l2/lTFW) 輫(JZ {VpmKFXnovf᫊)_NvۧX>xh8s5*}!D3VҹH-cD{o_z`CȇuaP Y(+ !7۹H,e! "LoXqW^Jr^`M%s]A g,_ ?sS·v8?{CD@g5#h'0^s2t7{u^Si {$BJ 0)I#Žŗz/.+QoWjDZ& ' ~ðp$ɕy6ZEƟ};1y)ۤF(L{2n 6~%V[%'odÇiL5 "Its-CpsuBB o2^tuN0Bxq@* g g슳!'P+e>&煻@C}$;>-g q>7i?L($'&J׸_|'gh8JUטpc1 fh%\Yvsy?_;ʡ!Mzg0 ]hj@IKeɓP$Շ69Q:&G gj?g*8 CÊal܀pw`bij%uv+2n+gӆ ~5F:CxҋQ83B^\u-U%j-VG'*AQ0M:N rߝhuOK oHsN+K hfd|EıW(B}t(.5K |-p\Xme/ErŅh}{kc%9Q38·|1 ?_ew|]\t(/I5oQ Sz\v*2:_"rV\7Eϟבp>Q-g`V?dt!W0rTLMXD0Z';'^ͪ%o}0KGM\:L%( 8p>5چqx nÖخC¹hPVSn<dɎ,yb$ɓ%O/Ή EN9{\>h8$c@rpKn],/KjUC*&KQ{o [7$PC ԗ0P8'㦑ʌC*_"M.'3EWX5<ݓDerGtR'cT\(O7լT=LE"lu wf^W(;pY݌# >$K0HdGɒܩC!bDFhʡ}_ |1iyVuH8PSN#te_7Ȳ@"I8_lo&˼M,Oy@\=a}Jy\ +yL-4vRt}ޔaQѿuC7 ==f`֒wPYPS\W~7C!${n.s--Q%HxctȒSd@I螸:CyR;Lp.A^rz)}Ŵ5yVܳ"bNe,&2d/?3 9.qx ?5nyJWpR#¨zIڂΚeH`@sVx]nn^2L:<⤭xHtytJhxy{廷B*bEI61)e럵U̥Y/BK#,ɫ>FNL^$gbqPDBUw0tcчpa '|.~՟GV8.󳊋L[N Swgoeoײ?ۖ#l"f,+רۺn 1 >_\"zR2KɨwA>sP[YT۽n&oHH8uJ&ay⋳v筒IJ>ڄ_`[πs$2N IDATUvGcvP;$/pqwse^ɸ-d?hd{ՑQ44EE:t'm.7w%pCJLt|3 [@ְ"H_NA!k sBT/H8+gsBI" g2*C'bSHܹ[|`F-sy~,;{cdKϦͷ~ӺT@|M\'~'ד"@ii2+ /}`.tcNFݪ"i6 G >~I6qJ bn@¹~\%wzC%IY}p:3>Q2AY(,ze&lDo[p,hⰸYJTT)2NMhhf@iS.nD_ d XQzp1Z]oDWq[]7[`7Ep8vP[I# gy|e^B[Z ›&Ńs>xqN;$^($"vj6'VS/޵o)X޹u3ARO]'B˜SIrzWJ'b*Q1cpsy}Qg'y(J9_)Dh o]qs '/#+Sn'gr;Qgn̊ߒ'?ťd̯(ˀP/r8|)׿W*T¿6s Ptӕ IW8 {BN%d6MU;36CʍQ+ ǕJhd4r/P);p#\S.7Dօ!c$fm^3{0'x~FSQ"O$y!; 棭0חVNL8 uTտ(](ݙ q_Rj?_>z)Òp * 58%#cH>u_!\?w'[׽aΑqíئ%oq9ߊ / dSAv; kŀ- VW IegU2 S6d1ZzI亞 e@ћs:;^#DYd A3U4Q#nh/s>)q-VF$%hH}>d럵U%tTP@Xr#*dO~VJ v:A(M=_|Wa0}sჃ=H#$1ɛpGqZ9% zww|sD0Ncl+@(C' 7%iʌJ0w>=&ʴ.Dׅ]deoHȎ$P^2 gշOtIt9j^H8S_ ;$A"[t]s/ x#+G257y:$etsIX#^y677|8.tA4w|5B^nK" [\73/G. Ul>q9X/x.p}`(͡_* 4F~C _O `۸+Ȋ,G7g'$Ću^|MGה:JI]ӥ RX[Ӊ-0+r]6IM1[&s 88B}NW CY$E<1  Ssq}ǿʮeRpo k~.<;6\ǢP.}3 4s)Z]S_ڄÅ:66GC"8Νw.P$V>Kf/IE0O@P@([.'U/Bde@W:ub|;p򶞯;=!'.? 2p:9hct(Oң7k\P[:GƵcG{6k|4YYnF ,s) "D &D_qh5.ӑIυ29/w;rbyf9GAބ4 2>x7WD>'@IL Nt#!. 4@M;'H8u$NĮgwI8]rp߂?:Hl|#Ydzk7&&70}םIiE@r `O[3>K?ܼZ[M}Ի96:HxN-w2BvS>$a/#A_#T>KRw V G!K*'1P/CRc O͓*(}rDW?\ l9@W^ބgYAYLސ_88W6~9?o^_{|7 8x <%"~W׊ QgH:y+"G23(,*\.G; DV r.xxK:WFEAdSltH$OOl&hTa|Z8*ד$׆_s[J'.INC2" B tpcѢf'!=e:!2 t~T #f~B\%Ae$~Dz$|Ŷ6 "I $9BȵVD@ m/p-r "yLtNݑp`^$Cka^8ʿf4۰hx/|{|م٩mr:z4`7AOF1}ٙ`yHY9"H*&07l_aGÜw.)Mi1O.H(({m1Q!,6.Fbb }"ᬜ r g: W$x|q79lw^?$\ſ[{W^q?p8+ BHȸ "R$)&#&exqyǪq q--B4>e2>Z-+uvv_I8;ЛzpCٛ%'+ߛ+G~날V8%et~px#wvI/p5N+E煛c'GylW~{$2^pjOOn^qrs23 ^Kno[: -"N#kHU G5_ܴ.x\ !ANĻIpX\tQ7Gr*Oo\x}2NZE'YZ|vn+$#grE$i煻@k7 #ٗ~~냷?13z:i?L)䋹[W]~pםw|st'vf슐n ј _Rs} dץ29p5:dP% : oxzyL;KE|?b?釟~yk,පyu.ԝ/<;W~>P59𲼚>J|: = ᎺT?S_ڽxW9UwK8#8JfRdG©p3B>V̳wsiŗ( 9\=W<x"$gQݦ71xLO}i?E!PK~p ׁ]jwx}l Z+y}9םte'p9Da+Ρ  X& ,#=!E>{QNo"4)ܽ<㠏/KOJWw O䛇 KMWksQPQFHF5$vwr]r{uv:uօk(hhqڤ_ !,?0FQ-i\Q,;*Y,K%Y}}޻K\r;_Yr^.w>u_C&So:Aupsa^|AES #7j-FC~^0XP0.KͿ[ M46 ]bcQ="mS갥ES%]9'lk~جtk6>\Š<}Ix}O<; ‡ʩyd ,Gk@}*O@"P2eƿ}9n>qخh>oksur|Ʒʡ1*|K']e-(tN!_;<=Y+׼l{Vp2_} 9}{}y`5/<@3.W?^|n6뉠Uz3(0գuϣDi_ڎY|al@œ^^@`ly=t%{= 1v+;{|8`c0T0+ɐt |Tz^.O,-}kWDw zˠ疚rn}q3ywHw9E.ͭa\xk")ik" |f`{*W|b!]A=_/^ c`xAeCxY0'~-5/@t @P  }닟y;uC am|qP`Ԣ1yepmg˰n&qslB 3nǹUyҢ)J偀UY$tBÆâu"_y @Ba{nR{lH>Q >?K`g7/#6ڰY}4M)ϸ,h*!؊S11|Q>dpk }{m6SG&kOڎ+RW>)BIAxTxzWX5D.no'u96?tyBViE`;HWG 2_Y!\y'|o}ލ&Z,TyWye7W6[pGUo6dw ҩlwqǂXev'q%^^Ae:+=ͪW\D[r/P5CX|z+̃wȎ?/\"n_po-ޏ FgcEη7+f*L]:= 5E*_n&6t2g\@/ܦ`w55@yay|ӓ"WͲ+'Ƿ6yz:Βhzx B{5œ"&U827ռ|3m{}O~Zh{{+cUho] vM * # 5o{{j^ODoȷPEop$hekoM\JOp]脁Qvk0%S=/>|q!k5-3tzO*nEHk0\_L'-VzXoA|ihߋKoO6V| {ƹ9G˪o4ZVs([!{=X]J]&Bn39+F!f)p IW-Hj]J력 jtݺUkrK E;mXz=SKg-o{3֬oye7 ;M>b]6g.Z~=w [&\2~-crs>:| A ch~[pLyӭ5 We:|mTr(GUFXbxB( hO]ys-lOk_DԠ81*[䏳t⢶;pYNmت4%x2 Q?1/-ZK 3 ɔd:e@\nDXO֗\8֮SK77@nX9K)=i1 bS06'3KI* K^{aqA{p+16=Mc^le_4nWFտknatb=/+iW US0jnt4Ĩr)0>stJ6pW-6%G9KeǔWEߙT8HyGZW >skI( E%ByM=O =0/|GƠ\u]d@~uiLF?L/TǘdI~=  ߾6 w!A`SA K+Ix v_t'glF,ʦBg/#d$*;yug1 jU*=;kDC}wݮc:~;|/os>Ku(EjA _a,a/dKy#aS y/]횣 N9Q~dk QE؊GW3|YiHVM+illi닇2 6%h_rEoz8o?h~ Xt[xWw9LvlG'(|ܲIwMVABv+:ǷOEz,qO*A EdVf]+iW PSӇ%{lYv{cSBa{!,pZ :Xjd438'P/dþxC95:D/1ǚxvJϪOAgs˓DzRmૢ!\)e!R'gEUxl-%>&]SP\[,Tyt58ֱWjaĽm{t}ؐvtγ]{_Ϧ׃JM@v}2oЬ|PՎsҴ?=Y jx_t'zDY$p_v~+>;KI*^q!Zw|,r۱*ҊFӱ{Uviu;=P?9/`CǏ7SR0*uxρ<ǥ|t\'k̤ rALQ;qmSP.d a\xwugA5 T`0gFN5q^lFv:w2aE7ɓSHƥFM#b:~=:cكoM|9a%D+.,-*㓂,ރ 2\UxL-%,<&wMΈr/m"S3`zF^a[Z|t%_h>/@9jv)Վ(JcO1xCֳr7()ߙ!:"ZNLXCX{,^iya7Tn0g al8-U +W>ܗħ_RʪWܿɶbmV *6v߄NEu˺|y6jv+s3zFR!t\~}9?s|̀xl{xI\TX["Fݔq=ve_tΏmKdN a\xwugAa9Rpu5,]_4%^{ UA6"6]}aSwDIZ)#d4p_:onR~<]݋k\Xo`A[;~y9C .AKH*<}TtBQŰ-K3nAb(6(Ϫ3M66ΓZ:)tA)R:V~Pa;KIJo&aQuKT-tJ (]])5Z)u)c14= [;16G: ֖HĖM$lԯWZvMsxJIvh8_xWwE @Bn{apԆUzb%%`< ̒900˨>6wwDFg1\-W'ϣZ>yؒ s/ CT8(\UxL-%q&xyκaqO5+eK[Y~F%].}WͣVO:RU0j>߅9$Vt,uqfG|4n{1x=wTz͐E{e׮ⳳG%- tE#xQE-Eˆ F5Hϕ.R]4qMc>ڰ{zz}PRY Po6?ݡM*츗ֺ^{a`bnv> ֨vst- |qdݴ9[:p5p-_ GZW,DG&Pb q[,Kw4LݪF |5&Yס|V󨕔$%E[s^bwFӼxzŎfq+JE&kH+\ 4j;yකq]uHv >+nă"ND[q\g1:^.PYw\/3uW7҃ϬNCJJJJԦw-yFno;7v&;;_o@Ϻ}åf+u{4%Uz.G-⿳O{xEܒ /45- M}HƆL2f^9\|IC\.ys/ߺYz2~|<=]ؘ놽g_w 3_JwԚ]#136z8VW[ϭำۻ /W{<#'Bs6!;֥zA5-<0yžW}ypUac(mƞY 4Z[:p+-7~(ѰdorJܗ.=+mzOͼ{NXezWzdw`.0oŤ{3Wp1>І~X':h]@;|,ohLέ}/sƅ-bP4ێFKv~hEsDȻ[3<}R+b2kM`JXӪt')cFڊn&Kȣ0 GF'd~P1W#(՝7TQG-lJPVӾ~%ߑ~nv'ⶸ;n}LV-|5핿Hcƫie)줛۫>!`1I5> i*ܫ0z۞~ ZdO~}paNf;R!^2viX6yn ˞#֚1ϥ|$E6y7j!S~ygp@s? )7W7"_x|y;\SX8Ё*\vO:$nC]w*ChE.egފ>~z%h;GEܒYZY}o~mQ]eΰR^md\y| x'VtV̗ 움}-1CVT耷vzd"y "m LI6jANbOϿ~^J3|J䭝?bѦK}~wڊ텧=,s~ ʁy 7}vd9C9Á}!c{vv1{iQ$uL6fm}hxEYMﭮ"#BVcQOaM7 7gsRWϳdyy6=O'eaa'+uŴZ;*iݾlɹ`c&M{C28 !>._lo=;vutɐwR;d3.tiG$o/3M[S{S)ފhS꭬ )-e~&f22cS߮ KtˢM=OMColF x_ngC'ځ&X2:}/+ۡgҜo|GGqN{U>\#adYԚkfAJ+4Mb5`R T{K EU&ymqk"yv@˗^_7u%~Cre G*+ ǔ3W7 O6֮]Uu3/G#_N¯=dLHsg[=(to x4 ^.ZFI7ݖE1lhRGMiTJC2Gdc'6W}9iثn{q\)|2gɛc6 7l(t8v,?}-UnV(0H\[,/7(BrޮV7) 8S^{G=93vN2n{}[YwwDng4}>dS*|#-_|gd&Z;8GOm\Vl{v Cߨ/eRR]ȴJ&Y^yy .\?YB1_yzWΔ+VGNΓ{Ϗw2CXL3\Gpsk*sKY ~cǘL6F.5m?!/23 k\*|K)1:-AD[ԑTZz̃rr#dwv= 7!AiMrݾ%ja2ERLHf'{y[.m;TqI'eSEu5)֑QQU6cT_/8~@An"_S }@n SYdOu;P{iӯ7ۚm­cRZB&R榔i$1ƊjNJ59'olI2FSŗ {LY1u+EdXm"lKm{ZE}I&vr+:]m[yY亚@ ۆ KzR̙4z, G @Nzjug ?3D+߾9)yMS#ϑ2Lf8 åHש.>XkEhIENDB`ruby-magic-0.6.0/test/fixtures/shell.magic000066400000000000000000000005571440414250500205230ustar00rootroot000000000000000 string/wt #!\ /bin/sh POSIX shell script text executable !:mime text/x-shellscript 0 string/wt #!\ /bin/bash Bourne-Again shell script text executable !:mime text/x-shellscript 0 string/t #!/ a >2 string >\0 %s script text executable !:strength / 2 ruby-magic-0.6.0/test/helpers/000077500000000000000000000000001440414250500161745ustar00rootroot00000000000000ruby-magic-0.6.0/test/helpers/magic_test_helper.rb000066400000000000000000000021561440414250500222030ustar00rootroot00000000000000# frozen_string_literal: true module MagicTestHelpers def capture_stderr(children: false) require 'thread' mutex = Mutex.new if children require 'tempfile' captured_stderr = Tempfile.new('captured_stderr') mutex.synchronize do backup_stderr = $stderr.dup $stderr.reopen(captured_stderr) begin yield $stderr.rewind captured_stderr.read ensure captured_stderr.unlink $stderr.reopen(backup_stderr) end end else require 'stringio' captured_stderr = StringIO.new mutex.synchronize do backup_stderr = $stderr $stderr = captured_stderr begin yield captured_stderr.string ensure $stderr = backup_stderr end end end end def with_fixtures(fixtures: 'fixtures', &block) cwd = File.join('test', fixtures) Dir.chdir(cwd) do yield(Dir.pwd) end end def with_env(env, &blk) before = ENV.to_h.dup env.each { |k, v| ENV[k] = v } yield ensure ENV.replace(before) end end ruby-magic-0.6.0/test/test_constants.rb000066400000000000000000000050401440414250500201310ustar00rootroot00000000000000# frozen_string_literal: true require 'test/unit' require 'magic' class MagicConstantsTest < Test::Unit::TestCase def test_flags_constants_defiend [ :NONE, :DEBUG, :SYMLINK, :COMPRESS, :DEVICES, :MIME_TYPE, :CONTINUE, :CHECK, :PRESERVE_ATIME, :RAW, :ERROR, :MIME_ENCODING, :MIME, :APPLE, :EXTENSION, :COMPRESS_TRANSP, :NO_CHECK_COMPRESS, :NO_CHECK_TAR, :NO_CHECK_SOFT, :NO_CHECK_APPTYPE, :NO_CHECK_ELF, :NO_CHECK_TEXT, :NO_CHECK_CDF, :NO_CHECK_CSV, :NO_CHECK_TOKENS, :NO_CHECK_ENCODING, :NO_CHECK_JSON, :NO_CHECK_BUILTIN, :NO_CHECK_ASCII, :NO_CHECK_FORTRAN, :NO_CHECK_TROFF ].each do |i| assert_const_defined(Magic, i) end end def test_parameters_constants_defiend [ :PARAM_INDIR_MAX, :PARAM_NAME_MAX, :PARAM_ELF_PHNUM_MAX, :PARAM_ELF_SHNUM_MAX, :PARAM_ELF_NOTES_MAX, :PARAM_REGEX_MAX, :PARAM_BYTES_MAX ].each do |i| assert_const_defined(Magic, i) end end def test_MIME_flag_constant expected = Magic::MIME_TYPE | Magic::MIME_ENCODING assert_equal(Magic::MIME, expected) end def test_NO_CHECK_ASCII_flag_constant assert_equal(Magic::NO_CHECK_ASCII, Magic::NO_CHECK_TEXT) end def test_NO_CHECK_BUILTIN_flag_constat expected = Magic::NO_CHECK_COMPRESS | Magic::NO_CHECK_TAR | Magic::NO_CHECK_APPTYPE | Magic::NO_CHECK_ELF | Magic::NO_CHECK_TEXT | Magic::NO_CHECK_CSV | Magic::NO_CHECK_CDF | Magic::NO_CHECK_TOKENS | Magic::NO_CHECK_ENCODING | Magic::NO_CHECK_JSON assert_equal(Magic::NO_CHECK_BUILTIN, expected) end def test_PARAM_INDIR_MAX_parameter_constant assert_equal(Magic::PARAM_INDIR_MAX, 0) end def test_PARAM_NAME_MAX_parameter_constant assert_equal(Magic::PARAM_NAME_MAX, 1) end def test_PARAM_ELF_PHNUM_MAX_parameter_constant assert_equal(Magic::PARAM_ELF_PHNUM_MAX, 2) end def test_PARAM_ELF_SHNUM_MAX_parameter_constant assert_equal(Magic::PARAM_ELF_SHNUM_MAX, 3) end def test_PARAM_ELF_NOTES_MAX_parameter_constant assert_equal(Magic::PARAM_ELF_NOTES_MAX, 4) end def test_PARAM_REGEX_MAX_parameter_constant assert_equal(Magic::PARAM_REGEX_MAX, 5) end def test_PARAM_BYTES_MAX_parameter_constant assert_equal(Magic::PARAM_BYTES_MAX, 6) end end ruby-magic-0.6.0/test/test_magic.rb000066400000000000000000000514711440414250500172060ustar00rootroot00000000000000# frozen_string_literal: true require 'test/unit' require 'magic' require_relative 'helpers/magic_test_helper' class MagicTest < Test::Unit::TestCase include MagicTestHelpers def setup @flags_limit = 0xfffffff @magic = Magic.new end def test_magic_singleton_methods [ :open, :mime, :mime_type, :type, :encoding, :compile, :check, :file, :buffer, :descriptor, :fd, :version, :version_array, :version_string, :version_to_a, :version_to_s ].each do |i| assert_respond_to(Magic, i) end end def test_magic_global_singleton_methods [ :do_not_auto_load, :do_not_auto_load=, :do_not_stop_on_error, :do_not_stop_on_error= ].each do |i| assert_respond_to(Magic, i) end end def test_magic_alias assert_same(FileMagic, Magic) end def test_magic_new_instance assert(@magic.class == Magic) end def test_magic_new_instance_default_flags assert_equal(Magic::NONE, @magic.flags) end def test_magic_new_with_block obtained = nil output = capture_stderr do obtained = Magic.new {} end assert_kind_of(Magic, obtained) expected = "Magic::new() does not take block; use Magic::open() instead\n" assert_equal(expected, output.split(/\.rb:\d+\:\s+?|warning:\s+?/).pop) end def test_magic_new_with_do_not_auto_load_set end def test_magic_new_with_MAGIC_DO_NOT_STOP_ON_ERROR_environment_variable end def test_magic_new_with_MAGIC_DO_NOT_AUTOLOAD_environment_variable end def test_magic_instance_methods [ :do_not_stop_on_error, :do_not_stop_on_error=, :open?, :close, :closed?, :paths, :get_parameter, :set_parameter, :flags, :flags=, :flags_list, :flags_names, :flags_to_a, :file, :buffer, :descriptor, :fd, :load, :load_files, :load_buffers, :loaded?, :compile, :check, :valid? ].each do |i| assert_respond_to(@magic, i) end end def test_magic_string_integration_methods [ :magic, :mime, :type ].each do |i| assert_respond_to(String.allocate, i) end end def test_magic_file_integration_singleton_methods [ :magic, :mime, :type ].each do |i| assert_respond_to(File, i) end end def test_magic_file_integration_instance_methods [ :magic, :mime, :type ].each do |i| assert_respond_to(File.allocate, i) end end def test_magic_open? assert_true(@magic.open?) @magic.close assert_false(@magic.open?) end def test_magic_close @magic.close assert_true(@magic.closed?) end def test_magic_close_twice assert_nothing_raised do @magic.close @magic.close end end def test_magic_close_error error = assert_raise Magic::LibraryError do @magic.close @magic.flags end assert_equal('Magic library is not open', error.message) end def test_magic_closed? assert_false(@magic.closed?) @magic.close assert_true(@magic.closed?) end def test_magic_inspect_when_magic_open assert_match(%r{^#$}, @magic.inspect) end def test_magic_inspect_when_magic_closed @magic.close assert_match(%r{^#$}, @magic.inspect) end def test_magic_paths assert_kind_of(Array, @magic.paths) assert_not_equal(0, @magic.paths.size) end def test_magic_paths_with_MAGIC_environment_variable with_fixtures do magic = with_env({"MAGIC" => "png-fake.magic"}) do Magic.new end assert_equal(["png-fake.magic"], magic.paths) assert_match(%r{^Ruby Gem image}, magic.file(Pathname.new('ruby.png'))) end end def test_magic_get_parameter_with_PARAM_INDIR_MAX assert_equal(50, @magic.get_parameter(Magic::PARAM_INDIR_MAX)) end def test_magic_get_parameter_with_PARAM_BYTES_MAX expected = 1024 * 1024 expected = expected * 7 if Magic.version > 543 assert_equal(expected, @magic.get_parameter(Magic::PARAM_BYTES_MAX)) end def test_magic_get_parameter_lower_boundary error = assert_raise Magic::ParameterError do @magic.get_parameter(-1) end assert_equal('unknown or invalid parameter specified', error.message) end def test_magic_get_parameter_upper_boundary error = assert_raise Magic::ParameterError do @magic.get_parameter(128) end assert_equal('unknown or invalid parameter specified', error.message) end def test_magic_set_parameter_with_PARAM_INDIR_MAX @magic.set_parameter(Magic::PARAM_INDIR_MAX, 128) assert_equal(128, @magic.get_parameter(Magic::PARAM_INDIR_MAX)) end def test_magic_set_parameter_with_PARAM_BYTES_MAX assert_nothing_raised do @magic.set_parameter(Magic::PARAM_BYTES_MAX, 1024 * 1024 * 10) end assert_equal(1024 * 1024 * 10, @magic.get_parameter(Magic::PARAM_BYTES_MAX)) end def test_magic_set_parameter_lower_boundary error = assert_raise Magic::ParameterError do @magic.set_parameter(-1, 0) end assert_equal('unknown or invalid parameter specified', error.message) assert_equal(Errno::EINVAL::Errno, error.errno) end def test_magic_set_parameter_upper_boundary error = assert_raise Magic::ParameterError do @magic.set_parameter(128, 0) end assert_equal('unknown or invalid parameter specified', error.message) assert_equal(Errno::EINVAL::Errno, error.errno) end def test_magic_set_parameter_value_lower_boundary assert_nothing_raised do @magic.set_parameter(0, 0) end end def test_magic_set_parameter_value_upper_boundary error = assert_raise Magic::ParameterError do @magic.set_parameter(0, -1) end assert_equal('invalid parameter value specified', error.message) assert_equal(Errno::EOVERFLOW::Errno, error.errno) end def test_magic_set_parameter_overflow_with_PARAM_INDIR_MAX error = assert_raise Magic::ParameterError do @magic.set_parameter(Magic::PARAM_INDIR_MAX, 128 * 1024) end assert_equal('invalid parameter value specified', error.message) assert_equal(Errno::EOVERFLOW::Errno, error.errno) end def test_magic_flags end def test_magic_flags_with_NONE_flag @magic.flags = 0x000000 assert_kind_of(Integer, @magic.flags) assert_equal(Magic::NONE, @magic.flags) end def test_magic_flags_with_DEBUG_flag output = capture_stderr do @magic.flags = Magic::DEBUG end assert_kind_of(Integer, @magic.flags) assert_equal(Magic::DEBUG, @magic.flags) assert_match(%r{^(.+)?Magic::DEBUG flag is set;}, output) end def test_magic_flags_with_MIME_TYPE_flag @magic.flags = 0x000010 assert_kind_of(Integer, @magic.flags) assert_equal(Magic::MIME_TYPE, @magic.flags) end def test_magic_flags_with_CHECK_flag output = capture_stderr do @magic.flags = Magic::CHECK end assert_kind_of(Integer, @magic.flags) assert_equal(Magic::CHECK, @magic.flags) assert_match(%r{^(.+)?Magic::CHECK flag is set;}, output) end def test_magic_flags_with_MIME_ENCODING_flag @magic.flags = 0x000400 assert_kind_of(Integer, @magic.flags) assert_equal(Magic::MIME_ENCODING, @magic.flags) end def test_magic_flags_with_MIME_flag @magic.flags = 0x000410 assert_kind_of(Integer, @magic.flags) assert_equal(Magic::MIME, @magic.flags) end def test_magic_flags_list end def test_magic_flags_list_alias assert_alias_method(@magic, :flags_to_a, :flags_list) end def test_magic_flags_list_with_NONE_flag @magic.flags = Magic::NONE assert_kind_of(Array, @magic.flags_list) assert_equal([Magic::NONE], @magic.flags_list) end def test_magic_flags_list_with_MIME_TYPE_flag @magic.flags = Magic::MIME_TYPE assert_kind_of(Array, @magic.flags_list) assert_equal([Magic::MIME_TYPE], @magic.flags_list) end def test_magic_flags_list_with_MIME_ENCODING_flag @magic.flags = Magic::MIME_ENCODING assert_kind_of(Array, @magic.flags_list) assert_equal([Magic::MIME_ENCODING], @magic.flags_list) end def test_magic_flags_list_with_MIME_flag @magic.flags = Magic::MIME_TYPE | Magic::MIME_ENCODING assert_kind_of(Array, @magic.flags_list) assert_equal([Magic::MIME_TYPE, Magic::MIME_ENCODING], @magic.flags_list) end def test_magic_flags_list_with_NONE_flag_and_argument_true @magic.flags = Magic::NONE assert_kind_of(Array, @magic.flags_list) assert_equal(['NONE'], @magic.flags_list(true)) end def test_magic_flags_list_with_MIME_TYPE_flag_and_argument_true @magic.flags = Magic::MIME_TYPE assert_kind_of(Array, @magic.flags_list) assert_equal(['MIME_TYPE'], @magic.flags_list(true)) end def test_magic_flags_list_with_MIME_ENCODING_flag_and_argument_true @magic.flags = Magic::MIME_ENCODING assert_kind_of(Array, @magic.flags_list) assert_equal(['MIME_ENCODING'], @magic.flags_list(true)) end def test_magic_flags_list_with_MIME_flag_and_argument_true @magic.flags = Magic::MIME_TYPE | Magic::MIME_ENCODING assert_kind_of(Array, @magic.flags_list) assert_equal(['MIME_TYPE', 'MIME_ENCODING'], @magic.flags_list(true)) end def test_magic_flags_names end def test_magic_flags_names_with_NONE_flag end def test_magic_flags_names_with_MIME_TYPE_flag end def test_magic_flags_names_with_MIME_ENCODING_flag end def test_magic_flags_names_with_MIME_flag end def test_magic_flags_error_lower_boundary error = assert_raise Magic::FlagsError do @magic.flags = -@flags_limit end assert_equal('unknown or invalid flag specified', error.message) assert_equal(Errno::EINVAL::Errno, error.errno) end def test_magic_flags_error_upper_boundary error = assert_raise Magic::FlagsError do @magic.flags = @flags_limit + 1 end assert_equal('unknown or invalid flag specified', error.message) assert_equal(Errno::EINVAL::Errno, error.errno) end def test_magic_do_not_stop_on_error_with_truthy_values end def test_magic_do_not_stop_on_error end def test_magic_do_not_stop_on_error_set_globally end def test_magic_file end def test_magic_file_with_do_not_stop_on_error_set end def test_magic_file_with_do_not_stop_on_error_set_globally end def test_magic_file_with_magic_library_not_loaded end def test_magic_file_with_nil_argument error = assert_raise TypeError do @magic.file nil end assert_equal('wrong argument type nil (expected String or IO-like object)', error.message) end def test_magic_file_argument_with_NULL assert_raise ArgumentError do @magic.file "string\0value" end end def test_magic_file_with_path_like_argument end def test_magic_file_with_IO_like_argument with_fixtures do @magic.load('png-fake.magic') File.open('ruby.png') do |file| assert_match(%r{^Ruby Gem image}, @magic.file(file)) assert_false(file.closed?) end end end def test_magic_file_with_IO_like_argument_stream_closed error = assert_raise IOError do IO.pipe do |r, w| r.close @magic.file r end end assert_equal('closed stream', error.message) end def test_magic_file_with_String_like_argument require 'pathname' with_fixtures do @magic.load('png-fake.magic') assert_equal(['png-fake.magic'], @magic.paths) assert_match(%r{^Ruby Gem image}, @magic.file(Pathname.new('ruby.png'))) end with_fixtures do @magic.load('png-fake.magic', 'shell.magic') assert_equal(['png-fake.magic', 'shell.magic'], @magic.paths) assert_match(%r{^Ruby Gem image}, @magic.file(Pathname.new('ruby.png'))) end end def test_magic_file_with_ERROR_flag end def test_magic_file_with_MAGIC_CONTINUE_flag end def test_magic_file_with_EXTENSION_flag end def test_magic_buffer end def test_magic_buffer_with_magic_library_not_loaded end def test_magic_buffer_with_nil_argument error = assert_raise TypeError do @magic.buffer nil end assert_equal('wrong argument type nil (expected String)', error.message) end def test_magic_buffer_argument_with_NULL assert_nothing_raised do @magic.buffer "string\0value" end end def test_magic_buffer_with_MAGIC_CONTINUE_flag end def test_magic_buffer_with_EXTENSION_flag end def test_magic_descriptor with_fixtures do @magic.load('png-fake.magic') File.open('ruby.png') do |file| assert_match(%r{^Ruby Gem image}, @magic.descriptor(file.fileno)) assert_false(file.closed?) end end end def test_magic_descriptor_alias assert_alias_method(@magic, :fd, :descriptor) end def test_magic_descriptor_with_magic_library_not_loaded end def test_magic_descriptor_with_nil_argument error = assert_raise TypeError do @magic.descriptor nil end expected = format('wrong argument type nil (expected %s)', 0.class) assert_equal(expected, error.message) end def test_magic_descriptor_with_invalid_descriptor error = assert_raise IOError do @magic.descriptor(-1) end assert_equal('Bad file descriptor', error.message) end def test_magic_descriptor_with_descriptor_closed error = assert_raise IOError do IO.pipe do |r, w| r.close @magic.descriptor r.fileno end end assert_equal('closed stream', error.message) end def test_magic_descriptor_with_old_descriptor_open end def test_magic_descriptor_with_MAGIC_CONTINUE_flag end def test_magic_descriptor_with_EXTENSION_flag end def test_magic_fd_with_integer end def test_magic_fd_with_object end def test_magic_load end def test_magic_load_alias assert_alias_method(@magic, :load_files, :load) end def test_magic_load_with_DEBUG_flag capture_stderr do @magic.flags = Magic::DEBUG end assert_kind_of(Integer, @magic.flags) assert_equal(Magic::DEBUG, @magic.flags) output = capture_stderr(children: true) do with_fixtures do assert_raise Magic::MagicError do @magic.load('invalid.magic') end end end assert_match(%r{^.+Not a valid Magic file!}, output) end def test_magic_load_with_do_not_auto_load_set end def test_magic_load_with_array_argument end def test_magic_load_with_custom_Magic_file_path end def test_magic_with_new_instance_custom_Magic_file_path end def test_magic_load_with_MAGIC_environment_variable original_paths = @magic.paths with_fixtures do with_env({"MAGIC" => "png-fake.magic"}) do # assert on setup magic = Magic.new assert_equal(["png-fake.magic"], magic.paths) assert_match(%r{^Ruby Gem image}, magic.file(Pathname.new('ruby.png'))) # verify that #load should override the existing @paths and MAGIC magic.load(original_paths) assert_equal(original_paths, magic.paths) assert_match(%r{^PNG image data}, magic.file(Pathname.new('ruby.png'))) end end end def test_magic_load_buffers end def test_magic_load_buffers_with_array_argument end def test_magic_load_buffers_with_DEBUG_flag end def test_magic_loaded? end def test_magic_loaded_with_do_not_auto_load_set end def test_magic_compile end def test_magic_compile_with_DEBUG_flag end def test_magic_check end def test_magic_check_alias assert_alias_method(@magic, :valid?, :check) end def test_magic_check_with_DEBUG_flag output = capture_stderr(children: true) do @magic.flags = Magic::DEBUG end assert_kind_of(Integer, @magic.flags) assert_equal(Magic::DEBUG, @magic.flags) assert_match(%r{(.+)?Magic::DEBUG flag is set;}, output) output = capture_stderr(children: true) do with_fixtures do assert_nothing_raised do @magic.check('invalid.magic') end end end assert_match(%r{^.+Not a valid Magic file!}, output) end def test_magic_version assert_kind_of(Integer, Magic.version) assert(Magic.version > 0) end def test_magic_version_array expected = [Magic.version / 100, Magic.version % 100] assert_equal(expected, Magic.version_array) end def test_magic_version_array_alias assert_alias_method(Magic, :version_array, :version_to_a) end def test_magic_version_string expected = '%d.%02d' % Magic.version_array assert_equal(expected, Magic.version_string) end def test_magic_version_string_alias assert_alias_method(Magic, :version_string, :version_to_s) end def test_magic_singleton_do_not_auto_load_global_with_truthy_values assert_false(Magic.do_not_auto_load) Magic.do_not_auto_load = 1 Magic.do_not_auto_load = 0 assert_true(Magic.do_not_auto_load) Magic.do_not_auto_load = false assert_false(Magic.do_not_auto_load) end def test_magic_singleton_do_not_auto_load_global omit_unless(Process.respond_to?(:fork), "Platform does not support fork") saved = Magic.do_not_auto_load klass = Class.new(Magic) assert_false(Magic.do_not_auto_load) assert_false(klass.do_not_auto_load) fork do Magic.do_not_auto_load = true magic = Magic.new error_1 = assert_raise Magic::MagicError do magic.buffer '' end error_2 = assert_raise Magic::MagicError do klass.buffer '' end assert_equal('Magic library not loaded', error_1.message) assert_equal('Magic library not loaded', error_2.message) assert_true(Magic.do_not_auto_load) assert_true(klass.do_not_auto_load) end Process.waitpid rescue Errno::ECHILD assert_false(Magic.do_not_auto_load) assert_false(klass.do_not_auto_load) Magic.do_not_auto_load = saved assert_false(Magic.do_not_auto_load) assert_false(klass.do_not_auto_load) end def test_magic_singleton_do_not_auto_load_global_no_fork omit_if(Process.respond_to?(:fork), "Platform supports fork") assert_false(Magic.do_not_auto_load) saved = Magic.do_not_auto_load klass = Class.new(Magic) assert_false(Magic.do_not_auto_load) assert_false(klass.do_not_auto_load) Magic.do_not_auto_load = true magic = Magic.new error_1 = assert_raise Magic::MagicError do magic.buffer '' end error_2 = assert_raise Magic::MagicError do klass.buffer '' end assert_equal('Magic library not loaded', error_1.message) assert_equal('Magic library not loaded', error_2.message) assert_true(Magic.do_not_auto_load) assert_true(klass.do_not_auto_load) Magic.do_not_auto_load = saved assert_false(Magic.do_not_auto_load) assert_false(klass.do_not_auto_load) end def test_magic_singleton_do_not_stop_on_error_with_truthy_values end def test_magic_singleton_do_not_stop_on_error_global end def test_magic_singleton_do_not_stop_on_error end def test_magic_singleton_open end def test_magic_singleton_open_custom_flag end def test_magic_singleton_open_block end def test_magic_singleton_open_block_custom_flag end def test_magic_singleton_mime end def test_magic_singleton_mime_block end def test_magic_singleton_type end def test_magic_singleton_type_block end def test_magic_singleton_encoding end def test_magic_singleton_encoding_block end def test_magic_singleton_compile end def test_magic_singleton_check end def test_magic_singleton_file end def test_magic_singleton_buffer end def test_magic_singleton_descriptor end def test_magic_magic_error message = 'The quick brown fox jumps over the lazy dog' error = Magic::Error.new(message) assert_respond_to(error, :errno) assert_equal(message, error.message) assert_nil(error.errno) end def test_magic_error_attribute_errno @magic.flags = @flags_limit + 1 rescue Magic::Error => error assert_kind_of(Magic::FlagsError, error) assert_equal(Errno::EINVAL::Errno, error.errno) end def test_magic_new_instance_with_arguments end def test_file_integration_magic end def test_file_integration_magic_with_custom_flag end def test_file_integration_mime end def test_file_integration_type end def test_file_integration_singleton_magic end def test_file_integration_singleton_magic_with_custom_flag end def test_file_integration_singleton_mime end def test_file_integration_singleton_type end def test_string_integration_magic end def test_string_integration_magic_with_custom_flag end def test_string_integration_mime end def test_string_integration_type end def test_gc_compaction omit_unless( defined?(GC.verify_compaction_references) == 'method', "Platform does not support GC.compact" ) begin GC.verify_compaction_references(double_heap: true, toward: :empty) rescue NotImplementedError => e omit(e) end end end